]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into terencehill/menu_gametype_tooltips_2
authorterencehill <piuntn@gmail.com>
Sat, 10 Oct 2015 11:32:08 +0000 (13:32 +0200)
committerterencehill <piuntn@gmail.com>
Sat, 10 Oct 2015 11:32:08 +0000 (13:32 +0200)
Conflicts:
qcsrc/menu/xonotic/dialog_settings_game.qc

569 files changed:
defaultXonotic.cfg
effectinfo.txt
gfx/hud/default/checkmark.tga [new file with mode: 0644]
gfx/hud/default/minigames/qto/board.jpg [deleted file]
gfx/hud/default/minigames/qto/board_alpha.jpg [deleted file]
gfx/hud/default/minigames/qto/icon.jpg [deleted file]
gfx/hud/default/minigames/qto/icon_notif.jpg [deleted file]
gfx/hud/default/minigames/qto/icon_notif_alpha.jpg [deleted file]
gfx/hud/default/minigames/qto/piece0.tga [deleted file]
gfx/hud/default/minigames/qto/piece1.tga [deleted file]
gfx/hud/default/minigames/snake/board.jpg [new file with mode: 0644]
gfx/hud/default/minigames/snake/board_alpha.jpg [new file with mode: 0644]
gfx/hud/default/minigames/snake/body.tga [new file with mode: 0644]
gfx/hud/default/minigames/snake/head.tga [new file with mode: 0644]
gfx/hud/default/minigames/snake/icon.jpg [new file with mode: 0644]
gfx/hud/default/minigames/snake/icon_notif.jpg [new file with mode: 0644]
gfx/hud/default/minigames/snake/icon_notif_alpha.jpg [new file with mode: 0644]
gfx/hud/default/minigames/snake/mouse.tga [new file with mode: 0644]
gfx/hud/default/minigames/snake/tail.tga [new file with mode: 0644]
gfx/hud/default/minigames/snake/tongue.tga [new file with mode: 0644]
minigames.cfg
mod/client/main.qc [deleted file]
mod/client/progs.inc [deleted file]
mod/menu/main.qc [deleted file]
mod/menu/progs.inc [deleted file]
mod/server/main.qc [deleted file]
mod/server/progs.inc [deleted file]
monsters.cfg
mutators.cfg
particles/hook_blue.tga
particles/hook_pink.tga
particles/hook_red.tga
particles/hook_white.tga
particles/hook_yellow.tga
physics.cfg
physicsCPMA.cfg
physicsFruit.cfg
physicsHavoc.cfg
physicsLeeStricklin-ModdedFruit.cfg
physicsLeeStricklin.cfg
physicsLeeStricklinOld.cfg
physicsLzd.cfg
physicsNexuiz10.cfg
physicsNexuiz11.cfg
physicsNexuiz151.cfg
physicsNexuiz151b.cfg
physicsNexuiz16rc1.cfg
physicsNexuiz20.cfg
physicsNexuiz25.cfg
physicsNexuiz26.cfg
physicsNoQWBunny-nexbased.cfg
physicsQ.cfg
physicsQ2.cfg
physicsQ2a.cfg
physicsQ3.cfg
physicsQBF.cfg
physicsQBFplus.cfg
physicsSamual.cfg
physicsWarsow.cfg
physicsWarsowClassicBunny.cfg
physicsWarsowDev.cfg
qcsrc/.gitignore [new file with mode: 0644]
qcsrc/Doxyfile [new file with mode: 0644]
qcsrc/Makefile
qcsrc/client/_all.qh
qcsrc/client/announcer.qc
qcsrc/client/command/cl_cmd.qc
qcsrc/client/controlpoint.qc
qcsrc/client/controlpoint.qh
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/csqcmodel_hooks.qh [deleted file]
qcsrc/client/damage.qc
qcsrc/client/generator.qc
qcsrc/client/generator.qh
qcsrc/client/gibs.qc
qcsrc/client/gibs.qh
qcsrc/client/hook.qc
qcsrc/client/hook.qh
qcsrc/client/hud.qc
qcsrc/client/hud.qh
qcsrc/client/hud_config.qc
qcsrc/client/laser.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/mapvoting.qc
qcsrc/client/modeleffects.qc
qcsrc/client/modeleffects.qh
qcsrc/client/mutators/events.qh
qcsrc/client/particles.qh
qcsrc/client/player_skeleton.qc
qcsrc/client/progs.inc [new file with mode: 0644]
qcsrc/client/progs.src
qcsrc/client/quickmenu.qc
qcsrc/client/rubble.qc
qcsrc/client/scoreboard.qc
qcsrc/client/t_items.qc
qcsrc/client/teamradar.qc
qcsrc/client/teamradar.qh
qcsrc/client/tuba.qc
qcsrc/client/view.qc
qcsrc/client/wall.qc
qcsrc/client/wall.qh
qcsrc/client/weapons/projectile.qc
qcsrc/client/weapons/projectile.qh
qcsrc/collect-precache.sh [deleted file]
qcsrc/common/animdecide.qc
qcsrc/common/buffs.qc [deleted file]
qcsrc/common/buffs.qh [deleted file]
qcsrc/common/buffs/all.inc [new file with mode: 0644]
qcsrc/common/buffs/all.qc [new file with mode: 0644]
qcsrc/common/buffs/all.qh [new file with mode: 0644]
qcsrc/common/command/generic.qc
qcsrc/common/constants.qh
qcsrc/common/csqcmodel_settings.qh
qcsrc/common/deathtypes.qh
qcsrc/common/effects.inc [deleted file]
qcsrc/common/effects.qc [deleted file]
qcsrc/common/effects.qh [deleted file]
qcsrc/common/effects/effectinfo.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo.qc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_buffs.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_ctf.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_gentle.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_gentle_happy.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_gentle_morphed.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_gentle_particlegibs.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_instagib.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_nades.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_onslaught.inc [new file with mode: 0644]
qcsrc/common/effects/effectinfo_vehicles.inc [new file with mode: 0644]
qcsrc/common/effects/effects.inc [new file with mode: 0644]
qcsrc/common/effects/effects.qc [new file with mode: 0644]
qcsrc/common/effects/effects.qh [new file with mode: 0644]
qcsrc/common/items/all.qc
qcsrc/common/items/all.qh
qcsrc/common/items/inventory.qh
qcsrc/common/items/item/ammo.qc
qcsrc/common/items/item/armor.qc
qcsrc/common/items/item/health.qc
qcsrc/common/items/item/jetpack.qc
qcsrc/common/items/item/pickup.qh
qcsrc/common/items/item/powerup.qc
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/minigame/all.qh
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/qto.qc [deleted file]
qcsrc/common/minigames/minigame/snake.qc [new file with mode: 0644]
qcsrc/common/minigames/minigame/ttt.qc
qcsrc/common/minigames/minigames.qc
qcsrc/common/minigames/minigames.qh
qcsrc/common/minigames/sv_minigames.qc
qcsrc/common/minigames/sv_minigames.qh
qcsrc/common/models/all.inc [new file with mode: 0644]
qcsrc/common/models/all.qh [new file with mode: 0644]
qcsrc/common/monsters/all.qc
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/monster/zombie.qc
qcsrc/common/monsters/spawn.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/movetypes/follow.qc
qcsrc/common/movetypes/movetypes.qc
qcsrc/common/movetypes/push.qc
qcsrc/common/movetypes/step.qc
qcsrc/common/movetypes/toss.qc
qcsrc/common/movetypes/walk.qc
qcsrc/common/mutators/base.qh
qcsrc/common/mutators/mutator/casings.qc
qcsrc/common/mutators/mutator/damagetext.qc
qcsrc/common/mutators/mutator/itemstime.qc
qcsrc/common/mutators/mutator/waypoints/all.inc
qcsrc/common/mutators/mutator/waypoints/all.qh
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh
qcsrc/common/nades.qc [deleted file]
qcsrc/common/nades.qh [deleted file]
qcsrc/common/nades/all.inc [new file with mode: 0644]
qcsrc/common/nades/all.qc [new file with mode: 0644]
qcsrc/common/nades/all.qh [new file with mode: 0644]
qcsrc/common/net_notice.qc
qcsrc/common/notifications.qc
qcsrc/common/notifications.qh
qcsrc/common/physics.qc
qcsrc/common/physics.qh
qcsrc/common/playerstats.qc
qcsrc/common/sounds/all.inc [new file with mode: 0644]
qcsrc/common/sounds/all.qh [new file with mode: 0644]
qcsrc/common/stats.qh
qcsrc/common/triggers/func/bobbing.qc
qcsrc/common/triggers/func/breakable.qc
qcsrc/common/triggers/func/breakable.qh
qcsrc/common/triggers/func/button.qc
qcsrc/common/triggers/func/conveyor.qc
qcsrc/common/triggers/func/door.qc
qcsrc/common/triggers/func/door_rotating.qc
qcsrc/common/triggers/func/door_secret.qc
qcsrc/common/triggers/func/fourier.qc
qcsrc/common/triggers/func/ladder.qc
qcsrc/common/triggers/func/pendulum.qc
qcsrc/common/triggers/func/plat.qc
qcsrc/common/triggers/func/pointparticles.qc
qcsrc/common/triggers/func/rainsnow.qc
qcsrc/common/triggers/func/rotating.qc
qcsrc/common/triggers/func/stardust.qc
qcsrc/common/triggers/func/train.qc
qcsrc/common/triggers/func/vectormamamam.qc
qcsrc/common/triggers/misc/corner.qc
qcsrc/common/triggers/misc/follow.qc
qcsrc/common/triggers/misc/laser.qc
qcsrc/common/triggers/misc/teleport_dest.qc
qcsrc/common/triggers/platforms.qc
qcsrc/common/triggers/subs.qc
qcsrc/common/triggers/subs.qh
qcsrc/common/triggers/target/changelevel.qc
qcsrc/common/triggers/target/location.qc
qcsrc/common/triggers/target/music.qc
qcsrc/common/triggers/target/spawn.qc
qcsrc/common/triggers/target/speaker.qc
qcsrc/common/triggers/target/voicescript.qc
qcsrc/common/triggers/teleporters.qc
qcsrc/common/triggers/trigger/counter.qc
qcsrc/common/triggers/trigger/delay.qc
qcsrc/common/triggers/trigger/disablerelay.qc
qcsrc/common/triggers/trigger/flipflop.qc
qcsrc/common/triggers/trigger/gamestart.qc
qcsrc/common/triggers/trigger/gravity.qc
qcsrc/common/triggers/trigger/heal.qc
qcsrc/common/triggers/trigger/hurt.qc
qcsrc/common/triggers/trigger/impulse.qc
qcsrc/common/triggers/trigger/jumppads.qc
qcsrc/common/triggers/trigger/jumppads.qh
qcsrc/common/triggers/trigger/keylock.qc
qcsrc/common/triggers/trigger/magicear.qc
qcsrc/common/triggers/trigger/monoflop.qc
qcsrc/common/triggers/trigger/multi.qc
qcsrc/common/triggers/trigger/multi.qh
qcsrc/common/triggers/trigger/multivibrator.qc
qcsrc/common/triggers/trigger/relay.qc
qcsrc/common/triggers/trigger/relay_activators.qc
qcsrc/common/triggers/trigger/relay_if.qc
qcsrc/common/triggers/trigger/relay_teamcheck.qc
qcsrc/common/triggers/trigger/secret.qc
qcsrc/common/triggers/trigger/swamp.qc
qcsrc/common/triggers/trigger/teleport.qc
qcsrc/common/triggers/trigger/viewloc.qc
qcsrc/common/triggers/triggers.qc
qcsrc/common/turrets/all.inc [new file with mode: 0644]
qcsrc/common/turrets/all.qc [new file with mode: 0644]
qcsrc/common/turrets/all.qh
qcsrc/common/turrets/checkpoint.qc
qcsrc/common/turrets/cl_turrets.qc
qcsrc/common/turrets/config.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 [new file with mode: 0644]
qcsrc/common/turrets/turret/ewheel.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/ewheel_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/flac.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/flac_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/fusionreactor.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/hellion.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/hellion_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/hk.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/hk_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/machinegun.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/machinegun_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/mlrs.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/mlrs_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/phaser.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/phaser_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/plasma.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/plasma_dual.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/plasma_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/tesla.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/tesla_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/walker.qc [new file with mode: 0644]
qcsrc/common/turrets/turret/walker_weapon.qc [new file with mode: 0644]
qcsrc/common/turrets/turrets.qc [deleted file]
qcsrc/common/turrets/turrets.qh [deleted file]
qcsrc/common/turrets/unit/ewheel.qc [deleted file]
qcsrc/common/turrets/unit/flac.qc [deleted file]
qcsrc/common/turrets/unit/fusionreactor.qc [deleted file]
qcsrc/common/turrets/unit/hellion.qc [deleted file]
qcsrc/common/turrets/unit/hk.qc [deleted file]
qcsrc/common/turrets/unit/machinegun.qc [deleted file]
qcsrc/common/turrets/unit/mlrs.qc [deleted file]
qcsrc/common/turrets/unit/phaser.qc [deleted file]
qcsrc/common/turrets/unit/plasma.qc [deleted file]
qcsrc/common/turrets/unit/plasma_dual.qc [deleted file]
qcsrc/common/turrets/unit/tesla.qc [deleted file]
qcsrc/common/turrets/unit/walker.qc [deleted file]
qcsrc/common/turrets/util.qc
qcsrc/common/util-post.qh
qcsrc/common/util-pre.qh
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/common/vehicles/all.inc
qcsrc/common/vehicles/all.qc
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/unit/bumblebee.qc [deleted file]
qcsrc/common/vehicles/unit/bumblebee.qh [deleted file]
qcsrc/common/vehicles/unit/racer.qc [deleted file]
qcsrc/common/vehicles/unit/raptor.qc [deleted file]
qcsrc/common/vehicles/unit/raptor.qh [deleted file]
qcsrc/common/vehicles/unit/spiderbot.qc [deleted file]
qcsrc/common/vehicles/vehicle.qh
qcsrc/common/vehicles/vehicle/bumblebee.qc [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/bumblebee.qh [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/racer.qc [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/racer_weapon.qc [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/raptor.qc [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/raptor.qh [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/raptor_weapons.qc [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/spiderbot.qc [new file with mode: 0644]
qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc [new file with mode: 0644]
qcsrc/common/viewloc.qc
qcsrc/common/weapons/all.inc
qcsrc/common/weapons/all.qc
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/config.qc
qcsrc/common/weapons/weapon.qh [new file with mode: 0644]
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/hmg.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/rpc.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/csqcmodellib/cl_model.qc
qcsrc/csqcmodellib/cl_player.qc
qcsrc/csqcmodellib/interpolate.qc
qcsrc/csqcmodellib/sv_model.qc
qcsrc/csqcmodellib/sv_model.qh
qcsrc/dpdefs/csprogsdefs.qh
qcsrc/dpdefs/progsdefs.qh
qcsrc/lib/Accumulate.qh [deleted file]
qcsrc/lib/Bool.qh [deleted file]
qcsrc/lib/Counting.qh [deleted file]
qcsrc/lib/Cvar.qh [deleted file]
qcsrc/lib/Defer.qh [deleted file]
qcsrc/lib/Draw.qh [deleted file]
qcsrc/lib/I18N.qh [deleted file]
qcsrc/lib/Lazy.qh [deleted file]
qcsrc/lib/Log.qh [deleted file]
qcsrc/lib/Math.qh [deleted file]
qcsrc/lib/Nil.qh [deleted file]
qcsrc/lib/OO.qh [deleted file]
qcsrc/lib/Player.qh [deleted file]
qcsrc/lib/Progname.qh [deleted file]
qcsrc/lib/Registry.qh [deleted file]
qcsrc/lib/Static.qh [deleted file]
qcsrc/lib/String.qh [deleted file]
qcsrc/lib/Struct.qh [deleted file]
qcsrc/lib/Vector.qh [deleted file]
qcsrc/lib/_all.inc
qcsrc/lib/accumulate.qh [new file with mode: 0644]
qcsrc/lib/bits.qh [new file with mode: 0644]
qcsrc/lib/bool.qh [new file with mode: 0644]
qcsrc/lib/counting.qh [new file with mode: 0644]
qcsrc/lib/cvar.qh [new file with mode: 0644]
qcsrc/lib/defer.qh [new file with mode: 0644]
qcsrc/lib/draw.qh [new file with mode: 0644]
qcsrc/lib/file.qh [new file with mode: 0644]
qcsrc/lib/i18n.qh [new file with mode: 0644]
qcsrc/lib/lazy.qh [new file with mode: 0644]
qcsrc/lib/log.qh [new file with mode: 0644]
qcsrc/lib/math.qh [new file with mode: 0644]
qcsrc/lib/net.qh [new file with mode: 0644]
qcsrc/lib/nil.qh [new file with mode: 0644]
qcsrc/lib/oo.qh [new file with mode: 0644]
qcsrc/lib/player.qh [new file with mode: 0644]
qcsrc/lib/prandom.qc [deleted file]
qcsrc/lib/prandom.qh [deleted file]
qcsrc/lib/progname.qh [new file with mode: 0644]
qcsrc/lib/random.qc [new file with mode: 0644]
qcsrc/lib/random.qh [new file with mode: 0644]
qcsrc/lib/registry.qh [new file with mode: 0644]
qcsrc/lib/replicate.qh [new file with mode: 0644]
qcsrc/lib/sort.qh [new file with mode: 0644]
qcsrc/lib/spawnfunc.qh [new file with mode: 0644]
qcsrc/lib/static.qh [new file with mode: 0644]
qcsrc/lib/string.qh [new file with mode: 0644]
qcsrc/lib/struct.qh [new file with mode: 0644]
qcsrc/lib/vector.qh [new file with mode: 0644]
qcsrc/menu/anim/animation.qc
qcsrc/menu/gamesettings.qh
qcsrc/menu/item/button.qc
qcsrc/menu/item/label.qc
qcsrc/menu/item/listbox.qc
qcsrc/menu/item/slider.qc
qcsrc/menu/item/textslider.qc
qcsrc/menu/progs.inc [new file with mode: 0644]
qcsrc/menu/progs.src
qcsrc/menu/xonotic/datasource.qc
qcsrc/menu/xonotic/dialog_monstertools.qc
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/menu/xonotic/dialog_settings_game.qc
qcsrc/menu/xonotic/keybinder.qc
qcsrc/menu/xonotic/radiobutton.qc
qcsrc/menu/xonotic/slider.qc
qcsrc/menu/xonotic/slider_decibels.qc
qcsrc/menu/xonotic/slider_particles.qc
qcsrc/menu/xonotic/slider_resolution.qc
qcsrc/menu/xonotic/slider_sbfadetime.qc
qcsrc/menu/xonotic/textslider.qc
qcsrc/menu/xonotic/util.qc
qcsrc/server-testcase/framework.qc
qcsrc/server/_all.qh
qcsrc/server/anticheat.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/aim.qc
qcsrc/server/bot/bot.qc
qcsrc/server/bot/bot.qh
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/bot/havocbot/role_keyhunt.qc
qcsrc/server/bot/havocbot/roles.qc
qcsrc/server/bot/navigation.qc
qcsrc/server/bot/scripting.qc
qcsrc/server/bot/waypoints.qc
qcsrc/server/bot/waypoints.qh
qcsrc/server/cheats.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_player.qc
qcsrc/server/command/cmd.qc
qcsrc/server/command/common.qc
qcsrc/server/command/radarmap.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/controlpoint.qc
qcsrc/server/defs.qh
qcsrc/server/ent_cs.qc
qcsrc/server/ent_cs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_damage.qh
qcsrc/server/g_hook.qc
qcsrc/server/g_hook.qh
qcsrc/server/g_lights.qc
qcsrc/server/g_models.qc
qcsrc/server/g_subs.qc
qcsrc/server/g_subs.qh
qcsrc/server/g_violence.qc
qcsrc/server/g_violence.qh
qcsrc/server/g_world.qc
qcsrc/server/generator.qc
qcsrc/server/generator.qh
qcsrc/server/ipban.qc
qcsrc/server/item_key.qc
qcsrc/server/mapvoting.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/movelib.qc
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/gamemode_assault.qc
qcsrc/server/mutators/gamemode_ca.qc
qcsrc/server/mutators/gamemode_ctf.qc
qcsrc/server/mutators/gamemode_cts.qc
qcsrc/server/mutators/gamemode_domination.qc
qcsrc/server/mutators/gamemode_freezetag.qc
qcsrc/server/mutators/gamemode_invasion.qc
qcsrc/server/mutators/gamemode_keepaway.qc
qcsrc/server/mutators/gamemode_keyhunt.qc
qcsrc/server/mutators/gamemode_lms.qc
qcsrc/server/mutators/gamemode_nexball.qc
qcsrc/server/mutators/gamemode_nexball_weapon.qc [new file with mode: 0644]
qcsrc/server/mutators/gamemode_onslaught.qc
qcsrc/server/mutators/gamemode_race.qc
qcsrc/server/mutators/gamemode_tdm.qc
qcsrc/server/mutators/mutator_bloodloss.qc
qcsrc/server/mutators/mutator_buffs.qc
qcsrc/server/mutators/mutator_buffs.qh
qcsrc/server/mutators/mutator_campcheck.qc
qcsrc/server/mutators/mutator_dodging.qc
qcsrc/server/mutators/mutator_hook.qc [new file with mode: 0644]
qcsrc/server/mutators/mutator_instagib.qc
qcsrc/server/mutators/mutator_instagib_items.qc
qcsrc/server/mutators/mutator_melee_only.qc
qcsrc/server/mutators/mutator_midair.qc
qcsrc/server/mutators/mutator_multijump.qc
qcsrc/server/mutators/mutator_nades.qc
qcsrc/server/mutators/mutator_new_toys.qc
qcsrc/server/mutators/mutator_nix.qc
qcsrc/server/mutators/mutator_overkill.qc
qcsrc/server/mutators/mutator_overkill.qh
qcsrc/server/mutators/mutator_physical_items.qc
qcsrc/server/mutators/mutator_pinata.qc
qcsrc/server/mutators/mutator_spawn_near_teammate.qc
qcsrc/server/mutators/mutator_superspec.qc
qcsrc/server/mutators/mutator_touchexplode.qc
qcsrc/server/mutators/mutator_vampirehook.qc
qcsrc/server/mutators/mutators_include.qc
qcsrc/server/mutators/mutators_include.qh
qcsrc/server/mutators/sandbox.qc
qcsrc/server/pathlib.qc [deleted file]
qcsrc/server/pathlib.qh [deleted file]
qcsrc/server/pathlib/costs.qc
qcsrc/server/pathlib/debug.qc
qcsrc/server/pathlib/main.qc
qcsrc/server/pathlib/movenode.qc
qcsrc/server/pathlib/path_waypoint.qc
qcsrc/server/pathlib/utility.qc
qcsrc/server/playerdemo.qc
qcsrc/server/portals.qc
qcsrc/server/progs.inc [new file with mode: 0644]
qcsrc/server/progs.src
qcsrc/server/race.qc
qcsrc/server/round_handler.qc
qcsrc/server/scores.qc
qcsrc/server/spawnpoints.qc
qcsrc/server/spawnpoints.qh
qcsrc/server/steerlib.qc
qcsrc/server/sv_main.qc
qcsrc/server/sys-pre.qh
qcsrc/server/t_halflife.qc
qcsrc/server/t_items.qc
qcsrc/server/t_items.qh
qcsrc/server/t_quake.qc
qcsrc/server/t_quake3.qc
qcsrc/server/teamplay.qc
qcsrc/server/teamplay.qh
qcsrc/server/weapons/accuracy.qc
qcsrc/server/weapons/accuracy.qh
qcsrc/server/weapons/common.qc
qcsrc/server/weapons/csqcprojectile.qc
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/spawning.qc
qcsrc/server/weapons/throwing.qc
qcsrc/server/weapons/tracing.qc
qcsrc/server/weapons/weaponsystem.qc
qcsrc/server/weapons/weaponsystem.qh
qcsrc/warpzonelib/client.qc
qcsrc/warpzonelib/common.qc
qcsrc/warpzonelib/server.qc
qcsrc/warpzonelib/util_server.qc
qcsrc/whitespace.sh
weapons.cfg

index ede4ffe1135b6ecfe9e3b3020d5cb70ac8daddc8..3735e55349da0713a11e59317ead64ebe0d13610 100644 (file)
@@ -305,6 +305,7 @@ set sv_doublejump 0 "allow Quake 2-style double jumps"
 set sv_jumpspeedcap_min "" "lower bound on the baseline velocity of a jump; final velocity will be >= (jumpheight * min + jumpheight)"
 set sv_jumpspeedcap_max "" "upper bound on the baseline velocity of a jump; final velocity will be <= (jumpheight * max + jumpheight)"
 set sv_jumpspeedcap_max_disable_on_ramps 0 "disable upper baseline velocity bound on ramps to preserve the old rampjump style"
+set sv_track_canjump 0 "track if the player released the jump key between 2 jumps to decide if they are able to jump or not"
 
 seta sv_precacheplayermodels 1
 seta sv_precacheweapons 0
@@ -541,6 +542,7 @@ gl_picmip_sprites 0
 gl_picmip_other 1 // so, picmip -1 is best possible quality
 r_mipsprites 1
 r_mipskins 1
+gl_max_lightmapsize 4096
 r_shadow_realtime_world_lightmaps 1
 r_shadow_realtime_world_importlightentitiesfrommap 0 // Whether build process uses keepLights is nontransparent and may change, so better make keepLights not matter.
 cl_decals_fadetime 5
@@ -639,6 +641,7 @@ alias weapon_group_7 "impulse 7"
 alias weapon_group_8 "impulse 8"
 alias weapon_group_9 "impulse 9"
 alias weapon_group_0 "impulse 14" // cycles the superweapons
+// TODO: remove after 0.8.2. Default impulse commands for 0.8.1 servers
 exec weapons.cfg
 
 // score log
index 2ba9a413b01ded720c47c53afbead18b3d3c99b0..4ba0766fbada789523c07289203696b734fb7208 100644 (file)
-// item respawn effect
-// flare particle and light
-// used in qcsrc/server/bots.qc:       //te_wizspike(e.origin)
-// used in qcsrc/server/bots.qc:               //te_wizspike(e.nearestwaypoint.wpnearestpoint)
-// used in qcsrc/server/havocbot.qc:                   //      te_wizspike(newgoal.origin)
+// ********************************************** //
+// ** WARNING - DO NOT MANUALLY EDIT THIS FILE ** //
+// **                                          ** //
+// **  This file is automatically generated by ** //
+// **  code with the command 'dumpeffectinfo'. ** //
+// **                                          ** //
+// **  If you modify an effect, please         ** //
+// **  regenerate this file with that command. ** //
+// **                                          ** //
+// ********************************************** //
+
 effect TE_WIZSPIKE
-countabsolute 1
-type static
-color 0x63F2EA 0x63f2EA
-size 20 20
-alpha 128 128 128
-lightradius 200
-lightradiusfade 200
-lightcolor 0.4 0.9 0.9
-// cloud of particles which expand rapidly and then slow to form a ball
+       type static
+       alpha 128 128 128
+       color 0x63F2EA 0x63f2EA
+       countabsolute 1
+       lightcolor 0.4 0.9 0.9
+       lightradiusfade 200
+       lightradius 200
+       size 20 20
 effect TE_WIZSPIKE
-count 50
-type static
-color 0x63F2EA 0x63f2EA
-size 2 2
-alpha 64 64 64
-airfriction 2
-liquidfriction 2
-originjitter 16 16 16
-velocityjitter 32 32 32
-
-// laser impact
-// decal
-// used in qcsrc/server/w_seeker.qc:   te_knightspike(org2)
+       type static
+       airfriction 2
+       alpha 64 64 64
+       color 0x63F2EA 0x63f2EA
+       count 50
+       liquidfriction 2
+       originjitter 16 16 16
+       size 2 2
+       velocityjitter 32 32 32
 effect TE_KNIGHTSPIKE
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 16 16 16
-lightradius 200
-lightradiusfade 1000
-lightcolor 4 0.2 0.2
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 4 0.2 0.2
+       lightradiusfade 1000
+       lightradius 200
+       originjitter 16 16 16
+       size 24 24
+       tex 47 47
 effect TE_KNIGHTSPIKE
-countabsolute 1
-type static
-tex 39 39
-color 0xFF2010 0xFF2010
-alpha 256 256 1024
-size 24 24
-// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect
+       type static
+       alpha 256 256 1024
+       color 0xFF2010 0xFF2010
+       countabsolute 1
+       size 24 24
+       tex 39 39
 effect TE_KNIGHTSPIKE
-count 128
-type spark
-color 0x800000 0xFF8020
-alpha 256 256 1024
-size 4 4
-//bounce 1.5
-airfriction 6
-liquidfriction 6
-//originjitter 32 32 32
-velocityjitter 256 256 256
-
-// machinegun bullet impact
-// bullet impact decal
-// used nowhere in code
+       type spark
+       airfriction 6
+       alpha 256 256 1024
+       color 0x800000 0xFF8020
+       count 128
+       liquidfriction 6
+       size 4 4
+       velocityjitter 256 256 256
 effect TE_SPIKE
-countabsolute 1
-type decal
-tex 56 59
-size 5 5
-alpha 256 256 0
-originjitter 6 6 6
-// dust/smoke drifting away from the impact
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 6 6 6
+       size 5 5
+       tex 56 59
 effect TE_SPIKE
-count 4
-type smoke
-tex 0 8
-color 0x101010 0x101010
-size 3 3
-sizeincrease 3
-alpha 255 255 256
-originjitter 0 0 0
-velocityjitter 8 8 8
-// dust/smoke staying at the impact
+       type smoke
+       alpha 255 255 256
+       color 0x101010 0x101010
+       count 4
+       sizeincrease 3
+       size 3 3
+       tex 0 8
+       velocityjitter 8 8 8
 effect TE_SPIKE
-count 0.5
-type smoke
-tex 0 8
-color 0x505050 0x505050
-size 4 4
-sizeincrease 4
-alpha 255 255 128
-originjitter 0 0 0
-velocityjitter 0 0 0
-// bouncing sparks
+       type smoke
+       alpha 255 255 128
+       color 0x505050 0x505050
+       count 0.500000
+       sizeincrease 4
+       size 4 4
+       tex 0 8
 effect TE_SPIKE
-count 10
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 0 256 256
-gravity 1
-bounce 1.5
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-
-// electro combo explosion
-// decal
-// used nowhere in code
+       type spark
+       alpha 0 256 256
+       bounce 1.500000
+       color 0x8f4333 0xfff31b
+       count 10
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocityoffset 0 0 80
 effect TE_SPIKEQUAD
-countabsolute 1
-type decal
-tex 59 59
-size 64 64
-alpha 256 256 0
-originjitter 34 34 34
-lightradius 400
-lightradiusfade 200
-lightcolor 2 2.5 3
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 2 2.5 3
+       lightradiusfade 200
+       lightradius 400
+       originjitter 34 34 34
+       size 64 64
+       tex 59 59
 effect TE_SPIKEQUAD
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 48 48
-alpha 256 256 128
-// large sparks
+       type static
+       alpha 256 256 128
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       size 48 48
+       tex 38 38
 effect TE_SPIKEQUAD
-count 10
-type static
-color 0x2030FF 0x80C0FF
-size 32 32
-alpha 256 256 256
-//gravity 1
-bounce 1.5
-airfriction 4
-liquidfriction 16
-//velocityoffset 0 0 120
-velocityjitter 512 512 512
-
-// quake effect
-// decal
-// used nowhere in code
+       type static
+       airfriction 4
+       alpha 256 256 256
+       bounce 1.500000
+       color 0x2030FF 0x80C0FF
+       count 10
+       liquidfriction 16
+       size 32 32
+       velocityjitter 512 512 512
 effect TE_SUPERSPIKE
-countabsolute 1
-type decal
-tex 56 59
-size 3 3
-alpha 256 256 0
-originjitter 6 6 6
-// dust/smoke drifting away from the impact
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 6 6 6
+       size 3 3
+       tex 56 59
 effect TE_SUPERSPIKE
-count 4
-type smoke
-tex 0 8
-color 0x101010 0x101010
-size 3 3
-sizeincrease 3
-alpha 255 255 256
-originjitter 0 0 0
-velocityjitter 8 8 8
-// dust/smoke staying at the impact
+       type smoke
+       alpha 255 255 256
+       color 0x101010 0x101010
+       count 4
+       sizeincrease 3
+       size 3 3
+       tex 0 8
+       velocityjitter 8 8 8
 effect TE_SUPERSPIKE
-count 0.5
-type smoke
-tex 0 8
-color 0x505050 0x505050
-size 4 4
-sizeincrease 4
-alpha 255 255 128
-originjitter 0 0 0
-velocityjitter 0 0 0
-// sparks that disappear on impact
+       type smoke
+       alpha 255 255 128
+       color 0x505050 0x505050
+       count 0.500000
+       sizeincrease 4
+       size 4 4
+       tex 0 8
 effect TE_SUPERSPIKE
-count 15
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 0 256 768
-gravity 1
-bounce -1
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-
-// quake effect
-// decal
-// used nowhere in code
+       type spark
+       alpha 0 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 15
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocityoffset 0 0 80
 effect TE_SUPERSPIKEQUAD
-countabsolute 1
-type decal
-tex 56 59
-size 3 3
-alpha 256 256 0
-originjitter 6 6 6
-lightradius 100
-lightradiusfade 500
-lightcolor 0.15 0.15 1.5
-// dust/smoke drifting away from the impact
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 0.2 0.2 1.5
+       lightradiusfade 500
+       lightradius 100
+       originjitter 6 6 6
+       size 3 3
+       tex 56 59
 effect TE_SUPERSPIKEQUAD
-count 4
-type smoke
-tex 0 8
-color 0x101010 0x101010
-size 3 3
-sizeincrease 3
-alpha 255 255 256
-originjitter 0 0 0
-velocityjitter 8 8 8
-// dust/smoke staying at the impact
+       type smoke
+       alpha 255 255 256
+       color 0x101010 0x101010
+       count 4
+       sizeincrease 3
+       size 3 3
+       tex 0 8
+       velocityjitter 8 8 8
 effect TE_SUPERSPIKEQUAD
-count 0.5
-type smoke
-tex 0 8
-color 0x505050 0x505050
-size 4 4
-sizeincrease 4
-alpha 255 255 128
-originjitter 0 0 0
-velocityjitter 0 0 0
-// sparks that disappear on impact
+       type smoke
+       alpha 255 255 128
+       color 0x505050 0x505050
+       count 0.500000
+       sizeincrease 4
+       size 4 4
+       tex 0 8
 effect TE_SUPERSPIKEQUAD
-count 15
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 0 256 768
-gravity 1
-bounce -1
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-
-// shotgun pellet impact
-// decal
-// used nowhere in code
+       type spark
+       alpha 0 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 15
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocityoffset 0 0 80
 effect TE_GUNSHOT
-countabsolute 1
-type decal
-tex 56 59
-size 3 3
-alpha 256 256 0
-originjitter 6 6 6
-// dust/smoke drifting away from the impact
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 6 6 6
+       size 3 3
+       tex 56 59
 effect TE_GUNSHOT
-count 0.8
-type smoke
-tex 0 8
-color 0x101010 0x101010
-size 3 3
-sizeincrease 3
-alpha 128 128 64
-originjitter 0 0 0
-velocityjitter 8 8 8
-// dust/smoke staying at the impact
+       type smoke
+       alpha 128 128 64
+       color 0x101010 0x101010
+       count 0.800000
+       sizeincrease 3
+       size 3 3
+       tex 0 8
+       velocityjitter 8 8 8
 effect TE_GUNSHOT
-count 0.2
-type smoke
-tex 0 8
-color 0x505050 0x505050
-size 4 4
-sizeincrease 4
-alpha 128 128 64
-originjitter 0 0 0
-velocityjitter 0 0 0
-// bouncing sparks
+       type smoke
+       alpha 128 128 64
+       color 0x505050 0x505050
+       count 0.200000
+       sizeincrease 4
+       size 4 4
+       tex 0 8
 effect TE_GUNSHOT
-count 2.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 0 64 64
-gravity 1
-bounce 1.5
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-
-// crylink impact effect
-// decal
-// used nowhere in code
+       type spark
+       alpha 0 64 64
+       bounce 1.500000
+       color 0x8f4333 0xfff31b
+       count 2.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocityoffset 0 0 80
 effect TE_GUNSHOTQUAD
-countabsolute 1
-type decal
-tex 47 47
-size 8 8
-alpha 256 256 0
-originjitter 12 12 12
-//lightradius 100
-//lightradiusfade 300
-//lightcolor 0.5 0.5 0.5
-// purple flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 12 12 12
+       size 8 8
+       tex 47 47
 effect TE_GUNSHOTQUAD
-countabsolute 1
-type static
-tex 39 39
-color 0x504060 0x504060
-size 8 8
-alpha 256 256 512
-// purple sparks
+       type static
+       alpha 256 256 512
+       color 0x504060 0x504060
+       countabsolute 1
+       size 8 8
+       tex 39 39
 effect TE_GUNSHOTQUAD
-count 6
-type spark
-color 0xA040C0 0xFFFFFF
-size 1 1
-alpha 128 128 384
-gravity 1
-bounce 1.5
-velocityoffset 0 0 80
-velocityjitter 128 128 128
-
-// mortar/hagar explosion (smaller than rocket)
-// decal
-// used in qcsrc/server/cl_client.qc:  te_explosion(org)
+       type spark
+       alpha 128 128 384
+       bounce 1.500000
+       color 0xA040C0 0xFFFFFF
+       count 6
+       gravity 1
+       size 1 1
+       velocityjitter 128 128 128
+       velocityoffset 0 0 80
 effect TE_EXPLOSION
-countabsolute 1
-type decal
-tex 8 16
-size 48 48
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 150
-lightradiusfade 300
-lightcolor 4 2 0.5
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 4 2 0.5
+       lightradiusfade 300
+       lightradius 150
+       originjitter 40 40 40
+       size 48 48
+       tex 8 16
 effect TE_EXPLOSION
-countabsolute 1
-type static
-tex 35 37
-color 0x404040 0x404040
-size 48 48
-alpha 192 192 64
-// fire effect which expands then slows
+       type static
+       alpha 192 192 64
+       color 0x404040 0x404040
+       countabsolute 1
+       size 48 48
+       tex 35 37
 effect TE_EXPLOSION
-notunderwater
-count 64
-type static
-tex 48 55
-color 0x902010 0xFFD080
-size 16 16
-alpha 128 128 256
-bounce 1.5
-airfriction 4
-liquidfriction 4
-originjitter 8 8 8
-velocityjitter 256 256 256
-// underwater bubbles
+       type static
+       airfriction 4
+       alpha 128 128 256
+       bounce 1.500000
+       color 0x902010 0xFFD080
+       count 64
+       liquidfriction 4
+       notunderwater
+       originjitter 8 8 8
+       size 16 16
+       tex 48 55
+       velocityjitter 256 256 256
 effect TE_EXPLOSION
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 16
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 96 96 96
 effect TE_EXPLOSION
-notunderwater
-count 16
-type spark
-color 0x903010 0xFFD030
-size 2 2
-alpha 256 256 384
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 256 256 256
-
-// quake effect
-// decal
-// used nowhere in code
+       type spark
+       airfriction 0.200000
+       alpha 256 256 384
+       bounce 1.500000
+       color 0x903010 0xFFD030
+       count 16
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       size 2 2
+       velocityjitter 256 256 256
+       velocityoffset 0 0 80
 effect TE_EXPLOSIONQUAD
-countabsolute 1
-type decal
-tex 8 16
-size 48 48
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 350
-lightradiusfade 700
-lightcolor 4 2 8
-// smoke cloud
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 4 2 8
+       lightradiusfade 700
+       lightradius 350
+       originjitter 40 40 40
+       size 48 48
+       tex 8 16
 effect TE_EXPLOSIONQUAD
-notunderwater
-count 16
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 12 12
-alpha 32 32 64
-velocityjitter 48 48 48
-// underwater bubbles
+       type smoke
+       alpha 32 32 64
+       color 0x202020 0x404040
+       count 16
+       notunderwater
+       size 12 12
+       tex 0 8
+       velocityjitter 48 48 48
 effect TE_EXPLOSIONQUAD
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// sparks which go through walls
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 16
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 96 96 96
 effect TE_EXPLOSIONQUAD
-notunderwater
-count 64
-type spark
-color 0x903010 0xFFD030
-size 1 1
-alpha 0 256 512
-gravity 1
-airfriction 0.2
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 256 256 256
-
-// quake effect
-// decal
-// used in qcsrc/server/keyhunt.qc:    te_tarexplosion(lostkey.origin)
+       type spark
+       airfriction 0.200000
+       alpha 0 256 512
+       color 0x903010 0xFFD030
+       count 64
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       size 1 1
+       velocityjitter 256 256 256
+       velocityoffset 0 0 80
 effect TE_TAREXPLOSION
-countabsolute 1
-type decal
-tex 8 16
-size 48 48
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 600
-lightradiusfade 1200
-lightcolor 1.6 0.8 2
-// smoke cloud
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 1.6 0.8 2
+       lightradiusfade 1200
+       lightradius 600
+       originjitter 40 40 40
+       size 48 48
+       tex 8 16
 effect TE_TAREXPLOSION
-notunderwater
-count 16
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 12 12
-alpha 32 32 64
-velocityjitter 48 48 48
-// underwater bubbles
+       type smoke
+       alpha 32 32 64
+       color 0x202020 0x404040
+       count 16
+       notunderwater
+       size 12 12
+       tex 0 8
+       velocityjitter 48 48 48
 effect TE_TAREXPLOSION
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// sparks which go through walls
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 16
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 96 96 96
 effect TE_TAREXPLOSION
-notunderwater
-count 64
-type spark
-color 0x903010 0xFFD030
-size 1 1
-alpha 0 256 512
-gravity 1
-airfriction 0.2
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 256 256 256
-
-// bloody impact effect indicating damage
-// used nowhere in code
+       type spark
+       airfriction 0.200000
+       alpha 0 256 512
+       color 0x903010 0xFFD030
+       count 64
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       size 1 1
+       velocityjitter 256 256 256
+       velocityoffset 0 0 80
 effect TE_BLOOD
-count 0.167
-type blood
-tex 24 32
-size 8 8
-alpha 256 256 64
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 1
-staincolor 0x808080 0x808080
-staintex 16 24
-
-
-
-// sparks (quake effect)
-// used in qcsrc/server/antilag.qc:            te_spark(antilag_takebackorigin(e, time - e.antilag_debug), '0 0 0', 32)
-// used in qcsrc/server/g_triggers.qc: self.mdl = "TE_SPARK"
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       count 0.167000
+       liquidfriction 4
+       size 8 8
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 64 64 64
+       velocitymultiplier 1
 effect TE_SPARK
-count 0.5
-type spark
-tex 40 40
-color 0x8f4333 0xfff31b
-size 0.4 0.6
-alpha 64 256 768
-gravity 1
-bounce -1
-velocityoffset 0 0 80
-velocityjitter 64 64 64
-velocitymultiplier 1
-
-// nex impact
-// decal
-// used in qcsrc/server/bots.qc:               te_plasmaburn(org)
+       type spark
+       alpha 64 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.600000
+       tex 40 40
+       velocityjitter 64 64 64
+       velocitymultiplier 1
+       velocityoffset 0 0 80
 effect TE_PLASMABURN
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 16 16 16
-lightradius 200
-lightradiusfade 400
-lightcolor 1 1 1
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 1 1 1
+       lightradiusfade 400
+       lightradius 200
+       originjitter 16 16 16
+       size 24 24
+       tex 47 47
 effect TE_PLASMABURN
-countabsolute 1
-type static
-tex 37 37
-color 0x80C0FF 0x80C0FF
-size 8 8
-alpha 256 256 512
-// small sparks which form a sphere as they slow down
+       type static
+       alpha 256 256 512
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       size 8 8
+       tex 37 37
 effect TE_PLASMABURN
-count 128
-type spark
-color 0x2030FF 0x80C0FF
-size 1 2
-alpha 256 256 1024
-bounce 2
-airfriction 8
-liquidfriction 8
-velocityjitter 128 128 128
-
-// quake effect
-// used in qcsrc/server/bots.qc:       //te_smallflash((e.absmin + e.absmax) * 0.5)
-// used in qcsrc/server/bots.qc:               //te_smallflash((e.absmin + e.absmax) * 0.5)
+       type spark
+       airfriction 8
+       alpha 256 256 1024
+       bounce 2
+       color 0x2030FF 0x80C0FF
+       count 128
+       liquidfriction 8
+       size 1 2
+       velocityjitter 128 128 128
 effect TE_SMALLFLASH
-lightradius 200
-lightradiusfade 1000
-lightcolor 2 2 2
-
-// quake effect
-// used nowhere in code
+       lightcolor 2 2 2
+       lightradiusfade 1000
+       lightradius 200
 effect TE_FLAMEJET
-count 0.5
-type smoke
-color 0x6f0f00 0xe3974f
-size 4 4
-alpha 64 128 384
-gravity -1
-bounce 1.1
-airfriction 1
-liquidfriction 4
-velocityjitter 128 128 128
-velocitymultiplier 1
-
-// quake effect
-// used nowhere in code
+       type smoke
+       airfriction 1
+       alpha 64 128 384
+       bounce 1.100000
+       color 0x6f0f00 0xe3974f
+       count 0.500000
+       gravity -1
+       liquidfriction 4
+       size 4 4
+       velocityjitter 128 128 128
+       velocitymultiplier 1
 effect TE_LAVASPLASH
-count 32
-type alphastatic
-color 0x6f0f00 0xe3974f
-size 12 12
-alpha 256 256 256
-gravity 0.05
-originoffset 0 0 32
-originjitter 128 128 32
-velocityoffset 0 0 256
-velocityjitter 128 128 0
-
-// player teleport effect
-// used nowhere in code
+       type alphastatic
+       alpha 256 256 256
+       color 0x6f0f00 0xe3974f
+       count 32
+       gravity 0.050000
+       originjitter 128 128 32
+       originoffset 0 0 32
+       size 12 12
+       velocityjitter 128 128 0
+       velocityoffset 0 0 256
 effect TE_TELEPORT
-count 56
-type static
-color 0xA0A0A0 0xFFFFFF
-size 10 10
-alpha 64 128 256
-airfriction 1
-liquidfriction 4
-originoffset 0 0 28
-originjitter 16 16 28
-velocityjitter 0 0 256
-
-// nex beam
-// used in qcsrc/server/w_minstanex.qc:        trailparticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, trace_endpos)
-// used in qcsrc/client/particles.qc:          trailparticles(world, particleeffectnum("TE_TEI_G3"), shotorg, endpos)
+       type static
+       airfriction 1
+       alpha 64 128 256
+       color 0xA0A0A0 0xFFFFFF
+       count 56
+       liquidfriction 4
+       originjitter 16 16 28
+       originoffset 0 0 28
+       size 10 10
+       velocityjitter 0 0 256
 effect TE_TEI_G3
-countabsolute 1
-type beam
-tex 200 200
-color 0xFFFFFF 0xFFFFFF
-size 4 4
-alpha 128 128 256
-// experimental
+       type beam
+       alpha 128 128 256
+       color 0xFFFFFF 0xFFFFFF
+       countabsolute 1
+       size 4 4
+       tex 200 200
 effect TE_TEI_G3
-trailspacing 4
-type static
-color 0x202020 0x404040
-size 1 1
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 8 8 8
-type smoke
-
-// smoke effect
-// used nowhere in code
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0x202020 0x404040
+       size 1 1
+       trailspacing 4
+       velocityjitter 8 8 8
 effect TE_TEI_SMOKE
-count 0.167
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 1
-
-// rocket explosion (bigger than mortar and hagar)
-// decal
-// used nowhere in code
+       type smoke
+       alpha 256 256 512
+       color 0x202020 0x404040
+       count 0.167000
+       originjitter 1.5 1.5 1.5
+       size 5 5
+       tex 0 8
+       velocityjitter 6 6 6
+       velocitymultiplier 1
 effect TE_TEI_BIGEXPLOSION
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 500
-lightradiusfade 500
-lightcolor 4 2 0.5
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 4 2 0.5
+       lightradiusfade 500
+       lightradius 500
+       originjitter 40 40 40
+       size 72 72
+       tex 8 16
 effect TE_TEI_BIGEXPLOSION
-countabsolute 1
-type static
-tex 35 37
-color 0x404040 0x404040
-size 72 72
-alpha 192 192 64
-// fire effect
+       type static
+       alpha 192 192 64
+       color 0x404040 0x404040
+       countabsolute 1
+       size 72 72
+       tex 35 37
 effect TE_TEI_BIGEXPLOSION
-notunderwater
-count 128
-type static
-tex 48 55
-color 0x902010 0xFFD080
-size 16 16
-alpha 128 128 256
-bounce 1.5
-airfriction 4
-liquidfriction 4
-originjitter 8 8 8
-velocityjitter 512 512 512
-// underwater bubbles
+       type static
+       airfriction 4
+       alpha 128 128 256
+       bounce 1.500000
+       color 0x902010 0xFFD080
+       count 128
+       liquidfriction 4
+       notunderwater
+       originjitter 8 8 8
+       size 16 16
+       tex 48 55
+       velocityjitter 512 512 512
 effect TE_TEI_BIGEXPLOSION
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 144 144 144
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 144 144 144
 effect TE_TEI_BIGEXPLOSION
-notunderwater
-count 64
-type spark
-color 0x903010 0xFFD030
-size 2 2
-alpha 256 256 384
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 384 384 384
-
-// electro explosion
-// decal
-// used nowhere in code
+       type spark
+       airfriction 0.200000
+       alpha 256 256 384
+       bounce 1.500000
+       color 0x903010 0xFFD030
+       count 64
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       size 2 2
+       velocityjitter 384 384 384
+       velocityoffset 0 0 80
 effect TE_TEI_PLASMAHIT
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-originjitter 20 20 20
-lightradius 200
-lightradiusfade 600
-lightcolor 2.4 4.8 8
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 2.4 4.8 8
+       lightradiusfade 600
+       lightradius 200
+       originjitter 20 20 20
+       size 32 32
+       tex 59 59
 effect TE_TEI_PLASMAHIT
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 32 32
-alpha 256 256 512
-// cloud of bouncing sparks
+       type static
+       alpha 256 256 512
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       size 32 32
+       tex 38 38
 effect TE_TEI_PLASMAHIT
-count 0.5
-type spark
-color 0x2030FF 0x80C0FF
-size 2 4
-alpha 256 256 1024
-//gravity 1
-bounce 1.5
-//velocityoffset 0 0 120
-velocityjitter 512 512 512
-
-
-
-
-
-
-
-
-
-//////////////////////////////////////////////////
-// New effects in 2.4
-//////////////////////////////////////////////////
-
-
-
-// bloody impact effect indicating damage
-// used in qcsrc/client/gibs.qc:       pointparticles(particleeffectnum("blood"), self.origin + '0 0 1', '0 0 30', 10)
-// used in qcsrc/client/gibs.qc:                       pointparticles(particleeffectnum("blood"), org, vel, amount * 16)
+       type spark
+       alpha 256 256 1024
+       bounce 1.500000
+       color 0x2030FF 0x80C0FF
+       count 0.500000
+       size 2 4
+       velocityjitter 512 512 512
 effect blood
-count 0.4
-type spark
-blend invmod
-tex 24 32
-size 5 11
-alpha 1560 2560 7000
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 0.4
-velocityjitter 99 99 55
-//velocitymultiplier 2
-staincolor 0x808080 0x808080
-staintex 16 24
-stainsize 1 2
-stretchfactor 20
-sizeincrease 20
-//blood mist
+       type spark
+       airfriction 0.400000
+       alpha 1560 2560 7000
+       blend invmod
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 0.400000
+       sizeincrease 20
+       size 5 11
+       staincolor 0x808080 0x808080
+       stainsize 1 2
+       staintex 16 24
+       stretchfactor 20
+       tex 24 32
+       velocityjitter 99 99 55
 effect blood
-countabsolute 1
-type alphastatic
-blend invmod
-tex 24 32
-size 25 30
-sizeincrease 20
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 11 11 11
-
-
-// player teleport effect
-// used in qcsrc/server/t_teleporters.qc:              pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1)
-// used in qcsrc/server/t_teleporters.qc:              pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1)
+       type alphastatic
+       alpha 100 256 400
+       blend invmod
+       color 0x000000 0x420000
+       countabsolute 1
+       originjitter 11 11 11
+       sizeincrease 20
+       size 25 30
+       tex 24 32
 effect teleport
-count 500
-type spark
-tex 64 64
-color 0x807aff 0x4463d5
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+       type spark
+       airfriction 2
+       alpha 0 256 100
+       bounce 1.500000
+       color 0x807aff 0x4463d5
+       count 500
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 1000 1000 1500
+       velocitymultiplier 0.500000
 effect teleport
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0x807aff 0x4463d5
-
-
-
-// normal super gory blood trail (used by gibs)
-// used in qcsrc/client/gibs.qc:               trailparticles(self, particleeffectnum("TR_BLOOD"), oldorg, self.origin)
+       type smoke
+       alpha 190 190 180
+       color 0x807aff 0x4463d5
+       countabsolute 1
+       sizeincrease -80
+       size 150 150
+       tex 65 65
 effect TR_BLOOD
-trailspacing 20
-type spark
-blend invmod
-color 0xA8FFFF 0xA8FFFF
-tex 24 32
-size 4 19
-alpha 384 984 1492
-bounce -1
-gravity 0.4
-airfriction -2
-liquidfriction 1
-velocityjitter 64 64 64
-velocitymultiplier -0.1
-staincolor 0x808080 0x808080
-staintex 16 24
-stainsize 1 2
-stretchfactor 7
-sizeincrease -5
-// splash around gib
+       type spark
+       airfriction -2
+       alpha 384 984 1492
+       blend invmod
+       bounce -1
+       color 0xA8FFFF 0xA8FFFF
+       gravity 0.400000
+       liquidfriction 1
+       sizeincrease -5
+       size 4 19
+       staincolor 0x808080 0x808080
+       stainsize 1 2
+       staintex 16 24
+       stretchfactor 7
+       tex 24 32
+       trailspacing 20
+       velocityjitter 64 64 64
+       velocitymultiplier -0.100000
 effect TR_BLOOD
-trailspacing 42
-type blood
-color 0xA8FFFF 0xA8FFFF
-tex 24 32
-size 4 6
-alpha 684 684 7492
-sizeincrease 500
-
-// thinner blood trail (used by quake zombies)
-// used in qcsrc/client/gibs.qc:               trailparticles(self, particleeffectnum("TR_SLIGHTBLOOD"), oldorg, self.origin)
+       type blood
+       alpha 684 684 7492
+       color 0xA8FFFF 0xA8FFFF
+       sizeincrease 500
+       size 4 6
+       tex 24 32
+       trailspacing 42
+effect TR_BLOOD
+       type blood
+       alpha 684 684 7492
+       color 0xA8FFFF 0xA8FFFF
+       sizeincrease 500
+       size 4 6
+       tex 24 32
+       trailspacing 42
 effect TR_SLIGHTBLOOD
-trailspacing 64
-type blood
-color 0xA8FFFF 0xA8FFFF
-tex 24 32
-size 8 8
-alpha 384 384 192
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 0.5
-staincolor 0x808080 0x808080
-staintex 16 24
-
-
-
-// func_stardust effect, used in some maps to indicate teleporters
-// used in qcsrc/server/g_triggers.qc: self.effects = EF_STARDUST
-// used in qcsrc/server/portals.qc:    portal.effects = EF_STARDUST | EF_BLUE
+       type blood
+       airfriction 1
+       alpha 384 384 192
+       bounce -1
+       color 0xA8FFFF 0xA8FFFF
+       liquidfriction 4
+       size 8 8
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       trailspacing 64
+       velocityjitter 64 64 64
+       velocitymultiplier 0.500000
 effect EF_STARDUST
-count 37.5
-type static
-color 0xfff368 0xfff368
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// flare particle and light
-// used in qcsrc/server/t_items.qc:    //pointparticles(particleeffectnum("item_respawn"), self.origin + self.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1)
-// used in qcsrc/server/t_items.qc:    pointparticles(particleeffectnum("item_respawn"), self.origin + 0.5 * (self.mins + self.maxs), '0 0 0', 1)
+       type static
+       airfriction 0.200000
+       alpha 64 128 128
+       color 0xfff368 0xfff368
+       count 37.500000
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 16 16 64
+       size 1 2
+       velocityjitter 32 32 0
 effect item_respawn
-countabsolute 1
-type static
-color 0x63F2EA 0x63f2EA
-size 32 32
-alpha 128 128 128
-// cloud of particles which expand rapidly and then slow to form a ball
+       type static
+       alpha 128 128 128
+       color 0x63F2EA 0x63f2EA
+       countabsolute 1
+       size 32 32
 effect item_respawn
-count 128
-type spark
-tex 41 41
-color 0x63F2EA 0x63f2EA
-size 2 2
-alpha 256 256 1280
-//originjitter 24 24 24
-velocityjitter 256 256 256
-
-
-
-// used in qcsrc/server/t_jumppads.qc:                 pointparticles(particleeffectnum("jumppad_activate"), other.origin, other.velocity, 1)
+       type spark
+       alpha 256 256 1280
+       color 0x63F2EA 0x63f2EA
+       count 128
+       size 2 2
+       tex 41 41
+       velocityjitter 256 256 256
 effect jumppad_activate
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 2 2
-
-
-
-// used in qcsrc/server/w_hlac.qc:     pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_hlac.qc:     pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_laser.qc:    pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+       lightcolor 2 2 2
+       lightradiusfade 2000
+       lightradius 200
 effect laser_muzzleflash
-// glow and light
-countabsolute 1
-type smoke
-color 0xcc0000 0xff0000
-tex 65 65
-size 10 15
-alpha 256 512 6280
-airfriction 10
-sizeincrease -100
-stretchfactor 2
-lightradius 200
-lightradiusfade 2000
-lightcolor 3 0.1 0.1
-// electricity
+       type smoke
+       airfriction 10
+       alpha 256 512 6280
+       color 0xcc0000 0xff0000
+       countabsolute 1
+       lightcolor 3 0.1 0.1
+       lightradiusfade 2000
+       lightradius 200
+       sizeincrease -100
+       size 10 15
+       stretchfactor 2
+       tex 65 65
 effect laser_muzzleflash
-count 3
-type spark
-color 0xb44215 0xff0000
-tex 43 43
-size 5 7
-alpha 256 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 150 150 150
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2.3
-rotate -180 180 4000 -4000
-// fire
+       type spark
+       airfriction 10
+       alpha 256 512 6280
+       color 0xb44215 0xff0000
+       count 3
+       originjitter 2 2 2
+       rotate -180 180 4000 -4000
+       sizeincrease -100
+       size 5 7
+       stretchfactor 2.300000
+       tex 43 43
+       velocityjitter 150 150 150
+       velocitymultiplier 0.200000
 effect laser_muzzleflash
-count 6
-type spark
-color 0xff4200 0xff0000
-tex 8 15
-size 7 9
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 100 100 100
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2
-
-
-// decal
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("laser_impact"), org2, backoff * 1000, 1)
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("laser_impact"), org2, backoff * 1000, 1)
+       type spark
+       airfriction 12
+       alpha 256 512 6280
+       color 0xff4200 0xff0000
+       count 6
+       originjitter 2 2 2
+       sizeincrease -100
+       size 7 9
+       stretchfactor 2
+       tex 8 15
+       velocityjitter 100 100 100
+       velocitymultiplier 0.200000
 effect laser_impact
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 14 14 14
-lightradius 200
-lightradiusfade 500
-lightcolor 8 0.4 0.4
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 8 0.4 0.4
+       lightradiusfade 500
+       lightradius 200
+       originjitter 14 14 14
+       size 24 24
+       tex 47 47
 effect laser_impact
-countabsolute 1
-type static
-tex 39 39
-color 0xFF2010 0xFF2010
-alpha 256 256 1024
-size 24 24
-// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect
+       type static
+       alpha 256 256 1024
+       color 0xFF2010 0xFF2010
+       countabsolute 1
+       size 24 24
+       tex 39 39
 effect laser_impact
-count 128
-type spark
-color 0x800000 0xFF8020
-alpha 256 256 1024
-size 4 4
-//bounce 1.5
-airfriction 6
-liquidfriction 6
-//originjitter 32 32 32
-velocityjitter 256 256 256
+       type spark
+       airfriction 6
+       alpha 256 256 1024
+       color 0x800000 0xFF8020
+       count 128
+       liquidfriction 6
+       size 4 4
+       velocityjitter 256 256 256
 effect laser_impact
-count 4
-type smoke
-tex 48 55
-color 0x800000 0xFF8020
-size 12 12
-alpha 128 256 256
-originjitter 1 1 1
-velocitymultiplier 0.01
-velocityjitter 16 16 16
-sizeincrease 6
-
-
-
-// used in qcsrc/server/w_campingrifle.qc:     pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 2000, 1)
-// used in qcsrc/server/w_shotgun.qc:  pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_primary_ammo"))
-// used in qcsrc/server/w_shotgun.qc:  pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_secondary_ammo"))
-effect shotgun_muzzleflash
-count 1.5
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
-sizeincrease 12
-velocitymultiplier 0.05
+       type smoke
+       alpha 128 256 256
+       color 0x800000 0xFF8020
+       count 4
+       originjitter 1 1 1
+       sizeincrease 6
+       size 12 12
+       tex 48 55
+       velocityjitter 16 16 16
+       velocitymultiplier 0.010000
 effect shotgun_muzzleflash
-count 16
-type spark
-tex 48 55
-color 0xffdb96 0xff5400
-size 10 20
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 100 100 100
-airfriction 5
-stretchfactor 2.5
-velocitymultiplier 0.5
-
-// shotgun pellet impact
-// decal
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("shotgun_impact"), org2, backoff * 1000, 1)
+       type smoke
+       alpha 256 256 512
+       color 0x202020 0x404040
+       count 1.500000
+       lightcolor 2 1.5 0.2
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       sizeincrease 12
+       size 5 5
+       tex 0 8
+       velocityjitter 6 6 6
+       velocitymultiplier 0.050000
+effect shotgun_muzzleflash
+       type spark
+       airfriction 5
+       alpha 0 128 1024
+       color 0xffdb96 0xff5400
+       count 16
+       originjitter 1 1 1
+       size 10 20
+       stretchfactor 2.500000
+       tex 48 55
+       velocityjitter 100 100 100
+       velocitymultiplier 0.500000
 effect shotgun_impact
-countabsolute 1
-type decal
-tex 56 59
-size 5 8
-alpha 256 256 0
-originjitter 10 10 10
-//lightradius 30
-//lightradiusfade 90
-//lightcolor 1 1 1
-// dust/smoke drifting away from the impact
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 10 10 10
+       size 5 8
+       tex 56 59
 effect shotgun_impact
-type alphastatic
-notunderwater
-tex 0 8
-count 1
-size 10 20
-sizeincrease 25
-alpha 300 550 756
-velocityjitter 150 150 150
-velocitymultiplier 0.2
-airfriction 5
-color 0x473a37 0x0b0a07
-rotate 0 360 -50 50
-// dust/smoke staying at the impact
+       type alphastatic
+       airfriction 5
+       alpha 300 550 756
+       color 0x473a37 0x0b0a07
+       count 1
+       notunderwater
+       rotate 0 360 -50 50
+       sizeincrease 25
+       size 10 20
+       tex 0 8
+       velocityjitter 150 150 150
+       velocitymultiplier 0.200000
 effect shotgun_impact
-type alphastatic
-notunderwater
-tex 36 36
-count 0.2
-size 10 11
-sizeincrease 74
-alpha 200 350 500
-velocityjitter 11 11 11
-airfriction 5
-color 0x201d1a 0x000000
-bounce 6
-velocitymultiplier 0.03
-rotate 0 360 -50 50
-// sparks
+       type alphastatic
+       airfriction 5
+       alpha 200 350 500
+       bounce 6
+       color 0x201d1a 0x000000
+       count 0.200000
+       notunderwater
+       rotate 0 360 -50 50
+       sizeincrease 74
+       size 10 11
+       tex 36 36
+       velocityjitter 11 11 11
+       velocitymultiplier 0.030000
 effect shotgun_impact
-notunderwater
-count 0.5
-type spark
-tex 40 40
-color 0xFDFFD9 0xFDFFD9
-size 0.6 0.6
-alpha 0 356 268
-gravity 1
-bounce 1.5
-airfriction 1.1
-originjitter 1 1 1
-velocityjitter 200 200 200
-velocitymultiplier 0.2
-
-
-// used in qcsrc/server/w_uzi.qc:      pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+       type spark
+       airfriction 1.100000
+       alpha 0 356 268
+       bounce 1.500000
+       color 0xFDFFD9 0xFDFFD9
+       count 0.500000
+       gravity 1
+       notunderwater
+       originjitter 1 1 1
+       size 0.600000 0.600000
+       tex 40 40
+       velocityjitter 200 200 200
+       velocitymultiplier 0.200000
 effect uzi_muzzleflash
-count 1
-type static
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 1 1 1
-velocitymultiplier 0.03
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
-gravity -0.1
+       type static
+       alpha 256 256 512
+       color 0x202020 0x404040
+       count 1
+       gravity -0.100000
+       lightcolor 2 1.5 0.2
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       size 5 5
+       tex 0 8
+       velocityjitter 1 1 1
+       velocitymultiplier 0.030000
 effect uzi_muzzleflash
-count 3
-type spark
-tex 40 40
-color 0xff9c00 0xffd200
-size 0.3 0.4
-alpha 0 256 6000
-originjitter 1 1 1
-velocityjitter 555 555 555
-velocitymultiplier 3
-stretchfactor 0.15
-airfriction 12
-
-
-// used in qcsrc/server/cl_client.qc:  //pointparticles(particleeffectnum("machinegun_impact"), self.origin + self.view_ofs + '0 0 7', '0 0 0', 1)
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("machinegun_impact"), org2, backoff * 1000, 1)
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("machinegun_impact"), org2, backoff * 1000, 1)
-// decal
+       type spark
+       airfriction 12
+       alpha 0 256 6000
+       color 0xff9c00 0xffd200
+       count 3
+       originjitter 1 1 1
+       size 0.300000 0.400000
+       stretchfactor 0.150000
+       tex 40 40
+       velocityjitter 555 555 555
+       velocitymultiplier 3
 effect machinegun_impact
-countabsolute 1
-type decal
-tex 56 59
-size 5 5
-alpha 256 256 0
-originjitter 10 10 10
-lightradius 80
-lightradiusfade 800
-lightcolor 6 3.6 0.6
-// dust/smoke drifting away from the impact
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 6 3.6 0.6
+       lightradiusfade 800
+       lightradius 80
+       originjitter 10 10 10
+       size 5 5
+       tex 56 59
 effect machinegun_impact
-type alphastatic
-notunderwater
-tex 0 8
-count 1.5
-size 10 20
-sizeincrease 15
-alpha 300 550 456
-velocityjitter 150 150 150
-velocitymultiplier 0.1
-airfriction 5
-color 0x473a37 0x0b0a07
-rotate 0 360 -50 50
-// dust/smoke staying at the impact
+       type alphastatic
+       airfriction 5
+       alpha 300 550 456
+       color 0x473a37 0x0b0a07
+       count 1.500000
+       notunderwater
+       rotate 0 360 -50 50
+       sizeincrease 15
+       size 10 20
+       tex 0 8
+       velocityjitter 150 150 150
+       velocitymultiplier 0.100000
 effect machinegun_impact
-type alphastatic
-notunderwater
-tex 36 36
-count 0.5
-size 10 11
-sizeincrease 74
-alpha 200 350 500
-velocityjitter 11 11 11
-airfriction 5
-color 0x201d1a 0x000000
-bounce 6
-velocitymultiplier 0.03
-rotate 0 360 -50 50
-//debris
+       type alphastatic
+       airfriction 5
+       alpha 200 350 500
+       bounce 6
+       color 0x201d1a 0x000000
+       count 0.500000
+       notunderwater
+       rotate 0 360 -50 50
+       sizeincrease 74
+       size 10 11
+       tex 36 36
+       velocityjitter 11 11 11
+       velocitymultiplier 0.030000
 effect machinegun_impact
-type alphastatic
-notunderwater
-tex 66 68
-count 1
-size 1 5
-airfriction 1
-gravity 1.4
-alpha 300 550 256
-velocityjitter 350 350 350
-velocitymultiplier 0.2
-bounce 1.7
-color 0x63493e 0xffffff
-rotate 0 360 -500 500
-// sparks
+       type alphastatic
+       airfriction 1
+       alpha 300 550 256
+       bounce 1.700000
+       color 0x63493e 0xffffff
+       count 1
+       gravity 1.400000
+       notunderwater
+       rotate 0 360 -500 500
+       size 1 5
+       tex 66 68
+       velocityjitter 350 350 350
+       velocitymultiplier 0.200000
 effect machinegun_impact
-notunderwater
-count 1
-type spark
-tex 40 40
-color 0xFDFFD9 0xFDFFD9
-size 0.3 0.3
-alpha 256 256 168
-gravity 1
-bounce 1
-airfriction 2
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.2
-
-
-
-
-// used in qcsrc/server/nexball.qc:    pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_grenadelauncher.qc:  pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_grenadelauncher.qc:  pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_porto.qc:    //pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+       type spark
+       airfriction 2
+       alpha 256 256 168
+       bounce 1
+       color 0xFDFFD9 0xFDFFD9
+       count 1
+       gravity 1
+       notunderwater
+       originjitter 1 1 1
+       size 0.300000 0.300000
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.200000
 effect grenadelauncher_muzzleflash
-count 1.5
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-airfriction 12
-velocityjitter 20 20 20
-velocitymultiplier 0.03
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+       type smoke
+       airfriction 12
+       alpha 256 256 512
+       color 0x202020 0x404040
+       count 1.500000
+       lightcolor 2 1.5 0.2
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       size 5 5
+       tex 0 8
+       velocityjitter 20 20 20
+       velocitymultiplier 0.030000
 effect grenadelauncher_muzzleflash
-count 16
-type spark
-tex 48 55
-color 0xffdb96 0xff5400
-size 10 20
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 100 100 100
-velocitymultiplier 0.5
-airfriction 5
-stretchfactor 2.5
-
-
-
-// mortar trail
-// smoke
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_GRENADE"), from, to)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_GRENADE"), from, to)
+       type spark
+       airfriction 5
+       alpha 0 128 1024
+       color 0xffdb96 0xff5400
+       count 16
+       originjitter 1 1 1
+       size 10 20
+       stretchfactor 2.500000
+       tex 48 55
+       velocityjitter 100 100 100
+       velocitymultiplier 0.500000
 effect TR_GRENADE
-trailspacing 4
-type smoke
-color 0x101010 0x000000
-tex 0 8
-size 3 2
-bounce 1
-sizeincrease 10
-alpha 300 400 780
-originjitter 1 1 1
-velocityjitter 1 1 1
-velocitymultiplier -0.02
-//gravity -0.11
-// fire
+       type smoke
+       alpha 300 400 780
+       bounce 1
+       color 0x101010 0x000000
+       originjitter 1 1 1
+       sizeincrease 10
+       size 3 2
+       tex 0 8
+       trailspacing 4
+       velocityjitter 1 1 1
+       velocitymultiplier -0.020000
 effect TR_GRENADE
-notunderwater
-trailspacing 4
-type static
-color 0xffdf72 0x811200
-tex 48 55
-size 5 2
-sizeincrease -15
-alpha 100 144 988
-airfriction 8
-velocityjitter 32 32 32
-velocitymultiplier -1.0
-// bubbles
+       type static
+       airfriction 8
+       alpha 100 144 988
+       color 0xffdf72 0x811200
+       notunderwater
+       sizeincrease -15
+       size 5 2
+       tex 48 55
+       trailspacing 4
+       velocityjitter 32 32 32
+       velocitymultiplier -1
 effect TR_GRENADE
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-
-
-// hookbomb trail
-// smoke
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_KNIGHTSPIKE"), from, to)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_KNIGHTSPIKE"), from, to)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_KNIGHTSPIKE"), from, to)
-effect TR_KNIGHTSPIKE // used for MF_TRACER2
-notunderwater
-trailspacing 6
-type smoke
-color 0x303030 0x000000
-tex 0 8
-size 3 3
-bounce 1
-sizeincrease 11
-alpha 300 400 600
-originjitter 2 2 2
-velocityjitter 3 3 3
-velocitymultiplier -0.02
-gravity -0.11
-//marker
-effect TR_KNIGHTSPIKE // used for MF_TRACER2
-type alphastatic
-color 0x666666 0x000000
-tex 62 62
-size 1 1
-sizeincrease -0.1
-trailspacing 2
-alpha 256 256 720
-// bubbles
-effect TR_KNIGHTSPIKE // used for MF_TRACER2
-underwater
-trailspacing 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-
-
-// decal
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1)
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0x404040 0x808080
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
+effect TR_KNIGHTSPIKE
+       type smoke
+       alpha 300 400 600
+       bounce 1
+       color 0x303030 0x000000
+       gravity -0.110000
+       notunderwater
+       originjitter 2 2 2
+       sizeincrease 11
+       size 3 3
+       tex 0 8
+       trailspacing 6
+       velocityjitter 3 3 3
+       velocitymultiplier -0.020000
+effect TR_KNIGHTSPIKE
+       type alphastatic
+       alpha 256 256 720
+       color 0x666666 0x000000
+       sizeincrease -0.100000
+       size 1 1
+       tex 62 62
+       trailspacing 2
+effect TR_KNIGHTSPIKE
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0x404040 0x808080
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 32
+       underwater
+       velocityjitter 16 16 16
 effect grenade_explode
-countabsolute 1
-type decal
-tex 8 16
-size 48 48
-alpha 256 256 0
-originjitter 26 26 26
-lightradius 250
-lightradiusfade 400
-lightcolor 8 4 1
-// fire effect which expands then slows
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 8 4 1
+       lightradiusfade 400
+       lightradius 250
+       originjitter 26 26 26
+       size 48 48
+       tex 8 16
 effect grenade_explode
-notunderwater
-count 40
-type static
-tex 48 55
-color 0xe03f00 0x5e0000
-size 16 26
-sizeincrease 20
-alpha 128 228 356
-bounce 4.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 256 256 256
-// fire effect which make brigt dot inside
+       type static
+       airfriction 8
+       alpha 128 228 356
+       bounce 4.500000
+       color 0xe03f00 0x5e0000
+       count 40
+       liquidfriction 8
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 20
+       size 16 26
+       tex 48 55
+       velocityjitter 256 256 256
 effect grenade_explode
-notunderwater
-count 15
-type static
-tex 48 55
-color 0xe03f00 0xffdf92
-size 6 16
-sizeincrease 40
-alpha 228 328 756
-bounce 1
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 256 256 256
-// smoke
+       type static
+       airfriction 8
+       alpha 228 328 756
+       bounce 1
+       color 0xe03f00 0xffdf92
+       count 15
+       liquidfriction 8
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 40
+       size 6 16
+       tex 48 55
+       velocityjitter 256 256 256
 effect grenade_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 10
-size 20 40
-sizeincrease 34
-alpha 300 550 556
-velocityjitter 256 256 256
-airfriction 5
-color 0x000000 0x111111
-bounce 6
-// underwater bubbles
+       type alphastatic
+       airfriction 5
+       alpha 300 550 556
+       bounce 6
+       color 0x000000 0x111111
+       count 10
+       notunderwater
+       sizeincrease 34
+       size 20 40
+       tex 0 8
+       velocityjitter 256 256 256
 effect grenade_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 6
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 196 196 196
-rotate 0 0 0 0
-// underwatershockwave
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 6
+       tex 62 62
+       underwater
+       velocityjitter 196 196 196
 effect grenade_explode
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 5 5
-sizeincrease 1500
-alpha 40 40 300
-velocitymultiplier 0.3
-// bouncing sparks
+       type smoke
+       alpha 40 40 300
+       countabsolute 1
+       sizeincrease 1500
+       size 5 5
+       tex 33 33
+       underwater
+       velocitymultiplier 0.300000
 effect grenade_explode
-notunderwater
-count 16
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 0.1
-alpha 644 956 484
-gravity 1
-airfriction 1
-bounce 1.6
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// debris
+       type spark
+       airfriction 1
+       alpha 644 956 484
+       bounce 1.600000
+       color 0xffa35b 0xfff2be
+       count 16
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 16 16 16
+       size 1 0.100000
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect grenade_explode
-notunderwater
-count 12
-type alphastatic
-tex 66 68
-color 0x6a3d25 0xcac5b4
-size 2 6
-alpha 644 956 684
-gravity 1.3
-airfriction 0.5
-bounce 1.6
-velocityjitter 324 324 524
-rotate -180 180 -1000 1000
-
-
-
-// used in qcsrc/server/w_electro.qc:  pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_electro.qc:  pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+       type alphastatic
+       airfriction 0.500000
+       alpha 644 956 684
+       bounce 1.600000
+       color 0x6a3d25 0xcac5b4
+       count 12
+       gravity 1.300000
+       notunderwater
+       rotate -180 180 -1000 1000
+       size 2 6
+       tex 66 68
+       velocityjitter 324 324 524
 effect electro_muzzleflash
-countabsolute 1
-type smoke
-color 0x283880 0x283880 // 0x202020 0x404040
-tex 65 65
-size 15 15
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease -10
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 1.5 3 6
-
+       type smoke
+       alpha 256 256 512
+       color 0x283880 0x283880
+       countabsolute 1
+       lightcolor 1.5 3 6
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       sizeincrease -10
+       size 15 15
+       tex 65 65
+       velocityjitter 6 6 6
+       velocitymultiplier 0.010000
 effect electro_muzzleflash
-count 7
-type spark
-tex 8 15
-color 0xD9FDFF 0xD9FDFF
-size 5 15
-alpha 110 228 2024
-originjitter 1 1 1
-velocityjitter 150 150 150
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 1.5
-
+       type spark
+       airfriction 2
+       alpha 110 228 2024
+       color 0xD9FDFF 0xD9FDFF
+       count 7
+       originjitter 1 1 1
+       size 5 15
+       stretchfactor 1.500000
+       tex 8 15
+       velocityjitter 150 150 150
+       velocitymultiplier 0.500000
 effect electro_muzzleflash
-count 5
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 7 6
-alpha 110 228 1024
-originjitter 1 1 1
-velocityjitter 350 350 350
-velocitymultiplier 2.5
-airfriction 8
-gravity 1.3
-stretchfactor 0.1
-
-
-// electro trail
-// glowing vapor trail
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_NEXUIZPLASMA"), from, to)
+       type spark
+       airfriction 8
+       alpha 110 228 1024
+       color 0xD9FDFF 0xD9FDFF
+       count 5
+       gravity 1.300000
+       originjitter 1 1 1
+       size 7 6
+       stretchfactor 0.100000
+       tex 41 41
+       velocityjitter 350 350 350
+       velocitymultiplier 2.500000
 effect TR_NEXUIZPLASMA
-trailspacing 2
-type static
-color 0x283880 0x283880
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+       type static
+       alpha 256 256 968
+       color 0x283880 0x283880
+       lightcolor 1.5 3 6
+       lightradius 90
+       size 3 3
+       tex 38 38
+       trailspacing 2
+       velocitymultiplier -0.100000
 effect TR_NEXUIZPLASMA
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0x629dff 0x0018ff
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-
-
-// decal
-// used in qcsrc/client/damage.qc:                                             pointparticles(particleeffectnum("electro_impact"), org2, '0 0 0', 1)
+       type snow
+       airfriction 12
+       alpha 444 512 1866
+       bounce 1
+       color 0x629dff 0x0018ff
+       count 1.500000
+       originjitter 1 1 1
+       sizeincrease -20
+       size 2 4
+       tex 42 42
+       trailspacing 12
+       velocityjitter 50 50 50
+       velocityoffset 0 0 15
 effect electro_impact
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-originjitter 17 17 17
-lightradius 250
-lightradiusfade 250
-lightcolor 3.125 4.375 10
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 3.1 4.4 10
+       lightradiusfade 250
+       lightradius 250
+       originjitter 17 17 17
+       size 32 32
+       tex 59 59
 effect electro_impact
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 1000
-color 0x80C0FF 0x80C0FF
-alpha 40 40 350
-velocitymultiplier 44
-// flare effect
+       type smoke
+       alpha 40 40 350
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       sizeincrease 1000
+       size 32 32
+       tex 33 33
+       velocitymultiplier 44
 effect electro_impact
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 12 32
-alpha 256 256 512
-// cloud of bouncing sparks
+       type static
+       alpha 256 256 512
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       size 12 32
+       tex 38 38
 effect electro_impact
-count 30
-type smoke
-tex 42 42
-color 0x629dff 0x0018ff
-size 36 36
-sizeincrease -50
-alpha 256 256 1024
-bounce 2
-gravity -0.3
-airfriction 6
-originjitter 1 1 1
-velocityjitter 512 512 512
-rotate -180 180 -9999 9999
-// inner cloud of smoke
+       type smoke
+       airfriction 6
+       alpha 256 256 1024
+       bounce 2
+       color 0x629dff 0x0018ff
+       count 30
+       gravity -0.300000
+       originjitter 1 1 1
+       rotate -180 180 -9999 9999
+       sizeincrease -50
+       size 36 36
+       tex 42 42
+       velocityjitter 512 512 512
 effect electro_impact
-count 30
-type smoke
-color 0x629dff 0x0018ff
-tex 0 8
-size 20 24
-sizeincrease 50
-alpha 200 256 512
-airfriction 30
-originjitter 20 20 20
-velocityjitter 320 320 320
-
-// decal
-// used in qcsrc/client/damage.qc:                                     pointparticles(particleeffectnum("electro_ballexplode"), org2, '0 0 0', 1)
+       type smoke
+       airfriction 30
+       alpha 200 256 512
+       color 0x629dff 0x0018ff
+       count 30
+       originjitter 20 20 20
+       sizeincrease 50
+       size 20 24
+       tex 0 8
+       velocityjitter 320 320 320
 effect electro_ballexplode
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-originjitter 17 17 17
-lightradius 250
-lightradiusfade 250
-lightcolor 3.125 4.375 10
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 3.1 4.4 10
+       lightradiusfade 250
+       lightradius 250
+       originjitter 17 17 17
+       size 32 32
+       tex 59 59
 effect electro_ballexplode
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 32 32
-alpha 256 256 512
-// cloud of bouncing sparks
+       type static
+       alpha 256 256 512
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       size 32 32
+       tex 38 38
 effect electro_ballexplode
-count 64
-type spark
-tex 41 41
-color 0xFDFFD9 0xFDFFD9
-size 1 2
-alpha 256 256 1024
-bounce 2
-stretchfactor 0.4
-//airfriction 2
-originjitter 1 1 1
-velocityjitter 512 512 512
-// inner cloud of smoke
+       type spark
+       alpha 256 256 1024
+       bounce 2
+       color 0xFDFFD9 0xFDFFD9
+       count 64
+       originjitter 1 1 1
+       size 1 2
+       stretchfactor 0.400000
+       tex 41 41
+       velocityjitter 512 512 512
 effect electro_ballexplode
-count 8
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 24 24
-alpha 256 256 512
-originjitter 20 20 20
-velocityjitter 32 32 32
-
-
-
-// decal
-// used in qcsrc/client/damage.qc:                                             pointparticles(particleeffectnum("electro_combo"), org2, '0 0 0', 1)
+       type smoke
+       alpha 256 256 512
+       color 0x202020 0x404040
+       count 8
+       originjitter 20 20 20
+       size 24 24
+       tex 0 8
+       velocityjitter 32 32 32
 effect electro_combo
-countabsolute 1
-type decal
-tex 59 59
-size 64 64
-alpha 256 256 0
-originjitter 17 17 17
-lightradius 400
-lightradiusfade 300
-lightcolor 4 5 6
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 4 5 6
+       lightradiusfade 300
+       lightradius 400
+       originjitter 17 17 17
+       size 64 64
+       tex 59 59
 effect electro_combo
-countabsolute 1
-type static
-tex 38 38
-color 0x80C0FF 0x80C0FF
-size 48 48
-alpha 128 128 64
-// large sparks
+       type static
+       alpha 128 128 64
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       size 48 48
+       tex 38 38
 effect electro_combo
-count 5
-type static
-color 0x2030FF 0x80C0FF
-size 32 32
-sizeincrease 50
-tex 0 7
-alpha 156 156 156
-bounce 2
-airfriction 6
-liquidfriction 16
-//velocityoffset 0 0 120
-velocityjitter 512 512 512
+       type static
+       airfriction 6
+       alpha 156 156 156
+       bounce 2
+       color 0x2030FF 0x80C0FF
+       count 5
+       liquidfriction 16
+       sizeincrease 50
+       size 32 32
+       tex 0 7
+       velocityjitter 512 512 512
 effect electro_combo
-count 32
-type spark
-tex 41 41
-color 0xa9cacf 0x0054ff
-size 2 4
-stretchfactor 2
-gravity 0.3
-alpha 444 512 700
-velocitymultiplier 3
-bounce 1.6
-//airfriction 2
-originjitter 1 1 1
-velocityjitter 312 312 312
-// inner cloud of smoke
+       type spark
+       alpha 444 512 700
+       bounce 1.600000
+       color 0xa9cacf 0x0054ff
+       count 32
+       gravity 0.300000
+       originjitter 1 1 1
+       size 2 4
+       stretchfactor 2
+       tex 41 41
+       velocityjitter 312 312 312
+       velocitymultiplier 3
 effect electro_combo
-count 0.125
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 24 24
-alpha 256 256 256
-originjitter 20 20 20
-velocityjitter 32 32 32
-// shockwave
+       type smoke
+       alpha 256 256 256
+       color 0x202020 0x404040
+       count 0.125000
+       originjitter 20 20 20
+       size 24 24
+       tex 0 8
+       velocityjitter 32 32 32
 effect electro_combo
-type smoke
-countabsolute 1
-color 0xa9cacf 0x0054ff
-tex 33 33
-size 30 30
-sizeincrease 600
-alpha 40 40 100
-velocitymultiplier 0.3
-
-
-
-// used in qcsrc/server/w_crylink.qc:  pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots)
-// used in qcsrc/server/w_crylink.qc:  pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots)
+       type smoke
+       alpha 40 40 100
+       color 0xa9cacf 0x0054ff
+       countabsolute 1
+       sizeincrease 600
+       size 30 30
+       tex 33 33
+       velocitymultiplier 0.300000
 effect crylink_muzzleflash
-count 0.5
-type smoke
-color 0xdd9cff 0xff0090
-tex 65 65
-size 15 20
-alpha 128 128 2024
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 1.6 0.2 2
+       type smoke
+       alpha 128 128 2024
+       color 0xdd9cff 0xff0090
+       count 0.500000
+       lightcolor 1.6 0.2 2
+       lightradiusfade 2000
+       lightradius 200
+       size 15 20
+       tex 65 65
+       velocitymultiplier 0.010000
 effect crylink_muzzleflash
-count 5
-type spark
-tex 35 36
-color 0xA080C0 0xA080C0
-size 5 10
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 200 200 200
-velocitymultiplier 0.3
-airfriction 12
-stretchfactor 1.5
-
-
-// crylink impact effect
-// decal
-// used in qcsrc/client/damage.qc:                                     pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1)
+       type spark
+       airfriction 12
+       alpha 0 128 1024
+       color 0xA080C0 0xA080C0
+       count 5
+       originjitter 1 1 1
+       size 5 10
+       stretchfactor 1.500000
+       tex 35 36
+       velocityjitter 200 200 200
+       velocitymultiplier 0.300000
 effect crylink_impact
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 12 12 12
-//lightradius 200
-//lightradiusfade 800
-//lightcolor 3.2 0.4 4
-// purple flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 12 12 12
+       size 24 24
+       tex 47 47
 effect crylink_impact
-countabsolute 1
-type static
-tex 39 39
-color 0x504060 0x504060
-size 24 24
-alpha 256 256 512
-// purple sparks
+       type static
+       alpha 256 256 512
+       color 0x504060 0x504060
+       countabsolute 1
+       size 24 24
+       tex 39 39
 effect crylink_impact
-count 40
-type spark
-tex 41 41
-color 0xA040C0 0xA040C0
-bounce 2
-size 6 6
-alpha 256 256 1024
-velocityjitter 512 512 512
-// purple splash
+       type spark
+       alpha 256 256 1024
+       bounce 2
+       color 0xA040C0 0xA040C0
+       count 40
+       size 6 6
+       tex 41 41
+       velocityjitter 512 512 512
 effect crylink_impact
-count 1.5
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 512
-velocityjitter 32 32 32
-// purple splash
+       type static
+       alpha 256 256 512
+       color 0xE070FF 0xE070FF
+       count 1.500000
+       size 16 16
+       velocityjitter 32 32 32
 effect crylink_impact
-count 3
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 1024
-velocityjitter 256 256 256
-
-
-
-// used in qcsrc/server/w_minstanex.qc:        pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/client/particles.qc:  pointparticles(particleeffectnum("nex_muzzleflash"), shotorg, normalize(endpos - shotorg) * 1000, 1)
+       type static
+       alpha 256 256 1024
+       color 0xE070FF 0xE070FF
+       count 3
+       size 16 16
+       velocityjitter 256 256 256
 effect nex_muzzleflash
-count 12
-type spark
-color 0x202020 0x0072ff
-tex 48 55
-size 16 16
-alpha 328 328 4000
-originjitter 4 4 4
-velocityjitter 180 180 180
-velocitymultiplier 1.4
-stretchfactor 2
-sizeincrease -100
-airfriction 9
-lightradius 200
-lightradiusfade 200
-lightcolor 2 2.5 3
+       type spark
+       airfriction 9
+       alpha 328 328 4000
+       color 0x202020 0x0072ff
+       count 12
+       lightcolor 2 2.5 3
+       lightradiusfade 200
+       lightradius 200
+       originjitter 4 4 4
+       sizeincrease -100
+       size 16 16
+       stretchfactor 2
+       tex 48 55
+       velocityjitter 180 180 180
+       velocitymultiplier 1.400000
 effect nex_muzzleflash
-count 50
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 1 1
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 600 600 600
-velocitymultiplier 1.5
-airfriction 9
-
-
-
-//// nex beam
-//effect nex_beam
-//countabsolute 1
-//type beam
-//tex 200 200
-//color 0xFFFFFF 0xFFFFFF
-//size 6 6
-//alpha 128 128 192
-// nex beam: ring smoke
-// used in qcsrc/client/particles.qc:          trailparticles(world, particleeffectnum("nex_beam"), shotorg, endpos)
+       type spark
+       airfriction 9
+       alpha 0 128 1024
+       color 0xD9FDFF 0xD9FDFF
+       count 50
+       originjitter 1 1 1
+       size 1 1
+       tex 41 41
+       velocityjitter 600 600 600
+       velocitymultiplier 1.500000
 effect nex_beam
-trailspacing 64
-color 0x1680A0 0x1680A0
-size 4 4
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
-// nex beam: drifting smoke
+       type static
+       airfriction 5
+       alpha 64 128 64
+       color 0x1680A0 0x1680A0
+       sizeincrease 2
+       size 4 4
+       tex 32 32
+       trailspacing 64
 effect nex_beam
-trailspacing 12
-color 0x5080A0 0x5080A0
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
-// nex beam: bright core
+       type static
+       airfriction 9
+       alpha 32 64 32
+       color 0x5080A0 0x5080A0
+       sizeincrease 8
+       size 1 1
+       tex 0 8
+       trailspacing 12
+       velocityjitter 64 64 64
 effect nex_beam
-trailspacing 12
-color 0x80CDFF 0x80CDFF
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-//sparks
+       type static
+       alpha 256 256 1280
+       color 0x80CDFF 0x80CDFF
+       size 4 4
+       trailspacing 12
 effect nex_beam
-trailspacing 16
-color 0x1680A0 0x1680A0
-size 1 1
-tex 63 63
-alpha 64 128 80
-airfriction 5
-gravity -0.01
-type snow
-
-// nex impact
-// decal
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1)
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1)
+       type snow
+       airfriction 5
+       alpha 64 128 80
+       color 0x1680A0 0x1680A0
+       gravity -0.010000
+       size 1 1
+       tex 63 63
+       trailspacing 16
 effect nex_impact
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 14 14 14
-lightradius 200
-lightradiusfade 250
-lightcolor 4 6 8
-rotate -180 180 0 0
-// rotating something
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 4 6 8
+       lightradiusfade 250
+       lightradius 200
+       originjitter 14 14 14
+       rotate -180 180 0 0
+       size 24 24
+       tex 47 47
 effect nex_impact
-count 5
-type smoke
-tex 46 46
-color 0x1680A0 0x1680A0
-size 25 28
-sizeincrease 20
-alpha 55 55 50
-rotate 180 -180 500 -500
-// shockwave
+       type smoke
+       alpha 55 55 50
+       color 0x1680A0 0x1680A0
+       count 5
+       rotate 180 -180 500 -500
+       sizeincrease 20
+       size 25 28
+       tex 46 46
 effect nex_impact
-countabsolute 1
-type static
-tex 33 33
-color 0x1680A0 0x1680A0
-size 16 16
-alpha 50 50 400
-sizeincrease 900
-// shockwave2
+       type static
+       alpha 50 50 400
+       color 0x1680A0 0x1680A0
+       countabsolute 1
+       sizeincrease 900
+       size 16 16
+       tex 33 33
 effect nex_impact
-countabsolute 1
-type static
-tex 65 65
-color 0x1680A0 0x1680A0
-size 5 5
-alpha 50 50 100
-sizeincrease 500
-
-// flare effect
+       type static
+       alpha 50 50 100
+       color 0x1680A0 0x1680A0
+       countabsolute 1
+       sizeincrease 500
+       size 5 5
+       tex 65 65
 effect nex_impact
-countabsolute 1
-type static
-tex 37 37
-color 0x80C0FF 0x80C0FF
-size 8 8
-alpha 256 256 256
-// small sparks which form a sphere as they slow down
-//effect nex_impact
-//count 256
-//type spark
-//color 0x2030FF 0x80C0FF
-//size 1 2
-//alpha 256 256 512
-//bounce 2
-//airfriction 8
-//liquidfriction 8
-//velocityjitter 384 384 384
-// small sparks which glow brightly but live briefly
+       type static
+       alpha 256 256 256
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       size 8 8
+       tex 37 37
 effect nex_impact
-count 64
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 4 4
-alpha 0 128 512
-bounce 2
-stretchfactor 3
-velocityjitter 600 600 600
-velocitymultiplier 0.5
-airfriction 9
-// small sparks that live longer
+       type spark
+       airfriction 9
+       alpha 0 128 512
+       bounce 2
+       color 0xD9FDFF 0xD9FDFF
+       count 64
+       size 4 4
+       stretchfactor 3
+       tex 41 41
+       velocityjitter 600 600 600
+       velocitymultiplier 0.500000
 effect nex_impact
-count 16
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 2 2
-alpha 255 255 112
-bounce 1.6
-stretchfactor 0.7
-velocityjitter 300 300 600
-velocitymultiplier 2.5
-airfriction 2
-gravity 1
-
-// used in qcsrc/server/w_hagar.qc:    pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_hagar.qc:    pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_seeker.qc:   pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+       type spark
+       airfriction 2
+       alpha 255 255 112
+       bounce 1.600000
+       color 0xD9FDFF 0xD9FDFF
+       count 16
+       gravity 1
+       size 2 2
+       stretchfactor 0.700000
+       tex 41 41
+       velocityjitter 300 300 600
+       velocitymultiplier 2.500000
 effect hagar_muzzleflash
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+       type smoke
+       alpha 256 256 512
+       color 0x202020 0x404040
+       count 2
+       lightcolor 2 1.5 0.2
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       size 5 5
+       tex 0 8
+       velocityjitter 6 6 6
+       velocitymultiplier 0.010000
 effect hagar_muzzleflash
-count 15
-type spark
-tex 48 55
-color 0xff8400 0xff4200
-size 5 10
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 200 200 200
-velocitymultiplier 0.5
-airfriction 12
-stretchfactor 2
-rotate -180 180 -400 400
-
-
-
-// used in qcsrc/server/w_hagar.qc:            pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1)
+       type spark
+       airfriction 12
+       alpha 0 128 1024
+       color 0xff8400 0xff4200
+       count 15
+       originjitter 1 1 1
+       rotate -180 180 -400 400
+       size 5 10
+       stretchfactor 2
+       tex 48 55
+       velocityjitter 200 200 200
+       velocitymultiplier 0.500000
 effect hagar_bounce
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 256
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 60
-lightradiusfade 300
-lightcolor 2 1.5 0.2
+       type smoke
+       alpha 256 256 256
+       color 0x202020 0x404040
+       count 2
+       lightcolor 2 1.5 0.2
+       lightradiusfade 300
+       lightradius 60
+       originjitter 1.5 1.5 1.5
+       size 5 5
+       tex 0 8
+       velocityjitter 6 6 6
+       velocitymultiplier 0.010000
 effect hagar_bounce
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
-alpha 0 256 256
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 600 600 600
-velocitymultiplier 0.5
-airfriction 12
-
-
-
-// decal
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1)
-// used in qcsrc/client/damage.qc:                                             pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1)
-// used in qcsrc/client/damage.qc:                                             pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1)
+       type spark
+       airfriction 12
+       alpha 0 256 256
+       bounce 1.500000
+       color 0xFFFDD9 0xFFFDD9
+       count 15
+       gravity 1
+       originjitter 1 1 1
+       size 3 3
+       tex 40 40
+       velocityjitter 600 600 600
+       velocitymultiplier 0.500000
 effect hagar_explode
-countabsolute 1
-type decal
-tex 8 16
-size 28 38
-alpha 256 256 0
-originjitter 14 14 14
-lightradius 120
-lightradiusfade 400
-lightcolor 8 4 1
-// fire effect which make bright dot inside
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 8 4 1
+       lightradiusfade 400
+       lightradius 120
+       originjitter 14 14 14
+       size 28 38
+       tex 8 16
 effect hagar_explode
-notunderwater
-count 3.5
-type smoke
-tex 48 55
-color 0xffe955 0xff5a00
-size 16 26
-sizeincrease 5
-alpha 80 200 356
-bounce 1.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 156 156 156
-// fire effect which expands then slows
+       type smoke
+       airfriction 8
+       alpha 80 200 356
+       bounce 1.500000
+       color 0xffe955 0xff5a00
+       count 3.500000
+       liquidfriction 8
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 5
+       size 16 26
+       tex 48 55
+       velocityjitter 156 156 156
 effect hagar_explode
-notunderwater
-count 12
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 26
-sizeincrease 15
-alpha 128 256 456
-bounce 1.5
-airfriction 12
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 286 286 286
-
-// smoke
+       type static
+       airfriction 12
+       alpha 128 256 456
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 12
+       liquidfriction 8
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 15
+       size 20 26
+       tex 48 55
+       velocityjitter 286 286 286
 effect hagar_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 7
-size 20 40
-sizeincrease 20
-alpha 200 500 600
-velocityjitter 244 244 244
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-
-// underwater bubbles
+       type alphastatic
+       airfriction 5
+       alpha 200 500 600
+       bounce 2
+       color 0x000000 0x111111
+       count 7
+       notunderwater
+       sizeincrease 20
+       size 20 40
+       tex 0 8
+       velocityjitter 244 244 244
 effect hagar_explode
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 16
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 96 96 96
 effect hagar_explode
-notunderwater
-count 4
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 0.1
-alpha 644 956 684
-gravity 1
-airfriction 1
-bounce 1.6
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 224 224 224
-
-
-
-// used in qcsrc/server/w_rocketlauncher.qc:   pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+       type spark
+       airfriction 1
+       alpha 644 956 684
+       bounce 1.600000
+       color 0xffa35b 0xfff2be
+       count 4
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 16 16 16
+       size 1 0.100000
+       tex 40 40
+       velocityjitter 224 224 224
+       velocityoffset 0 0 80
 effect rocketlauncher_muzzleflash
-count 10
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 1 1
-sizeincrease 20
-alpha 256 256 256
-airfriction 2
-originjitter 1.5 1.5 1.5
-velocityjitter 40 40 40
-velocitymultiplier -0.13
-//lightradius 200
-//lightradiusfade 2000
-//lightcolor 2 1.5 0.2
+       type smoke
+       airfriction 2
+       alpha 256 256 256
+       color 0x202020 0x404040
+       count 10
+       originjitter 1.5 1.5 1.5
+       sizeincrease 20
+       size 1 1
+       tex 0 8
+       velocityjitter 40 40 40
+       velocitymultiplier -0.130000
 effect rocketlauncher_muzzleflash
-count 6
-type smoke
-tex 35 36
-color 0xFFFDD9 0xFFFDD9
-size 5 10
-sizeincrease 20
-alpha 10 25 20
-originjitter 3 3 3
-velocityjitter 100 100 100
-velocitymultiplier 0.3
-airfriction 9
-rotate -180 180 -30 30
-
-
-
-// rocket trail
-// smoke
-// used in qcsrc/server/cl_client.qc:          self.modelflags |= MF_ROCKET
-// used in qcsrc/server/cl_client.qc:          self.modelflags &~= MF_ROCKET
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_ROCKET"), from, to)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_ROCKET"), from, to)
+       type smoke
+       airfriction 9
+       alpha 10 25 20
+       color 0xFFFDD9 0xFFFDD9
+       count 6
+       originjitter 3 3 3
+       rotate -180 180 -30 30
+       sizeincrease 20
+       size 5 10
+       tex 35 36
+       velocityjitter 100 100 100
+       velocitymultiplier 0.300000
 effect TR_ROCKET
-trailspacing 10
-type smoke
-notunderwater
-color 0x000000 0x666666
-tex 0 8
-size 3 4
-bounce 1
-sizeincrease 11
-alpha 200 300 200
-lightradius 150
-lighttime 0
-lightcolor 6 3 1
-originjitter 2 2 2
-velocityjitter 3 3 3
-velocitymultiplier -0.02
-rotate -180 180 -30 30
-//gravity -0.11
-// fire
+       type smoke
+       alpha 200 300 200
+       bounce 1
+       color 0x000000 0x666666
+       lightcolor 6 3 1
+       lightradius 150
+       notunderwater
+       originjitter 2 2 2
+       rotate -180 180 -30 30
+       sizeincrease 11
+       size 3 4
+       tex 0 8
+       trailspacing 10
+       velocityjitter 3 3 3
+       velocitymultiplier -0.020000
 effect TR_ROCKET
-trailspacing 4
-type static
-color 0xffdf72 0x811200
-tex 48 55
-size 7 7
-sizeincrease -30
-alpha 100 144 588
-airfriction 8
-velocityjitter 32 32 32
-velocitymultiplier -1.5
-// bubbles
+       type static
+       airfriction 8
+       alpha 100 144 588
+       color 0xffdf72 0x811200
+       sizeincrease -30
+       size 7 7
+       tex 48 55
+       trailspacing 4
+       velocityjitter 32 32 32
+       velocitymultiplier -1.500000
 effect TR_ROCKET
-type bubble
-underwater
-trailspacing 16
-tex 62 62
-size 1 2
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-velocitymultiplier -0.31
-rotate 0 0 0 0
-// sparks
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       gravity -0.125000
+       liquidfriction 4
+       size 1 2
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
+       velocitymultiplier -0.310000
 effect TR_ROCKET
-notunderwater
-trailspacing 20
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 0.5 0.5
-alpha 444 512 1866
-stretchfactor 0.3
-//gravity 1
-bounce 1
-//velocityoffset 0 0 15
-airfriction 5
-originjitter 1 1 1
-velocityjitter 100 100 100
-velocitymultiplier -0.31
-
-// rocket explosion (bigger than mortar and hagar)
+       type spark
+       airfriction 5
+       alpha 444 512 1866
+       bounce 1
+       color 0xFFFDD9 0xFFFDD9
+       notunderwater
+       originjitter 1 1 1
+       size 0.500000 0.500000
+       stretchfactor 0.300000
+       tex 40 40
+       trailspacing 20
+       velocityjitter 100 100 100
+       velocitymultiplier -0.310000
 effect rocket_explode
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 23 23 23
-lightradius 400
-lightradiusfade 750
-lightcolor 8 4 1
-// fire effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 8 4 1
+       lightradiusfade 750
+       lightradius 400
+       originjitter 23 23 23
+       size 72 72
+       tex 8 16
 effect rocket_explode
-notunderwater
-count 32
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 33 44
-sizeincrease 45
-alpha 200 256 512
-bounce 1.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 512 512 512
-// fire effect 2
+       type static
+       airfriction 8
+       alpha 200 256 512
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 32
+       liquidfriction 8
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 45
+       size 33 44
+       tex 48 55
+       velocityjitter 512 512 512
 effect rocket_explode
-notunderwater
-count 14
-type smoke
-tex 48 55
-color 0xea691b 0xeed05a
-size 33 44
-sizeincrease 55
-alpha 200 256 612
-bounce 2.5
-airfriction 19
-liquidfriction 19
-originjitter 8 8 8
-velocityjitter 912 912 912
-// smoke
+       type smoke
+       airfriction 19
+       alpha 200 256 612
+       bounce 2.500000
+       color 0xea691b 0xeed05a
+       count 14
+       liquidfriction 19
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 55
+       size 33 44
+       tex 48 55
+       velocityjitter 912 912 912
 effect rocket_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 32
-size 20 40
-sizeincrease 44
-alpha 200 450 456
-velocityjitter 444 444 444
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-// underwater bubbles
+       type alphastatic
+       airfriction 5
+       alpha 200 450 456
+       bounce 2
+       color 0x000000 0x111111
+       count 32
+       notunderwater
+       sizeincrease 44
+       size 20 40
+       tex 0 8
+       velocityjitter 444 444 444
 effect rocket_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 144 144 144
-// underwatershockwave
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 144 144 144
 effect rocket_explode
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 1900
-alpha 40 40 300
-velocitymultiplier 0.3
-// bouncing sparks
+       type smoke
+       alpha 40 40 300
+       countabsolute 1
+       sizeincrease 1900
+       size 30 30
+       tex 33 33
+       underwater
+       velocitymultiplier 0.300000
 effect rocket_explode
-notunderwater
-count 16
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 0.1
-alpha 644 956 484
-gravity 1
-airfriction 1
-bounce 1.6
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// debris
+       type spark
+       airfriction 1
+       alpha 644 956 484
+       bounce 1.600000
+       color 0xffa35b 0xfff2be
+       count 16
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 16 16 16
+       size 1 0.100000
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect rocket_explode
-notunderwater
-count 12
-type alphastatic
-tex 66 68
-color 0x6a3d25 0xcac5b4
-size 2 6
-alpha 644 956 684
-gravity 1.3
-airfriction 0.5
-bounce 1.6
-velocityjitter 324 324 524
-rotate -180 180 -1000 1000
-
-// used in qcsrc/server/g_hook.qc:     pointparticles(particleeffectnum("grapple_muzzleflash"), org, '0 0 0', 1)
+       type alphastatic
+       airfriction 0.500000
+       alpha 644 956 684
+       bounce 1.600000
+       color 0x6a3d25 0xcac5b4
+       count 12
+       gravity 1.300000
+       notunderwater
+       rotate -180 180 -1000 1000
+       size 2 6
+       tex 66 68
+       velocityjitter 324 324 524
 effect grapple_muzzleflash
-lightradius 160
-lightradiusfade 800
-lightcolor 1 0 0
-
-
-
-// used in qcsrc/server/g_hook.qc:     pointparticles(particleeffectnum("grapple_impact"), self.origin, '0 0 0', 1)
+       lightcolor 1 0 0
+       lightradiusfade 800
+       lightradius 160
 effect grapple_impact
-lightradius 160
-lightradiusfade 800
-lightcolor 1 0 0
-
-
-
-// used nowhere in code
+       lightcolor 1 0 0
+       lightradiusfade 800
+       lightradius 160
 effect nex242_misc_laser_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xff0000 0xff0000
-sizeincrease 1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 64
+       color 0xff0000 0xff0000
+       countabsolute 1
+       sizeincrease 1
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-
-
-// used nowhere in code
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect nex242_misc_laser_beam_fast
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 640
-color 0xff0000 0xff0000
-sizeincrease 0.1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 640
+       color 0xff0000 0xff0000
+       countabsolute 1
+       sizeincrease 0.100000
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_beam_fast_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// additional laser colors (mike)
-// used nowhere in code
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect nex242_misc_laser_green_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0x00ff00 0x00ff00
-sizeincrease 1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 64
+       color 0x00ff00 0x00ff00
+       countabsolute 1
+       sizeincrease 1
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_green_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect nex242_misc_laser_blue_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0x0000ff 0x0000ff
-sizeincrease 1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 64
+       color 0x0000ff 0x0000ff
+       countabsolute 1
+       sizeincrease 1
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_blue_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect nex242_misc_laser_yellow_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xffff00 0xffff00
-sizeincrease 1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 64
+       color 0xffff00 0xffff00
+       countabsolute 1
+       sizeincrease 1
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_yellow_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect nex242_misc_laser_cyan_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0x00ffff 0x00ffff
-sizeincrease 1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 64
+       color 0x00ffff 0x00ffff
+       countabsolute 1
+       sizeincrease 1
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_cyan_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect nex242_misc_laser_magenta_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xff00ff 0xff00ff
-sizeincrease 1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 64
+       color 0xff00ff 0xff00ff
+       countabsolute 1
+       sizeincrease 1
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_magenta_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect nex242_misc_laser_white_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xffffff 0xffffff
-sizeincrease 1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 64
+       color 0xffffff 0xffffff
+       countabsolute 1
+       sizeincrease 1
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_white_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect nex242_misc_laser_black_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0x000000 0x000000
-sizeincrease 1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 64
+       color 0x000000 0x000000
+       countabsolute 1
+       sizeincrease 1
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_black_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-// used nowhere in code
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect nex242_misc_laser_orange_beam
-countabsolute 1
-type beam
-tex 200 200
-size 1 1
-alpha 256 256 64
-color 0xff6600 0xff6600
-sizeincrease 1
-
-// used nowhere in code
+       type beam
+       alpha 256 256 64
+       color 0xff6600 0xff6600
+       countabsolute 1
+       sizeincrease 1
+       size 1 1
+       tex 200 200
 effect nex242_misc_laser_orange_beam_end
-count 0.5
-type spark
-color 0x8f4333 0xfff31b
-size 0.4 0.4
-alpha 128 256 768
-gravity 1
-bounce -1
-velocityjitter 64 64 64
-velocitymultiplier 100
-
-
-
-
-// bigger crylink impact effect
-// decal
-// used in qcsrc/client/damage.qc:                                     pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1)
+       type spark
+       alpha 128 256 768
+       bounce -1
+       color 0x8f4333 0xfff31b
+       count 0.500000
+       gravity 1
+       size 0.400000 0.400000
+       velocityjitter 64 64 64
+       velocitymultiplier 100
 effect crylink_impactbig
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 12 12 12
-//lightradius 200
-//lightradiusfade 800
-//lightcolor 3.2 0.4 4
-// purple flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 12 12 12
+       size 24 24
+       tex 47 47
 effect crylink_impactbig
-countabsolute 1
-type static
-tex 39 39
-color 0x504060 0x504060
-size 24 24
-alpha 256 256 512
-// purple sparks
+       type static
+       alpha 256 256 512
+       color 0x504060 0x504060
+       countabsolute 1
+       size 24 24
+       tex 39 39
 effect crylink_impactbig
-count 40
-type spark
-tex 41 41
-color 0xA040C0 0xA040C0
-bounce 2
-size 6 6
-alpha 256 256 1024
-velocityjitter 512 512 512
-// purple splash
+       type spark
+       alpha 256 256 1024
+       bounce 2
+       color 0xA040C0 0xA040C0
+       count 40
+       size 6 6
+       tex 41 41
+       velocityjitter 512 512 512
 effect crylink_impactbig
-count 1.5
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 512
-velocityjitter 32 32 32
-// purple splash
+       type static
+       alpha 256 256 512
+       color 0xE070FF 0xE070FF
+       count 1.500000
+       size 16 16
+       velocityjitter 32 32 32
 effect crylink_impactbig
-count 3
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 1024
-velocityjitter 256 256 256
-
-// Zero-violence effects
-
-// impact effect indicating damage
-// used in qcsrc/client/gibs.qc:                       pointparticles(particleeffectnum("damage_hit"), org, vel, amount * 16)
+       type static
+       alpha 256 256 1024
+       color 0xE070FF 0xE070FF
+       count 3
+       size 16 16
+       velocityjitter 256 256 256
 effect damage_hit
-tex 48 55
-count 0.5
-type alphastatic
-color 0x00FFFF 0xFF00FF
-size 16 16
-sizeincrease -24
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 256 256 256
+       type alphastatic
+       airfriction 5
+       alpha 128 128 192
+       bounce 1.500000
+       color 0x00FFFF 0xFF00FF
+       count 0.500000
+       gravity -0.400000
+       liquidfriction 10
+       sizeincrease -24
+       size 16 16
+       tex 48 55
+       velocityjitter 256 256 256
 effect damage_hit
-tex 48 55
-count 0.5
-type alphastatic
-color 0xFF00FF 0xFFFF00
-size 16 16
-sizeincrease -24
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 256 256 256
+       type alphastatic
+       airfriction 5
+       alpha 128 128 192
+       bounce 1.500000
+       color 0xFF00FF 0xFFFF00
+       count 0.500000
+       gravity -0.400000
+       liquidfriction 10
+       sizeincrease -24
+       size 16 16
+       tex 48 55
+       velocityjitter 256 256 256
 effect damage_hit
-tex 48 55
-count 0.5
-type alphastatic
-color 0xFFFF00 0x00FFFF
-size 16 16
-sizeincrease -24
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 256 256 256
-
-// effect for removing player model
-// "teleport"
-// NOTE: maintained by div0, make your own new effect instead of changing this one without asking!
-// large sparks
-// used in qcsrc/client/gibs.qc:                       pointparticles(particleeffectnum("damage_dissolve"), org, vel, amount)
+       type alphastatic
+       airfriction 5
+       alpha 128 128 192
+       bounce 1.500000
+       color 0xFFFF00 0x00FFFF
+       count 0.500000
+       gravity -0.400000
+       liquidfriction 10
+       sizeincrease -24
+       size 16 16
+       tex 48 55
+       velocityjitter 256 256 256
 effect damage_dissolve
-tex 48 55
-count 15
-type alphastatic
-color 0x00FFFF 0xFF00FF
-size 32 32
-sizeincrease -16
-alpha 256 256 128
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 512 512 512
+       type alphastatic
+       airfriction 3
+       alpha 256 256 128
+       bounce 1.500000
+       color 0x00FFFF 0xFF00FF
+       count 15
+       gravity -0.400000
+       liquidfriction 6
+       sizeincrease -16
+       size 32 32
+       tex 48 55
+       velocityjitter 512 512 512
 effect damage_dissolve
-tex 48 55
-count 15
-type alphastatic
-color 0xFF00FF 0xFFFF00
-size 32 32
-sizeincrease -16
-alpha 256 256 128
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 512 512 512
+       type alphastatic
+       airfriction 3
+       alpha 256 256 128
+       bounce 1.500000
+       color 0xFF00FF 0xFFFF00
+       count 15
+       gravity -0.400000
+       liquidfriction 6
+       sizeincrease -16
+       size 32 32
+       tex 48 55
+       velocityjitter 512 512 512
 effect damage_dissolve
-tex 48 55
-count 15
-type alphastatic
-color 0xFFFF00 0x00FFFF
-size 32 32
-sizeincrease -16
-alpha 256 256 128
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 512 512 512
-
-
-// decal
-// used in qcsrc/server/g_triggers.qc:                                 self.cnt = particleeffectnum("laser_deadly")
-// used in qcsrc/server/g_triggers.qc:                 self.cnt = particleeffectnum("laser_deadly")
+       type alphastatic
+       airfriction 3
+       alpha 256 256 128
+       bounce 1.500000
+       color 0xFFFF00 0x00FFFF
+       count 15
+       gravity -0.400000
+       liquidfriction 6
+       sizeincrease -16
+       size 32 32
+       tex 48 55
+       velocityjitter 512 512 512
 effect laser_deadly
-countabsolute 1
-type decal
-tex 56 59
-size 5 5
-alpha 256 256 0
-originjitter 6 6 6
-// dust/smoke drifting away from the impact
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 6 6 6
+       size 5 5
+       tex 56 59
 effect laser_deadly
-count 0.025
-type smoke
-tex 48 55
-color 0xFFFFFF 0xFFFFFF
-size 3 3
-alpha 0 64 64
-originjitter 1 1 1
-airfriction 7
-liquidfriction 16
-velocityjitter 15 15 15
-sizeincrease 2
-velocitymultiplier 20
-// sparks
+       type smoke
+       airfriction 7
+       alpha 0 64 64
+       color 0xFFFFFF 0xFFFFFF
+       count 0.025000
+       liquidfriction 16
+       originjitter 1 1 1
+       sizeincrease 2
+       size 3 3
+       tex 48 55
+       velocityjitter 15 15 15
+       velocitymultiplier 20
 effect laser_deadly
-notunderwater
-count 0.025
-type spark
-tex 40 40
-color 0xFDFFD9 0xFDFFD9
-size 0.6 0.6
-alpha 256 256 768
-gravity 1
-bounce 1
-airfriction 5
-originjitter 1 1 1
-velocityjitter 100 100 100
-velocitymultiplier 100
-
-
-//torch
-//fire
-// used nowhere in code
+       type spark
+       airfriction 5
+       alpha 256 256 768
+       bounce 1
+       color 0xFDFFD9 0xFDFFD9
+       count 0.025000
+       gravity 1
+       notunderwater
+       originjitter 1 1 1
+       size 0.600000 0.600000
+       tex 40 40
+       velocityjitter 100 100 100
+       velocitymultiplier 100
 effect torch_small
-//notunderwater
-count 8
-type smoke
-tex 48 55
-size 1 11
-alpha 200 256 512
-gravity -0.5
-color 0x8f0d00 0xff5a00
-//bounce 1
-sizeincrease -1
-originjitter 5 5 5
-velocityjitter 1 1 50
-// smoke
+       type smoke
+       alpha 200 256 512
+       color 0x8f0d00 0xff5a00
+       count 8
+       gravity -0.500000
+       originjitter 5 5 5
+       sizeincrease -1
+       size 1 11
+       tex 48 55
+       velocityjitter 1 1 50
 effect torch_small
-type alphastatic
-count 4
-tex 0 8
-size 5 10
-sizeincrease 5
-alpha 200 256 200
-color 0x000000 0x111111
-gravity -0.3
-originjitter 3 3 3
-velocityjitter 11 11 50
-//bounce 1
-
-//fountain01
-// used nowhere in code
+       type alphastatic
+       alpha 200 256 200
+       color 0x000000 0x111111
+       count 4
+       gravity -0.300000
+       originjitter 3 3 3
+       sizeincrease 5
+       size 5 10
+       tex 0 8
+       velocityjitter 11 11 50
 effect fountain01
-count 16
-tex 0 8
-size 10 15
-alpha 0 100 100
-gravity 0.6
-bounce 1
-sizeincrease 20
-type snow
-bounce 1
-originjitter 5 5 5
-velocityjitter 81 81 150
-color 0x7cbaff 0xcfd1ff
-velocitymultiplier 2
-
-// decal
-// used in qcsrc/client/damage.qc:                             pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1)
+       type snow
+       alpha 0 100 100
+       bounce 1
+       color 0x7cbaff 0xcfd1ff
+       count 16
+       gravity 0.600000
+       originjitter 5 5 5
+       sizeincrease 20
+       size 10 15
+       tex 0 8
+       velocityjitter 81 81 150
+       velocitymultiplier 2
 effect hookbomb_explode
-count 25
-type static
-tex 38 38
-color 0x807aff 0x4463d5
-size 150 200
-sizeincrease -160
-alpha 0 256 200
-//gravity 1
-bounce 1.5
-originjitter 10 10 10
-velocityjitter 550 550 550
-//velocitymultiplier -20
-airfriction 10
-// decal in the air
+       type static
+       airfriction 10
+       alpha 0 256 200
+       bounce 1.500000
+       color 0x807aff 0x4463d5
+       count 25
+       originjitter 10 10 10
+       sizeincrease -160
+       size 150 200
+       tex 38 38
+       velocityjitter 550 550 550
 effect hookbomb_explode
-countabsolute 3
-type static
-tex 38 38
-color 0x807aff 0x4463d5
-size 160 200
-alpha 256 265 100
-sizeincrease -60
-originoffset 0 0 6
-// decal on the ground
+       type static
+       alpha 256 265 100
+       color 0x807aff 0x4463d5
+       countabsolute 3
+       originoffset 0 0 6
+       sizeincrease -60
+       size 160 200
+       tex 38 38
 effect hookbomb_explode
-countabsolute 1
-type decal
-tex 39 39
-size 80 100
-alpha 256 256 0
-originjitter 6 6 6
-// some sparks
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 6 6 6
+       size 80 100
+       tex 39 39
 effect hookbomb_explode
-count 30
-type spark
-tex 38 38
-color 0x807aff 0x4463d5
-size 20 30
-alpha 256 256 456
-sizeincrease -60
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1900 1900 1300
-velocitymultiplier 0.5
-airfriction 2
-
-
-// smoke
+       type spark
+       airfriction 2
+       alpha 256 256 456
+       bounce 1.500000
+       color 0x807aff 0x4463d5
+       count 30
+       gravity 1
+       originjitter 1 1 1
+       sizeincrease -60
+       size 20 30
+       tex 38 38
+       velocityjitter 1900 1900 1300
+       velocitymultiplier 0.500000
 effect EF_MGTURRETTRAIL
-notunderwater
-trailspacing 10
-type smoke
-color 0xd0d0a0 0xffffff
-tex 0 8
-size 5 4
-alpha 128 196 768
-sizeincrease -8
-gravity -0.01
-// bubbles
+       type smoke
+       alpha 128 196 768
+       color 0xd0d0a0 0xffffff
+       gravity -0.010000
+       notunderwater
+       sizeincrease -8
+       size 5 4
+       tex 0 8
+       trailspacing 10
 effect EF_MGTURRETTRAIL
-underwater
-trailspacing 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-//fire_big
-//fire
-// used nowhere in code
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0x404040 0x808080
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 32
+       underwater
+       velocityjitter 16 16 16
 effect fire_big
-//notunderwater
-count 26
-type smoke
-tex 48 55
-size 11 31
-alpha 200 356 512
-gravity -0.5
-color 0x8f0d00 0xff5a00
-bounce 2
-sizeincrease -3
-originjitter 33 33 33
-velocityjitter 22 22 50
-// smoke
+       type smoke
+       alpha 200 356 512
+       bounce 2
+       color 0x8f0d00 0xff5a00
+       count 26
+       gravity -0.500000
+       originjitter 33 33 33
+       sizeincrease -3
+       size 11 31
+       tex 48 55
+       velocityjitter 22 22 50
 effect fire_big
-type alphastatic
-count 11
-tex 0 8
-size 22 33
-sizeincrease 11
-alpha 200 256 200
-color 0x000000 0x111111
-gravity -0.3
-originjitter 44 44 44
-velocityjitter 11 11 50
-bounce 2
-
-//red_flare
-//smoke
-// used nowhere in code
+       type alphastatic
+       alpha 200 256 200
+       bounce 2
+       color 0x000000 0x111111
+       count 11
+       gravity -0.300000
+       originjitter 44 44 44
+       sizeincrease 11
+       size 22 33
+       tex 0 8
+       velocityjitter 11 11 50
 effect red_flare
-type alphastatic
-count 10.5
-tex 0 8
-size 1 11
-sizeincrease 11
-alpha 200 256 160
-color 0xff0000 0xdc7171
-gravity -0.24
-originjitter 2 2 0
-velocityjitter 15 15 30
-bounce 1
-
-//blue_flare
-//smoke
-// used nowhere in code
+       type alphastatic
+       alpha 200 256 160
+       bounce 1
+       color 0xff0000 0xdc7171
+       count 10.500000
+       gravity -0.240000
+       originjitter 2 2 0
+       sizeincrease 11
+       size 1 11
+       tex 0 8
+       velocityjitter 15 15 30
 effect blue_flare
-type alphastatic
-count 10.5
-tex 0 8
-size 1 11
-sizeincrease 11
-alpha 200 256 160
-color 0x0000ff 0x7194dc
-gravity -0.24
-originjitter 2 2 0
-velocityjitter 15 15 30
-bounce 1
-
-//smoke_ring
-//smoke
-// used in qcsrc/server/ctf.qc:                pointparticles(particleeffectnum("smoke_ring"), 0.5 * (self.absmin + self.absmax), '0 0 0', 1);
+       type alphastatic
+       alpha 200 256 160
+       bounce 1
+       color 0x0000ff 0x7194dc
+       count 10.500000
+       gravity -0.240000
+       originjitter 2 2 0
+       sizeincrease 11
+       size 1 11
+       tex 0 8
+       velocityjitter 15 15 30
 effect smoke_ring
-type smoke
-count 45
-tex 0 8
-size 1 11
-sizeincrease 21
-gravity 0.1
-airfriction 3
-alpha 100 156 200
-color 0x111111 0x979797
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.1
-notunderwater
-
-//smoke_large
-//smoke
-// used nowhere in code
+       type smoke
+       airfriction 3
+       alpha 100 156 200
+       bounce 1.100000
+       color 0x111111 0x979797
+       count 45
+       gravity 0.100000
+       notunderwater
+       sizeincrease 21
+       size 1 11
+       tex 0 8
+       velocityjitter 190 190 50
 effect smoke_large
-type alphastatic
-count 25
-tex 0 8
-size 11 21
-sizeincrease 21
-gravity -0.15
-airfriction 7
-alpha 140 256 190
-color 0x9e895f 0xffd39b
-//originjitter 2 2 0
-velocityjitter 390 390 390
-bounce 1.1
-notunderwater
-
-//sparks
-// used nowhere in code
+       type alphastatic
+       airfriction 7
+       alpha 140 256 190
+       bounce 1.100000
+       color 0x9e895f 0xffd39b
+       count 25
+       gravity -0.150000
+       notunderwater
+       sizeincrease 21
+       size 11 21
+       tex 0 8
+       velocityjitter 390 390 390
 effect sparks
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 1 3
-alpha 0 256 256
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 200
-velocitymultiplier 1.5
-airfriction 3
-
-//sparks
-// used nowhere in code
+       type spark
+       airfriction 3
+       alpha 0 256 256
+       bounce 1.500000
+       color 0xFFFDD9 0xFFFDD9
+       count 15
+       gravity 1
+       originjitter 1 1 1
+       size 1 3
+       tex 40 40
+       velocityjitter 300 300 200
+       velocitymultiplier 1.500000
 effect electricity_sparks
-count 35
-type spark
-tex 40 40
-color 0x807aff 0x4463d5
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-//steam, it needs direction
-// used nowhere in code
+       type spark
+       airfriction 3
+       alpha 0 256 556
+       bounce 1.500000
+       color 0x807aff 0x4463d5
+       count 35
+       gravity 1
+       originjitter 1 1 1
+       size 1 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect steam
-type smoke
-count 1
-tex 0 8
-size 1 3
-sizeincrease 7
-gravity -0.25
-velocitymultiplier 14
-airfriction 5
-alpha 140 256 190
-color 0xfffbdf 0xffffff
-//originjitter 2 2 0
-velocityjitter 19 19 19
-bounce 1.1
-notunderwater
-
-// smoke emiter
-// used nowhere in code
+       type smoke
+       airfriction 5
+       alpha 140 256 190
+       bounce 1.100000
+       color 0xfffbdf 0xffffff
+       count 1
+       gravity -0.250000
+       notunderwater
+       sizeincrease 7
+       size 1 3
+       tex 0 8
+       velocityjitter 19 19 19
+       velocitymultiplier 14
 effect smoking
-count 10
-type alphastatic
-tex 0 8
-color 0x292929 0x000000
-size 10 40
-sizeincrease 5
-alpha 100 256 100
-gravity -0.1
-bounce 1.5
-originjitter 10 10 10
-velocityjitter 5 5 20
-//velocitymultiplier -20
-airfriction -1
-
-//golden dust (create it once per second to cover large area in small yellow particles)
-// used nowhere in code
+       type alphastatic
+       airfriction -1
+       alpha 100 256 100
+       bounce 1.500000
+       color 0x292929 0x000000
+       count 10
+       gravity -0.100000
+       originjitter 10 10 10
+       sizeincrease 5
+       size 10 40
+       tex 0 8
+       velocityjitter 5 5 20
 effect goldendust
-count 25
-type snow
-tex 38 38
-color 0xff9600 0xffefb8
-size 2 3
-sizeincrease -0.3
-alpha 256 256 70
-//gravity -0.1
-bounce 1.5
-originjitter 500 500 500
-velocityjitter 0.1 0.1 0.1
-//velocitymultiplier -20
-//airfriction -0.1
-
-// used nowhere in code
+       type snow
+       alpha 256 256 70
+       bounce 1.500000
+       color 0xff9600 0xffefb8
+       count 25
+       originjitter 500 500 500
+       sizeincrease -0.300000
+       size 2 3
+       tex 38 38
+       velocityjitter 0.1 0.1 0.1
 effect healing_fx
-count 25
-type spark
-tex 40 40
-color 0xff0000 0xff0000
-size 1 3
-sizeincrease -0.05
-alpha 256 256 170
-gravity -0.1
-bounce 1.5
-originjitter 5 5 100
-velocityjitter 50 50 0
-//velocitymultiplier 20
-airfriction -0.5
-
-// used nowhere in code
+       type spark
+       airfriction -0.500000
+       alpha 256 256 170
+       bounce 1.500000
+       color 0xff0000 0xff0000
+       count 25
+       gravity -0.100000
+       originjitter 5 5 100
+       sizeincrease -0.050000
+       size 1 3
+       tex 40 40
+       velocityjitter 50 50 0
 effect armorrepair_fx
-count 25
-type spark
-tex 40 40
-color 0x00ff00 0x00ff00
-size 1 3
-sizeincrease -0.05
-alpha 256 256 170
-gravity -0.1
-bounce 1.5
-originjitter 5 5 50
-velocityjitter 50 50 0
-//velocitymultiplier 20
-airfriction -0.5
-
-// used nowhere in code
+       type spark
+       airfriction -0.500000
+       alpha 256 256 170
+       bounce 1.500000
+       color 0x00ff00 0x00ff00
+       count 25
+       gravity -0.100000
+       originjitter 5 5 50
+       sizeincrease -0.050000
+       size 1 3
+       tex 40 40
+       velocityjitter 50 50 0
 effect ammoregen_fx
-count 25
-type spark
-tex 40 40
-color 0x0000ff 0x0000ff
-size 1 3
-sizeincrease -0.05
-alpha 256 256 170
-gravity -0.1
-bounce 1.5
-originjitter 5 5 50
-velocityjitter 50 50 0
-//velocitymultiplier 20
-airfriction -0.5
-
-// red-yellow flame like fx
-// used nowhere in code
+       type spark
+       airfriction -0.500000
+       alpha 256 256 170
+       bounce 1.500000
+       color 0x0000ff 0x0000ff
+       count 25
+       gravity -0.100000
+       originjitter 5 5 50
+       sizeincrease -0.050000
+       size 1 3
+       tex 40 40
+       velocityjitter 50 50 0
 effect rage
-count 2.5
-type smoke
-tex 35 36
-color 0xff0000 0xff7800
-size 1 3
-sizeincrease 10
-gravity -0.06
-alpha 256 256 190
-originjitter 5 5 5
-velocityjitter 25 25 25
-airfriction 2
-
-// pieces of glass or ice falling on the floor
-// used nowhere in code
+       type smoke
+       airfriction 2
+       alpha 256 256 190
+       color 0xff0000 0xff7800
+       count 2.500000
+       gravity -0.060000
+       originjitter 5 5 5
+       sizeincrease 10
+       size 1 3
+       tex 35 36
+       velocityjitter 25 25 25
 effect iceorglass
-count 15
-type alphastatic
-tex 44 44
-color 0xffffff 0xb2d3e6
-size 3 7
-//sizeincrease 10
-gravity 1.3
-alpha 256 256 0
-time 1 3
-bounce 2
-originjitter 30 30 30
-velocityjitter 100 100 100
-airfriction 3
-
-// cover small area in poison gas, spawn it once per second
-// used nowhere in code
+       type alphastatic
+       airfriction 3
+       alpha 256 256 0
+       bounce 2
+       color 0xffffff 0xb2d3e6
+       count 15
+       gravity 1.300000
+       originjitter 30 30 30
+       size 3 7
+       tex 44 44
+       time 1 3
+       velocityjitter 100 100 100
 effect poisonfield
-count 15
-type smoke
-tex 0 8
-color 0x00ff00 0x7db843
-size 1 1
-sizeincrease 30
- gravity -0.01
-alpha 256 256 50
-bounce 1.5
-originjitter 333 333 50
-velocityjitter 5 5 5
-airfriction 1
-
-// cover small area in icy mist, spawn it once per second
-// used nowhere in code
+       type smoke
+       airfriction 1
+       alpha 256 256 50
+       bounce 1.500000
+       color 0x00ff00 0x7db843
+       count 15
+       gravity -0.010000
+       originjitter 333 333 50
+       sizeincrease 30
+       size 1 1
+       tex 0 8
+       velocityjitter 5 5 5
 effect icefield
-count 10
-type smoke
-tex 0 8
-color 0x008aff 0x75e7ff
-size 1 1
-sizeincrease 10
- gravity -0.01
-alpha 256 256 50
-bounce 1.5
-originjitter 333 333 0
-velocityjitter 5 5 30
-airfriction 1
+       type smoke
+       airfriction 1
+       alpha 256 256 50
+       bounce 1.500000
+       color 0x008aff 0x75e7ff
+       count 10
+       gravity -0.010000
+       originjitter 333 333 0
+       sizeincrease 10
+       size 1 1
+       tex 0 8
+       velocityjitter 5 5 30
 effect icefield
-count 5
-type smoke
-tex 48 55
-size 1 1
-sizeincrease 10
-color 0x008aff 0x75e7ff
-alpha 256 256 50
-gravity -0.001
-originjitter 333 333 0
-
-
-// cover very small area in flames, spawn it 3 times per second (or more often to get better looking fire at cost of fps hit )
-// flames that go up
-// used nowhere in code
+       type smoke
+       alpha 256 256 50
+       color 0x008aff 0x75e7ff
+       count 5
+       gravity -0.001000
+       originjitter 333 333 0
+       sizeincrease 10
+       size 1 1
+       tex 48 55
 effect firefield
-count 100
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 20
- gravity -0.06
-alpha 50 256 200
-bounce 1.5
-originjitter 180 180 0
-velocityjitter 5 5 30
-airfriction 1
-//flames that stay on the ground
+       type smoke
+       airfriction 1
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 100
+       gravity -0.060000
+       originjitter 180 180 0
+       sizeincrease 20
+       size 1 1
+       tex 48 55
+       velocityjitter 5 5 30
 effect firefield
-count 50
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 40
-alpha 50 256 200
-originjitter 180 180 0
-// smoke
+       type smoke
+       alpha 50 256 200
+       color 0x8f0d00 0xff5a00
+       count 50
+       originjitter 180 180 0
+       sizeincrease 40
+       size 1 1
+       tex 48 55
 effect firefield
-count 20
-type alphastatic
-tex 0 8
-size 1 1
-sizeincrease 7
-color 0x000000 0x111111
-alpha 256 256 70
-gravity -0.02
-originjitter 180 180 0
-
-//flamethrower, spawn it as fast as you can  20 times per second or more, it needs direction
-//fast fire
-// used nowhere in code
+       type alphastatic
+       alpha 256 256 70
+       color 0x000000 0x111111
+       count 20
+       gravity -0.020000
+       originjitter 180 180 0
+       sizeincrease 7
+       size 1 1
+       tex 0 8
 effect flamethrower
-count 3
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
- gravity -0.06
-alpha 50 256 250
-bounce 1.5
-velocityjitter 40 40 11
-velocitymultiplier 30
-airfriction 1.2
-//slowfire
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 250
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 3
+       gravity -0.060000
+       sizeincrease 20
+       size 5 5
+       tex 48 55
+       velocityjitter 40 40 11
+       velocitymultiplier 30
 effect flamethrower
-count 2.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
- gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 40 40 40
-velocitymultiplier 20
-airfriction 1.2
-// very slow and small fire
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 2.500000
+       gravity -0.060000
+       sizeincrease 20
+       size 5 5
+       tex 48 55
+       velocityjitter 40 40 40
+       velocitymultiplier 20
 effect flamethrower
-count 1.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 10
- gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 30 30 30
-velocitymultiplier 10
-airfriction 0.3
-//decreasing fire
+       type smoke
+       airfriction 0.300000
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 1.500000
+       gravity -0.060000
+       sizeincrease 10
+       size 5 5
+       tex 48 55
+       velocityjitter 30 30 30
+       velocitymultiplier 10
 effect flamethrower
-count 2
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 30
-sizeincrease -10
- gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 10 10 10
-velocitymultiplier 15
-airfriction 0.3
-//smoke
+       type smoke
+       airfriction 0.300000
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 2
+       gravity -0.060000
+       sizeincrease -10
+       size 20 30
+       tex 48 55
+       velocityjitter 10 10 10
+       velocitymultiplier 15
 effect flamethrower
-count 0.5
-type alphastatic
-tex 0 8
-size 5 15
-sizeincrease 7
-color 0x000000 0x111111
-alpha 256 256 90
-//gravity -0.2
-originjitter 10 10 10
-velocitymultiplier 20
-velocityoffset 0 0 10
-airfriction 1
-
-// port-o-launch trail
-// glowing vapor trail
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_WIZSPIKE"), from, to)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_WIZSPIKE"), from, to)
+       type alphastatic
+       airfriction 1
+       alpha 256 256 90
+       color 0x000000 0x111111
+       count 0.500000
+       originjitter 10 10 10
+       sizeincrease 7
+       size 5 15
+       tex 0 8
+       velocitymultiplier 20
+       velocityoffset 0 0 10
 effect TR_WIZSPIKE
-trailspacing 4
-type static
-color 0x404040 0x404040
-size 3 3
-tex 62 62
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+       type static
+       alpha 256 256 968
+       color 0x404040 0x404040
+       lightcolor 1.5 3 6
+       lightradius 90
+       size 3 3
+       tex 62 62
+       trailspacing 4
+       velocitymultiplier -0.100000
 effect TR_WIZSPIKE
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0x404040 0x404040
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// TAG trail
-// glowing vapor trail
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_VORESPIKE"), from, to)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_VORESPIKE"), from, to)
+       type snow
+       airfriction 12
+       alpha 444 512 1866
+       bounce 1
+       color 0x404040 0x404040
+       count 1.500000
+       originjitter 1 1 1
+       sizeincrease -20
+       size 2 4
+       tex 42 42
+       trailspacing 12
+       velocityjitter 50 50 50
+       velocityoffset 0 0 15
 effect TR_VORESPIKE
-trailspacing 4
-type static
-color 0x804000 0x804000
-size 3 3
-tex 62 62
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+       type static
+       alpha 256 256 968
+       color 0x804000 0x804000
+       lightcolor 1.5 3 6
+       lightradius 90
+       size 3 3
+       tex 62 62
+       trailspacing 4
+       velocitymultiplier -0.100000
 effect TR_VORESPIKE
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xff8000 0xff8000
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// used in qcsrc/client/damage.qc:                                     pointparticles(particleeffectnum("flac_explode"), org2, '0 0 0', 1)
+       type snow
+       airfriction 12
+       alpha 444 512 1866
+       bounce 1
+       color 0xff8000 0xff8000
+       count 1.500000
+       originjitter 1 1 1
+       sizeincrease -20
+       size 2 4
+       tex 42 42
+       trailspacing 12
+       velocityjitter 50 50 50
+       velocityoffset 0 0 15
 effect flac_explode
-countabsolute 1
-type decal
-tex 8 16
-size 18 28
-alpha 256 256 0
-originjitter 40 40 40
-lightradius 150
-lightradiusfade 400
-lightcolor 8 4 1
-// fire effect which make bright dot inside
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 8 4 1
+       lightradiusfade 400
+       lightradius 150
+       originjitter 40 40 40
+       size 18 28
+       tex 8 16
 effect flac_explode
-notunderwater
-count 3
-type smoke
-tex 48 55
-color 0xffe955 0xff5a00
-size 6 16
-sizeincrease 5
-alpha 128 256 456
-bounce 1.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 156 156 156
-// fire effect which expands then slows
+       type smoke
+       airfriction 8
+       alpha 128 256 456
+       bounce 1.500000
+       color 0xffe955 0xff5a00
+       count 3
+       liquidfriction 8
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 5
+       size 6 16
+       tex 48 55
+       velocityjitter 156 156 156
 effect flac_explode
-notunderwater
-count 6
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 10 16
-sizeincrease 15
-alpha 128 256 456
-bounce 1.5
-airfriction 12
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 256 256 256
-
-// smoke
+       type static
+       airfriction 12
+       alpha 128 256 456
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 6
+       liquidfriction 8
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 15
+       size 10 16
+       tex 48 55
+       velocityjitter 256 256 256
 effect flac_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 5
-size 10 20
-sizeincrease 20
-alpha 500 600 556
-velocityjitter 244 244 244
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-
-// underwater bubbles
+       type alphastatic
+       airfriction 5
+       alpha 500 600 556
+       bounce 2
+       color 0x000000 0x111111
+       count 5
+       notunderwater
+       sizeincrease 20
+       size 10 20
+       tex 0 8
+       velocityjitter 244 244 244
 effect flac_explode
-underwater
-count 8
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 2
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 8
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 1 2
+       tex 62 62
+       underwater
+       velocityjitter 96 96 96
 effect flac_explode
-notunderwater
-count 4
-type spark
-color 0x903010 0xFFD030
-size 2 2
-tex 40 40
-alpha 256 256 384
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 256 256 256
-
-
-// bullet trail (somewhat like a tracer)
-// used in qcsrc/server/w_common.qc:                           zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("tr_bullet"), from, to)
+       type spark
+       airfriction 0.200000
+       alpha 256 256 384
+       bounce 1.500000
+       color 0x903010 0xFFD030
+       count 4
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       size 2 2
+       tex 40 40
+       velocityjitter 256 256 256
+       velocityoffset 0 0 80
 effect tr_bullet
-trailspacing 750
-type spark
-tex 70 70
-color 0xff8960 0xff8533
-alpha 256 256 2560
-size 4 4
-stretchfactor 0.2
-velocitymultiplier 3
-
-// smoke emitter for small pipes
-// used nowhere in code
+       type spark
+       alpha 256 256 2560
+       color 0xff8960 0xff8533
+       size 4 4
+       stretchfactor 0.200000
+       tex 70 70
+       trailspacing 750
+       velocitymultiplier 3
 effect smoking_smallemitter
-count 10
-type alphastatic
-tex 0 8
-color 0x292929 0x000000
-size 6 15
-sizeincrease 20
-alpha 200 256 100
-gravity -0.1
-bounce 0
-originjitter 10 10 10
-velocityjitter 5 5 20
-//velocitymultiplier -20
-airfriction -1
-
-// crylink trail
-// plasma smoke
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_CRYLINKPLASMA"), from, to)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("TR_CRYLINKPLASMA"), from, to)
+       type alphastatic
+       airfriction -1
+       alpha 200 256 100
+       color 0x292929 0x000000
+       count 10
+       gravity -0.100000
+       originjitter 10 10 10
+       sizeincrease 20
+       size 6 15
+       tex 0 8
+       velocityjitter 5 5 20
 effect TR_CRYLINKPLASMA
-trailspacing 128
-type static
-color 0x5522aa 0x6622ff
-size 2 2
-sizeincrease 8
-tex 32 32
-alpha 256 256 1024
-velocityjitter 8 8 8
-//lightradius 90
-//lighttime 0
-//lightcolor 1 0 1
-velocitymultiplier -0.01
-// crylink main trail
+       type static
+       alpha 256 256 1024
+       color 0x5522aa 0x6622ff
+       sizeincrease 8
+       size 2 2
+       tex 32 32
+       trailspacing 128
+       velocityjitter 8 8 8
+       velocitymultiplier -0.010000
 effect TR_CRYLINKPLASMA
-trailspacing 16
-type static
-color 0x5522aa 0x6622ff
-size 3 3
-sizeincrease 15
-tex 3 3
-alpha 256 256 2600
-velocityjitter 2 2 2
-velocitymultiplier 0.01
-
+       type static
+       alpha 256 256 2600
+       color 0x5522aa 0x6622ff
+       sizeincrease 15
+       size 3 3
+       tex 3 3
+       trailspacing 16
+       velocityjitter 2 2 2
+       velocitymultiplier 0.010000
 effect cherryblossom
-count 1.5
-type static
-color 0xb123ff 0xb183ff
-size 1.5 2
-alpha 128 256 32
-gravity 0.05
-bounce 1.5
-airfriction 1
-liquidfriction 1
-originjitter 16 16 16
-velocityjitter 32 32 0
-tex 40 40
-//lightradius 200
-//lighttime 0
-
+       type static
+       airfriction 1
+       alpha 128 256 32
+       bounce 1.500000
+       color 0xb123ff 0xb183ff
+       count 1.500000
+       gravity 0.050000
+       liquidfriction 1
+       originjitter 16 16 16
+       size 1.500000 2
+       tex 40 40
+       velocityjitter 32 32 0
 effect alien_blood
-count 0.4
-type spark
-blend invmod
-tex 24 32
-size 5 11
-alpha 1560 2560 7000
-color 0xDC9BCD 0xDC9BCD
-bounce -1
-airfriction 0.4
-velocityjitter 99 99 55
-//velocitymultiplier 2
-staincolor 0xDC9BCD 0xDC9BCD
-staintex 16 24
-stainsize 1 2
-stretchfactor 25
-sizeincrease 20
-//blood mist
+       type spark
+       airfriction 0.400000
+       alpha 1560 2560 7000
+       blend invmod
+       bounce -1
+       color 0xDC9BCD 0xDC9BCD
+       count 0.400000
+       sizeincrease 20
+       size 5 11
+       staincolor 0xDC9BCD 0xDC9BCD
+       stainsize 1 2
+       staintex 16 24
+       stretchfactor 25
+       tex 24 32
+       velocityjitter 99 99 55
 effect alien_blood
-countabsolute 1
-type smoke
-blend invmod
-tex 24 32
-size 25 30
-sizeincrease 20
-alpha 3000 5560 12000
-color 0xDC9BCD 0xDC9BCD
-originjitter 11 11 11
-
+       type smoke
+       alpha 3000 5560 12000
+       blend invmod
+       color 0xDC9BCD 0xDC9BCD
+       countabsolute 1
+       originjitter 11 11 11
+       sizeincrease 20
+       size 25 30
+       tex 24 32
 effect robot_blood
-count 0.167
-type spark
-tex 70 70
-size 1 2
-alpha 256 256 64
-color 0xff3000 0xff7373
-bounce -1
-gravity 1
-airfriction 1
-liquidfriction 4
-velocityjitter 264 264 264
-velocityoffset 0 0 100
-//shockwave
+       type spark
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xff3000 0xff7373
+       count 0.167000
+       gravity 1
+       liquidfriction 4
+       size 1 2
+       tex 70 70
+       velocityjitter 264 264 264
+       velocityoffset 0 0 100
 effect robot_blood
-countabsolute 1
-type smoke
-tex 74 74
-size 2 2
-alpha 0 90 1000
-color 0xff8400 0xffbb72
-originjitter 11 11 11
-sizeincrease 800
-// electo sparcks
+       type smoke
+       alpha 0 90 1000
+       color 0xff8400 0xffbb72
+       countabsolute 1
+       originjitter 11 11 11
+       sizeincrease 800
+       size 2 2
+       tex 74 74
 effect robot_blood
-count 0.1
-type smoke
-tex 71 73
-size 20 40
-alpha 256 256 5120
-color 0xff3000 0xff8585
-originjitter 41 41 21
-rotate -180 180 4000 -4000
-
-
-
+       type smoke
+       alpha 256 256 5120
+       color 0xff3000 0xff8585
+       count 0.100000
+       originjitter 41 41 21
+       rotate -180 180 4000 -4000
+       size 20 40
+       tex 71 73
 effect alien_TR_BLOOD
-trailspacing 20
-type spark
-blend invmod
-color 0xC080B0 0xC080B0
-tex 24 32
-size 4 19
-alpha 384 984 1492
-bounce -1
-gravity 0.4
-airfriction -2
-liquidfriction 1
-velocityjitter 64 64 64
-velocitymultiplier -0.1
-staincolor 0xC080B0 0xC080B0
-staintex 16 24
-stainsize 1 2
-stretchfactor 7
-sizeincrease -5
-// splash around gib
-effect TR_BLOOD
-trailspacing 42
-type blood
-color 0xA8FFFF 0xA8FFFF
-tex 24 32
-size 4 6
-alpha 684 684 7492
-sizeincrease 500
-
+       type spark
+       airfriction -2
+       alpha 384 984 1492
+       blend invmod
+       bounce -1
+       color 0xC080B0 0xC080B0
+       gravity 0.400000
+       liquidfriction 1
+       sizeincrease -5
+       size 4 19
+       staincolor 0xC080B0 0xC080B0
+       stainsize 1 2
+       staintex 16 24
+       stretchfactor 7
+       tex 24 32
+       trailspacing 20
+       velocityjitter 64 64 64
+       velocitymultiplier -0.100000
 effect robot_TR_BLOOD
-trailspacing 16
-type spark
-blend invmod
-color 0xC0D890 0xC0D890
-tex 24 32
-size 4 13
-alpha 384 984 1892
-bounce -1
-gravity 0.4
-airfriction -2
-liquidfriction 1
-velocityjitter 64 64 64
-velocitymultiplier -0.3
-staincolor 0x808080 0x808080
-staintex 16 24
-stainsize 1 3
-stretchfactor 6
-sizeincrease -6
-// fire
+       type spark
+       airfriction -2
+       alpha 384 984 1892
+       blend invmod
+       bounce -1
+       color 0xC0D890 0xC0D890
+       gravity 0.400000
+       liquidfriction 1
+       sizeincrease -6
+       size 4 13
+       staincolor 0x808080 0x808080
+       stainsize 1 3
+       staintex 16 24
+       stretchfactor 6
+       tex 24 32
+       trailspacing 16
+       velocityjitter 64 64 64
+       velocitymultiplier -0.300000
 effect robot_TR_BLOOD
-notunderwater
-trailspacing 16
-type spark
-tex 48 55
-color 0x902010 0xff3600
-size 5 20
-alpha 128 256 900
-gravity -1
-airfriction 4
-liquidfriction 4
-stretchfactor 5
-sizeincrease 10
-velocityjitter 44 44 44
-// arcs
+       type spark
+       airfriction 4
+       alpha 128 256 900
+       color 0x902010 0xff3600
+       gravity -1
+       liquidfriction 4
+       notunderwater
+       sizeincrease 10
+       size 5 20
+       stretchfactor 5
+       tex 48 55
+       trailspacing 16
+       velocityjitter 44 44 44
 effect robot_TR_BLOOD
-trailspacing 128
-type smoke
-tex 71 73
-color 0xff3000 0xff8585
-size 25 30
-alpha 1128 1256 44900
-rotate -180 180 4000 -4000
-velocityjitter 44 44 44
-
-
+       type smoke
+       alpha 1128 1256 44900
+       color 0xff3000 0xff8585
+       rotate -180 180 4000 -4000
+       size 25 30
+       tex 71 73
+       trailspacing 128
+       velocityjitter 44 44 44
 effect alien_TR_SLIGHTBLOOD
-trailspacing 64
-type blood
-color 0xC080B0 0xC080B0
-tex 24 32
-size 80 80
-alpha 384 384 192
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 0.5
-staincolor 0x808080 0x808080
-staintex 16 24
-
+       type blood
+       airfriction 1
+       alpha 384 384 192
+       bounce -1
+       color 0xC080B0 0xC080B0
+       liquidfriction 4
+       size 80 80
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       trailspacing 64
+       velocityjitter 64 64 64
+       velocitymultiplier 0.500000
 effect robot_TR_SLIGHTBLOOD
-trailspacing 64
-type blood
-color 0xC0D890 0xC0D890
-tex 24 32
-size 8 8
-alpha 384 384 192
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 0.5
-staincolor 0x808080 0x808080
-staintex 16 24
-
-// flare particle and light
-// used in qcsrc/server/t_items.qc:    pointparticles(particleeffectnum("item_pickup"), self.origin, '0 0 0', 1)
+       type blood
+       airfriction 1
+       alpha 384 384 192
+       bounce -1
+       color 0xC0D890 0xC0D890
+       liquidfriction 4
+       size 8 8
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       trailspacing 64
+       velocityjitter 64 64 64
+       velocitymultiplier 0.500000
 effect item_pickup
-countabsolute 1
-type static
-color 0x63F2EA 0xB0C5C4
-size 8 16
-alpha 128 64 64
-// cloud of particles which expand rapidly and then slow to form a ball
+       type static
+       alpha 128 64 64
+       color 0x63F2EA 0xB0C5C4
+       countabsolute 1
+       size 8 16
 effect item_pickup
-count 32
-type spark
-tex 41 41
-color 0x63F2EA 0xB0C5C4
-size 1 1
-alpha 256 256 1280
-//originjitter 24 24 24
-velocityjitter 256 256 256
-
+       type spark
+       alpha 256 256 1280
+       color 0x63F2EA 0xB0C5C4
+       count 32
+       size 1 1
+       tex 41 41
+       velocityjitter 256 256 256
 effect bloodshower
-count 125
-type spark
-blend invmod
-tex 24 32
-size 8 28
-color 0xA8FFFF 0xA8FFFFF
-alpha 156 656 1664
-bounce -1
-gravity 1
-stretchfactor 3
-liquidfriction 4
-velocityjitter 764 764 764
-// velocitymultiplier 1
-staincolor 0x808080 0x808080
-staintex 16 24
-stainsize 1 2
-// center blood
+       type spark
+       alpha 156 656 1664
+       blend invmod
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 125
+       gravity 1
+       liquidfriction 4
+       size 8 28
+       staincolor 0x808080 0x808080
+       stainsize 1 2
+       staintex 16 24
+       stretchfactor 3
+       tex 24 32
+       velocityjitter 764 764 764
 effect bloodshower
-countabsolute 0.1
-type smoke
-blend invmod
-tex 24 32
-size 1 28
-sizeincrease 300
-originjitter 50 50 50
-color 0xA8FFFF 0xA8FFFFF
-alpha 156 656 1664
-
-effect alien_bloodshower
-count 125
-type spark
-blend invmod
-tex 24 32
-size 8 28
-color 0xC080B0 0xC080B0
-alpha 156 656 1664
-bounce -1
-gravity 1
-stretchfactor 3
-liquidfriction 4
-velocityjitter 764 764 764
-// velocitymultiplier 1
-staincolor 0xC080B0 0xC080B0
-staintex 16 24
-stainsize 1 2
-// center blood
+       type smoke
+       alpha 156 656 1664
+       blend invmod
+       color 0xA8FFFF 0xA8FFFFF
+       countabsolute 0.100000
+       originjitter 50 50 50
+       sizeincrease 300
+       size 1 28
+       tex 24 32
 effect bloodshower
-countabsolute 0.1
-type smoke
-blend invmod
-tex 24 32
-size 1 28
-sizeincrease 300
-originjitter 50 50 50
-color 0xA8FFFF 0xA8FFFFF
-alpha 156 656 1664
-
-
+       type smoke
+       alpha 156 656 1664
+       blend invmod
+       color 0xA8FFFF 0xA8FFFFF
+       countabsolute 0.100000
+       originjitter 50 50 50
+       sizeincrease 300
+       size 1 28
+       tex 24 32
+effect alien_bloodshower
+       type spark
+       alpha 156 656 1664
+       blend invmod
+       bounce -1
+       color 0xC080B0 0xC080B0
+       count 125
+       gravity 1
+       liquidfriction 4
+       size 8 28
+       staincolor 0xC080B0 0xC080B0
+       stainsize 1 2
+       staintex 16 24
+       stretchfactor 3
+       tex 24 32
+       velocityjitter 764 764 764
 effect robot_bloodshower
-count 100
-type spark
-blend invmod
-tex 24 32
-size 8 28
-color 0xC0D890 0xC0D890
-alpha 156 656 1664
-bounce -1
-gravity 1
-stretchfactor 3
-liquidfriction 4
-velocityjitter 764 764 764
-// velocitymultiplier 1
-staincolor 0xC0D890 0xC0D890
-staintex 16 24
-stainsize 1 2
-// arc
+       type spark
+       alpha 156 656 1664
+       blend invmod
+       bounce -1
+       color 0xC0D890 0xC0D890
+       count 100
+       gravity 1
+       liquidfriction 4
+       size 8 28
+       staincolor 0xC0D890 0xC0D890
+       stainsize 1 2
+       staintex 16 24
+       stretchfactor 3
+       tex 24 32
+       velocityjitter 764 764 764
 effect robot_bloodshower
-count 2.5
-type smoke
-tex 71 73
-color 0xff3000 0xff8585
-size 25 40
-alpha 1128 1256 4200
-rotate -180 180 99 -99
-velocityjitter 44 44 44
-originjitter 150 150 150
-// shockwave
+       type smoke
+       alpha 1128 1256 4200
+       color 0xff3000 0xff8585
+       count 2.500000
+       originjitter 150 150 150
+       rotate -180 180 99 -99
+       size 25 40
+       tex 71 73
+       velocityjitter 44 44 44
 effect robot_bloodshower
-count 2.5
-type smoke
-tex 74 74
-color 0xff3000 0xff8585
-size 5 50
-sizeincrease 3000
-alpha 11 125 990
-
-//red_ground_quake
-//smoke
-// used in qsrc/server/ctf.qc:         pointparticles(particleeffectnum("red_ground_quake"), self.origin, '0 0 0', 1);
+       type smoke
+       alpha 11 125 990
+       color 0xff3000 0xff8585
+       count 2.500000
+       sizeincrease 3000
+       size 5 50
+       tex 74 74
 effect red_ground_quake
-type smoke
-count 90
-tex 0 8
-size 20 50
-sizeincrease 100
-gravity 0.5
-time 5 10
-airfriction 3
-alpha 100 126 200
-color 0x111111 0xbbbbbb
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.1
-notunderwater
+       type smoke
+       airfriction 3
+       alpha 100 126 200
+       bounce 1.100000
+       color 0x111111 0xbbbbbb
+       count 90
+       gravity 0.500000
+       notunderwater
+       sizeincrease 100
+       size 20 50
+       tex 0 8
+       time 5 10
+       velocityjitter 190 190 50
 effect red_ground_quake
-type smoke
-count 40
-tex 0 8
-size 10 30
-sizeincrease 60
-gravity 0.2
-time 10 15
-airfriction 4
-alpha 100 126 200
-color 0x111111 0x979797
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.2
-notunderwater
+       type smoke
+       airfriction 4
+       alpha 100 126 200
+       bounce 1.200000
+       color 0x111111 0x979797
+       count 40
+       gravity 0.200000
+       notunderwater
+       sizeincrease 60
+       size 10 30
+       tex 0 8
+       time 10 15
+       velocityjitter 190 190 50
 effect red_ground_quake
-//notunderwater
-count 16
-type smoke
-tex 48 55
-size 4 20
-time 15 25
-alpha 200 356 512
-gravity -0.5
-color 0x9E6A64 0x91302D
-bounce 6
-sizeincrease 5
-originjitter 33 33 33
-velocityjitter 22 22 50
-// smoke
+       type smoke
+       alpha 200 356 512
+       bounce 6
+       color 0x9E6A64 0x91302D
+       count 16
+       gravity -0.500000
+       originjitter 33 33 33
+       sizeincrease 5
+       size 4 20
+       tex 48 55
+       time 15 25
+       velocityjitter 22 22 50
 effect red_ground_quake
-type alphastatic
-count 11
-tex 0 8
-size 22 33
-sizeincrease 11
-time 25 35
-alpha 200 256 200
-color 0x000000 0xffffff
-gravity -0.3
-originjitter 44 44 44
-velocityjitter 11 11 50
-bounce 2
-
-//blue_ground_quake
-//smoke
-// used in qsrc/server/ctf.qc:         pointparticles(particleeffectnum("blue_ground_quake"), self.origin, '0 0 0', 1);
+       type alphastatic
+       alpha 200 256 200
+       bounce 2
+       color 0x000000 0xffffff
+       count 11
+       gravity -0.300000
+       originjitter 44 44 44
+       sizeincrease 11
+       size 22 33
+       tex 0 8
+       time 25 35
+       velocityjitter 11 11 50
 effect blue_ground_quake
-type smoke
-count 90
-tex 0 8
-size 20 50
-sizeincrease 100
-gravity 0.5
-time 5 10
-airfriction 3
-alpha 100 126 200
-color 0x111111 0xbbbbbb
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.1
-notunderwater
+       type smoke
+       airfriction 3
+       alpha 100 126 200
+       bounce 1.100000
+       color 0x111111 0xbbbbbb
+       count 90
+       gravity 0.500000
+       notunderwater
+       sizeincrease 100
+       size 20 50
+       tex 0 8
+       time 5 10
+       velocityjitter 190 190 50
 effect blue_ground_quake
-type smoke
-count 40
-tex 0 8
-size 10 30
-sizeincrease 60
-gravity 0.2
-time 10 15
-airfriction 4
-alpha 100 126 200
-color 0x111111 0x979797
-//originjitter 2 2 0
-velocityjitter 190 190 50
-bounce 1.2
-notunderwater
+       type smoke
+       airfriction 4
+       alpha 100 126 200
+       bounce 1.200000
+       color 0x111111 0x979797
+       count 40
+       gravity 0.200000
+       notunderwater
+       sizeincrease 60
+       size 10 30
+       tex 0 8
+       time 10 15
+       velocityjitter 190 190 50
 effect blue_ground_quake
-//notunderwater
-count 16
-type smoke
-tex 48 55
-size 4 20
-time 15 25
-alpha 200 356 512
-gravity -0.5
-color 0x64679E 0x2D4C91
-bounce 6
-sizeincrease 5
-originjitter 33 33 33
-velocityjitter 22 22 50
-// smoke
+       type smoke
+       alpha 200 356 512
+       bounce 6
+       color 0x64679E 0x2D4C91
+       count 16
+       gravity -0.500000
+       originjitter 33 33 33
+       sizeincrease 5
+       size 4 20
+       tex 48 55
+       time 15 25
+       velocityjitter 22 22 50
 effect blue_ground_quake
-type alphastatic
-count 11
-tex 0 8
-size 22 33
-sizeincrease 11
-time 25 35
-alpha 200 256 200
-color 0x000000 0xffffff
-gravity -0.3
-originjitter 44 44 44
-velocityjitter 11 11 50
-bounce 2
-
-
-
-// cl_gentle impact effect indicating damage
-// maintained by morphed
-// used in qcsrc/client/gibs.qc:                       pointparticles(particleeffectnum("damage_hit"), org, vel, amount * 16)
+       type alphastatic
+       alpha 200 256 200
+       bounce 2
+       color 0x000000 0xffffff
+       count 11
+       gravity -0.300000
+       originjitter 44 44 44
+       sizeincrease 11
+       size 22 33
+       tex 0 8
+       time 25 35
+       velocityjitter 11 11 50
 effect morphed_damage_hit
-tex 43 43
-count 0.5
-type spark
-color 0xffffff 0x9271fb
-size 14 24
-sizeincrease -24
-alpha 128 128 292
-gravity -0.4
-airfriction 5
-liquidfriction 10
-velocityjitter 356 356 456
-
+       type spark
+       airfriction 5
+       alpha 128 128 292
+       color 0xffffff 0x9271fb
+       count 0.500000
+       gravity -0.400000
+       liquidfriction 10
+       sizeincrease -24
+       size 14 24
+       tex 43 43
+       velocityjitter 356 356 456
 effect morphed_damage_hit
-tex 0 8
-count 0.5
-type smoke
-color 0xffffff 0x9271fb
-size 24 24
-sizeincrease -24
-alpha 128 128 292
-airfriction 5
-liquidfriction 10
-originjitter 10 10 10
-
-
-// effect for removing player model
-// "teleport"
-
-// cl_gentle deathfx
-// used in qcsrc/client/gibs.qc:                       pointparticles(particleeffectnum("damage_dissolve"), org, vel, amount)
+       type smoke
+       airfriction 5
+       alpha 128 128 292
+       color 0xffffff 0x9271fb
+       count 0.500000
+       liquidfriction 10
+       originjitter 10 10 10
+       sizeincrease -24
+       size 24 24
+       tex 0 8
 effect morphed_damage_dissolve
-tex 43 43
-count 10
-type smoke
-color 0xffffff 0x9271fb
-size 40 40
-sizeincrease -16
-alpha 456 456 1828
-gravity -1.9
-airfriction 8
-liquidfriction 6
-velocityjitter 256 256 512
-rotate -180 180 -399 -99
-
+       type smoke
+       airfriction 8
+       alpha 456 456 1828
+       color 0xffffff 0x9271fb
+       count 10
+       gravity -1.900000
+       liquidfriction 6
+       rotate -180 180 -399 -99
+       sizeincrease -16
+       size 40 40
+       tex 43 43
+       velocityjitter 256 256 512
 effect morphed_damage_dissolve
-tex 43 43
-count 2.5
-type smoke
-color 0x7bdbff 0xbed2ff
-size 40 40
-sizeincrease -16
-alpha 256 256 628
-gravity -0.8
-airfriction 9
-liquidfriction 6
-velocityjitter 256 256 512
-rotate -180 180 0 0
-
+       type smoke
+       airfriction 9
+       alpha 256 256 628
+       color 0x7bdbff 0xbed2ff
+       count 2.500000
+       gravity -0.800000
+       liquidfriction 6
+       rotate -180 180 0 0
+       sizeincrease -16
+       size 40 40
+       tex 43 43
+       velocityjitter 256 256 512
 effect morphed_damage_dissolve
-tex 65 65
-count 5
-type smoke
-color 0xffffff 0x9271fb
-size 44 44
-sizeincrease -16
-alpha 156 156 128
-airfriction 3
-liquidfriction 6
-originjitter 22 22 76
-
+       type smoke
+       airfriction 3
+       alpha 156 156 128
+       color 0xffffff 0x9271fb
+       count 5
+       liquidfriction 6
+       originjitter 22 22 76
+       sizeincrease -16
+       size 44 44
+       tex 65 65
 effect morphed_damage_dissolve
-tex 46 46
-count 15
-type smoke
-color 0xffffff 0x9271fb
-size 32 32
-sizeincrease -16
-alpha 56 56 128
-gravity 1
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 400 400 0
-rotate -180 180 999 -999
-
-// Team / hit minsta effects
+       type smoke
+       airfriction 3
+       alpha 56 56 128
+       bounce 1.500000
+       color 0xffffff 0x9271fb
+       count 15
+       gravity 1
+       liquidfriction 6
+       rotate -180 180 999 -999
+       sizeincrease -16
+       size 32 32
+       tex 46 46
+       velocityjitter 400 400 0
 effect TE_TEI_G3RED
-countabsolute 1
-type beam
-tex 200 200
-color 0xFF0000 0xFF0000
-size 4 4
-alpha 128 128 256
-// experimental
+       type beam
+       alpha 128 128 256
+       color 0xFF0000 0xFF0011
+       countabsolute 1
+       size 4 4
+       tex 200 200
 effect TE_TEI_G3RED
-trailspacing 8
-type static
-color 0x200000 0x400000
-size 0.3 0.3
-sizeincrease 3
-tex 46 46
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 3 3 3
-type smoke
-
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0x200000 0x400000
+       sizeincrease 3
+       size 0.300000 0.300000
+       tex 46 46
+       trailspacing 8
+       velocityjitter 3 3 3
 effect TE_TEI_G3RED_HIT
-countabsolute 1
-type beam
-tex 200 200
-color 0xFF0000 0xFF0000
-size 8 8
-alpha 128 128 256
-// experimental
+       type beam
+       alpha 128 128 256
+       color 0xFF0000 0xFF0011
+       countabsolute 1
+       size 8 8
+       tex 200 200
 effect TE_TEI_G3RED_HIT
-trailspacing 20
-type static
-color 0xFFFFFF 0xFF0011
-size 2 2
-sizeincrease -2
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 2 2 2
-type smoke
-// rings
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFFFFFF 0xFF0011
+       sizeincrease -2
+       size 2 2
+       trailspacing 20
+       velocityjitter 2 2 2
 effect TE_TEI_G3RED_HIT
-trailspacing 40
-type static
-color 0xFF0000 0xFF0011
-size 10 10 
-sizeincrease -6
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-type smoke
-
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFF0000 0xFF0011
+       sizeincrease -6
+       size 10 10
+       trailspacing 40
 effect TE_TEI_G3BLUE
-countabsolute 1
-type beam
-tex 200 200
-color 0x0000FF 0x1100FF
-size 4 4
-alpha 128 128 256
-// experimental
+       type beam
+       alpha 128 128 256
+       color 0x0000FF 0x1100FF
+       countabsolute 1
+       size 4 4
+       tex 200 200
 effect TE_TEI_G3BLUE
-trailspacing 8
-type static
-color 0x000020 0x000040
-size 0.3 0.3
-sizeincrease 3
-tex 46 46
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 3 3 3
-type smoke
-
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0x000020 0x000040
+       sizeincrease 3
+       size 0.300000 0.300000
+       tex 46 46
+       trailspacing 8
+       velocityjitter 3 3 3
 effect TE_TEI_G3BLUE_HIT
-countabsolute 1
-type beam
-tex 200 200
-color 0x0000FF 0x1100FF
-size 8 8
-alpha 128 128 256
-// experimental
+       type beam
+       alpha 128 128 256
+       color 0x0000FF 0x1100FF
+       countabsolute 1
+       size 8 8
+       tex 200 200
 effect TE_TEI_G3BLUE_HIT
-trailspacing 20
-type static
-color 0xFFFFFF 0x100FF
-size 2 2
-sizeincrease -2
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 2 2 2
-type smoke
-// rings
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFFFFFF 0x1100FF
+       sizeincrease -2
+       size 2 2
+       trailspacing 20
+       velocityjitter 2 2 2
 effect TE_TEI_G3BLUE_HIT
-trailspacing 40
-type static
-color 0x0000FF 0x1100FF
-size 10 10 
-sizeincrease -6
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-type smoke
-
-// Yellow 
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0x0000FF 0x1100FF
+       sizeincrease -6
+       size 10 10
+       trailspacing 40
 effect TE_TEI_G3YELLOW
-countabsolute 1
-type beam
-tex 200 200
-color 0xffff00 0xffff11
-size 4 4
-alpha 128 128 256
+       type beam
+       alpha 128 128 256
+       color 0xffff00 0xffff11
+       countabsolute 1
+       size 4 4
+       tex 200 200
 effect TE_TEI_G3YELLOW
-trailspacing 8
-type static
-color 0x202000 0x404000
-size 0.3 0.3
-sizeincrease 3
-tex 46 46
-alpha 256 256 512
-airfriction -4
-velocityjitter 3 3 3
-type smoke
-
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0x202000 0x404000
+       sizeincrease 3
+       size 0.300000 0.300000
+       tex 46 46
+       trailspacing 8
+       velocityjitter 3 3 3
 effect TE_TEI_G3YELLOW_HIT
-countabsolute 1
-type beam
-tex 200 200
-color 0xffff00 0xffff11
-size 8 8
-alpha 128 128 256
+       type beam
+       alpha 128 128 256
+       color 0xffff00 0xffff11
+       countabsolute 1
+       size 8 8
+       tex 200 200
 effect TE_TEI_G3YELLOW_HIT
-trailspacing 20
-type static
-color 0xFFFFFF 0xffff10
-size 2 2
-sizeincrease -2
-alpha 256 256 512
-airfriction -4
-velocityjitter 2 2 2
-type smoke
-// rings
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFFFFFF 0xffff11
+       sizeincrease -2
+       size 2 2
+       trailspacing 20
+       velocityjitter 2 2 2
 effect TE_TEI_G3YELLOW_HIT
-trailspacing 40
-type static
-color 0xffff00 0xffff11
-size 10 10 
-sizeincrease -6
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-type smoke
-
-
-// Pink
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xffff00 0xffff11
+       sizeincrease -6
+       size 10 10
+       trailspacing 40
 effect TE_TEI_G3PINK
-countabsolute 1
-type beam
-tex 200 200
-color 0xFF00FF 0xFF11FF
-size 4 4
-alpha 128 128 256
-// experimental
+       type beam
+       alpha 128 128 256
+       color 0xFF00FF 0xFF11FF
+       countabsolute 1
+       size 4 4
+       tex 200 200
 effect TE_TEI_G3PINK
-trailspacing 8
-type static
-color 0x200020 0x400040
-size 0.3 0.3
-sizeincrease 3
-tex 46 46
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 3 3 3
-type smoke
-
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0x200020 0x400040
+       sizeincrease 3
+       size 0.300000 0.300000
+       tex 46 46
+       trailspacing 8
+       velocityjitter 3 3 3
 effect TE_TEI_G3PINK_HIT
-countabsolute 1
-type beam
-tex 200 200
-color 0xFF00FF 0xFF11FF
-size 8 8
-alpha 128 128 256
-// experimental
+       type beam
+       alpha 128 128 256
+       color 0xFF00FF 0xFF11FF
+       countabsolute 1
+       size 8 8
+       tex 200 200
 effect TE_TEI_G3PINK_HIT
-trailspacing 20
-type static
-color 0xFFFFFF 0xFF10FF
-size 2 2
-sizeincrease -2
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-velocityjitter 2 2 2
-type smoke
-// rings
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFFFFFF 0xFF11FF
+       sizeincrease -2
+       size 2 2
+       trailspacing 20
+       velocityjitter 2 2 2
 effect TE_TEI_G3PINK_HIT
-trailspacing 40
-type static
-color 0xFF00FF 0xFF11FF
-size 10 10 
-sizeincrease -6
-alpha 256 256 512
-airfriction -4
-//liquidfriction -4
-type smoke
-
-
-
-
-// cl_gentle impact effect indicating damage
-// maintained by particlegibs
-// used in qcsrc/client/gibs.qc:                        pointparticles(particleeffectnum("damage_hit"), org, vel, amount * 16)
-// core decal
+       type smoke
+       airfriction -4
+       alpha 256 256 512
+       color 0xFF00FF 0xFF11FF
+       sizeincrease -6
+       size 10 10
+       trailspacing 40
 effect particlegibs_damage_hit
-type blood
-count 0.5
-tex 0 8
-size 5 10
-color 0xA8FFFF 0xA8FFFFF
-alpha 256 256 428
-gravity 1
-bounce -1
-airfriction 3
-liquidfriction 6
-velocityjitter 156 156 212
-staincolor 0x808080 0x808080
-staintex 16 24
-// front blood
+       type blood
+       airfriction 3
+       alpha 256 256 428
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 0.500000
+       gravity 1
+       liquidfriction 6
+       size 5 10
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 0 8
+       velocityjitter 156 156 212
 effect particlegibs_damage_hit
-type blood
-count 0.1
-tex 24 32
-size 10 20
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease -15
-alpha 256 256 328
-bounce -1
-gravity 0.5
-airfriction 1
-liquidfriction 3
-velocityjitter 6 6 30
-velocitymultiplier -1
-staincolor 0x808080 0x808080
-staintex 16 24
-// back blood
+       type blood
+       airfriction 1
+       alpha 256 256 328
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 0.100000
+       gravity 0.500000
+       liquidfriction 3
+       sizeincrease -15
+       size 10 20
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 6 6 30
+       velocitymultiplier -1
 effect particlegibs_damage_hit
-type blood
-count 0.1
-tex 24 32
-size 5 15
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease 10
-alpha 256 256 328
-bounce -1
-gravity 1
-airfriction 1
-liquidfriction 3
-velocityjitter 26 26 112
-originjitter 3 3 3
-velocitymultiplier 2
-staincolor 0x808080 0x808080
-staintex 16 24
-// effect for removing player model
-// "teleport"
-// cl_gentle deathfx
-// used in qcsrc/client/gibs.qc:                        pointparticles(particleeffectnum("damage_dissolve"), org, vel, amount)
-// small core blood no decals
+       type blood
+       airfriction 1
+       alpha 256 256 328
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 0.100000
+       gravity 1
+       liquidfriction 3
+       originjitter 3 3 3
+       sizeincrease 10
+       size 5 15
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 26 26 112
+       velocitymultiplier 2
 effect particlegibs_damage_dissolve
-type blood
-count 32
-tex 0 8
-size 15 20
-color 0x00ffff 0x82ffff
-alpha 256 256 328
-gravity 1
-airfriction 3
-liquidfriction 6
-originjitter 10 10 25
-velocityjitter 256 256 312
-staincolor 0x808080 0x808080
-staintex 16 24
-// core decal
+       type blood
+       airfriction 3
+       alpha 256 256 328
+       color 0x00ffff 0x82ffff
+       count 32
+       gravity 1
+       liquidfriction 6
+       originjitter 10 10 25
+       size 15 20
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 0 8
+       velocityjitter 256 256 312
 effect particlegibs_damage_dissolve
-type blood
-count 12
-tex 0 8
-size 20 40
-color 0xA8FFFF 0xA8FFFFF
-alpha 256 256 528
-gravity 2
-bounce -1
-airfriction 2
-liquidfriction 6
-originjitter 10 10 25
-velocityjitter 356 356 412
-staincolor 0x808080 0x808080
-staintex 16 24
-// front blood
+       type blood
+       airfriction 2
+       alpha 256 256 528
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 12
+       gravity 2
+       liquidfriction 6
+       originjitter 10 10 25
+       size 20 40
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 0 8
+       velocityjitter 356 356 412
 effect particlegibs_damage_dissolve
-type blood
-count 32
-tex 24 32
-size 10 20
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease -15
-alpha 256 256 328
-bounce -1
-gravity 0.5
-airfriction 1
-liquidfriction 3
-velocityjitter 56 56 212
-originjitter 5 5 10
-velocitymultiplier -0.3
-staincolor 0x808080 0x808080
-staintex 16 24
-// back blood
+       type blood
+       airfriction 1
+       alpha 256 256 328
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 32
+       gravity 0.500000
+       liquidfriction 3
+       originjitter 5 5 10
+       sizeincrease -15
+       size 10 20
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 56 56 212
+       velocitymultiplier -0.300000
 effect particlegibs_damage_dissolve
-type blood
-count 32
-tex 24 32
-size 5 15
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease 10
-alpha 256 256 328
-bounce -1
-gravity 1
-airfriction 1
-liquidfriction 3
-velocityjitter 56 56 212
-originjitter 5 5 10
-velocitymultiplier 0.5
-staincolor 0x808080 0x808080
-staintex 16 24
-// small bits
+       type blood
+       airfriction 1
+       alpha 256 256 328
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 32
+       gravity 1
+       liquidfriction 3
+       originjitter 5 5 10
+       sizeincrease 10
+       size 5 15
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 56 56 212
+       velocitymultiplier 0.500000
 effect particlegibs_damage_dissolve
-type blood
-count 75
-tex 24 32
-size 1 1
-color 0xA8FFFF 0xA8FFFFF
-sizeincrease 10
-alpha 256 256 328
-gravity 1
-airfriction 1.5
-liquidfriction 3
-originjitter 10 10 25
-velocityjitter 656 656 912
-staincolor 0x808080 0x808080
-staintex 16 24
-
-// fire effect which expands then slows
+       type blood
+       airfriction 1.500000
+       alpha 256 256 328
+       color 0xA8FFFF 0xA8FFFFF
+       count 75
+       gravity 1
+       liquidfriction 3
+       originjitter 10 10 25
+       sizeincrease 10
+       size 1 1
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 656 656 912
 effect onslaught_generator_gib_explode
-notunderwater
-count 17
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 26
-sizeincrease 45
-alpha 128 256 356
-bounce 1.5
-airfriction 5
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 286 286 286
-
-// smoke
+       type static
+       airfriction 5
+       alpha 128 256 356
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 17
+       liquidfriction 8
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 45
+       size 20 26
+       tex 48 55
+       velocityjitter 286 286 286
 effect onslaught_generator_gib_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 6
-size 1 10
-sizeincrease 90
-gravity -0.3
-alpha 200 500 600
-velocityjitter 244 244 244
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-
-// underwater bubbles
+       type alphastatic
+       airfriction 5
+       alpha 200 500 600
+       bounce 2
+       color 0x000000 0x111111
+       count 6
+       gravity -0.300000
+       notunderwater
+       sizeincrease 90
+       size 1 10
+       tex 0 8
+       velocityjitter 244 244 244
 effect onslaught_generator_gib_explode
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-
-// fire effect which expands then slows
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 16
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 96 96 96
 effect onslaught_generator_gib_flame
-notunderwater
-count 15
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 10
-sizeincrease 25
-alpha 128 256 356
-gravity -0.5
-airfriction 5
-liquidfriction 8
-originjitter 3 3 3
-velocityjitter 86 86 86
-// smoke
+       type static
+       airfriction 5
+       alpha 128 256 356
+       color 0x8f0d00 0xff5a00
+       count 15
+       gravity -0.500000
+       liquidfriction 8
+       notunderwater
+       originjitter 3 3 3
+       sizeincrease 25
+       size 5 10
+       tex 48 55
+       velocityjitter 86 86 86
 effect onslaught_generator_gib_flame
-type alphastatic
-notunderwater
-tex 0 8
-count 1
-size 10 20
-sizeincrease 30
-gravity -0.8
-alpha 200 500 600
-velocityjitter 44 44 44
-airfriction 5
-color 0x000000 0x111111
-bounce 2
-
-// underwater bubbles
+       type alphastatic
+       airfriction 5
+       alpha 200 500 600
+       bounce 2
+       color 0x000000 0x111111
+       count 1
+       gravity -0.800000
+       notunderwater
+       sizeincrease 30
+       size 10 20
+       tex 0 8
+       velocityjitter 44 44 44
 effect onslaught_generator_gib_flame
-underwater
-count 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 96 96 96
-
-
-// used nowhere in code
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 16
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 96 96 96
 effect firemine
-trailspacing 2
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 5
-gravity -0.06
-alpha 50 256 250
-bounce 1.5
-velocityjitter 10 10 2
-airfriction 1.2
-//slowfire
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 250
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       gravity -0.060000
+       sizeincrease 5
+       size 1 1
+       tex 48 55
+       trailspacing 2
+       velocityjitter 10 10 2
 effect firemine
-trailspacing 2
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 5
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 10 10 10
-airfriction 1.2
-// very slow and small fire
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       gravity -0.060000
+       sizeincrease 5
+       size 1 1
+       tex 48 55
+       trailspacing 2
+       velocityjitter 10 10 10
 effect firemine
-trailspacing 4
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 1
-sizeincrease 2
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 8 8 8
-airfriction 0.3
-//decreasing fire
+       type smoke
+       airfriction 0.300000
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       gravity -0.060000
+       sizeincrease 2
+       size 1 1
+       tex 48 55
+       trailspacing 4
+       velocityjitter 8 8 8
 effect firemine
-trailspacing 4
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 7
-sizeincrease -3
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 3 3 3
-airfriction 0.3
-//smoke
+       type smoke
+       airfriction 0.300000
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       gravity -0.060000
+       sizeincrease -3
+       size 5 7
+       tex 48 55
+       trailspacing 4
+       velocityjitter 3 3 3
 effect firemine
-trailspacing 8
-count 0.5
-type alphastatic
-tex 0 8
-size 1 4
-sizeincrease 1
-color 0x000000 0x111111
-alpha 256 256 90
-//gravity -0.2
-originjitter 2 2 2
-velocityoffset 0 0 3
-airfriction 1
-//fastfire
+       type alphastatic
+       airfriction 1
+       alpha 256 256 90
+       color 0x000000 0x111111
+       count 0.500000
+       originjitter 2 2 2
+       sizeincrease 1
+       size 1 4
+       tex 0 8
+       trailspacing 8
+       velocityoffset 0 0 3
 effect firemine
-trailspacing 1
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 12 12
-sizeincrease 0
-gravity 0
-alpha 50 256 1600
-bounce 1.5
-velocityjitter 0 0 0
-airfriction 1.2
-// light only
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 1600
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       size 12 12
+       tex 48 55
+       trailspacing 1
 effect firemine
-trailspacing 16
-lightradius 50
-lightradiusfade 50000
-lightcolor 2.7 2.7 0.6
-
-// used nowhere in code
+       lightcolor 2.7 2.7 0.6
+       lightradiusfade 50000
+       lightradius 50
+       trailspacing 16
 effect fireball
-trailspacing 2
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
-gravity -0.06
-alpha 50 256 250
-bounce 1.5
-velocityjitter 40 40 11
-airfriction 1.2
-//slowfire
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 250
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       gravity -0.060000
+       sizeincrease 20
+       size 5 5
+       tex 48 55
+       trailspacing 2
+       velocityjitter 40 40 11
 effect fireball
-trailspacing 2
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 40 40 40
-airfriction 1.2
-// very slow and small fire
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       gravity -0.060000
+       sizeincrease 20
+       size 5 5
+       tex 48 55
+       trailspacing 2
+       velocityjitter 40 40 40
 effect fireball
-trailspacing 4
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 10
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 30 30 30
-airfriction 0.3
-//decreasing fire
+       type smoke
+       airfriction 0.300000
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       gravity -0.060000
+       sizeincrease 10
+       size 5 5
+       tex 48 55
+       trailspacing 4
+       velocityjitter 30 30 30
 effect fireball
-trailspacing 4
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 30
-sizeincrease -10
-gravity -0.06
-alpha 50 256 200
-bounce 1.5
-velocityjitter 10 10 10
-airfriction 0.3
-//smoke
+       type smoke
+       airfriction 0.300000
+       alpha 50 256 200
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       gravity -0.060000
+       sizeincrease -10
+       size 20 30
+       tex 48 55
+       trailspacing 4
+       velocityjitter 10 10 10
 effect fireball
-trailspacing 8
-count 0.5
-type alphastatic
-tex 0 8
-size 5 15
-sizeincrease 7
-color 0x000000 0x111111
-alpha 256 256 90
-//gravity -0.2
-originjitter 10 10 10
-velocityoffset 0 0 10
-airfriction 1
-//fastfire
+       type alphastatic
+       airfriction 1
+       alpha 256 256 90
+       color 0x000000 0x111111
+       count 0.500000
+       originjitter 10 10 10
+       sizeincrease 7
+       size 5 15
+       tex 0 8
+       trailspacing 8
+       velocityoffset 0 0 10
 effect fireball
-trailspacing 1
-count 0.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 48 48
-sizeincrease 0
-gravity 0
-alpha 50 256 1600
-bounce 1.5
-velocityjitter 0 0 0
-airfriction 1.2
-// light only
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 1600
+       bounce 1.500000
+       color 0x8f0d00 0xff5a00
+       count 0.500000
+       size 48 48
+       tex 48 55
+       trailspacing 1
 effect fireball
-trailspacing 16
-lightradius 300
-lightradiusfade 3000
-lightcolor 2.7 2.7 0.6
-
-// fireball
+       lightcolor 2.7 2.7 0.6
+       lightradiusfade 3000
+       lightradius 300
+       trailspacing 16
 effect fireball_laser
-count 10
-type spark
-color 0x800000 0xFF8020
-alpha 192 256 2560
-size 1 1
-velocityjitter 1 1 1
-velocitymultiplier 10
-stretchfactor 0.7
-
-// rocket explosion (bigger than mortar and hagar)
-// decal
-// used nowhere in code
+       type spark
+       alpha 192 256 2560
+       color 0x800000 0xFF8020
+       count 10
+       size 1 1
+       stretchfactor 0.700000
+       velocityjitter 1 1 1
+       velocitymultiplier 10
 effect fireball_explode
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 56 56 56
-lightradius 500
-lightradiusfade 500
-lightcolor 4 2 0.5
-// flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 4 2 0.5
+       lightradiusfade 500
+       lightradius 500
+       originjitter 56 56 56
+       size 72 72
+       tex 8 16
 effect fireball_explode
-countabsolute 1
-type static
-tex 35 37
-color 0x404040 0x404040
-size 72 72
-alpha 192 192 64
-// fire effect
+       type static
+       alpha 192 192 64
+       color 0x404040 0x404040
+       countabsolute 1
+       size 72 72
+       tex 35 37
 effect fireball_explode
-notunderwater
-count 128
-type static
-tex 48 55
-color 0x902010 0xFFD080
-size 16 16
-alpha 128 128 256
-bounce 1.5
-airfriction 4
-liquidfriction 4
-originjitter 8 8 8
-velocityjitter 512 512 512
-// underwater bubbles
+       type static
+       airfriction 4
+       alpha 128 128 256
+       bounce 1.500000
+       color 0x902010 0xFFD080
+       count 128
+       liquidfriction 4
+       notunderwater
+       originjitter 8 8 8
+       size 16 16
+       tex 48 55
+       velocityjitter 512 512 512
 effect fireball_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 144 144 144
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 144 144 144
 effect fireball_explode
-notunderwater
-count 64
-type spark
-color 0x903010 0xFFD030
-size 2 2
-alpha 256 256 384
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 384 384 384
-
+       type spark
+       airfriction 0.200000
+       alpha 256 256 384
+       bounce 1.500000
+       color 0x903010 0xFFD030
+       count 64
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       size 2 2
+       velocityjitter 384 384 384
+       velocityoffset 0 0 80
 effect fireball_muzzleflash
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+       type smoke
+       alpha 256 256 512
+       color 0x202020 0x404040
+       count 2
+       lightcolor 2 1.5 0.2
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       size 5 5
+       tex 0 8
+       velocityjitter 6 6 6
+       velocitymultiplier 0.010000
 effect fireball_muzzleflash
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 12
-
+       type spark
+       airfriction 12
+       alpha 0 128 1024
+       color 0xFFFDD9 0xFFFDD9
+       count 15
+       originjitter 1 1 1
+       size 3 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect fireball_preattack_muzzleflash
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+       type smoke
+       alpha 256 256 512
+       color 0x202020 0x404040
+       count 2
+       lightcolor 2 1.5 0.2
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       size 5 5
+       tex 0 8
+       velocityjitter 6 6 6
+       velocitymultiplier 0.010000
 effect fireball_preattack_muzzleflash
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 12
-
+       type spark
+       airfriction 12
+       alpha 0 128 1024
+       color 0xFFFDD9 0xFFFDD9
+       count 15
+       originjitter 1 1 1
+       size 3 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect fireball_bfgdamage
-count 2
-type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 2 1.5 0.2
+       type smoke
+       alpha 256 256 512
+       color 0x202020 0x404040
+       count 2
+       lightcolor 2 1.5 0.2
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       size 5 5
+       tex 0 8
+       velocityjitter 6 6 6
+       velocitymultiplier 0.010000
 effect fireball_bfgdamage
-count 15
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 12
-
-//EF_FLAME
-//fire
-// used nowhere in code
+       type spark
+       airfriction 12
+       alpha 0 128 1024
+       color 0xFFFDD9 0xFFFDD9
+       count 15
+       originjitter 1 1 1
+       size 3 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect EF_FLAME
-//notunderwater
-count 100
-type smoke
-tex 48 55
-size 5 21
-alpha 200 356 512
-gravity -0.5
-color 0x8f0d00 0xff5a00
-bounce 2
-sizeincrease -1
-originoffset 0 0 10
-originjitter 12 12 34
-velocityjitter 22 22 50
-// smoke
+       type smoke
+       alpha 200 356 512
+       bounce 2
+       color 0x8f0d00 0xff5a00
+       count 100
+       gravity -0.500000
+       originjitter 12 12 34
+       originoffset 0 0 10
+       sizeincrease -1
+       size 5 21
+       tex 48 55
+       velocityjitter 22 22 50
 effect EF_FLAME
-type alphastatic
-count 50
-tex 0 8
-size 11 15
-sizeincrease 6
-alpha 200 256 200
-color 0x000000 0x111111
-gravity -0.3
-originoffset 0 0 10
-originjitter 12 12 34
-velocityjitter 11 11 50
-bounce 2
+       type alphastatic
+       alpha 200 256 200
+       bounce 2
+       color 0x000000 0x111111
+       count 50
+       gravity -0.300000
+       originjitter 12 12 34
+       originoffset 0 0 10
+       sizeincrease 6
+       size 11 15
+       tex 0 8
+       velocityjitter 11 11 50
 effect EF_FLAME
-count 0.5
-lightradius 200
-lightradiusfade 10000
-lightcolor 0.9 0.9 0.2
-
-// rifle bullet trail (somewhat like a tracer)
-// used in qcsrc/server/w_common.qc:                           zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("tr_bullet"), from, to)
+       count 0.500000
+       lightcolor 0.9 0.9 0.2
+       lightradiusfade 10000
+       lightradius 200
 effect tr_rifle
-trailspacing 128
-type spark
-color 0x800000 0xFF8020
-alpha 256 256 2560
-size 1.5 1.5
-stretchfactor 1
-velocitymultiplier 0.7
+       type spark
+       alpha 256 256 2560
+       color 0x800000 0xFF8020
+       size 1.500000 1.500000
+       stretchfactor 1
+       trailspacing 128
+       velocitymultiplier 0.700000
 effect tr_rifle
-notunderwater
-tex 0 8
-trailspacing 8
-type static
-color 0x202020 0x404040
-size 4 4
-sizeincrease 0.4
-alpha 256 256 256
-airfriction -4
-velocityjitter 4 4 4
-type smoke
+       type smoke
+       airfriction -4
+       alpha 256 256 256
+       color 0x202020 0x404040
+       notunderwater
+       sizeincrease 0.400000
+       size 4 4
+       tex 0 8
+       trailspacing 8
+       velocityjitter 4 4 4
 effect tr_rifle
-underwater
-trailspacing 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 2 2
-alpha 256 256 128
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-// rocket guiding start
-// underwater bubbles
+       type bubble
+       alpha 256 256 128
+       bounce 1.500000
+       color 0x404040 0x808080
+       gravity -0.125000
+       liquidfriction 4
+       size 2 2
+       tex 62 62
+       trailspacing 32
+       underwater
+       velocityjitter 16 16 16
 effect rocket_guide
-underwater
-count 2
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1.5 1.5
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 8 8 8
-velocityjitter 48 48 48
-velocitymultiplier -0.1
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 2
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 8 8 8
+       size 1.500000 1.500000
+       tex 62 62
+       underwater
+       velocityjitter 48 48 48
+       velocitymultiplier -0.100000
 effect rocket_guide
-notunderwater
-count 8
-type spark
-color 0x903010 0xFFD030
-size 0.3 0.7
-tex 40 40
-alpha 256 256 984
-gravity 1
-airfriction 0.2
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 80
-velocityjitter 156 156 156
-velocitymultiplier -0.3
-stretchfactor 0.4
+       type spark
+       airfriction 0.200000
+       alpha 256 256 984
+       bounce 1.500000
+       color 0x903010 0xFFD030
+       count 8
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       size 0.300000 0.700000
+       stretchfactor 0.400000
+       tex 40 40
+       velocityjitter 156 156 156
+       velocitymultiplier -0.300000
+       velocityoffset 0 0 80
 effect rocket_guide
-countabsolute 1
-type smoke
-tex 65 65
-color 0x903010 0xFFD030
-size 10 10
-sizeincrease 300
-alpha 100 100 500
-
-
-// gauntlet laser
-// based off morphed's cl_gentle
-// used in qcsrc/server/w_laser.qc
+       type smoke
+       alpha 100 100 500
+       color 0x903010 0xFFD030
+       countabsolute 1
+       sizeincrease 300
+       size 10 10
+       tex 65 65
 effect laser_gauntlet
-count 3
-type spark
-color 0xb44215 0x880000
-tex 43 43
-size 7 10
-alpha 128 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 150 150 150
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2.3
-rotate -180 180 4000 -4000
-
+       type spark
+       airfriction 10
+       alpha 128 512 6280
+       color 0xb44215 0x880000
+       count 3
+       originjitter 2 2 2
+       rotate -180 180 4000 -4000
+       sizeincrease -100
+       size 7 10
+       stretchfactor 2.300000
+       tex 43 43
+       velocityjitter 150 150 150
+       velocitymultiplier 0.200000
 effect laser_gauntlet
-count 6
-type spark
-color 0xff4200 0xff0000
-tex 8 15
-size 7 9
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 100 100 100
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2
-
-
-// muzzle flash
+       type spark
+       airfriction 12
+       alpha 256 512 6280
+       color 0xff4200 0xff0000
+       count 6
+       originjitter 2 2 2
+       sizeincrease -100
+       size 7 9
+       stretchfactor 2
+       tex 8 15
+       velocityjitter 100 100 100
+       velocitymultiplier 0.200000
 effect laser_gauntletmuzzleflash
-// glow and light
-countabsolute 1
-type smoke
-color 0x220000 0x880000
-tex 65 65
-size 10 15
-alpha 256 512 6280
-airfriction 10
-sizeincrease -100
-stretchfactor 2
-lightradius 150
-lightradiusfade 500
-lightcolor 3 0.1 0.1
-// electricity
+       type smoke
+       airfriction 10
+       alpha 256 512 6280
+       color 0x220000 0x880000
+       countabsolute 1
+       lightcolor 3 0.1 0.1
+       lightradiusfade 500
+       lightradius 150
+       sizeincrease -100
+       size 10 15
+       stretchfactor 2
+       tex 65 65
 effect laser_gauntletmuzzleflash
-count 3
-type spark
-color 0xb44215 0x880000
-tex 43 43
-size 7 10
-alpha 128 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 150 150 150
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2.3
-rotate -180 180 4000 -4000
-
-
-// fire
+       type spark
+       airfriction 10
+       alpha 128 512 6280
+       color 0xb44215 0x880000
+       count 3
+       originjitter 2 2 2
+       rotate -180 180 4000 -4000
+       sizeincrease -100
+       size 7 10
+       stretchfactor 2.300000
+       tex 43 43
+       velocityjitter 150 150 150
+       velocitymultiplier 0.200000
 effect laser_gauntletmuzzleflash
-count 6
-type spark
-color 0xff4200 0xff0000
-tex 8 15
-size 7 9
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 100 100 100
-velocitymultiplier 0.2
-sizeincrease -100
-stretchfactor 2
-
-//torch flame, spawn it as fast as you can  20 times per second or more, supports direction but not required
-//fast fire
-// used nowhere in code, meant for maps
+       type spark
+       airfriction 12
+       alpha 256 512 6280
+       color 0xff4200 0xff0000
+       count 6
+       originjitter 2 2 2
+       sizeincrease -100
+       size 7 9
+       stretchfactor 2
+       tex 8 15
+       velocityjitter 100 100 100
+       velocitymultiplier 0.200000
 effect torchflame
-count 3
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
- gravity -0.06
-alpha 50 256 250
-velocityjitter 40 40 11
-velocitymultiplier 30
-airfriction 1.2
-//slowfire
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 250
+       color 0x8f0d00 0xff5a00
+       count 3
+       gravity -0.060000
+       sizeincrease 20
+       size 5 5
+       tex 48 55
+       velocityjitter 40 40 11
+       velocitymultiplier 30
 effect torchflame
-count 2.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 20
- gravity -0.06
-alpha 50 256 200
-velocityjitter 40 40 40
-velocitymultiplier 20
-airfriction 1.2
-// very slow and small fire
+       type smoke
+       airfriction 1.200000
+       alpha 50 256 200
+       color 0x8f0d00 0xff5a00
+       count 2.500000
+       gravity -0.060000
+       sizeincrease 20
+       size 5 5
+       tex 48 55
+       velocityjitter 40 40 40
+       velocitymultiplier 20
 effect torchflame
-count 1.5
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 5
-sizeincrease 10
- gravity -0.06
-alpha 50 256 200
-velocityjitter 30 30 30
-velocitymultiplier 10
-airfriction 0.3
-//decreasing fire
+       type smoke
+       airfriction 0.300000
+       alpha 50 256 200
+       color 0x8f0d00 0xff5a00
+       count 1.500000
+       gravity -0.060000
+       sizeincrease 10
+       size 5 5
+       tex 48 55
+       velocityjitter 30 30 30
+       velocitymultiplier 10
 effect torchflame
-count 2
-type smoke
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 20 30
-sizeincrease -10
- gravity -0.06
-alpha 50 256 200
-velocityjitter 10 10 10
-velocitymultiplier 15
-airfriction 0.3
-//smoke
+       type smoke
+       airfriction 0.300000
+       alpha 50 256 200
+       color 0x8f0d00 0xff5a00
+       count 2
+       gravity -0.060000
+       sizeincrease -10
+       size 20 30
+       tex 48 55
+       velocityjitter 10 10 10
+       velocitymultiplier 15
 effect torchflame
-count 0.5
-type alphastatic
-tex 0 8
-size 5 15
-sizeincrease 7
-color 0x000000 0x111111
-alpha 256 256 90
-//gravity -0.2
-originjitter 10 10 10
-velocitymultiplier 20
-velocityoffset 0 0 10
-airfriction 1
-
-//happy death fx for cl_gentle
+       type alphastatic
+       airfriction 1
+       alpha 256 256 90
+       color 0x000000 0x111111
+       count 0.500000
+       originjitter 10 10 10
+       sizeincrease 7
+       size 5 15
+       tex 0 8
+       velocitymultiplier 20
+       velocityoffset 0 0 10
 effect happy_damage_dissolve
-tex 69 69
-count 15
-type alphastatic
-color 0x00FFFF 0xFF00FF
-size 32 32
-sizeincrease -10
-alpha 256 256 228
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 312 312 312
+       type alphastatic
+       airfriction 3
+       alpha 256 256 228
+       bounce 1.500000
+       color 0x00FFFF 0xFF00FF
+       count 15
+       gravity -0.400000
+       liquidfriction 6
+       sizeincrease -10
+       size 32 32
+       tex 69 69
+       velocityjitter 312 312 312
 effect happy_damage_dissolve
-tex 69 69
-count 15
-type alphastatic
-color 0xFF00FF 0xFFFF00
-size 32 32
-sizeincrease -10
-alpha 256 256 228
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 312 312 312
+       type alphastatic
+       airfriction 3
+       alpha 256 256 228
+       bounce 1.500000
+       color 0xFF00FF 0xFFFF00
+       count 15
+       gravity -0.400000
+       liquidfriction 6
+       sizeincrease -10
+       size 32 32
+       tex 69 69
+       velocityjitter 312 312 312
 effect happy_damage_dissolve
-tex 69 69
-count 15
-type alphastatic
-color 0xFFFF00 0x00FFFF
-size 32 32
-sizeincrease -10
-alpha 256 256 228
-gravity -0.4
-bounce 1.5
-airfriction 3
-liquidfriction 6
-velocityjitter 312 312 312
-
-
-//happy damage fx for cl_gentle
+       type alphastatic
+       airfriction 3
+       alpha 256 256 228
+       bounce 1.500000
+       color 0xFFFF00 0x00FFFF
+       count 15
+       gravity -0.400000
+       liquidfriction 6
+       sizeincrease -10
+       size 32 32
+       tex 69 69
+       velocityjitter 312 312 312
 effect happy_damage_hit
-tex 69 69
-count 0.1
-type alphastatic
-color 0x00FFFF 0xFF00FF
-size 26 26
-sizeincrease -28
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 156 156 156
+       type alphastatic
+       airfriction 5
+       alpha 128 128 192
+       bounce 1.500000
+       color 0x00FFFF 0xFF00FF
+       count 0.100000
+       gravity -0.400000
+       liquidfriction 10
+       sizeincrease -28
+       size 26 26
+       tex 69 69
+       velocityjitter 156 156 156
 effect happy_damage_hit
-tex 69 69
-count 0.1
-type alphastatic
-color 0xFF00FF 0xFFFF00
-size 26 26
-sizeincrease -28
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 156 156 156
+       type alphastatic
+       airfriction 5
+       alpha 128 128 192
+       bounce 1.500000
+       color 0xFF00FF 0xFFFF00
+       count 0.100000
+       gravity -0.400000
+       liquidfriction 10
+       sizeincrease -28
+       size 26 26
+       tex 69 69
+       velocityjitter 156 156 156
 effect happy_damage_hit
-tex 69 69
-count 0.1
-type alphastatic
-color 0xFFFF00 0x00FFFF
-size 26 26
-sizeincrease -28
-alpha 128 128 192
-gravity -0.4
-bounce 1.5
-airfriction 5
-liquidfriction 10
-velocityjitter 156 156 156
-
-
-
-// used in qcsrc/server/w_electro.qc:  pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
-// used in qcsrc/server/w_electro.qc:  pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+       type alphastatic
+       airfriction 5
+       alpha 128 128 192
+       bounce 1.500000
+       color 0xFFFF00 0x00FFFF
+       count 0.100000
+       gravity -0.400000
+       liquidfriction 10
+       sizeincrease -28
+       size 26 26
+       tex 69 69
+       velocityjitter 156 156 156
 effect electro_lightning
-countabsolute 1
-type decal
-tex 59 59
-size 16 16
-alpha 256 256 0
-originjitter 2 2 2
-lightradius 50
-lightradiusfade 500
-lightcolor 3.125 4.375 10
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 3.1 4.4 10
+       lightradiusfade 500
+       lightradius 50
+       originjitter 2 2 2
+       size 16 16
+       tex 59 59
 effect electro_lightning
-count 300
-type spark
-// color 0x501860 0x501860 // 0x202020 0x404040
-color 0x2030FF 0x80C0FF
-tex 65 65
-size 6 6
-alpha 100 206 1724
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease 10
-velocitymultiplier 2000
+       type spark
+       alpha 100 206 1724
+       color 0x2030FF 0x80C0FF
+       count 300
+       originjitter 1.5 1.5 1.5
+       sizeincrease 10
+       size 6 6
+       tex 65 65
+       velocityjitter 6 6 6
+       velocitymultiplier 2000
 effect electro_lightning
-count 30
-type spark
-tex 8 15
-color 0xDDFDFF 0xFDFDFF
-size 2 5
-alpha 110 170 1500
-originjitter 1 1 1
-velocityjitter 150 150 150
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 1.5
+       type spark
+       airfriction 2
+       alpha 110 170 1500
+       color 0xDDFDFF 0xFDFDFF
+       count 30
+       originjitter 1 1 1
+       size 2 5
+       stretchfactor 1.500000
+       tex 8 15
+       velocityjitter 150 150 150
+       velocitymultiplier 0.500000
 effect electro_lightning
-count 50
-type spark
-tex 41 41
-color 0xFDFDFF 0xF9FDFF
-size 2 3
-alpha 110 170 1500
-originjitter 1 1 1
-velocityjitter 350 350 350
-velocitymultiplier 2.5
-airfriction 8
-gravity 1.3
-stretchfactor 0.1
-
-// used in qcsrc/server/w_gauntlet.qc: pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
+       type spark
+       airfriction 8
+       alpha 110 170 1500
+       color 0xFDFDFF 0xF9FDFF
+       count 50
+       gravity 1.300000
+       originjitter 1 1 1
+       size 2 3
+       stretchfactor 0.100000
+       tex 41 41
+       velocityjitter 350 350 350
+       velocitymultiplier 2.500000
 effect gauntlet_lightning
-count 300
-type spark
-color 0x280000 0x280000 // 0x202020 0x404040
-tex 65 65
-size 3 3
-alpha 256 256 1024
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease 15
-velocitymultiplier 2000
+       type spark
+       alpha 256 256 1024
+       color 0x280000 0x280000
+       count 300
+       originjitter 1.5 1.5 1.5
+       sizeincrease 15
+       size 3 3
+       tex 65 65
+       velocityjitter 6 6 6
+       velocitymultiplier 2000
 effect gauntlet_lightning
-count 30
-type spark
-tex 8 15
-color 0xDD0000 0xFD0000
-size 2 5
-alpha 110 228 1024
-originjitter 1 1 1
-velocityjitter 150 150 150
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 1.5
+       type spark
+       airfriction 2
+       alpha 110 228 1024
+       color 0xDD0000 0xFD0000
+       count 30
+       originjitter 1 1 1
+       size 2 5
+       stretchfactor 1.500000
+       tex 8 15
+       velocityjitter 150 150 150
+       velocitymultiplier 0.500000
 effect gauntlet_lightning
-count 50
-type spark
-tex 41 41
-color 0xFD0000 0xF90000
-size 2 3
-alpha 110 228 600
-originjitter 1 1 1
-velocityjitter 350 350 350
-velocitymultiplier 2.5
-airfriction 8
-gravity 1.3
-stretchfactor 0.1
-
-
-// crylink joinexplode effect
-// decal
-// used in qcsrc/client/damage.qc:                                     pointparticles(particleeffectnum("crylink_joinexplode"), org2, '0 0 0', 1)
+       type spark
+       airfriction 8
+       alpha 110 228 600
+       color 0xFD0000 0xF90000
+       count 50
+       gravity 1.300000
+       originjitter 1 1 1
+       size 2 3
+       stretchfactor 0.100000
+       tex 41 41
+       velocityjitter 350 350 350
+       velocitymultiplier 2.500000
 effect crylink_joinexplode
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 12 12 12
-//lightradius 200
-//lightradiusfade 800
-//lightcolor 3.2 0.4 4
-// purple flare effect
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 12 12 12
+       size 24 24
+       tex 47 47
 effect crylink_joinexplode
-countabsolute 1
-type static
-tex 39 39
-color 0x504060 0x504060
-size 24 24
-alpha 256 256 512
-// purple sparks
+       type static
+       alpha 256 256 512
+       color 0x504060 0x504060
+       countabsolute 1
+       size 24 24
+       tex 39 39
 effect crylink_joinexplode
-count 40
-type spark
-tex 41 41
-color 0xA040C0 0xA040C0
-bounce 2
-size 6 6
-alpha 256 256 1024
-velocityjitter 512 512 512
-// purple splash
+       type spark
+       alpha 256 256 1024
+       bounce 2
+       color 0xA040C0 0xA040C0
+       count 40
+       size 6 6
+       tex 41 41
+       velocityjitter 512 512 512
 effect crylink_joinexplode
-count 1.5
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 512
-velocityjitter 32 32 32
-// purple splash
+       type static
+       alpha 256 256 512
+       color 0xE070FF 0xE070FF
+       count 1.500000
+       size 16 16
+       velocityjitter 32 32 32
 effect crylink_joinexplode
-count 3
-type static
-color 0xE070FF 0xE070FF
-size 16 16
-alpha 256 256 1024
-velocityjitter 256 256 256
-
-//sparks for keepaway ball touch
-// used nowhere in code
+       type static
+       alpha 256 256 1024
+       color 0xE070FF 0xE070FF
+       count 3
+       size 16 16
+       velocityjitter 256 256 256
 effect kaball_sparks
-count 35
-type spark
-tex 40 40
-color 0xa9cacf 0x0054ff
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-
-// weak rifle bullet trail (somewhat like a tracer)
-// used in qcsrc/server/w_common.qc:                           zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity)
-// used in qcsrc/client/projectile.qc:                 trailparticles(self, particleeffectnum("tr_bullet"), from, to)
+       type spark
+       airfriction 3
+       alpha 0 256 556
+       bounce 1.500000
+       color 0xa9cacf 0x0054ff
+       count 35
+       gravity 1
+       originjitter 1 1 1
+       size 1 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect tr_rifle_weak
-trailspacing 128
-type spark
-color 0x800000 0xFF8020
-alpha 256 256 2560
-size 1.5 1.5
-stretchfactor 1
-velocitymultiplier 0.7
+       type spark
+       alpha 256 256 2560
+       color 0x800000 0xFF8020
+       size 1.500000 1.500000
+       stretchfactor 1
+       trailspacing 128
+       velocitymultiplier 0.700000
 effect tr_rifle_weak
-notunderwater
-tex 0 8
-trailspacing 48
-type static
-color 0x202020 0x404040
-size 4 4
-sizeincrease 0.4
-alpha 256 256 256
-airfriction -4
-velocityjitter 4 4 4
-type smoke
+       type smoke
+       airfriction -4
+       alpha 256 256 256
+       color 0x202020 0x404040
+       notunderwater
+       sizeincrease 0.400000
+       size 4 4
+       tex 0 8
+       trailspacing 48
+       velocityjitter 4 4 4
 effect tr_rifle_weak
-underwater
-trailspacing 192
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 2 2
-alpha 256 256 128
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-// red smoke emiter
-// used nowhere in code
+       type bubble
+       alpha 256 256 128
+       bounce 1.500000
+       color 0x404040 0x808080
+       gravity -0.125000
+       liquidfriction 4
+       size 2 2
+       tex 62 62
+       trailspacing 192
+       underwater
+       velocityjitter 16 16 16
 effect red_smoke
-count 2
-type smoke
-tex 0 8
-color 0xff8866 0x331100
-size 60 120
-sizeincrease 0
-alpha 32 64 32
-gravity -0.007
-originjitter 0 0 0
-velocityjitter 0 0 0
-velocitymultiplier 5
-airfriction -1
-rotate 0 360 -30 30
-
-// pipe smoke emiter
-// used nowhere in code
+       type smoke
+       airfriction -1
+       alpha 32 64 32
+       color 0xff8866 0x331100
+       count 2
+       gravity -0.007000
+       rotate 0 360 -30 30
+       size 60 120
+       tex 0 8
+       velocitymultiplier 5
 effect pipe_smoke
-count 2
-type smoke
-tex 0 8
-color 0x999999 0x555555
-size 5 10
-sizeincrease 35
-alpha 32 64 48
-gravity -0.015
-originjitter 0 0 0
-velocityjitter 0 0 5
-velocitymultiplier 15
-airfriction -1
-rotate 0 360 -180 180
-
-// seeker missile trail
+       type smoke
+       airfriction -1
+       alpha 32 64 48
+       color 0x999999 0x555555
+       count 2
+       gravity -0.015000
+       rotate 0 360 -180 180
+       sizeincrease 35
+       size 5 10
+       tex 0 8
+       velocityjitter 0 0 5
+       velocitymultiplier 15
 effect TR_SEEKER
-trailspacing 10
-type smoke
-notunderwater
-color 0x000000 0x666666
-tex 0 8
-size 2 2
-bounce 1
-sizeincrease 11
-alpha 200 300 200
-lightradius 100
-lighttime 0
-lightcolor 6 3 1
-originjitter 2 2 2
-velocityjitter 3 3 3
-velocitymultiplier -0.02
-rotate -180 180 -30 30
-//gravity -0.11
-// fire
+       type smoke
+       alpha 200 300 200
+       bounce 1
+       color 0x000000 0x666666
+       lightcolor 6 3 1
+       lightradius 100
+       notunderwater
+       originjitter 2 2 2
+       rotate -180 180 -30 30
+       sizeincrease 11
+       size 2 2
+       tex 0 8
+       trailspacing 10
+       velocityjitter 3 3 3
+       velocitymultiplier -0.020000
 effect TR_SEEKER
-trailspacing 4
-type static
-color 0xffdf72 0x811200
-tex 48 55
-size 5 5
-sizeincrease -30
-alpha 100 144 588
-airfriction 8
-velocityjitter 32 32 32
-velocitymultiplier -1.5
-// bubbles
+       type static
+       airfriction 8
+       alpha 100 144 588
+       color 0xffdf72 0x811200
+       sizeincrease -30
+       size 5 5
+       tex 48 55
+       trailspacing 4
+       velocityjitter 32 32 32
+       velocitymultiplier -1.500000
 effect TR_SEEKER
-type bubble
-underwater
-trailspacing 16
-tex 62 62
-size 1 2
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-velocitymultiplier -0.31
-rotate 0 0 0 0
-// sparks
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       gravity -0.125000
+       liquidfriction 4
+       size 1 2
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
+       velocitymultiplier -0.310000
 effect TR_SEEKER
-notunderwater
-trailspacing 20
-type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 0.5 0.5
-alpha 444 512 1866
-stretchfactor 0.3
-//gravity 1
-bounce 1
-//velocityoffset 0 0 15
-airfriction 5
-originjitter 1 1 1
-velocityjitter 100 100 100
-velocitymultiplier -0.31
-
-// --------------- vehicles
-
+       type spark
+       airfriction 5
+       alpha 444 512 1866
+       bounce 1
+       color 0xFFFDD9 0xFFFDD9
+       notunderwater
+       originjitter 1 1 1
+       size 0.500000 0.500000
+       stretchfactor 0.300000
+       tex 40 40
+       trailspacing 20
+       velocityjitter 100 100 100
+       velocitymultiplier -0.310000
 effect spiderbot_minigun_trail
-notunderwater
-trailspacing 10
-type smoke
-color 0xd0d0a0 0xffffff
-tex 0 8
-size 1 2
-alpha 20 50 100
-sizeincrease 2
-velocityjitter 5 5 5
-gravity -0.03
-airfriction 1
-
+       type smoke
+       airfriction 1
+       alpha 20 50 100
+       color 0xd0d0a0 0xffffff
+       gravity -0.030000
+       notunderwater
+       sizeincrease 2
+       size 1 2
+       tex 0 8
+       trailspacing 10
+       velocityjitter 5 5 5
 effect spiderbot_minigun_muzzleflash
-count 3
-type spark
-color 0xff9c00 0xff8400
-tex 48 55
-size 10 15
-alpha 256 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 150 150 150
-velocitymultiplier 0.35
-sizeincrease -100
-stretchfactor 1.3
-rotate -180 180 4000 -4000
-// fire
+       type spark
+       airfriction 10
+       alpha 256 512 6280
+       color 0xff9c00 0xff8400
+       count 3
+       originjitter 2 2 2
+       rotate -180 180 4000 -4000
+       sizeincrease -100
+       size 10 15
+       stretchfactor 1.300000
+       tex 48 55
+       velocityjitter 150 150 150
+       velocitymultiplier 0.350000
 effect spiderbot_minigun_muzzleflash
-count 6
-type spark
-color 0xff9c00 0xff8400
-tex 8 15
-size 5 7
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 200 200 200
-velocitymultiplier 0.2
-sizeincrease -10
-stretchfactor 0.8
+       type spark
+       airfriction 12
+       alpha 256 512 6280
+       color 0xff9c00 0xff8400
+       count 6
+       originjitter 2 2 2
+       sizeincrease -10
+       size 5 7
+       stretchfactor 0.800000
+       tex 8 15
+       velocityjitter 200 200 200
+       velocitymultiplier 0.200000
 effect spiderbot_minigun_muzzleflash
-countabsolute 2
-type static
-tex 48 55
-color 0xff9c00 0xff8400
-size 32 32
-alpha 256 512 6680
-sizeincrease -100
-stretchfactor 0.1
-rotate -180 180 4000 -4000
-lightradius 120
-lightradiusfade 8000
-lightcolor 3 3 0
-
+       type static
+       alpha 256 512 6680
+       color 0xff9c00 0xff8400
+       countabsolute 2
+       lightcolor 3 3 0
+       lightradiusfade 8000
+       lightradius 120
+       rotate -180 180 4000 -4000
+       sizeincrease -100
+       size 32 32
+       stretchfactor 0.100000
+       tex 48 55
 effect spiderbot_minigun_impact
-countabsolute 1
-type static
-tex 65 65
-color 0xff9c00 0xf6ff00
-size 52 52
-alpha 50 100 1680
-sizeincrease -100
-stretchfactor 0.1
-rotate -180 180 4000 -4000
-// fire
+       type static
+       alpha 50 100 1680
+       color 0xff9c00 0xf6ff00
+       countabsolute 1
+       rotate -180 180 4000 -4000
+       sizeincrease -100
+       size 52 52
+       stretchfactor 0.100000
+       tex 65 65
 effect spiderbot_minigun_impact
-count 7
-type spark
-color 0xff9c00 0xff8400
-tex 48 55
-size 9 15
-alpha 256 512 6280
-airfriction 10
-originjitter 2 2 2
-velocityjitter 250 250 150
-velocitymultiplier 0.2
-sizeincrease 100
-stretchfactor 3
-airfriction 6
-rotate -180 180 4000 -4000
-// smoke 
+       type spark
+       airfriction 6
+       alpha 256 512 6280
+       color 0xff9c00 0xff8400
+       count 7
+       originjitter 2 2 2
+       rotate -180 180 4000 -4000
+       sizeincrease 100
+       size 9 15
+       stretchfactor 3
+       tex 48 55
+       velocityjitter 250 250 150
+       velocitymultiplier 0.200000
 effect spiderbot_minigun_impact
-count 6
-type smoke
-color 0xd0d0a0 0xffffff
-tex 0 8
-size 10 20
-alpha 50 50 190
-sizeincrease 80
-velocityjitter 100 100 250
-velocitymultiplier 0.49
-gravity 1.3
-airfriction 10
-rotate -180 180 0 0
-// smoke 2
+       type smoke
+       airfriction 10
+       alpha 50 50 190
+       color 0xd0d0a0 0xffffff
+       count 6
+       gravity 1.300000
+       rotate -180 180 0 0
+       sizeincrease 80
+       size 10 20
+       tex 0 8
+       velocityjitter 100 100 250
+       velocitymultiplier 0.490000
 effect spiderbot_minigun_impact
-count 7
-type spark
-color 0xd0d0a0 0xffffff
-tex 0 8
-size 15 19
-alpha 25 51 128
-airfriction 6
-originjitter 2 2 2
-velocityjitter 250 250 150
-velocitymultiplier 0.2
-sizeincrease 100
-stretchfactor 7.6
-// debris
+       type spark
+       airfriction 6
+       alpha 25 51 128
+       color 0xd0d0a0 0xffffff
+       count 7
+       originjitter 2 2 2
+       sizeincrease 100
+       size 15 19
+       stretchfactor 7.600000
+       tex 0 8
+       velocityjitter 250 250 150
+       velocitymultiplier 0.200000
 effect spiderbot_minigun_impact
-notunderwater
-count 3
-type alphastatic
-tex 66 68
-color 0x99977D 0xFFFFFF
-size 6 8
-alpha 644 756 1484
-gravity 1.1
-airfriction 0.4
-sizeincrease -10
-velocitymultiplier 0.15
-originjitter 16 16 16
-velocityjitter 124 124 224
-rotate -180 180 -1000 1000
-// decal
+       type alphastatic
+       airfriction 0.400000
+       alpha 644 756 1484
+       color 0x99977D 0xFFFFFF
+       count 3
+       gravity 1.100000
+       notunderwater
+       originjitter 16 16 16
+       rotate -180 180 -1000 1000
+       sizeincrease -10
+       size 6 8
+       tex 66 68
+       velocityjitter 124 124 224
+       velocitymultiplier 0.150000
 effect spiderbot_minigun_impact
-countabsolute 1
-type decal
-tex 56 59
-size 20 25
-alpha 256 256 0
-originjitter 16 16 16
-rotate -180 180 0 0
-
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 16 16 16
+       rotate -180 180 0 0
+       size 20 25
+       tex 56 59
 effect spiderbot_rocket_explode
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 23 23 23
-lightradius 300
-lightradiusfade 1750
-lightcolor 8 4 0
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 8 4 0
+       lightradiusfade 1750
+       lightradius 300
+       originjitter 23 23 23
+       size 72 72
+       tex 8 16
 effect spiderbot_rocket_explode
-countabsolute 1
-type static
-tex 33 33 
-size 22 22
-alpha 56 56 230
-color 0x8f0d00 0xff5a00
-sizeincrease 2400
-// glow
+       type static
+       alpha 56 56 230
+       color 0x8f0d00 0xff5a00
+       countabsolute 1
+       sizeincrease 2400
+       size 22 22
+       tex 33 33
 effect spiderbot_rocket_explode
-countabsolute 1
-type static
-tex 64 64
-size 120 120
-alpha 156 156 830
-color 0x8f0d00 0xff5a00
-sizeincrease 240
-// fire effect
+       type static
+       alpha 156 156 830
+       color 0x8f0d00 0xff5a00
+       countabsolute 1
+       sizeincrease 240
+       size 120 120
+       tex 64 64
 effect spiderbot_rocket_explode
-notunderwater
-count 32
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 12 21
-sizeincrease 495
-alpha 200 256 812
-airfriction 8
-liquidfriction 8
-originjitter 100 100 100
-velocityjitter 512 512 512
-rotate -180 180 -50 50
-// fire effect 2
+       type static
+       airfriction 8
+       alpha 200 256 812
+       color 0x8f0d00 0xff5a00
+       count 32
+       liquidfriction 8
+       notunderwater
+       originjitter 100 100 100
+       rotate -180 180 -50 50
+       sizeincrease 495
+       size 12 21
+       tex 48 55
+       velocityjitter 512 512 512
 effect spiderbot_rocket_explode
-notunderwater
-count 16
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 3 3
-sizeincrease 120
-alpha 200 256 912
-airfriction -2
-liquidfriction 8
-velocityjitter 412 412 412
-rotate -180 180 -150 150
-stretchfactor 10
-// fire rays
+       type spark
+       airfriction -2
+       alpha 200 256 912
+       color 0x8f0d00 0xff5a00
+       count 16
+       liquidfriction 8
+       notunderwater
+       rotate -180 180 -150 150
+       sizeincrease 120
+       size 3 3
+       stretchfactor 10
+       tex 48 55
+       velocityjitter 412 412 412
 effect spiderbot_rocket_explode
-notunderwater
-count 10
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 13 54
-sizeincrease 120
-alpha 200 256 1600
-airfriction -3
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 712 712 712
-stretchfactor 10
-// smoke
+       type spark
+       airfriction -3
+       alpha 200 256 1600
+       color 0x8f0d00 0xff5a00
+       count 10
+       liquidfriction 8
+       notunderwater
+       originjitter 40 40 40
+       sizeincrease 120
+       size 13 54
+       stretchfactor 10
+       tex 48 55
+       velocityjitter 712 712 712
 effect spiderbot_rocket_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 10
-size 10 15
-sizeincrease 280
-alpha 300 650 756
-originjitter 100 100 100
-velocityjitter 200 200 200
-airfriction 3
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// smoke2
+       type alphastatic
+       airfriction 3
+       alpha 300 650 756
+       color 0x4F4B46 0x000000
+       count 10
+       notunderwater
+       originjitter 100 100 100
+       rotate -180 180 -20 20
+       sizeincrease 280
+       size 10 15
+       tex 0 8
+       velocityjitter 200 200 200
 effect spiderbot_rocket_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 3
-size 100 150
-sizeincrease 30
-alpha 300 650 556
-originjitter 10 10 10
-velocityjitter 200 200 200
-airfriction 2
-gravity -0.5
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// underwater bubbles
+       type alphastatic
+       airfriction 2
+       alpha 300 650 556
+       color 0x4F4B46 0x000000
+       count 3
+       gravity -0.500000
+       notunderwater
+       originjitter 10 10 10
+       rotate -180 180 -20 20
+       sizeincrease 30
+       size 100 150
+       tex 0 8
+       velocityjitter 200 200 200
 effect spiderbot_rocket_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 144 144 144
-// underwatershockwave
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 160 160 160
+       size 1 3
+       tex 62 62
+       underwater
+       velocityjitter 144 144 144
 effect spiderbot_rocket_explode
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 1200
-alpha 40 40 300
-
-
+       type smoke
+       alpha 40 40 300
+       countabsolute 1
+       sizeincrease 1200
+       size 30 30
+       tex 33 33
+       underwater
 effect spiderbot_rocket_thrust
-notunderwater
-count 3
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 5 10
-sizeincrease -40
-alpha 200 256 1600
-velocityjitter 20 20 20
-velocitymultiplier -1.4
-stretchfactor 0.9
+       type spark
+       alpha 200 256 1600
+       color 0x8f0d00 0xff5a00
+       count 3
+       notunderwater
+       sizeincrease -40
+       size 5 10
+       stretchfactor 0.900000
+       tex 48 55
+       velocityjitter 20 20 20
+       velocitymultiplier -1.400000
 effect spiderbot_rocket_thrust
-notunderwater
-count 4
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 25 25
-sizeincrease -3000
-alpha 200 200 9000
-velocityjitter 60 60 60
-velocitymultiplier -1.4
-stretchfactor 1
-rotate -180 180 -500 500
-
-
-
-// long lasting smoke
+       type static
+       alpha 200 200 9000
+       color 0x8f0d00 0xff5a00
+       count 4
+       notunderwater
+       rotate -180 180 -500 500
+       sizeincrease -3000
+       size 25 25
+       stretchfactor 1
+       tex 48 55
+       velocityjitter 60 60 60
+       velocitymultiplier -1.400000
 effect spiderbot_rocket_launch
-notunderwater
-count 8
-type smoke
-tex 0 8
-color 0xFFFFFF 0xD9C4B0
-size 30 30
-sizeincrease 20
-alpha 100 156 60
-velocityjitter 60 60 60
-velocitymultiplier -0.1
-airfriction 0.3
-gravity -0.01
-// fast smoke
+       type smoke
+       airfriction 0.300000
+       alpha 100 156 60
+       color 0xFFFFFF 0xD9C4B0
+       count 8
+       gravity -0.010000
+       notunderwater
+       sizeincrease 20
+       size 30 30
+       tex 0 8
+       velocityjitter 60 60 60
+       velocitymultiplier -0.100000
 effect spiderbot_rocket_launch
-notunderwater
-count 14
-type smoke
-tex 0 8
-color 0xFFFFFF 0xD9C4B0
-size 30 30
-sizeincrease 20
-alpha 100 156 260
-gravity -0.3
-velocityjitter 160 160 60
-airfriction 0.3
-// fire
+       type smoke
+       airfriction 0.300000
+       alpha 100 156 260
+       color 0xFFFFFF 0xD9C4B0
+       count 14
+       gravity -0.300000
+       notunderwater
+       sizeincrease 20
+       size 30 30
+       tex 0 8
+       velocityjitter 160 160 60
 effect spiderbot_rocket_launch
-notunderwater
-count 14
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 30 30
-sizeincrease 40
-velocitymultiplier 0.5
-alpha 200 256 1960
-velocityjitter 60 60 60
-airfriction 0.3
-stretchfactor 3
-airfriction 0.3
-//sparks
+       type spark
+       airfriction 0.300000
+       alpha 200 256 1960
+       color 0x8f0d00 0xff5a00
+       count 14
+       notunderwater
+       sizeincrease 40
+       size 30 30
+       stretchfactor 3
+       tex 48 55
+       velocityjitter 60 60 60
+       velocitymultiplier 0.500000
 effect spiderbot_rocket_launch
-notunderwater
-count 10
-type spark
-tex 40 40
-color 0xFFFFFF 0xD9C4B0
-size 1 4
-alpha 200 256 1000
-velocityjitter 160 160 160
-velocitymultiplier -0.5
-
+       type spark
+       alpha 200 256 1000
+       color 0xFFFFFF 0xD9C4B0
+       count 10
+       notunderwater
+       size 1 4
+       tex 40 40
+       velocityjitter 160 160 160
+       velocitymultiplier -0.500000
 effect wakizashi_gun_impact
-count 15
-type spark
-color 0xff0000 0xc03535
-tex 41 41
-size 4 7
-alpha 256 512 1180
-airfriction 4
-gravity 3
-originjitter 40 40 10
-velocityjitter 350 350 550
-velocityoffset 0 0 700
-stretchfactor 0.9
+       type spark
+       airfriction 4
+       alpha 256 512 1180
+       color 0xff0000 0xc03535
+       count 15
+       gravity 3
+       originjitter 40 40 10
+       size 4 7
+       stretchfactor 0.900000
+       tex 41 41
+       velocityjitter 350 350 550
+       velocityoffset 0 0 700
 effect wakizashi_gun_impact
-type smoke
-count 24
-color 0xd0d0a0 0xc03535
-tex 0 8
-size 10 20
-alpha 50 90 150
-sizeincrease 80
-velocityjitter 250 250 450
-velocityoffset 0 0 600
-originjitter 40 40 10
-airfriction 4
-sizeincrease 80
-rotate -180 180 0 0
+       type smoke
+       airfriction 4
+       alpha 50 90 150
+       color 0xd0d0a0 0xc03535
+       count 24
+       originjitter 40 40 10
+       rotate -180 180 0 0
+       sizeincrease 80
+       size 10 20
+       tex 0 8
+       velocityjitter 250 250 450
+       velocityoffset 0 0 600
 effect wakizashi_gun_impact
-countabsolute 1
-type smoke
-tex 65 65
-color 0xff0000 0xc03535
-size 82 82
-alpha 250 300 680
-sizeincrease -180
+       type smoke
+       alpha 250 300 680
+       color 0xff0000 0xc03535
+       countabsolute 1
+       sizeincrease -180
+       size 82 82
+       tex 65 65
 effect wakizashi_gun_impact
-countabsolute 1
-type smoke
-tex 33 33
-color 0xff0000 0xc03535
-size 40 40
-alpha 50 100 620
-sizeincrease 900
-rotate -180 180 400 -400
+       type smoke
+       alpha 50 100 620
+       color 0xff0000 0xc03535
+       countabsolute 1
+       rotate -180 180 400 -400
+       sizeincrease 900
+       size 40 40
+       tex 33 33
 effect wakizashi_gun_impact
-countabsolute 1
-type decal
-tex 59 59
-size 14 14
-alpha 256 256 0
-originjitter 16 16 16
-rotate -180 180 0 0
-
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 16 16 16
+       rotate -180 180 0 0
+       size 14 14
+       tex 59 59
 effect wakizashi_gun_muzzleflash
-count 16
-type spark
-color 0xff0000 0xc03535
-tex 8 15
-size 5 7
-alpha 256 512 6280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 200 200 200
-velocitymultiplier 0.2
-sizeincrease -10
-stretchfactor 0.7
-
+       type spark
+       airfriction 12
+       alpha 256 512 6280
+       color 0xff0000 0xc03535
+       count 16
+       originjitter 2 2 2
+       sizeincrease -10
+       size 5 7
+       stretchfactor 0.700000
+       tex 8 15
+       velocityjitter 200 200 200
+       velocitymultiplier 0.200000
 effect wakizashi_rocket_explode
-countabsolute 1
-type decal
-tex 8 16
-size 72 72
-alpha 256 256 0
-originjitter 23 23 23
-lightradius 300
-lightradiusfade 1750
-lightcolor 8 4 0
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 8 4 0
+       lightradiusfade 1750
+       lightradius 300
+       originjitter 23 23 23
+       size 72 72
+       tex 8 16
 effect wakizashi_rocket_explode
-countabsolute 1
-type static
-tex 33 33 
-size 22 22
-alpha 56 56 230
-color 0x8f0d00 0xff5a00
-sizeincrease 2400
-// glow
+       type static
+       alpha 56 56 230
+       color 0x8f0d00 0xff5a00
+       countabsolute 1
+       sizeincrease 2400
+       size 22 22
+       tex 33 33
 effect wakizashi_rocket_explode
-countabsolute 1
-type static
-tex 64 64
-size 120 120
-alpha 156 156 830
-color 0x8f0d00 0xff5a00
-sizeincrease 240
-// fire effect
+       type static
+       alpha 156 156 830
+       color 0x8f0d00 0xff5a00
+       countabsolute 1
+       sizeincrease 240
+       size 120 120
+       tex 64 64
 effect wakizashi_rocket_explode
-notunderwater
-count 64
-type static
-tex 48 55
-color 0xFFAE00 0xff5a00
-size 12 21
-sizeincrease 195
-alpha 200 256 512
-airfriction 2
-liquidfriction 8
-originjitter 10 10 10
-velocityjitter 512 512 512
-rotate -180 180 -50 50
-// fire rays
+       type static
+       airfriction 2
+       alpha 200 256 512
+       color 0xFFAE00 0xff5a00
+       count 64
+       liquidfriction 8
+       notunderwater
+       originjitter 10 10 10
+       rotate -180 180 -50 50
+       sizeincrease 195
+       size 12 21
+       tex 48 55
+       velocityjitter 512 512 512
 effect wakizashi_rocket_explode
-notunderwater
-count 10
-type spark
-tex 48 55
-color 0xFFEA00 0xff5a00
-size 43 54
-sizeincrease 120
-alpha 200 256 1600
-airfriction -3
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 512 512 512
-stretchfactor 10
-// smoke
+       type spark
+       airfriction -3
+       alpha 200 256 1600
+       color 0xFFEA00 0xff5a00
+       count 10
+       liquidfriction 8
+       notunderwater
+       originjitter 40 40 40
+       sizeincrease 120
+       size 43 54
+       stretchfactor 10
+       tex 48 55
+       velocityjitter 512 512 512
 effect wakizashi_rocket_explode
-type alphastatic
-notunderwater
-tex 0 8
-count 32
-size 10 15
-sizeincrease 230
-alpha 300 450 556
-originjitter 100 100 100
-velocityjitter 200 200 200
-airfriction 3
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// bouncing sparks
+       type alphastatic
+       airfriction 3
+       alpha 300 450 556
+       color 0x4F4B46 0x000000
+       count 32
+       notunderwater
+       originjitter 100 100 100
+       rotate -180 180 -20 20
+       sizeincrease 230
+       size 10 15
+       tex 0 8
+       velocityjitter 200 200 200
 effect wakizashi_rocket_explode
-notunderwater
-count 14
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 2
-alpha 644 956 884
-gravity 1
-airfriction 1
-liquidfriction 0.8
-velocityoffset 0 0 170
-originjitter 60 60 60
-velocityjitter 524 524 524
-// underwater bubbles
+       type spark
+       airfriction 1
+       alpha 644 956 884
+       color 0xffa35b 0xfff2be
+       count 14
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 60 60 60
+       size 1 2
+       tex 40 40
+       velocityjitter 524 524 524
+       velocityoffset 0 0 170
 effect wakizashi_rocket_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 144 144 144
-// underwatershockwave
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 160 160 160
+       size 1 3
+       tex 62 62
+       underwater
+       velocityjitter 144 144 144
 effect wakizashi_rocket_explode
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 1200
-alpha 40 40 300
-
+       type smoke
+       alpha 40 40 300
+       countabsolute 1
+       sizeincrease 1200
+       size 30 30
+       tex 33 33
+       underwater
 effect wakizashi_rocket_thrust
-notunderwater
-countabsolute 3
-type spark
-tex 48 55
-color 0x00FFDD 0x6200FF
-size 14 19
-sizeincrease -2
-alpha 200 256 1600
-velocityjitter 60 60 60
-velocitymultiplier -1.1
-stretchfactor 1
+       type spark
+       alpha 200 256 1600
+       color 0x00FFDD 0x6200FF
+       countabsolute 3
+       notunderwater
+       sizeincrease -2
+       size 14 19
+       stretchfactor 1
+       tex 48 55
+       velocityjitter 60 60 60
+       velocitymultiplier -1.100000
 effect wakizashi_rocket_thrust
-notunderwater
-countabsolute 2
-type spark
-tex 48 55
-color 0xFFFF33 0xFFEE00
-size 5 10
-sizeincrease -2
-alpha 200 256 1900
-velocityjitter 60 60 60
-velocitymultiplier -0.3
-stretchfactor 3
-
-// long lasting smoke
+       type spark
+       alpha 200 256 1900
+       color 0xFFFF33 0xFFEE00
+       countabsolute 2
+       notunderwater
+       sizeincrease -2
+       size 5 10
+       stretchfactor 3
+       tex 48 55
+       velocityjitter 60 60 60
+       velocitymultiplier -0.300000
 effect wakizashi_rocket_launch
-notunderwater
-count 8
-type smoke
-tex 0 8
-color 0xFFFFFF 0xD9C4B0
-size 3 30
-sizeincrease 20
-alpha 100 156 60
-velocityjitter 160 160 60
-velocitymultiplier -0.1
-airfriction 0.3
-// fast smoke
+       type smoke
+       airfriction 0.300000
+       alpha 100 156 60
+       color 0xFFFFFF 0xD9C4B0
+       count 8
+       notunderwater
+       sizeincrease 20
+       size 3 30
+       tex 0 8
+       velocityjitter 160 160 60
+       velocitymultiplier -0.100000
 effect wakizashi_rocket_launch
-notunderwater
-count 14
-type smoke
-tex 0 8
-color 0xFFFFFF 0xD9C4B0
-size 30 30
-sizeincrease 20
-alpha 100 156 260
-velocityjitter 160 160 60
-velocitymultiplier 0.4
-airfriction 0.3
-//sparks
+       type smoke
+       airfriction 0.300000
+       alpha 100 156 260
+       color 0xFFFFFF 0xD9C4B0
+       count 14
+       notunderwater
+       sizeincrease 20
+       size 30 30
+       tex 0 8
+       velocityjitter 160 160 60
+       velocitymultiplier 0.400000
 effect wakizashi_rocket_launch
-notunderwater
-count 10
-type spark
-tex 40 40
-color 0xFFFFFF 0xD9C4B0
-size 1 4
-alpha 200 256 1000
-velocityjitter 60 60 60
-velocitymultiplier -1.5
-
+       type spark
+       alpha 200 256 1000
+       color 0xFFFFFF 0xD9C4B0
+       count 10
+       notunderwater
+       size 1 4
+       tex 40 40
+       velocityjitter 60 60 60
+       velocitymultiplier -1.500000
 effect wakizashi_booster_smoke
-type alphastatic
-notunderwater
-tex 0 8
-count 3
-size 60 100
-sizeincrease 10
-gravity -0.1
-alpha 200 750 200
-velocityjitter 40 40 40
-originjitter 60 60 60
-airfriction 2
-color 0xA69A80 0xB3B39F
-rotate -180 180 -20 20
-
-// decal
+       type alphastatic
+       airfriction 2
+       alpha 200 750 200
+       color 0xA69A80 0xB3B39F
+       count 3
+       gravity -0.100000
+       notunderwater
+       originjitter 60 60 60
+       rotate -180 180 -20 20
+       sizeincrease 10
+       size 60 100
+       tex 0 8
+       velocityjitter 40 40 40
 effect raptor_cannon_impact
-countabsolute 1
-type decal
-tex 47 47
-size 24 24
-alpha 256 256 0
-originjitter 16 16 16
-rotate -180 180 0 0
-//spark
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 16 16 16
+       rotate -180 180 0 0
+       size 24 24
+       tex 47 47
 effect raptor_cannon_impact
-notunderwater
-count 6
-type spark
-tex 40 40
-color 0xD400FF 0x571863
-size 1 1
-alpha 644 956 784
-gravity 1
-airfriction 0.2
-velocityoffset 0 0 150
-originjitter 16 16 16
-velocityjitter 124 124 524
-// smoke
+       type spark
+       airfriction 0.200000
+       alpha 644 956 784
+       color 0xD400FF 0x571863
+       count 6
+       gravity 1
+       notunderwater
+       originjitter 16 16 16
+       size 1 1
+       tex 40 40
+       velocityjitter 124 124 524
+       velocityoffset 0 0 150
 effect raptor_cannon_impact
-count 4
-type alphastatic
-tex 0 7
-size 50 50
-color 0x646364 0x151515
-alpha 428 428 600
-rotate -180 180 0 0
-velocityjitter 200 200 300
-velocityoffset 0 0 340
-gravity 0.7
-airfriction 2
-// fire
+       type alphastatic
+       airfriction 2
+       alpha 428 428 600
+       color 0x646364 0x151515
+       count 4
+       gravity 0.700000
+       rotate -180 180 0 0
+       size 50 50
+       tex 0 7
+       velocityjitter 200 200 300
+       velocityoffset 0 0 340
 effect raptor_cannon_impact
-notunderwater
-count 10
-type static
-tex 48 55
-color 0xD400FF 0x571863
-size 33 44
-sizeincrease 25
-alpha 200 256 812
-bounce 1.5
-airfriction 8
-liquidfriction 8
-originjitter 8 8 8
-velocityjitter 312 312 312
-
-
+       type static
+       airfriction 8
+       alpha 200 256 812
+       bounce 1.500000
+       color 0xD400FF 0x571863
+       count 10
+       liquidfriction 8
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease 25
+       size 33 44
+       tex 48 55
+       velocityjitter 312 312 312
 effect raptor_cannon_muzzleflash
-count 16
-type spark
-color 0xD400FF 0x571863
-tex 8 15
-size 10 17
-alpha 1256 1512 56280
-airfriction 12
-originjitter 2 2 2
-velocityjitter 200 200 200
-velocitymultiplier 0.2
-sizeincrease -10
-stretchfactor 0.6
+       type spark
+       airfriction 12
+       alpha 1256 1512 56280
+       color 0xD400FF 0x571863
+       count 16
+       originjitter 2 2 2
+       sizeincrease -10
+       size 10 17
+       stretchfactor 0.600000
+       tex 8 15
+       velocityjitter 200 200 200
+       velocitymultiplier 0.200000
 effect raptor_cannon_muzzleflash
-countabsolute 1
-type static
-tex 48 55
-color 0xD400FF 0x571863
-size 32 32
-alpha 6056 20112 406280
-sizeincrease -100
-stretchfactor 0.1
-rotate -180 180 4000 -4000
-lightradius 150
-lightradiusfade 6000
-lightcolor 3 0 6
-
-// decal
+       type static
+       alpha 6056 20112 406280
+       color 0xD400FF 0x571863
+       countabsolute 1
+       lightcolor 3 0 6
+       lightradiusfade 6000
+       lightradius 150
+       rotate -180 180 4000 -4000
+       sizeincrease -100
+       size 32 32
+       stretchfactor 0.100000
+       tex 48 55
 effect raptor_bomb_impact
-countabsolute 1
-type decal
-tex 8 16
-size 84 84
-alpha 256 256 0
-originjitter 16 16 16
-rotate -180 180 0 0
-
-//spark vertical
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       originjitter 16 16 16
+       rotate -180 180 0 0
+       size 84 84
+       tex 8 16
 effect raptor_bomb_impact
-count 3
-type spark
-color 0xff9c00 0xff3c00
-tex 48 55
-size 20 40
-alpha 300 300 600
-originjitter 10 10 10
-velocityjitter 40 40 120
-stretchfactor 210
-sizeincrease 50
-
-//fire
+       type spark
+       alpha 300 300 600
+       color 0xff9c00 0xff3c00
+       count 3
+       originjitter 10 10 10
+       sizeincrease 50
+       size 20 40
+       stretchfactor 210
+       tex 48 55
+       velocityjitter 40 40 120
 effect raptor_bomb_impact
-count 4
-type static 
-color 0xff9c00 0xff3c00
-tex 48 55
-size 30 120
-alpha 300 300 500
-originjitter 10 10 10
-velocityjitter 950 950 0
-sizeincrease 230
-airfriction 2
-
-//smoke
+       type static
+       airfriction 2
+       alpha 300 300 500
+       color 0xff9c00 0xff3c00
+       count 4
+       originjitter 10 10 10
+       sizeincrease 230
+       size 30 120
+       tex 48 55
+       velocityjitter 950 950 0
 effect raptor_bomb_impact
-count 4
-type spark
-blend alpha
-tex 0 7
-size 120 180
-color 0x646364 0x151515
-alpha 428 428 600
-rotate -180 180 0 0
-velocityjitter 200 200 280
-velocityoffset 0 0 280
-originjitter 30 30 10
-stretchfactor 10
-
-//smoke 2
+       type spark
+       alpha 428 428 600
+       blend alpha
+       color 0x646364 0x151515
+       count 4
+       originjitter 30 30 10
+       rotate -180 180 0 0
+       size 120 180
+       stretchfactor 10
+       tex 0 7
+       velocityjitter 200 200 280
+       velocityoffset 0 0 280
 effect raptor_bomb_impact
-count 4
-//type alphastatic
-type spark
-blend alpha
-tex 0 7
-size 40 100
-color 0x646364 0x151515
-alpha 328 328 350
-rotate -180 180 0 0
-velocityjitter 200 200 300
-velocityoffset 0 0 580
-originjitter 30 30 10
-sizeincrease 60
-airfriction 0.6
-gravity 2
-
-// sparks
+       type spark
+       airfriction 0.600000
+       alpha 328 328 350
+       blend alpha
+       color 0x646364 0x151515
+       count 4
+       gravity 2
+       originjitter 30 30 10
+       rotate -180 180 0 0
+       sizeincrease 60
+       size 40 100
+       tex 0 7
+       velocityjitter 200 200 300
+       velocityoffset 0 0 580
 effect raptor_bomb_impact
-notunderwater
-count 5
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 3 5
-alpha 644 956 984
-gravity 1
-airfriction 0.3
-velocityoffset 0 0 350
-originjitter 16 16 16
-velocityjitter 174 174 924
-stretchfactor 2
-
+       type spark
+       airfriction 0.300000
+       alpha 644 956 984
+       color 0xffa35b 0xfff2be
+       count 5
+       gravity 1
+       notunderwater
+       originjitter 16 16 16
+       size 3 5
+       stretchfactor 2
+       tex 40 40
+       velocityjitter 174 174 924
+       velocityoffset 0 0 350
 effect raptor_bomb_spread
-notunderwater
-count 34
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 1 2
-alpha 644 956 1284
-gravity 1
-airfriction 1
-liquidfriction 0.8
-originjitter 110 110 110
-velocityjitter 324 324 324
-
-
-// generic explosion size:big (biggest explosion ever)
+       type spark
+       airfriction 1
+       alpha 644 956 1284
+       color 0xffa35b 0xfff2be
+       count 34
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 110 110 110
+       size 1 2
+       tex 40 40
+       velocityjitter 324 324 324
 effect explosion_big
-countabsolute 1
-type decal
-tex 8 16
-size 172 172
-alpha 256 256 0
-originjitter 23 23 23
-lightradius 600
-lightradiusfade 1750
-lightcolor 8 4 0
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 8 4 0
+       lightradiusfade 1750
+       lightradius 600
+       originjitter 23 23 23
+       size 172 172
+       tex 8 16
 effect explosion_big
-countabsolute 1
-type static
-tex 33 33 
-size 72 72
-alpha 56 56 330
-color 0x8f0d00 0xff5a00
-sizeincrease 4400
-// fire effect
+       type static
+       alpha 56 56 330
+       color 0x8f0d00 0xff5a00
+       countabsolute 1
+       sizeincrease 4400
+       size 72 72
+       tex 33 33
 effect explosion_big
-notunderwater
-count 64
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 133 144
-sizeincrease 45
-alpha 200 256 712
-airfriction 8
-liquidfriction 8
-originjitter 80 80 80
-velocityjitter 2512 2512 2512
-// fire rays
+       type static
+       airfriction 8
+       alpha 200 256 712
+       color 0x8f0d00 0xff5a00
+       count 64
+       liquidfriction 8
+       notunderwater
+       originjitter 80 80 80
+       sizeincrease 45
+       size 133 144
+       tex 48 55
+       velocityjitter 2512 2512 2512
 effect explosion_big
-notunderwater
-count 64
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 133 144
-sizeincrease 45
-alpha 200 256 800
-airfriction -5
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 512 512 512
-stretchfactor 10
-// smoke
+       type spark
+       airfriction -5
+       alpha 200 256 800
+       color 0x8f0d00 0xff5a00
+       count 64
+       liquidfriction 8
+       notunderwater
+       originjitter 40 40 40
+       sizeincrease 45
+       size 133 144
+       stretchfactor 10
+       tex 48 55
+       velocityjitter 512 512 512
 effect explosion_big
-type alphastatic
-notunderwater
-tex 0 8
-count 32
-size 50 100
-sizeincrease 244
-alpha 300 650 456
-velocityjitter 3444 3444 3444
-airfriction 8
-color 0x4F4B46 0x000000
-// bouncing sparks
+       type alphastatic
+       airfriction 8
+       alpha 300 650 456
+       color 0x4F4B46 0x000000
+       count 32
+       notunderwater
+       sizeincrease 244
+       size 50 100
+       tex 0 8
+       velocityjitter 3444 3444 3444
 effect explosion_big
-notunderwater
-count 34
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 3 4
-alpha 644 956 1284
-gravity 1
-airfriction 1
-liquidfriction 0.8
-velocityoffset 0 0 370
-originjitter 160 160 160
-velocityjitter 924 924 924
-stretchfactor 0.7
-// debris
+       type spark
+       airfriction 1
+       alpha 644 956 1284
+       color 0xffa35b 0xfff2be
+       count 34
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 160 160 160
+       size 3 4
+       stretchfactor 0.700000
+       tex 40 40
+       velocityjitter 924 924 924
+       velocityoffset 0 0 370
 effect explosion_big
-notunderwater
-count 16
-type alphastatic
-tex 66 68
-color 0xFFFFFF 0xcac5b4
-size 10 16
-alpha 444 1356 1184
-gravity 2.3
-airfriction 0.5
-velocityjitter 1800 1800 1800
-velocityoffset 0 0 970
-sizeincrease -5
-rotate -180 180 -1000 1000
-// underwater bubbles
+       type alphastatic
+       airfriction 0.500000
+       alpha 444 1356 1184
+       color 0xFFFFFF 0xcac5b4
+       count 16
+       gravity 2.300000
+       notunderwater
+       rotate -180 180 -1000 1000
+       sizeincrease -5
+       size 10 16
+       tex 66 68
+       velocityjitter 1800 1800 1800
+       velocityoffset 0 0 970
 effect explosion_big
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 444 444 444
-// underwatershockwave
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 160 160 160
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 444 444 444
 effect explosion_big
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 2900
-alpha 40 40 300
-velocitymultiplier 0.3
-
-
-// generic explosion size:medium (it leaves rising smoke for a longer time)
-// shockwave
+       type smoke
+       alpha 40 40 300
+       countabsolute 1
+       sizeincrease 2900
+       size 30 30
+       tex 33 33
+       underwater
+       velocitymultiplier 0.300000
 effect explosion_medium
-countabsolute 1
-type static
-tex 33 33 
-size 72 72
-alpha 56 56 330
-color 0x8f0d00 0xff5a00
-sizeincrease 2400
-// fire effect
+       type static
+       alpha 56 56 330
+       color 0x8f0d00 0xff5a00
+       countabsolute 1
+       sizeincrease 2400
+       size 72 72
+       tex 33 33
 effect explosion_medium
-notunderwater
-count 32
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 133 144
-sizeincrease 45
-alpha 200 256 712
-airfriction 8
-liquidfriction 8
-originjitter 30 30 30
-velocityjitter 1512 1512 1512
-rotate -180 180 -500 500
-// fire effect 2
+       type static
+       airfriction 8
+       alpha 200 256 712
+       color 0x8f0d00 0xff5a00
+       count 32
+       liquidfriction 8
+       notunderwater
+       originjitter 30 30 30
+       rotate -180 180 -500 500
+       sizeincrease 45
+       size 133 144
+       tex 48 55
+       velocityjitter 1512 1512 1512
 effect explosion_medium
-notunderwater
-count 32
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 73 94
-sizeincrease 40
-gravity -2
-alpha 200 256 612
-airfriction 8
-liquidfriction 8
-originjitter 30 30 30
-velocityjitter 1512 1512 1512
-rotate -180 180 -150 150
-// fire rays
+       type static
+       airfriction 8
+       alpha 200 256 612
+       color 0x8f0d00 0xff5a00
+       count 32
+       gravity -2
+       liquidfriction 8
+       notunderwater
+       originjitter 30 30 30
+       rotate -180 180 -150 150
+       sizeincrease 40
+       size 73 94
+       tex 48 55
+       velocityjitter 1512 1512 1512
 effect explosion_medium
-notunderwater
-count 14
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 43 74
-sizeincrease 40
-alpha 200 256 800
-airfriction -3
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 512 512 512
-stretchfactor 8
-// smoke 
+       type spark
+       airfriction -3
+       alpha 200 256 800
+       color 0x8f0d00 0xff5a00
+       count 14
+       liquidfriction 8
+       notunderwater
+       originjitter 40 40 40
+       sizeincrease 40
+       size 43 74
+       stretchfactor 8
+       tex 48 55
+       velocityjitter 512 512 512
 effect explosion_medium
-type alphastatic
-notunderwater
-tex 0 8
-count 5
-size 250 300
-sizeincrease -30
-alpha 300 650 756
-originjitter 100 100 100
-velocityjitter 200 200 200
-airfriction 3
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// smoke 2
+       type alphastatic
+       airfriction 3
+       alpha 300 650 756
+       color 0x4F4B46 0x000000
+       count 5
+       notunderwater
+       originjitter 100 100 100
+       rotate -180 180 -20 20
+       sizeincrease -30
+       size 250 300
+       tex 0 8
+       velocityjitter 200 200 200
 effect explosion_medium
-type alphastatic
-notunderwater
-tex 0 8
-count 10
-size 50 100
-sizeincrease 50
-gravity -0.3
-alpha 300 650 256
-originjitter 100 100 100
-velocityjitter 500 500 500
-velocityoffset 0 0 200
-airfriction 3
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-// smoke rays
+       type alphastatic
+       airfriction 3
+       alpha 300 650 256
+       color 0x4F4B46 0x000000
+       count 10
+       gravity -0.300000
+       notunderwater
+       originjitter 100 100 100
+       rotate -180 180 -20 20
+       sizeincrease 50
+       size 50 100
+       tex 0 8
+       velocityjitter 500 500 500
+       velocityoffset 0 0 200
 effect explosion_medium
-type spark
-notunderwater
-tex 0 8
-count 13
-size 150 200
-sizeincrease 100
-alpha 140 255 350
-velocityjitter 250 250 250
-originjitter 40 40 40
-color 0x4F4B46 0x000000
-stretchfactor 50
-// bouncing sparks
+       type spark
+       alpha 140 255 350
+       color 0x4F4B46 0x000000
+       count 13
+       notunderwater
+       originjitter 40 40 40
+       sizeincrease 100
+       size 150 200
+       stretchfactor 50
+       tex 0 8
+       velocityjitter 250 250 250
 effect explosion_medium
-notunderwater
-count 14
-type spark
-tex 40 40
-color 0xffa35b 0xfff2be
-size 2 3
-alpha 644 956 984
-gravity 1
-airfriction 1
-liquidfriction 0.8
-velocityoffset 0 0 370
-originjitter 100 100 100
-velocityjitter 624 624 624
-stretchfactor 0.7
-// underwater bubbles
+       type spark
+       airfriction 1
+       alpha 644 956 984
+       color 0xffa35b 0xfff2be
+       count 14
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 100 100 100
+       size 2 3
+       stretchfactor 0.700000
+       tex 40 40
+       velocityjitter 624 624 624
+       velocityoffset 0 0 370
 effect explosion_medium
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 444 444 444
-// underwatershockwave
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 160 160 160
+       size 3 3
+       tex 62 62
+       underwater
+       velocityjitter 444 444 444
 effect explosion_medium
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 2900
-alpha 40 40 300
-velocitymultiplier 0.3
-
-// generic explosion size:small (its fire only, made to support other explosions)
-// shockwave
+       type smoke
+       alpha 40 40 300
+       countabsolute 1
+       sizeincrease 2900
+       size 30 30
+       tex 33 33
+       underwater
+       velocitymultiplier 0.300000
 effect explosion_small
-countabsolute 1
-type static
-tex 33 33 
-size 22 22
-alpha 56 56 330
-color 0x8f0d00 0xff5a00
-sizeincrease 2400
-// fire effect
+       type static
+       alpha 56 56 330
+       color 0x8f0d00 0xff5a00
+       countabsolute 1
+       sizeincrease 2400
+       size 22 22
+       tex 33 33
 effect explosion_small
-notunderwater
-count 16
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 1 44
-sizeincrease 45
-alpha 200 256 1212
-airfriction 5
-liquidfriction 8
-velocityjitter 512 512 512
-rotate -180 180 -500 500
-// fire effect 2
+       type static
+       airfriction 5
+       alpha 200 256 1212
+       color 0x8f0d00 0xff5a00
+       count 16
+       liquidfriction 8
+       notunderwater
+       rotate -180 180 -500 500
+       sizeincrease 45
+       size 1 44
+       tex 48 55
+       velocityjitter 512 512 512
 effect explosion_small
-notunderwater
-count 16
-type static
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 73 94
-sizeincrease 40
-alpha 200 256 812
-airfriction 8
-liquidfriction 8
-velocityjitter 912 912 912
-rotate -180 180 -150 150
-// fire rays
+       type static
+       airfriction 8
+       alpha 200 256 812
+       color 0x8f0d00 0xff5a00
+       count 16
+       liquidfriction 8
+       notunderwater
+       rotate -180 180 -150 150
+       sizeincrease 40
+       size 73 94
+       tex 48 55
+       velocityjitter 912 912 912
 effect explosion_small
-notunderwater
-count 14
-type spark
-tex 48 55
-color 0x8f0d00 0xff5a00
-size 13 54
-sizeincrease 30
-alpha 200 256 1300
-airfriction -3
-liquidfriction 8
-originjitter 40 40 40
-velocityjitter 512 512 512
-stretchfactor 8
-// underwater bubbles
+       type spark
+       airfriction -3
+       alpha 200 256 1300
+       color 0x8f0d00 0xff5a00
+       count 14
+       liquidfriction 8
+       notunderwater
+       originjitter 40 40 40
+       sizeincrease 30
+       size 13 54
+       stretchfactor 8
+       tex 48 55
+       velocityjitter 512 512 512
 effect explosion_small
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 3
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 160 160 160
-velocityjitter 144 144 144
-// underwatershockwave
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 160 160 160
+       size 1 3
+       tex 62 62
+       underwater
+       velocityjitter 144 144 144
 effect explosion_small
-underwater
-type smoke
-countabsolute 1
-tex 33 33
-size 30 30
-sizeincrease 1200
-alpha 40 40 300
-
-// big smoke ( for spamming on damaged stuff )
+       type smoke
+       alpha 40 40 300
+       countabsolute 1
+       sizeincrease 1200
+       size 30 30
+       tex 33 33
+       underwater
 effect smoke_big
-type alphastatic
-notunderwater
-tex 0 8
-count 3
-size 30 60
-sizeincrease 15
-gravity -0.5
-alpha 200 750 200
-originjitter 55 55 55
-velocityjitter 140 140 200
-velocityoffset 0 0 200
-airfriction 4
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-
-// small smoke ( more precise than big one, for spamming on damaged parts like raptors spinner )
+       type alphastatic
+       airfriction 4
+       alpha 200 750 200
+       color 0x4F4B46 0x000000
+       count 3
+       gravity -0.500000
+       notunderwater
+       originjitter 55 55 55
+       rotate -180 180 -20 20
+       sizeincrease 15
+       size 30 60
+       tex 0 8
+       velocityjitter 140 140 200
+       velocityoffset 0 0 200
 effect smoke_small
-type alphastatic
-notunderwater
-tex 0 8
-count 3
-size 60 100
-sizeincrease -10
-gravity -0.5
-alpha 200 750 200
-velocityjitter 40 40 400
-velocityoffset 0 0 200
-airfriction 4
-color 0x4F4B46 0x000000
-rotate -180 180 -20 20
-
-// metal impact effect
-// used in qcsrc/server/mutators/sandbox.qc:   pointparticles(particleeffectnum("impact_metal"), self.origin, '0 0 0', 1);
+       type alphastatic
+       airfriction 4
+       alpha 200 750 200
+       color 0x4F4B46 0x000000
+       count 3
+       gravity -0.500000
+       notunderwater
+       rotate -180 180 -20 20
+       sizeincrease -10
+       size 60 100
+       tex 0 8
+       velocityjitter 40 40 400
+       velocityoffset 0 0 200
 effect impact_metal
-count 1
-type alphastatic
-tex 0 8
-size 3 6
-sizeincrease 10
-alpha 25 64 50
-gravity -0.01
-color 0x000000 0x886666
-originjitter 20 20 5
-// sparks
+       type alphastatic
+       alpha 25 64 50
+       color 0x000000 0x886666
+       count 1
+       gravity -0.010000
+       originjitter 20 20 5
+       sizeincrease 10
+       size 3 6
+       tex 0 8
 effect impact_metal
-count 2
-type spark
-tex 41 41
-color 0xFFCC22 0xFF4422
-size 2 2
-alpha 255 255 112
-bounce 1.8
-stretchfactor 0.5
-velocityjitter 200 200 300
-velocitymultiplier 2
-airfriction 2
-gravity 1
-
-// stone impact effect
-// used in qcsrc/server/mutators/sandbox.qc:   pointparticles(particleeffectnum("impact_stone"), self.origin, '0 0 0', 1);
+       type spark
+       airfriction 2
+       alpha 255 255 112
+       bounce 1.800000
+       color 0xFFCC22 0xFF4422
+       count 2
+       gravity 1
+       size 2 2
+       stretchfactor 0.500000
+       tex 41 41
+       velocityjitter 200 200 300
+       velocitymultiplier 2
 effect impact_stone
-count 1
-type alphastatic
-tex 0 8
-size 3 6
-sizeincrease 15
-alpha 50 128 75
-gravity -0.01
-color 0x000000 0xcc9966
-originjitter 20 20 5
-// debris
+       type alphastatic
+       alpha 50 128 75
+       color 0x000000 0xcc9966
+       count 1
+       gravity -0.010000
+       originjitter 20 20 5
+       sizeincrease 15
+       size 3 6
+       tex 0 8
 effect impact_stone
-notunderwater
-count 1
-type alphastatic
-tex 66 68
-color 0x000000 0x886644
-size 1 2
-alpha 450 750 300
-gravity 1.3
-airfriction 0.5
-bounce 1.2
-velocityjitter 124 124 324
-rotate -180 180 -1000 1000
-
-// wood impact effect
-// used in qcsrc/server/mutators/sandbox.qc:   pointparticles(particleeffectnum("impact_wood"), self.origin, '0 0 0', 1);
+       type alphastatic
+       airfriction 0.500000
+       alpha 450 750 300
+       bounce 1.200000
+       color 0x000000 0x886644
+       count 1
+       gravity 1.300000
+       notunderwater
+       rotate -180 180 -1000 1000
+       size 1 2
+       tex 66 68
+       velocityjitter 124 124 324
 effect impact_wood
-count 1
-type alphastatic
-tex 0 8
-size 3 6
-sizeincrease 10
-alpha 50 128 75
-gravity -0.01
-color 0x000000 0xcc9966
-originjitter 20 20 5
-// sparks
+       type alphastatic
+       alpha 50 128 75
+       color 0x000000 0xcc9966
+       count 1
+       gravity -0.010000
+       originjitter 20 20 5
+       sizeincrease 10
+       size 3 6
+       tex 0 8
 effect impact_wood
-count 2
-type spark
-tex 41 41
-color 0x221100 0x221100
-size 1 8
-alpha 255 255 75
-bounce 1.5
-velocityjitter 180 180 260
-velocitymultiplier 2
-airfriction 2
-gravity 1
-
-// flesh impact effect
-// used in qcsrc/server/mutators/sandbox.qc:   pointparticles(particleeffectnum("impact_flesh"), self.origin, '0 0 0', 1);
+       type spark
+       airfriction 2
+       alpha 255 255 75
+       bounce 1.500000
+       color 0x221100 0x221100
+       count 2
+       gravity 1
+       size 1 8
+       tex 41 41
+       velocityjitter 180 180 260
+       velocitymultiplier 2
 effect impact_flesh
-count 0.5
-type alphastatic
-tex 0 8
-size 8 12
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 11 11 11
-// blood splash
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x420000
+       count 0.500000
+       originjitter 11 11 11
+       size 8 12
+       tex 0 8
 effect impact_flesh
-count 0.3
-type blood
-tex 24 32
-size 2 6
-alpha 256 256 64
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 96 96 96
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-
-// hagar trail
-// smoke
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 0.300000
+       liquidfriction 4
+       size 2 6
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 96 96 96
+       velocitymultiplier 5
 effect tr_hagar
-trailspacing 4
-type smoke
-color 0x101010 0x000000
-tex 0 8
-size 3 2
-bounce 1
-sizeincrease 10
-alpha 300 400 780
-originjitter 1 1 1
-velocityjitter 1 1 1
-velocitymultiplier -0.02
-//gravity -0.11
-// fire
+       type smoke
+       alpha 300 400 780
+       bounce 1
+       color 0x101010 0x000000
+       originjitter 1 1 1
+       sizeincrease 10
+       size 3 2
+       tex 0 8
+       trailspacing 4
+       velocityjitter 1 1 1
+       velocitymultiplier -0.020000
 effect tr_hagar
-notunderwater
-trailspacing 4
-type static
-color 0xffdf72 0x811200
-tex 48 55
-size 5 2
-sizeincrease -15
-alpha 100 144 988
-airfriction 8
-velocityjitter 32 32 32
-velocitymultiplier -1.0
-// bubbles
+       type static
+       airfriction 8
+       alpha 100 144 988
+       color 0xffdf72 0x811200
+       notunderwater
+       sizeincrease -15
+       size 5 2
+       tex 48 55
+       trailspacing 4
+       velocityjitter 32 32 32
+       velocitymultiplier -1
 effect tr_hagar
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
-// laser damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0x404040 0x808080
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect damage_laser
-notunderwater
-count 3
-type smoke
-tex 0 8
-color 0x880000 0xff4400
-size 2 4
-sizeincrease 8
-alpha 128 16 128
-gravity 0
-originjitter 2 2 2
-velocityjitter 0.4 0.4 0.6
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-
-// shotgun damage effect, normal blood
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type smoke
+       airfriction -0.350000
+       alpha 128 16 128
+       color 0x880000 0xff4400
+       count 3
+       notunderwater
+       originjitter 2 2 2
+       rotate 0 180 -30 30
+       sizeincrease 8
+       size 2 4
+       tex 0 8
+       velocityjitter 0.4 0.4 0.6
 effect damage_shotgun
-count 0.6
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 0.600000
+       liquidfriction 4
+       size 2 4
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 64 64 64
+       velocitymultiplier 5
 effect damage_shotgun
-count 1
-type alphastatic
-tex 0 8
-size 8 16
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 1 1 1
-
-// shotgun damage effect, alien blood
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x420000
+       count 1
+       originjitter 1 1 1
+       size 8 16
+       tex 0 8
 effect damage_shotgun_alien
-count 0.6
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xDC9BCD 0xDC9BCD
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xDC9BCD 0xDC9BCD
+       count 0.600000
+       liquidfriction 4
+       size 2 4
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 64 64 64
+       velocitymultiplier 5
 effect damage_shotgun_alien
-count 1
-type alphastatic
-tex 0 8
-size 8 16
-alpha 100 256 400
-color 0x000000 0x204010
-originjitter 1 1 1
-
-// shotgun damage effect, robot blood
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x204010
+       count 1
+       originjitter 1 1 1
+       size 8 16
+       tex 0 8
 effect damage_shotgun_robot
-count 0.6
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xC0D890 0xC0D890
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 64 64 64
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xC0D890 0xC0D890
+       count 0.600000
+       liquidfriction 4
+       size 2 4
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 64 64 64
+       velocitymultiplier 5
 effect damage_shotgun_robot
-count 1
-type alphastatic
-tex 0 8
-size 8 16
-alpha 100 256 400
-color 0x000000 0x301860
-originjitter 1 1 1
-
-// uzi damage effect, normal blood
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x301860
+       count 1
+       originjitter 1 1 1
+       size 8 16
+       tex 0 8
 effect damage_uzi
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 0.300000
+       liquidfriction 4
+       size 2 4
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 32 32 32
+       velocitymultiplier 5
 effect damage_uzi
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 0 0 0
-
-// uzi damage effect, alien blood
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x420000
+       count 1
+       size 6 12
+       tex 0 8
 effect damage_uzi_alien
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xDC9BCD 0xDC9BCD
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xDC9BCD 0xDC9BCD
+       count 0.300000
+       liquidfriction 4
+       size 2 4
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 32 32 32
+       velocitymultiplier 5
 effect damage_uzi_alien
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x204010
-originjitter 0 0 0
-
-// uzi damage effect, robot blood
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x204010
+       count 1
+       size 6 12
+       tex 0 8
 effect damage_uzi_robot
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xC0D890 0xC0D890
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xC0D890 0xC0D890
+       count 0.300000
+       liquidfriction 4
+       size 2 4
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 32 32 32
+       velocitymultiplier 5
 effect damage_uzi_robot
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x301860
-originjitter 0 0 0
-
-// minelayer damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x301860
+       count 1
+       size 6 12
+       tex 0 8
 effect damage_minelayer
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 4 8
-alpha 512 64 1024
-gravity -0.5
-color 0x8f0d00 0xff5a00
-sizeincrease -15
-originjitter 2 2 2
-velocityjitter 22 22 50
-// smoke
+       type smoke
+       alpha 512 64 1024
+       color 0x8f0d00 0xff5a00
+       count 3
+       gravity -0.500000
+       notunderwater
+       originjitter 2 2 2
+       sizeincrease -15
+       size 4 8
+       tex 48 55
+       velocityjitter 22 22 50
 effect damage_minelayer
-notunderwater
-type alphastatic
-count 2
-tex 0 8
-size 4 8
-sizeincrease 5
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_minelayer
-notunderwater
-trailspacing 8
-lightradius 60
-lightradiusfade 280
-lightcolor 0.7 0.4 0.2*/
-
-// grenadelauncher damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 128 32 128
+       color 0x000000 0x111111
+       count 2
+       gravity -0.300000
+       notunderwater
+       originjitter 4 4 4
+       sizeincrease 5
+       size 4 8
+       tex 0 8
+       velocityjitter 11 11 50
 effect damage_grenadelauncher
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 4 8
-alpha 512 64 1024
-gravity -0.5
-color 0x8f0d00 0xff5a00
-sizeincrease -15
-originjitter 2 2 2
-velocityjitter 22 22 50
-// smoke
+       type smoke
+       alpha 512 64 1024
+       color 0x8f0d00 0xff5a00
+       count 3
+       gravity -0.500000
+       notunderwater
+       originjitter 2 2 2
+       sizeincrease -15
+       size 4 8
+       tex 48 55
+       velocityjitter 22 22 50
 effect damage_grenadelauncher
-notunderwater
-type alphastatic
-count 2
-tex 0 8
-size 4 8
-sizeincrease 5
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_grenadelauncher
-notunderwater
-trailspacing 8
-lightradius 60
-lightradiusfade 280
-lightcolor 0.7 0.4 0.2*/
-
-// electro damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 128 32 128
+       color 0x000000 0x111111
+       count 2
+       gravity -0.300000
+       notunderwater
+       originjitter 4 4 4
+       sizeincrease 5
+       size 4 8
+       tex 0 8
+       velocityjitter 11 11 50
 effect damage_electro
-notunderwater
-count 2
-type static
-tex 47 47
-color 0x66ffff 0x2288ff
-size 6 10
-sizeincrease -14
-alpha 48 8 48
-gravity -0.0001
-airfriction 0.2
-liquidfriction 0.8
-originjitter 3 3 3
-velocityjitter 8 8 16
-velocitymultiplier 0
-airfriction -0.5
-rotate 180 360 -30 30
-// plasma smoke
+       type static
+       airfriction -0.500000
+       alpha 48 8 48
+       color 0x66ffff 0x2288ff
+       count 2
+       gravity -0.000100
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 3 3 3
+       rotate 180 360 -30 30
+       sizeincrease -14
+       size 6 10
+       tex 47 47
+       velocityjitter 8 8 16
 effect damage_electro
-notunderwater
-count 4
-type smoke
-tex 0 8
-color 0x2244ff 0x002266
-size 4 8
-sizeincrease 10
-alpha 64 16 64
-gravity 0
-originjitter 4 4 4
-velocityjitter 0.4 0.4 0.6
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-// bouncing sparks
+       type smoke
+       airfriction -0.350000
+       alpha 64 16 64
+       color 0x2244ff 0x002266
+       count 4
+       notunderwater
+       originjitter 4 4 4
+       rotate 0 180 -30 30
+       sizeincrease 10
+       size 4 8
+       tex 0 8
+       velocityjitter 0.4 0.4 0.6
 effect damage_electro
-count 0.5
-type spark
-tex 66 68
-color 0x003090 0x00CCFF
-size 1 1
-alpha 768 64 256
-gravity 0.2
-airfriction 1
-bounce 1.5
-liquidfriction 0.8
-velocityoffset 0 0 0
-velocityjitter 32 32 32
-// light
-/*effect damage_electro
-notunderwater
-trailspacing 8
-lightradius 50
-lightradiusfade 220
-lightcolor 0.2 0.6 0.8*/
-
-// crylink damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type spark
+       airfriction 1
+       alpha 768 64 256
+       bounce 1.500000
+       color 0x003090 0x00CCFF
+       count 0.500000
+       gravity 0.200000
+       liquidfriction 0.800000
+       size 1 1
+       tex 66 68
+       velocityjitter 32 32 32
 effect damage_crylink
-notunderwater
-count 2
-type static
-tex 38 38
-color 0xff44ff 0x9966ff
-size 0.5 1
-sizeincrease -8
-alpha 48 16 48
-gravity -0.0001
-airfriction 0.6
-liquidfriction 0.8
-originjitter 3 3 3
-velocityjitter 10 10 20
-velocitymultiplier 0
-airfriction -0.5
-rotate 180 360 -30 30
-// plasma smoke
+       type static
+       airfriction -0.500000
+       alpha 48 16 48
+       color 0xff44ff 0x9966ff
+       count 2
+       gravity -0.000100
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 3 3 3
+       rotate 180 360 -30 30
+       sizeincrease -8
+       size 0.500000 1
+       tex 38 38
+       velocityjitter 10 10 20
 effect damage_crylink
-notunderwater
-count 4
-type smoke
-tex 0 8
-color 0x8844ff 0x662244
-size 5 10
-sizeincrease 6
-alpha 64 16 64
-gravity 0.001
-originjitter 4 4 4
-velocityjitter 0.4 0.4 0.6
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-// floating sparks
+       type smoke
+       airfriction -0.350000
+       alpha 64 16 64
+       color 0x8844ff 0x662244
+       count 4
+       gravity 0.001000
+       notunderwater
+       originjitter 4 4 4
+       rotate 0 180 -30 30
+       sizeincrease 6
+       size 5 10
+       tex 0 8
+       velocityjitter 0.4 0.4 0.6
 effect damage_crylink
-count 0.3
-type spark
-color 0x903090 0xFFD0FF
-size 0.5 0.5
-sizeincrease -5
-alpha 192 192 128
-gravity 0
-airfriction 0.2
-liquidfriction 0.8
-velocityoffset 0 0 0
-velocityjitter 12 12 12
-// light
-/*effect damage_crylink
-notunderwater
-trailspacing 8
-lightradius 50
-lightradiusfade 240
-lightcolor 0.6 0.2 0.8*/
-
-// hlac damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type spark
+       airfriction 0.200000
+       alpha 192 192 128
+       color 0x903090 0xFFD0FF
+       count 0.300000
+       liquidfriction 0.800000
+       sizeincrease -5
+       size 0.500000 0.500000
+       velocityjitter 12 12 12
 effect damage_hlac
-notunderwater
-count 3
-type smoke
-tex 0 8
-color 0x880000 0xff4400
-size 2 4
-sizeincrease 10
-alpha 128 16 128
-gravity 0
-originjitter 4 4 4
-velocityjitter 0.4 0.4 0.6
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-
-// nex damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type smoke
+       airfriction -0.350000
+       alpha 128 16 128
+       color 0x880000 0xff4400
+       count 3
+       notunderwater
+       originjitter 4 4 4
+       rotate 0 180 -30 30
+       sizeincrease 10
+       size 2 4
+       tex 0 8
+       velocityjitter 0.4 0.4 0.6
 effect damage_nex
-count 1
-type static
-tex 47 47
-color 0xffffff 0x88ffff
-size 5 10
-sizeincrease -14
-alpha 64 8 64
-gravity -0.0001
-airfriction 0.1
-liquidfriction 0.6
-originjitter 4 4 4
-velocityjitter 8 8 16
-velocitymultiplier 0
-airfriction -0.5
-rotate 180 360 -30 30
-// plasma smoke
+       type static
+       airfriction -0.500000
+       alpha 64 8 64
+       color 0xffffff 0x88ffff
+       count 1
+       gravity -0.000100
+       liquidfriction 0.600000
+       originjitter 4 4 4
+       rotate 180 360 -30 30
+       sizeincrease -14
+       size 5 10
+       tex 47 47
+       velocityjitter 8 8 16
 effect damage_nex
-count 2
-type smoke
-tex 0 8
-color 0x6688ff 0x226688
-size 4 8
-sizeincrease 8
-alpha 64 16 64
-gravity 0
-originjitter 2 2 2
-velocityjitter 0.5 0.5 0.8
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-// bouncing sparks
+       type smoke
+       airfriction -0.350000
+       alpha 64 16 64
+       color 0x6688ff 0x226688
+       count 2
+       originjitter 2 2 2
+       rotate 0 180 -30 30
+       sizeincrease 8
+       size 4 8
+       tex 0 8
+       velocityjitter 0.5 0.5 0.8
 effect damage_nex
-count 0.2
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 1 1
-alpha 255 255 112
-bounce 1.6
-stretchfactor 0.7
-velocityjitter 100 100 300
-velocitymultiplier 3
-airfriction 2
-gravity 1
-// light
-/*effect damage_nex
-trailspacing 8
-lightradius 60
-lightradiusfade 280
-lightcolor 0.6 0.8 0.8*/
-
-// minstanex damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type spark
+       airfriction 2
+       alpha 255 255 112
+       bounce 1.600000
+       color 0xD9FDFF 0xD9FDFF
+       count 0.200000
+       gravity 1
+       size 1 1
+       stretchfactor 0.700000
+       tex 41 41
+       velocityjitter 100 100 300
+       velocitymultiplier 3
 effect damage_minstanex
-count 2
-type static
-tex 47 47
-color 0xffffff 0x88ffff
-size 5 10
-sizeincrease -14
-alpha 64 8 64
-gravity -0.0001
-airfriction 0.1
-liquidfriction 0.6
-originjitter 4 4 4
-velocityjitter 8 8 16
-velocitymultiplier 0
-airfriction -0.5
-rotate 180 360 -30 30
-// plasma smoke
+       type static
+       airfriction -0.500000
+       alpha 64 8 64
+       color 0xffffff 0x88ffff
+       count 2
+       gravity -0.000100
+       liquidfriction 0.600000
+       originjitter 4 4 4
+       rotate 180 360 -30 30
+       sizeincrease -14
+       size 5 10
+       tex 47 47
+       velocityjitter 8 8 16
 effect damage_minstanex
-count 4
-type smoke
-tex 0 8
-color 0x6688ff 0x226688
-size 4 8
-sizeincrease 8
-alpha 64 16 64
-gravity 0
-originjitter 2 2 2
-velocityjitter 0.5 0.5 0.8
-velocitymultiplier 0
-airfriction -0.35
-rotate 0 180 -30 30
-// bouncing sparks
+       type smoke
+       airfriction -0.350000
+       alpha 64 16 64
+       color 0x6688ff 0x226688
+       count 4
+       originjitter 2 2 2
+       rotate 0 180 -30 30
+       sizeincrease 8
+       size 4 8
+       tex 0 8
+       velocityjitter 0.5 0.5 0.8
 effect damage_minstanex
-count 0.2
-type spark
-tex 41 41
-color 0xD9FDFF 0xD9FDFF
-size 1 1
-alpha 255 255 112
-bounce 1.6
-stretchfactor 0.7
-velocityjitter 100 100 300
-velocitymultiplier 3
-airfriction 2
-gravity 1
-// light
-/*effect damage_minstanex
-trailspacing 8
-lightradius 60
-lightradiusfade 240
-lightcolor 0.6 0.8 0.8*/
-
-// sniperrifle damage effect, normal blood
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type spark
+       airfriction 2
+       alpha 255 255 112
+       bounce 1.600000
+       color 0xD9FDFF 0xD9FDFF
+       count 0.200000
+       gravity 1
+       size 1 1
+       stretchfactor 0.700000
+       tex 41 41
+       velocityjitter 100 100 300
+       velocitymultiplier 3
 effect damage_rifle
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xA8FFFF 0xA8FFFFF
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xA8FFFF 0xA8FFFFF
+       count 0.300000
+       liquidfriction 4
+       size 2 4
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 32 32 32
+       velocitymultiplier 5
 effect damage_rifle
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x420000
-originjitter 0 0 0
-
-// sniperrifle damage effect, alien blood
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x420000
+       count 1
+       size 6 12
+       tex 0 8
 effect damage_rifle_alien
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xDC9BCD 0xDC9BCD
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xDC9BCD 0xDC9BCD
+       count 0.300000
+       liquidfriction 4
+       size 2 4
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 32 32 32
+       velocitymultiplier 5
 effect damage_rifle_alien
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x204010
-originjitter 0 0 0
-
-// sniperrifle damage effect, robot blood
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x204010
+       count 1
+       size 6 12
+       tex 0 8
 effect damage_rifle_robot
-count 0.3
-type blood
-tex 24 32
-size 2 4
-alpha 256 256 64
-color 0xC0D890 0xC0D890
-bounce -1
-airfriction 1
-liquidfriction 4
-velocityjitter 32 32 32
-velocitymultiplier 5
-staincolor 0x808080 0x808080
-staintex 16 24
-//blood mist
+       type blood
+       airfriction 1
+       alpha 256 256 64
+       bounce -1
+       color 0xC0D890 0xC0D890
+       count 0.300000
+       liquidfriction 4
+       size 2 4
+       staincolor 0x808080 0x808080
+       staintex 16 24
+       tex 24 32
+       velocityjitter 32 32 32
+       velocitymultiplier 5
 effect damage_rifle_robot
-count 1
-type alphastatic
-tex 0 8
-size 6 12
-alpha 100 256 400
-color 0x000000 0x301860
-originjitter 0 0 0
-
-// seeker damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 100 256 400
+       color 0x000000 0x301860
+       count 1
+       size 6 12
+       tex 0 8
 effect damage_seeker
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 4 8
-alpha 512 32 1024
-gravity -0.3
-color 0x8f0c00 0xff2200
-sizeincrease -10
-originjitter 2 2 2
-velocityjitter 22 22 50
-// smoke
+       type smoke
+       alpha 512 32 1024
+       color 0x8f0c00 0xff2200
+       count 3
+       gravity -0.300000
+       notunderwater
+       originjitter 2 2 2
+       sizeincrease -10
+       size 4 8
+       tex 48 55
+       velocityjitter 22 22 50
 effect damage_seeker
-notunderwater
-type alphastatic
-count 2
-tex 0 8
-size 2 4
-sizeincrease 10
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_seeker
-notunderwater
-trailspacing 8
-lightradius 65
-lightradiusfade 280
-lightcolor 0.7 0.5 0.1*/
-
-// hagar damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 128 32 128
+       color 0x000000 0x111111
+       count 2
+       gravity -0.300000
+       notunderwater
+       originjitter 4 4 4
+       sizeincrease 10
+       size 2 4
+       tex 0 8
+       velocityjitter 11 11 50
 effect damage_hagar
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 4 8
-alpha 512 32 1024
-gravity -0.3
-color 0x8f0c00 0xff3a00
-sizeincrease -10
-originjitter 2 2 2
-velocityjitter 22 22 50
-// smoke
+       type smoke
+       alpha 512 32 1024
+       color 0x8f0c00 0xff3a00
+       count 3
+       gravity -0.300000
+       notunderwater
+       originjitter 2 2 2
+       sizeincrease -10
+       size 4 8
+       tex 48 55
+       velocityjitter 22 22 50
 effect damage_hagar
-notunderwater
-type alphastatic
-count 2
-tex 0 8
-size 2 4
-sizeincrease 10
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_hagar
-notunderwater
-trailspacing 8
-lightradius 65
-lightradiusfade 280
-lightcolor 0.7 0.5 0.1*/
-
-// fireball damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 128 32 128
+       color 0x000000 0x111111
+       count 2
+       gravity -0.300000
+       notunderwater
+       originjitter 4 4 4
+       sizeincrease 10
+       size 2 4
+       tex 0 8
+       velocityjitter 11 11 50
 effect damage_fireball
-notunderwater
-count 4
-type smoke
-tex 48 55
-size 5 10
-alpha 256 16 512
-gravity -0.5
-color 0x8f0d00 0xff5a00
-sizeincrease -10
-originjitter 8 8 8
-velocityjitter 22 22 50
-// smoke
+       type smoke
+       alpha 256 16 512
+       color 0x8f0d00 0xff5a00
+       count 4
+       gravity -0.500000
+       notunderwater
+       originjitter 8 8 8
+       sizeincrease -10
+       size 5 10
+       tex 48 55
+       velocityjitter 22 22 50
 effect damage_fireball
-notunderwater
-type alphastatic
-count 4
-tex 0 8
-size 4 8
-sizeincrease 10
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 6 6 6
-velocityjitter 11 11 50
-// light
-/*effect damage_fireball
-notunderwater
-trailspacing 8
-lightradius 65
-lightradiusfade 280
-lightcolor 1.0 0.8 0.4*/
-
-// rocketlauncher damage effect
-// used in qcsrc/client/damage.qc:                     pointparticles(self.team, org, '0 0 0', 1);
+       type alphastatic
+       alpha 128 32 128
+       color 0x000000 0x111111
+       count 4
+       gravity -0.300000
+       notunderwater
+       originjitter 6 6 6
+       sizeincrease 10
+       size 4 8
+       tex 0 8
+       velocityjitter 11 11 50
 effect damage_rocketlauncher
-notunderwater
-count 3
-type smoke
-tex 48 55
-size 5 10
-alpha 512 64 1024
-gravity -0.7
-color 0x8f0c00 0xff2a00
-sizeincrease -10
-originjitter 4 4 4
-velocityjitter 22 22 30
-// smoke
+       type smoke
+       alpha 512 64 1024
+       color 0x8f0c00 0xff2a00
+       count 3
+       gravity -0.700000
+       notunderwater
+       originjitter 4 4 4
+       sizeincrease -10
+       size 5 10
+       tex 48 55
+       velocityjitter 22 22 30
 effect damage_rocketlauncher
-notunderwater
-type alphastatic
-count 3
-tex 0 8
-size 4 8
-sizeincrease 10
-alpha 128 32 128
-color 0x000000 0x111111
-gravity -0.3
-originjitter 4 4 4
-velocityjitter 11 11 50
-// light
-/*effect damage_rocketlauncher
-notunderwater
-trailspacing 8
-lightradius 60
-lightradiusfade 280
-lightcolor 0.8 0.6 0.2*/
-
-// fireflies
-// used nowhere in code
+       type alphastatic
+       alpha 128 32 128
+       color 0x000000 0x111111
+       count 3
+       gravity -0.300000
+       notunderwater
+       originjitter 4 4 4
+       sizeincrease 10
+       size 4 8
+       tex 0 8
+       velocityjitter 11 11 50
 effect fireflies
-count 1
-bounce -1
-airfriction 5
-time 1 2
-type static
-tex 38 38
-color 0xff9600 0xffefb8
-size 2 3
-sizeincrease -0.3
-alpha 256 256 70
-gravity 0
-originoffset 8 8 8
-originjitter 32 32 32
-velocityoffset 2 2 2
-velocityjitter 64 64 64
-//lightradius 50
-//lightradiusfade 50
-//lightcolor 1 0.9 0.7
-//lightshadow 1
-
-// heal ray muzzleflash
+       type static
+       airfriction 5
+       alpha 256 256 70
+       bounce -1
+       color 0xff9600 0xffefb8
+       count 1
+       originjitter 32 32 32
+       originoffset 8 8 8
+       sizeincrease -0.300000
+       size 2 3
+       tex 38 38
+       time 1 2
+       velocityjitter 64 64 64
+       velocityoffset 2 2 2
 effect healray_muzzleflash
-countabsolute 1
-type smoke
-color 0x283880 0x283880 // 0x202020 0x404040
-tex 65 65
-size 20 20
-alpha 256 256 512
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease -10
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 1.5 3 6
-
+       type smoke
+       alpha 256 256 512
+       color 0x283880 0x283880
+       countabsolute 1
+       lightcolor 1.5 3 6
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       sizeincrease -10
+       size 20 20
+       tex 65 65
+       velocityjitter 6 6 6
+       velocitymultiplier 0.010000
 effect healray_muzzleflash
-count 22
-type spark
-tex 71 73
-color 0xD9FDFF 0x00f0ff
-size 1 15
-sizeincrease 3
-alpha 50 150 1924
-originjitter 1 1 1
-velocityjitter 150 150 150
-velocitymultiplier 0.4
-airfriction 5
-stretchfactor 3.9
-
+       type spark
+       airfriction 5
+       alpha 50 150 1924
+       color 0xD9FDFF 0x00f0ff
+       count 22
+       originjitter 1 1 1
+       sizeincrease 3
+       size 1 15
+       stretchfactor 3.900000
+       tex 71 73
+       velocityjitter 150 150 150
+       velocitymultiplier 0.400000
 effect healray_muzzleflash
-count 4
-type spark
-tex 70 70
-color 0xD9FDFF 0x00f0ff
-size 1 1
-alpha 110 228 4024
-originjitter 1 1 1
-velocityjitter 650 650 650
-velocitymultiplier 1.1
-stretchfactor 0.2
-
-
-
-//healray impact
-
+       type spark
+       alpha 110 228 4024
+       color 0xD9FDFF 0x00f0ff
+       count 4
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.200000
+       tex 70 70
+       velocityjitter 650 650 650
+       velocitymultiplier 1.100000
 effect healray_impact
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-color 0xd800ff 0xd800ff
-originjitter 17 17 17
-lightradius 125
-lightradiusfade 450
-lightcolor 0 4.375 0
-// shockwave
+       type decal
+       alpha 256 256 0
+       color 0xd800ff 0xd800ff
+       countabsolute 1
+       lightcolor 0 4.4 0
+       lightradiusfade 450
+       lightradius 125
+       originjitter 17 17 17
+       size 32 32
+       tex 59 59
 effect healray_impact
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 1400
-color 0x00ff00 0x84c52f
-alpha 40 40 350
-velocitymultiplier 44
-// cloud of bouncing sparks
+       type smoke
+       alpha 40 40 350
+       color 0x00ff00 0x84c52f
+       countabsolute 1
+       sizeincrease 1400
+       size 32 32
+       tex 33 33
+       velocitymultiplier 44
 effect healray_impact
-count 30
-type spark
-tex 70 70
-color 0x00ff00 0x84c52f
-size 1 2
-alpha 156 300 1024
-gravity 2
-airfriction 6
-originjitter 1 1 1
-velocityjitter 1112 1112 1112
-// inner cloud of smoke
+       type spark
+       airfriction 6
+       alpha 156 300 1024
+       color 0x00ff00 0x84c52f
+       count 30
+       gravity 2
+       originjitter 1 1 1
+       size 1 2
+       tex 70 70
+       velocityjitter 1112 1112 1112
 effect healray_impact
-count 15
-type smoke
-color 0x00ff00 0x84c52f
-tex 40 40
-size 2 3 
-alpha 200 456 512
-airfriction 3
-gravity -2
-velocityjitter 120 120 420
-rotate -180 180 -90 90
-
-
-
-
-// big plasma muzzle flash
-
+       type smoke
+       airfriction 3
+       alpha 200 456 512
+       color 0x00ff00 0x84c52f
+       count 15
+       gravity -2
+       rotate -180 180 -90 90
+       size 2 3
+       tex 40 40
+       velocityjitter 120 120 420
 effect bigplasma_muzzleflash
-countabsolute 1
-type smoke
-color 0x283880 0x283880 // 0x202020 0x404040
-tex 65 65
-size 50 50
-alpha 256 256 812
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-sizeincrease -10
-velocitymultiplier 0.01
-lightradius 200
-lightradiusfade 2000
-lightcolor 1.5 3 6
-
+       type smoke
+       alpha 256 256 812
+       color 0x283880 0x283880
+       countabsolute 1
+       lightcolor 1.5 3 6
+       lightradiusfade 2000
+       lightradius 200
+       originjitter 1.5 1.5 1.5
+       sizeincrease -10
+       size 50 50
+       tex 65 65
+       velocityjitter 6 6 6
+       velocitymultiplier 0.010000
 effect bigplasma_muzzleflash
-countabsolute 1
-type smoke
-color 0x00f0ff 0x00f0ff
-tex 74 74
-size 20 20
-alpha 56 56 1112
-sizeincrease 300
-
+       type smoke
+       alpha 56 56 1112
+       color 0x00f0ff 0x00f0ff
+       countabsolute 1
+       sizeincrease 300
+       size 20 20
+       tex 74 74
 effect bigplasma_muzzleflash
-count 14
-type spark
-tex 51 55
-color 0xD9FDFF 0x00f0ff
-size 5 10
-sizeincrease 135
-alpha 50 150 1924
-originjitter 1 1 1
-velocityjitter 350 350 350
-velocitymultiplier 0.4
-airfriction 5
-stretchfactor 1.9
-
+       type spark
+       airfriction 5
+       alpha 50 150 1924
+       color 0xD9FDFF 0x00f0ff
+       count 14
+       originjitter 1 1 1
+       sizeincrease 135
+       size 5 10
+       stretchfactor 1.900000
+       tex 51 55
+       velocityjitter 350 350 350
+       velocitymultiplier 0.400000
 effect bigplasma_muzzleflash
-count 4
-type spark
-tex 70 70
-color 0xD9FDFF 0x00f0ff
-size 20 20
-alpha 110 228 4024
-originjitter 1 1 1
-velocityjitter 650 650 650
-velocitymultiplier 1.1
-stretchfactor 0.2
-
-
-// big plasma impact
-
+       type spark
+       alpha 110 228 4024
+       color 0xD9FDFF 0x00f0ff
+       count 4
+       originjitter 1 1 1
+       size 20 20
+       stretchfactor 0.200000
+       tex 70 70
+       velocityjitter 650 650 650
+       velocitymultiplier 1.100000
 effect bigplasma_impact
-countabsolute 1
-type decal
-tex 59 59
-size 32 32
-alpha 256 256 0
-originjitter 17 17 17
-lightradius 125
-lightradiusfade 450
-lightcolor 3.125 4.375 10
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 3.1 4.4 10
+       lightradiusfade 450
+       lightradius 125
+       originjitter 17 17 17
+       size 32 32
+       tex 59 59
 effect bigplasma_impact
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 1400
-color 0x80C0FF 0x80C0FF
-alpha 40 40 350
-velocitymultiplier 44
-// cloud of bouncing sparks
+       type smoke
+       alpha 40 40 350
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       sizeincrease 1400
+       size 32 32
+       tex 33 33
+       velocitymultiplier 44
 effect bigplasma_impact
-count 30
-type spark
-tex 70 70
-color 0x629dff 0x0018ff
-size 1 2
-alpha 156 300 1024
-gravity 2
-airfriction 6
-originjitter 1 1 1
-velocityjitter 1512 1512 1512
-// inner cloud of smoke
+       type spark
+       airfriction 6
+       alpha 156 300 1024
+       color 0x629dff 0x0018ff
+       count 30
+       gravity 2
+       originjitter 1 1 1
+       size 1 2
+       tex 70 70
+       velocityjitter 1512 1512 1512
 effect bigplasma_impact
-count 15
-type smoke
-color 0x629dff 0x0018ff
-tex 48 55
-size 20 24
-sizeincrease 555
-alpha 200 456 1512
-airfriction 30
-originjitter 20 20 20
-velocityjitter 320 320 320
-rotate -180 180 -9 9
-// smoke
+       type smoke
+       airfriction 30
+       alpha 200 456 1512
+       color 0x629dff 0x0018ff
+       count 15
+       originjitter 20 20 20
+       rotate -180 180 -9 9
+       sizeincrease 555
+       size 20 24
+       tex 48 55
+       velocityjitter 320 320 320
 effect bigplasma_impact
-type smoke
-count 16
-blend alpha
-tex 0 7
-size 60 30
-color 0x222222 0x000000
-alpha 128 328 390
-rotate -180 180 2 -2
-velocityjitter 100 100 200
-velocityoffset 0 0 180
-originjitter 80 80 10
-sizeincrease 30
-airfriction 0.04
-gravity 0.4
-// smoke in the middle
+       type smoke
+       airfriction 0.040000
+       alpha 128 328 390
+       blend alpha
+       color 0x222222 0x000000
+       count 16
+       gravity 0.400000
+       originjitter 80 80 10
+       rotate -180 180 2 -2
+       sizeincrease 30
+       size 60 30
+       tex 0 7
+       velocityjitter 100 100 200
+       velocityoffset 0 0 180
 effect bigplasma_impact
-type alphastatic
-count 10
-tex 0 7
-size 60 70
-color 0x222222 0x000000
-alpha 128 328 310
-rotate -180 180 20 -20
-velocityjitter 10 10 10
-originjitter 80 80 80
-sizeincrease -10
-airfriction 0.04
-gravity -0.2
-
-// redflag_touch -- effects for touching the red flag
-// used nowhere in code
+       type alphastatic
+       airfriction 0.040000
+       alpha 128 328 310
+       color 0x222222 0x000000
+       count 10
+       gravity -0.200000
+       originjitter 80 80 80
+       rotate -180 180 20 -20
+       sizeincrease -10
+       size 60 70
+       tex 0 7
+       velocityjitter 10 10 10
 effect redflag_touch
-count 35
-type spark
-tex 40 40
-color 0xFF0000 0x970000
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// blueflag_touch -- effects for touching the blue flag
-// used nowhere in code
+       type spark
+       airfriction 3
+       alpha 0 256 556
+       bounce 1.500000
+       color 0xFF0000 0x970000
+       count 35
+       gravity 1
+       originjitter 1 1 1
+       size 1 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect blueflag_touch
-count 35
-type spark
-tex 40 40
-color 0x0000FF 0x000097
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// red_pass
-// used nowhere in code
+       type spark
+       airfriction 3
+       alpha 0 256 556
+       bounce 1.500000
+       color 0x0000FF 0x000097
+       count 35
+       gravity 1
+       originjitter 1 1 1
+       size 1 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect red_pass
-trailspacing 64
-color 0xFF0000 0x970000
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+       type static
+       airfriction 5
+       alpha 64 128 64
+       color 0xFF0000 0x970000
+       sizeincrease 2
+       size 2 2
+       tex 32 32
+       trailspacing 64
 effect red_pass
-trailspacing 12
-color 0xFF0000 0x970000
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+       type static
+       airfriction 9
+       alpha 32 64 32
+       color 0xFF0000 0x970000
+       sizeincrease 8
+       size 1 1
+       tex 0 8
+       trailspacing 12
+       velocityjitter 64 64 64
 effect red_pass
-trailspacing 12
-color 0xFF0000 0x970000
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// blue_pass
-// used nowhere in code
+       type static
+       alpha 256 256 1280
+       color 0xFF0000 0x970000
+       size 4 4
+       trailspacing 12
 effect blue_pass
-trailspacing 64
-color 0x0000FF 0x000097
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+       type static
+       airfriction 5
+       alpha 64 128 64
+       color 0x0000FF 0x000097
+       sizeincrease 2
+       size 2 2
+       tex 32 32
+       trailspacing 64
 effect blue_pass
-trailspacing 12
-color 0x0000FF 0x000097
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+       type static
+       airfriction 9
+       alpha 32 64 32
+       color 0x0000FF 0x000097
+       sizeincrease 8
+       size 1 1
+       tex 0 8
+       trailspacing 12
+       velocityjitter 64 64 64
 effect blue_pass
-trailspacing 12
-color 0x0000FF 0x000097
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// red_cap -- red team capture effect
+       type static
+       alpha 256 256 1280
+       color 0x0000FF 0x000097
+       size 4 4
+       trailspacing 12
 effect red_cap
-count 500
-type spark
-tex 64 64
-color 0xFF0000 0x970000
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+       type spark
+       airfriction 2
+       alpha 0 256 100
+       bounce 1.500000
+       color 0xFF0000 0x970000
+       count 500
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 1000 1000 1500
+       velocitymultiplier 0.500000
 effect red_cap
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0xFF0000 0x970000
-
-// blue_cap -- blue team capture effect
+       type smoke
+       alpha 190 190 180
+       color 0xFF0000 0x970000
+       countabsolute 1
+       sizeincrease -80
+       size 150 150
+       tex 65 65
 effect blue_cap
-count 500
-type spark
-tex 64 64
-color 0x0000FF 0x000097
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+       type spark
+       airfriction 2
+       alpha 0 256 100
+       bounce 1.500000
+       color 0x0000FF 0x000097
+       count 500
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 1000 1000 1500
+       velocitymultiplier 0.500000
 effect blue_cap
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0x0000FF 0x000097
-
-// spawn_point_red -- red team idle spawn point effect
+       type smoke
+       alpha 190 190 180
+       color 0x0000FF 0x000097
+       countabsolute 1
+       sizeincrease -80
+       size 150 150
+       tex 65 65
 effect spawn_point_red
-count 37.5
-type static
-color 0xFF0F0F 0xFF0F0F
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_point_blue -- blue team idle spawn point effect
+       type static
+       airfriction 0.200000
+       alpha 64 128 128
+       color 0xFF0F0F 0xFF0F0F
+       count 37.500000
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 16 16 64
+       size 1 2
+       velocityjitter 32 32 0
 effect spawn_point_blue
-count 37.5
-type static
-color 0x0F0FFF 0x0F0FFF
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_point_yellow -- yellow team idle spawn point effect
+       type static
+       airfriction 0.200000
+       alpha 64 128 128
+       color 0x0F0FFF 0x0F0FFF
+       count 37.500000
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 16 16 64
+       size 1 2
+       velocityjitter 32 32 0
 effect spawn_point_yellow
-count 37.5
-type static
-color 0xFFFF0F 0xFFFF0F
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_point_pink -- pink team idle spawn point effect
+       type static
+       airfriction 0.200000
+       alpha 64 128 128
+       color 0xFFFF0F 0xFFFF0F
+       count 37.500000
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 16 16 64
+       size 1 2
+       velocityjitter 32 32 0
 effect spawn_point_pink
-count 37.5
-type static
-color 0xFF0FFF 0xFF0FFF
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_point_neutral -- neutral idle spawn point effect
+       type static
+       airfriction 0.200000
+       alpha 64 128 128
+       color 0xFF0FFF 0xFF0FFF
+       count 37.500000
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 16 16 64
+       size 1 2
+       velocityjitter 32 32 0
 effect spawn_point_neutral
-count 37.5
-type static
-color 0xFFFFFF 0xFFFFFF
-size 1.0 2.0
-alpha 64 128 128
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 16 16 64
-velocityjitter 32 32 0
-//lightradius 200
-//lighttime 0
-//lightcolor 0.4 0.9 0.9
-
-// spawn_event_red -- red team spawning effect
+       type static
+       airfriction 0.200000
+       alpha 64 128 128
+       color 0xFFFFFF 0xFFFFFF
+       count 37.500000
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 16 16 64
+       size 1 2
+       velocityjitter 32 32 0
 effect spawn_event_red
-count 100
-type spark
-tex 64 64
-color 0xFF0F0F 0xFF0F0F
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+       type spark
+       airfriction 2
+       alpha 0 256 256
+       bounce 1
+       color 0xFF0F0F 0xFF0F0F
+       count 100
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 500 500 500
+       velocitymultiplier 0.100000
 effect spawn_event_red
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0xFF0F0F 0xFF0F0F
-
-// spawn_event_blue -- blue team spawning effect
+       type smoke
+       alpha 190 190 180
+       color 0xFF0F0F 0xFF0F0F
+       countabsolute 1
+       sizeincrease -80
+       size 100 100
+       tex 65 65
 effect spawn_event_blue
-count 100
-type spark
-tex 64 64
-color 0x0F0FFF 0x0F0FFF
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+       type spark
+       airfriction 2
+       alpha 0 256 256
+       bounce 1
+       color 0x0F0FFF 0x0F0FFF
+       count 100
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 500 500 500
+       velocitymultiplier 0.100000
 effect spawn_event_blue
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0x0F0FFF 0x0F0FFF
-
-// spawn_event_yellow -- yellow team spawning effect
+       type smoke
+       alpha 190 190 180
+       color 0x0F0FFF 0x0F0FFF
+       countabsolute 1
+       sizeincrease -80
+       size 100 100
+       tex 65 65
 effect spawn_event_yellow
-count 100
-type spark
-tex 64 64
-color 0xFFFF0F 0xFFFF0F
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+       type spark
+       airfriction 2
+       alpha 0 256 256
+       bounce 1
+       color 0xFFFF0F 0xFFFF0F
+       count 100
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 500 500 500
+       velocitymultiplier 0.100000
 effect spawn_event_yellow
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0xFFFF0F 0xFFFF0F
-
-// spawn_event_pink -- pink team spawning effect
+       type smoke
+       alpha 190 190 180
+       color 0xFFFF0F 0xFFFF0F
+       countabsolute 1
+       sizeincrease -80
+       size 100 100
+       tex 65 65
 effect spawn_event_pink
-count 100
-type spark
-tex 64 64
-color 0xFF0FFF 0xFF0FFF
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+       type spark
+       airfriction 2
+       alpha 0 256 256
+       bounce 1
+       color 0xFF0FFF 0xFF0FFF
+       count 100
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 500 500 500
+       velocitymultiplier 0.100000
 effect spawn_event_pink
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0xFF0FFF 0xFF0FFF
-
-// spawn_event_neutral -- neutral spawning effect
+       type smoke
+       alpha 190 190 180
+       color 0xFF0FFF 0xFF0FFF
+       countabsolute 1
+       sizeincrease -80
+       size 100 100
+       tex 65 65
 effect spawn_event_neutral
-count 100
-type spark
-tex 64 64
-color 0xFFFFFF 0xFFFFFF
-size 1 1
-alpha 0 256 256
-stretchfactor 0.6
-//gravity 1
-bounce 1
-originjitter 1 1 1
-velocityjitter 500 500 500
-velocitymultiplier 0.1
-airfriction 2
+       type spark
+       airfriction 2
+       alpha 0 256 256
+       bounce 1
+       color 0xFFFFFF 0xFFFFFF
+       count 100
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 500 500 500
+       velocitymultiplier 0.100000
 effect spawn_event_neutral
-countabsolute 1
-type smoke
-tex 65 65
-size 100 100
-alpha 190 190 180
-sizeincrease -80
-color 0xFFFFFF 0xFFFFFF
-
-// nade effects
+       type smoke
+       alpha 190 190 180
+       color 0xFFFFFF 0xFFFFFF
+       countabsolute 1
+       sizeincrease -80
+       size 100 100
+       tex 65 65
 effect nade_blue
-trailspacing 1
-type smoke
-color 0x006cff 0x0600ff
-tex 65 65
-size 3 3
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0x006cff 0x0600ff
+       sizeincrease -1
+       size 3 3
+       tex 65 65
+       trailspacing 1
 effect nade_blue
-notunderwater
-trailspacing 8
-type smoke
-color 0x0600ff 0x9794ff
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+       type smoke
+       alpha 30 30 150
+       color 0x0600ff 0x9794ff
+       notunderwater
+       sizeincrease -10
+       size 15 25
+       tex 65 65
+       trailspacing 8
 effect nade_blue
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0x006cff 0x0600ff
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0x006cff 0x0600ff
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_red
-trailspacing 1
-type smoke
-color 0xff0000 0xff3c00
-tex 65 65
-size 3 3
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0xff0000 0xff3c00
+       sizeincrease -1
+       size 3 3
+       tex 65 65
+       trailspacing 1
 effect nade_red
-notunderwater
-trailspacing 8
-type smoke
-color 0xff0000 0xffa2a2
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+       type smoke
+       alpha 30 30 150
+       color 0xff0000 0xffa2a2
+       notunderwater
+       sizeincrease -10
+       size 15 25
+       tex 65 65
+       trailspacing 8
 effect nade_red
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0xff0000 0xff3c00
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0xff0000 0xff3c00
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_yellow
-trailspacing 1
-type smoke
-color 0xFFFF0F 0xFFFF0F
-tex 65 65
-size 3 3
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0xFFFF0F 0xFFFF0F
+       sizeincrease -1
+       size 3 3
+       tex 65 65
+       trailspacing 1
 effect nade_yellow
-notunderwater
-trailspacing 8
-type smoke
-color 0xFFFF0F 0xFFFF0F
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+       type smoke
+       alpha 30 30 150
+       color 0xFFFF0F 0xFFFF0F
+       notunderwater
+       sizeincrease -10
+       size 15 25
+       tex 65 65
+       trailspacing 8
 effect nade_yellow
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0xFFFF0F 0xFFFF0F
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0xFFFF0F 0xFFFF0F
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_pink
-trailspacing 1
-type smoke
-color 0xFF0FFF 0xFF0FFF
-tex 65 65
-size 3 3
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0xFF0FFF 0xFF0FFF
+       sizeincrease -1
+       size 3 3
+       tex 65 65
+       trailspacing 1
 effect nade_pink
-notunderwater
-trailspacing 8
-type smoke
-color 0xFF0FFF 0xFF0FFF
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+       type smoke
+       alpha 30 30 150
+       color 0xFF0FFF 0xFF0FFF
+       notunderwater
+       sizeincrease -10
+       size 15 25
+       tex 65 65
+       trailspacing 8
 effect nade_pink
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0xFF0FFF 0xFF0FFF
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0xFF0FFF 0xFF0FFF
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_neutral
-trailspacing 1
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 65 65
-size 3 3
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease -1
+       size 3 3
+       tex 65 65
+       trailspacing 1
 effect nade_neutral
-notunderwater
-trailspacing 8
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 65 65
-size 15 25
-sizeincrease -10
-alpha 30 30 150
-// bubbles
+       type smoke
+       alpha 30 30 150
+       color 0xFFFFFF 0xFFFFFF
+       notunderwater
+       sizeincrease -10
+       size 15 25
+       tex 65 65
+       trailspacing 8
 effect nade_neutral
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0xFFFFFF 0xFFFFFF
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
-
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0xFFFFFF 0xFFFFFF
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_red_burn
-trailspacing 1
-type smoke
-color 0xff0000 0xff3c00
-tex 65 65
-size 5 5
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0xff0000 0xff3c00
+       sizeincrease -1
+       size 5 5
+       tex 65 65
+       trailspacing 1
 effect nade_red_burn
-notunderwater
-trailspacing 64
-type smoke
-color 0xff0000 0xffa2a2
-tex 65 65
-size 45 25
-sizeincrease -30
-alpha 200 200 1000
-// bubbles
+       type smoke
+       alpha 200 200 1000
+       color 0xff0000 0xffa2a2
+       notunderwater
+       sizeincrease -30
+       size 45 25
+       tex 65 65
+       trailspacing 64
 effect nade_red_burn
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0xff0000 0xff3c00
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0xff0000 0xff3c00
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_red_burn
-trailspacing 16
-type smoke
-color 0xff0000 0xff3c00
-tex 71 73
-size 15 25
-sizeincrease -40
-rotate -180 180 20 -20
-originjitter 2 2 2
-velocityjitter 10 10 10
-alpha 300 900 1500
-
+       type smoke
+       alpha 300 900 1500
+       color 0xff0000 0xff3c00
+       originjitter 2 2 2
+       rotate -180 180 20 -20
+       sizeincrease -40
+       size 15 25
+       tex 71 73
+       trailspacing 16
+       velocityjitter 10 10 10
 effect nade_blue_burn
-trailspacing 1
-type smoke
-color 0x006cff 0x0600ff
-tex 65 65
-size 5 5
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0x006cff 0x0600ff
+       sizeincrease -1
+       size 5 5
+       tex 65 65
+       trailspacing 1
 effect nade_blue_burn
-notunderwater
-trailspacing 64
-type smoke
-color 0x0600ff 0x9794ff
-tex 65 65
-size 45 25
-sizeincrease -30
-alpha 200 200 1000
-// bubbles
+       type smoke
+       alpha 200 200 1000
+       color 0x0600ff 0x9794ff
+       notunderwater
+       sizeincrease -30
+       size 45 25
+       tex 65 65
+       trailspacing 64
 effect nade_blue_burn
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0x006cff 0x0600ff
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0x006cff 0x0600ff
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_blue_burn
-trailspacing 16
-type smoke
-color 0x006cff 0x0600ff
-tex 33 33
-size 25 25
-sizeincrease -30
-
+       type smoke
+       alpha 300 900 1500
+       color 0x006cff 0x0600ff
+       originjitter 2 2 2
+       rotate -180 180 20 -20
+       sizeincrease -40
+       size 15 25
+       tex 71 73
+       trailspacing 16
+       velocityjitter 10 10 10
 effect nade_yellow_burn
-trailspacing 1
-type smoke
-color 0xFFFF0F 0xFFFF0F
-tex 65 65
-size 5 5
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0xFFFF0F 0xFFFF0F
+       sizeincrease -1
+       size 5 5
+       tex 65 65
+       trailspacing 1
 effect nade_yellow_burn
-notunderwater
-trailspacing 64
-type smoke
-color 0xFFFF0F 0xFFFF0F
-tex 65 65
-size 45 25
-sizeincrease -30
-alpha 200 200 1000
-// bubbles
+       type smoke
+       alpha 200 200 1000
+       color 0xFFFF0F 0xFFFF0F
+       notunderwater
+       sizeincrease -30
+       size 45 25
+       tex 65 65
+       trailspacing 64
 effect nade_yellow_burn
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0xFFFF0F 0xFFFF0F
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0xFFFF0F 0xFFFF0F
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_yellow_burn
-trailspacing 16
-type smoke
-color 0xFFFF0F 0xFFFF0F
-tex 33 33
-size 25 25
-sizeincrease -30
-
+       type smoke
+       alpha 300 900 1500
+       color 0xFFFF0F 0xFFFF0F
+       originjitter 2 2 2
+       rotate -180 180 20 -20
+       sizeincrease -40
+       size 15 25
+       tex 71 73
+       trailspacing 16
+       velocityjitter 10 10 10
 effect nade_pink_burn
-trailspacing 1
-type smoke
-color 0xFF0FFF 0xFF0FFF
-tex 65 65
-size 5 5
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0xFF0FFF 0xFF0FFF
+       sizeincrease -1
+       size 5 5
+       tex 65 65
+       trailspacing 1
 effect nade_pink_burn
-notunderwater
-trailspacing 64
-type smoke
-color 0xFF0FFF 0xFF0FFF
-tex 65 65
-size 45 25
-sizeincrease -30
-alpha 200 200 1000
-// bubbles
+       type smoke
+       alpha 200 200 1000
+       color 0xFF0FFF 0xFF0FFF
+       notunderwater
+       sizeincrease -30
+       size 45 25
+       tex 65 65
+       trailspacing 64
 effect nade_pink_burn
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0xFF0FFF 0xFF0FFF
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0xFF0FFF 0xFF0FFF
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_pink_burn
-trailspacing 16
-type smoke
-color 0xFF0FFF 0xFF0FFF
-tex 33 33
-size 25 25
-sizeincrease -30
-
+       type smoke
+       alpha 300 900 1500
+       color 0xFF0FFF 0xFF0FFF
+       originjitter 2 2 2
+       rotate -180 180 20 -20
+       sizeincrease -40
+       size 15 25
+       tex 71 73
+       trailspacing 16
+       velocityjitter 10 10 10
 effect nade_neutral_burn
-trailspacing 1
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 65 65
-size 5 5
-sizeincrease -1
-alpha 100 100 250
-//gravity -0.11
-// fire
+       type smoke
+       alpha 100 100 250
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease -1
+       size 5 5
+       tex 65 65
+       trailspacing 1
 effect nade_neutral_burn
-notunderwater
-trailspacing 64
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 65 65
-size 45 25
-sizeincrease -30
-alpha 200 200 1000
-// bubbles
+       type smoke
+       alpha 200 200 1000
+       color 0xFFFFFF 0xFFFFFF
+       notunderwater
+       sizeincrease -30
+       size 45 25
+       tex 65 65
+       trailspacing 64
 effect nade_neutral_burn
-underwater
-trailspacing 16
-type bubble
-tex 62 62
-color 0xFFFFFF 0xFFFFFF
-size 1 1
-alpha 256 256 256
-gravity -0.125
-bounce 1.5
-liquidfriction 4
-velocityjitter 16 16 16
+       type bubble
+       alpha 256 256 256
+       bounce 1.500000
+       color 0xFFFFFF 0xFFFFFF
+       gravity -0.125000
+       liquidfriction 4
+       size 1 1
+       tex 62 62
+       trailspacing 16
+       underwater
+       velocityjitter 16 16 16
 effect nade_neutral_burn
-trailspacing 16
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 33 33
-size 25 25
-sizeincrease -30
-
+       type smoke
+       alpha 300 900 1500
+       color 0xFFFFFF 0xFFFFFF
+       originjitter 2 2 2
+       rotate -180 180 20 -20
+       sizeincrease -40
+       size 15 25
+       tex 71 73
+       trailspacing 16
+       velocityjitter 10 10 10
 effect nade_blue_explode
-countabsolute 1
-type decal
-tex 8 16
-size 88 88
-alpha 256 256 0
-originjitter 26 26 26
-lightradius 300
-lightradiusfade 1500
-lightcolor 20 20 100
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 20 20 100
+       lightradiusfade 1500
+       lightradius 300
+       originjitter 26 26 26
+       size 88 88
+       tex 8 16
 effect nade_blue_explode
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 1800
-color 0x80C0FF 0x80C0FF
-alpha 80 80 650
-velocitymultiplier 44
-// fire
+       type smoke
+       alpha 80 80 650
+       color 0x80C0FF 0x80C0FF
+       countabsolute 1
+       sizeincrease 1800
+       size 32 32
+       tex 33 33
+       velocitymultiplier 44
 effect nade_blue_explode
-notunderwater
-count 16
-type smoke
-color 0x629dff 0x0018ff
-tex 48 55
-size 20 24
-sizeincrease 555
-alpha 400 656 2000
-airfriction 30
-originjitter 50 50 50
-velocityjitter 320 320 320
-rotate -180 180 -9 9
-// fire stretched
+       type smoke
+       airfriction 30
+       alpha 400 656 2000
+       color 0x629dff 0x0018ff
+       count 16
+       notunderwater
+       originjitter 50 50 50
+       rotate -180 180 -9 9
+       sizeincrease 555
+       size 20 24
+       tex 48 55
+       velocityjitter 320 320 320
 effect nade_blue_explode
-count 8
-type spark
-tex 48 55
-color 0x629dff 0x0018ff
-size 60 90
-alpha 1500 3000 13000
-stretchfactor 80
-sizeincrease 40
-velocityjitter 30 30 30
-airfriction -9
-//smoke
+       type spark
+       airfriction -9
+       alpha 1500 3000 13000
+       color 0x629dff 0x0018ff
+       count 8
+       sizeincrease 40
+       size 60 90
+       stretchfactor 80
+       tex 48 55
+       velocityjitter 30 30 30
 effect nade_blue_explode
-type smoke
-count 32
-blend alpha
-tex 0 7
-size 60 30
-color 0x222222 0x000000
-alpha 128 328 390
-rotate -180 180 2 -2
-velocityjitter 200 200 200
-velocityoffset 0 0 180
-originjitter 50 50 10
-sizeincrease 50
-airfriction 0.04
-gravity 0.4
-// underwater bubbles
+       type smoke
+       airfriction 0.040000
+       alpha 128 328 390
+       blend alpha
+       color 0x222222 0x000000
+       count 32
+       gravity 0.400000
+       originjitter 50 50 10
+       rotate -180 180 2 -2
+       sizeincrease 50
+       size 60 30
+       tex 0 7
+       velocityjitter 200 200 200
+       velocityoffset 0 0 180
 effect nade_blue_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 6
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 196 196 196
-rotate 0 0 0 0
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 6
+       tex 62 62
+       underwater
+       velocityjitter 196 196 196
 effect nade_blue_explode
-notunderwater
-count 8
-type spark
-tex 40 40
-color 0x006cff 0x0600ff
-size 1 2
-alpha 644 956 484
-gravity 1
-airfriction 1
-bounce 1.6
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// notbouncing sparks
+       type spark
+       airfriction 1
+       alpha 644 956 484
+       bounce 1.600000
+       color 0x006cff 0x0600ff
+       count 8
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_blue_explode
-count 16
-type spark
-tex 40 40
-color 0x006cff 0x0600ff
-size 1 2
-alpha 644 956 684
-gravity 0.5
-airfriction 0.7
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// debris
+       type spark
+       airfriction 0.700000
+       alpha 644 956 684
+       color 0x006cff 0x0600ff
+       count 16
+       gravity 0.500000
+       liquidfriction 0.800000
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_blue_explode
-notunderwater
-count 12
-type alphastatic
-tex 66 68
-color 0x6a3d25 0xcac5b4
-size 2 6
-alpha 644 956 684
-gravity 1.3
-airfriction 0.5
-bounce 1.6
-velocityjitter 324 324 524
-rotate -180 180 -1000 1000
-
+       type smoke
+       alpha 644 956 2500
+       color 0x006cff 0x0600ff
+       count 8
+       notunderwater
+       originjitter 64 64 64
+       rotate -180 180 -100 100
+       size 20 40
+       tex 71 73
+       velocityjitter 324 324 324
 effect nade_red_explode
-countabsolute 1
-type decal
-tex 8 16
-size 88 88
-alpha 256 256 0
-originjitter 26 26 26
-lightradius 300
-lightradiusfade 1500
-lightcolor 100 20 20
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 100 20 20
+       lightradiusfade 1500
+       lightradius 300
+       originjitter 26 26 26
+       size 88 88
+       tex 8 16
 effect nade_red_explode
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 2200
-color 0xff0000 0xffa2a2
-alpha 80 80 650
-velocitymultiplier 44
-// fire
+       type smoke
+       alpha 80 80 650
+       color 0xff0000 0xffa2a2
+       countabsolute 1
+       sizeincrease 1800
+       size 32 32
+       tex 33 33
+       velocitymultiplier 44
 effect nade_red_explode
-notunderwater
-count 16
-type smoke
-color 0xff0000 0xff4200
-tex 48 55
-size 20 24
-sizeincrease 555
-alpha 400 656 2000
-airfriction 30
-originjitter 50 50 50
-velocityjitter 320 320 320
-rotate -180 180 -9 9
-// fire stretched
+       type smoke
+       airfriction 30
+       alpha 400 656 2000
+       color 0xff0000 0xff4200
+       count 16
+       notunderwater
+       originjitter 50 50 50
+       rotate -180 180 -9 9
+       sizeincrease 555
+       size 20 24
+       tex 48 55
+       velocityjitter 320 320 320
 effect nade_red_explode
-count 8
-type spark
-tex 48 55
-color 0xff0000 0xff4200
-size 60 90
-alpha 1500 3000 13000
-stretchfactor 80
-sizeincrease 40
-velocityjitter 30 30 30
-airfriction -9
-//smoke
+       type spark
+       airfriction -9
+       alpha 1500 3000 13000
+       color 0xff0000 0xff4200
+       count 8
+       sizeincrease 40
+       size 60 90
+       stretchfactor 80
+       tex 48 55
+       velocityjitter 30 30 30
 effect nade_red_explode
-type smoke
-count 32
-blend alpha
-tex 0 7
-size 60 30
-color 0x222222 0x000000
-alpha 128 328 390
-rotate -180 180 2 -2
-velocityjitter 200 200 200
-velocityoffset 0 0 180
-originjitter 50 50 10
-sizeincrease 50
-airfriction 0.04
-gravity 0.4
-// underwater bubbles
+       type smoke
+       airfriction 0.040000
+       alpha 128 328 390
+       blend alpha
+       color 0x222222 0x000000
+       count 32
+       gravity 0.400000
+       originjitter 50 50 10
+       rotate -180 180 2 -2
+       sizeincrease 50
+       size 60 30
+       tex 0 7
+       velocityjitter 200 200 200
+       velocityoffset 0 0 180
 effect nade_red_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 6
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 196 196 196
-rotate 0 0 0 0
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 6
+       tex 62 62
+       underwater
+       velocityjitter 196 196 196
 effect nade_red_explode
-notunderwater
-count 8
-type spark
-tex 40 40
-color 0xff0000 0xffa2a2
-size 1 2
-alpha 644 956 484
-gravity 1
-airfriction 1
-bounce 1.6
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// notbouncing sparks
+       type spark
+       airfriction 1
+       alpha 644 956 484
+       bounce 1.600000
+       color 0xff0000 0xffa2a2
+       count 8
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_red_explode
-count 16
-type spark
-tex 40 40
-color 0xff0000 0xffa2a2
-size 1 2
-alpha 644 956 684
-gravity 0.5
-airfriction 0.7
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// debris
+       type spark
+       airfriction 0.700000
+       alpha 644 956 684
+       color 0xff0000 0xffa2a2
+       count 16
+       gravity 0.500000
+       liquidfriction 0.800000
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_red_explode
-notunderwater
-count 8
-type smoke
-tex 71 73
-color 0xff0000 0xffa2a2
-size 20 40
-alpha 644 956 2500
-originjitter 64 64 64
-velocityjitter 324 324 324
-rotate -180 180 -100 100
-
+       type smoke
+       alpha 644 956 2500
+       color 0xff0000 0xffa2a2
+       count 8
+       notunderwater
+       originjitter 64 64 64
+       rotate -180 180 -100 100
+       size 20 40
+       tex 71 73
+       velocityjitter 324 324 324
 effect nade_yellow_explode
-countabsolute 1
-type decal
-tex 8 16
-size 88 88
-alpha 256 256 0
-originjitter 26 26 26
-lightradius 300
-lightradiusfade 1500
-lightcolor 100 20 20
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 100 20 20
+       lightradiusfade 1500
+       lightradius 300
+       originjitter 26 26 26
+       size 88 88
+       tex 8 16
 effect nade_yellow_explode
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 2200
-color 0xff0000 0xffa2a2
-alpha 80 80 650
-velocitymultiplier 44
-// fire
+       type smoke
+       alpha 80 80 650
+       color 0xff0000 0xffa2a2
+       countabsolute 1
+       sizeincrease 1800
+       size 32 32
+       tex 33 33
+       velocitymultiplier 44
 effect nade_yellow_explode
-notunderwater
-count 16
-type smoke
-color 0xFFFF0F 0xFFFF0F
-tex 48 55
-size 20 24
-sizeincrease 555
-alpha 400 656 2000
-airfriction 30
-originjitter 50 50 50
-velocityjitter 320 320 320
-rotate -180 180 -9 9
-// fire stretched
+       type smoke
+       airfriction 30
+       alpha 400 656 2000
+       color 0xFFFF0F 0xFFFF0F
+       count 16
+       notunderwater
+       originjitter 50 50 50
+       rotate -180 180 -9 9
+       sizeincrease 555
+       size 20 24
+       tex 48 55
+       velocityjitter 320 320 320
 effect nade_yellow_explode
-count 8
-type spark
-tex 48 55
-color 0xFFFF0F 0xFFFF0F
-size 60 90
-alpha 1500 3000 13000
-stretchfactor 80
-sizeincrease 40
-velocityjitter 30 30 30
-airfriction -9
-//smoke
+       type spark
+       airfriction -9
+       alpha 1500 3000 13000
+       color 0xFFFF0F 0xFFFF0F
+       count 8
+       sizeincrease 40
+       size 60 90
+       stretchfactor 80
+       tex 48 55
+       velocityjitter 30 30 30
 effect nade_yellow_explode
-type smoke
-count 32
-blend alpha
-tex 0 7
-size 60 30
-color 0x222222 0x000000
-alpha 128 328 390
-rotate -180 180 2 -2
-velocityjitter 200 200 200
-velocityoffset 0 0 180
-originjitter 50 50 10
-sizeincrease 50
-airfriction 0.04
-gravity 0.4
-// underwater bubbles
+       type smoke
+       airfriction 0.040000
+       alpha 128 328 390
+       blend alpha
+       color 0x222222 0x000000
+       count 32
+       gravity 0.400000
+       originjitter 50 50 10
+       rotate -180 180 2 -2
+       sizeincrease 50
+       size 60 30
+       tex 0 7
+       velocityjitter 200 200 200
+       velocityoffset 0 0 180
 effect nade_yellow_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 6
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 196 196 196
-rotate 0 0 0 0
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 6
+       tex 62 62
+       underwater
+       velocityjitter 196 196 196
 effect nade_yellow_explode
-notunderwater
-count 8
-type spark
-tex 40 40
-color 0xff0000 0xffa2a2
-size 1 2
-alpha 644 956 484
-gravity 1
-airfriction 1
-bounce 1.6
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// notbouncing sparks
+       type spark
+       airfriction 1
+       alpha 644 956 484
+       bounce 1.600000
+       color 0xff0000 0xffa2a2
+       count 8
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_yellow_explode
-count 16
-type spark
-tex 40 40
-color 0xff0000 0xffa2a2
-size 1 2
-alpha 644 956 684
-gravity 0.5
-airfriction 0.7
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// debris
+       type spark
+       airfriction 0.700000
+       alpha 644 956 684
+       color 0xff0000 0xffa2a2
+       count 16
+       gravity 0.500000
+       liquidfriction 0.800000
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_yellow_explode
-notunderwater
-count 8
-type smoke
-tex 71 73
-color 0xff0000 0xffa2a2
-size 20 40
-alpha 644 956 2500
-originjitter 64 64 64
-velocityjitter 324 324 324
-rotate -180 180 -100 100
-
+       type smoke
+       alpha 644 956 2500
+       color 0xff0000 0xffa2a2
+       count 8
+       notunderwater
+       originjitter 64 64 64
+       rotate -180 180 -100 100
+       size 20 40
+       tex 71 73
+       velocityjitter 324 324 324
 effect nade_pink_explode
-countabsolute 1
-type decal
-tex 8 16
-size 88 88
-alpha 256 256 0
-originjitter 26 26 26
-lightradius 300
-lightradiusfade 1500
-lightcolor 100 20 20
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 100 20 20
+       lightradiusfade 1500
+       lightradius 300
+       originjitter 26 26 26
+       size 88 88
+       tex 8 16
 effect nade_pink_explode
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 2200
-color 0xff0000 0xffa2a2
-alpha 80 80 650
-velocitymultiplier 44
-// fire
+       type smoke
+       alpha 80 80 650
+       color 0xff0000 0xffa2a2
+       countabsolute 1
+       sizeincrease 1800
+       size 32 32
+       tex 33 33
+       velocitymultiplier 44
 effect nade_pink_explode
-notunderwater
-count 16
-type smoke
-color 0xFF0FFF 0xFF0FFF
-tex 48 55
-size 20 24
-sizeincrease 555
-alpha 400 656 2000
-airfriction 30
-originjitter 50 50 50
-velocityjitter 320 320 320
-rotate -180 180 -9 9
-// fire stretched
+       type smoke
+       airfriction 30
+       alpha 400 656 2000
+       color 0xFF0FFF 0xFF0FFF
+       count 16
+       notunderwater
+       originjitter 50 50 50
+       rotate -180 180 -9 9
+       sizeincrease 555
+       size 20 24
+       tex 48 55
+       velocityjitter 320 320 320
 effect nade_pink_explode
-count 8
-type spark
-tex 48 55
-color 0xFF0FFF 0xFF0FFF
-size 60 90
-alpha 1500 3000 13000
-stretchfactor 80
-sizeincrease 40
-velocityjitter 30 30 30
-airfriction -9
-//smoke
+       type spark
+       airfriction -9
+       alpha 1500 3000 13000
+       color 0xFF0FFF 0xFF0FFF
+       count 8
+       sizeincrease 40
+       size 60 90
+       stretchfactor 80
+       tex 48 55
+       velocityjitter 30 30 30
 effect nade_pink_explode
-type smoke
-count 32
-blend alpha
-tex 0 7
-size 60 30
-color 0x222222 0x000000
-alpha 128 328 390
-rotate -180 180 2 -2
-velocityjitter 200 200 200
-velocityoffset 0 0 180
-originjitter 50 50 10
-sizeincrease 50
-airfriction 0.04
-gravity 0.4
-// underwater bubbles
+       type smoke
+       airfriction 0.040000
+       alpha 128 328 390
+       blend alpha
+       color 0x222222 0x000000
+       count 32
+       gravity 0.400000
+       originjitter 50 50 10
+       rotate -180 180 2 -2
+       sizeincrease 50
+       size 60 30
+       tex 0 7
+       velocityjitter 200 200 200
+       velocityoffset 0 0 180
 effect nade_pink_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 6
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 196 196 196
-rotate 0 0 0 0
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 6
+       tex 62 62
+       underwater
+       velocityjitter 196 196 196
 effect nade_pink_explode
-notunderwater
-count 8
-type spark
-tex 40 40
-color 0xff0000 0xffa2a2
-size 1 2
-alpha 644 956 484
-gravity 1
-airfriction 1
-bounce 1.6
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// notbouncing sparks
+       type spark
+       airfriction 1
+       alpha 644 956 484
+       bounce 1.600000
+       color 0xff0000 0xffa2a2
+       count 8
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_pink_explode
-count 16
-type spark
-tex 40 40
-color 0xff0000 0xffa2a2
-size 1 2
-alpha 644 956 684
-gravity 0.5
-airfriction 0.7
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// debris
+       type spark
+       airfriction 0.700000
+       alpha 644 956 684
+       color 0xff0000 0xffa2a2
+       count 16
+       gravity 0.500000
+       liquidfriction 0.800000
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_pink_explode
-notunderwater
-count 8
-type smoke
-tex 71 73
-color 0xff0000 0xffa2a2
-size 20 40
-alpha 644 956 2500
-originjitter 64 64 64
-velocityjitter 324 324 324
-rotate -180 180 -100 100
-
+       type smoke
+       alpha 644 956 2500
+       color 0xff0000 0xffa2a2
+       count 8
+       notunderwater
+       originjitter 64 64 64
+       rotate -180 180 -100 100
+       size 20 40
+       tex 71 73
+       velocityjitter 324 324 324
 effect nade_neutral_explode
-countabsolute 1
-type decal
-tex 8 16
-size 88 88
-alpha 256 256 0
-originjitter 26 26 26
-lightradius 300
-lightradiusfade 1500
-lightcolor 100 20 20
-// shockwave
+       type decal
+       alpha 256 256 0
+       countabsolute 1
+       lightcolor 100 20 20
+       lightradiusfade 1500
+       lightradius 300
+       originjitter 26 26 26
+       size 88 88
+       tex 8 16
 effect nade_neutral_explode
-type smoke
-countabsolute 1
-tex 33 33
-size 32 32
-sizeincrease 2200
-color 0xff0000 0xffa2a2
-alpha 80 80 650
-velocitymultiplier 44
-// fire
+       type smoke
+       alpha 80 80 650
+       color 0xff0000 0xffa2a2
+       countabsolute 1
+       sizeincrease 1800
+       size 32 32
+       tex 33 33
+       velocitymultiplier 44
 effect nade_neutral_explode
-notunderwater
-count 16
-type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 48 55
-size 20 24
-sizeincrease 555
-alpha 400 656 2000
-airfriction 30
-originjitter 50 50 50
-velocityjitter 320 320 320
-rotate -180 180 -9 9
-// fire stretched
+       type smoke
+       airfriction 30
+       alpha 400 656 2000
+       color 0xFFFFFF 0xFFFFFF
+       count 16
+       notunderwater
+       originjitter 50 50 50
+       rotate -180 180 -9 9
+       sizeincrease 555
+       size 20 24
+       tex 48 55
+       velocityjitter 320 320 320
 effect nade_neutral_explode
-count 8
-type spark
-tex 48 55
-color 0xFFFFFF 0xFFFFFF
-size 60 90
-alpha 1500 3000 13000
-stretchfactor 80
-sizeincrease 40
-velocityjitter 30 30 30
-airfriction -9
-//smoke
+       type spark
+       airfriction -9
+       alpha 1500 3000 13000
+       color 0xFFFFFF 0xFFFFFF
+       count 8
+       sizeincrease 40
+       size 60 90
+       stretchfactor 80
+       tex 48 55
+       velocityjitter 30 30 30
 effect nade_neutral_explode
-type smoke
-count 32
-blend alpha
-tex 0 7
-size 60 30
-color 0x222222 0x000000
-alpha 128 328 390
-rotate -180 180 2 -2
-velocityjitter 200 200 200
-velocityoffset 0 0 180
-originjitter 50 50 10
-sizeincrease 50
-airfriction 0.04
-gravity 0.4
-// underwater bubbles
+       type smoke
+       airfriction 0.040000
+       alpha 128 328 390
+       blend alpha
+       color 0x222222 0x000000
+       count 32
+       gravity 0.400000
+       originjitter 50 50 10
+       rotate -180 180 2 -2
+       sizeincrease 50
+       size 60 30
+       tex 0 7
+       velocityjitter 200 200 200
+       velocityoffset 0 0 180
 effect nade_neutral_explode
-underwater
-count 32
-type bubble
-tex 62 62
-color 0x404040 0x808080
-size 3 6
-alpha 128 256 64
-gravity -0.125
-bounce 1.5
-liquidfriction 0.25
-originjitter 16 16 16
-velocityjitter 196 196 196
-rotate 0 0 0 0
-// bouncing sparks
+       type bubble
+       alpha 128 256 64
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 32
+       gravity -0.125000
+       liquidfriction 0.250000
+       originjitter 16 16 16
+       size 3 6
+       tex 62 62
+       underwater
+       velocityjitter 196 196 196
 effect nade_neutral_explode
-notunderwater
-count 8
-type spark
-tex 40 40
-color 0xff0000 0xffa2a2
-size 1 2
-alpha 644 956 484
-gravity 1
-airfriction 1
-bounce 1.6
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// notbouncing sparks
+       type spark
+       airfriction 1
+       alpha 644 956 484
+       bounce 1.600000
+       color 0xff0000 0xffa2a2
+       count 8
+       gravity 1
+       liquidfriction 0.800000
+       notunderwater
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_neutral_explode
-count 16
-type spark
-tex 40 40
-color 0xff0000 0xffa2a2
-size 1 2
-alpha 644 956 684
-gravity 0.5
-airfriction 0.7
-liquidfriction 0.8
-velocityoffset 0 0 80
-originjitter 16 16 16
-velocityjitter 424 424 624
-// debris
+       type spark
+       airfriction 0.700000
+       alpha 644 956 684
+       color 0xff0000 0xffa2a2
+       count 16
+       gravity 0.500000
+       liquidfriction 0.800000
+       originjitter 16 16 16
+       size 1 2
+       tex 40 40
+       velocityjitter 424 424 624
+       velocityoffset 0 0 80
 effect nade_neutral_explode
-notunderwater
-count 8
-type smoke
-tex 71 73
-color 0xff0000 0xffa2a2
-size 20 40
-alpha 644 956 2500
-originjitter 64 64 64
-velocityjitter 324 324 324
-rotate -180 180 -100 100
-
-// shockwave_attack
-// used nowhere in code
-effect shockwave_attack // glow and light
-       //countabsolute 1
-       //type smoke
-       //color 0xcc0000 0xff0000
-       //tex 65 65
-       //size 10 15
-       //alpha 256 512 6280
-       //airfriction 10
-       //sizeincrease 1.5
-       //stretchfactor 2
-       //lightradius 200
-       //lightradiusfade 2000
-       //lightcolor 3 0.1 0.1
-effect shockwave_attack // electricity
-       count 1
+       type smoke
+       alpha 644 956 2500
+       color 0xff0000 0xffa2a2
+       count 8
+       notunderwater
+       originjitter 64 64 64
+       rotate -180 180 -100 100
+       size 20 40
+       tex 71 73
+       velocityjitter 324 324 324
+effect shockwave_attack
        type spark
-       color 0xb44215 0xff0000
-       tex 43 43
-       size 5 7
-       bounce 0
-       alpha 4096 4096 20000
        airfriction 1
+       alpha 4096 4096 20000
+       color 0xb44215 0xff0000
+       count 1
        originjitter 2 2 2
+       rotate -180 180 4000 -4000
+       sizeincrease 1.500000
+       size 5 7
+       stretchfactor 2.300000
+       tex 43 43
        velocityjitter 10 10 10
        velocitymultiplier 10
-       sizeincrease 1.5
-       stretchfactor 2.3
-       rotate -180 180 4000 -4000
-effect shockwave_attack // fire
-       count 1
+effect shockwave_attack
        type spark
-       color 0xff4200 0xff0000
-       tex 8 15
-       size 7 9
-       bounce 0
-       alpha 4096 4096 20000
        airfriction 1
+       alpha 4096 4096 20000
+       color 0xff4200 0xff0000
+       count 1
        originjitter 2 2 2
+       sizeincrease 1.500000
+       size 7 9
+       stretchfactor 2
+       tex 8 15
        velocityjitter 10 10 10
        velocitymultiplier 10
-       sizeincrease 1.5
-       stretchfactor 2
-
-// ARC
-// used in qcsrc/server/w_arc.qc
-effect arc_lightning // impact decal
-       countabsolute 1
+effect arc_lightning
        type decal
-       tex 16 32 // fps killer, spamming decals like that
-       size 16 16
        alpha 32 32 0
-       originjitter 2 2 2
-       lightradius 50
+       countabsolute 1
+       lightcolor 3.1 4.4 10
        lightradiusfade 200
-       lightcolor 3.125 4.375 10
-
-effect arc_lightning // impact sparks
+       lightradius 50
+       originjitter 2 2 2
+       size 16 16
+       tex 16 32
+effect arc_lightning
        type static
+       airfriction 110
+       alpha 256 256 512
+       color 0xDDFDFF 0xFDFDFF
        count 100
-       tex 71 74
+       originjitter 20 20 20
        rotate 0 360 -36000 36000
-       stretchfactor 1
-       size 0 5
        sizeincrease -5
-       color 0xDDFDFF 0xFDFDFF
-       alpha 256 256 512
-       originjitter 20 20 20
+       size 0 5
+       stretchfactor 1
+       tex 71 74
        velocityjitter 250 250 250
        velocitymultiplier 100
-       airfriction 110
-
-effect arc_lightning // impact sparks (underwater)
+effect arc_lightning
        type static
-       underwater
+       airfriction 5
+       alpha 256 256 512
+       color 0xDDFDFF 0xFDFDFF
        count 100
-       tex 71 74
+       liquidfriction 5
+       orientation spark
+       originjitter 20 20 20
        rotate 0 360 -36000 36000
-       stretchfactor 1
-       size 0 5
        sizeincrease -5
-       color 0xDDFDFF 0xFDFDFF
-       alpha 256 256 512
-       originjitter 20 20 20
+       size 0 5
+       stretchfactor 1
+       tex 71 74
+       underwater
        velocityjitter 250 250 250
-       // underwater
-       orientation spark
        velocitymultiplier 20
-       airfriction 5
-       liquidfriction 5
-
-effect arc_beam // sparks on beam
+effect arc_beam
        type spark
-       stretchfactor 1
-       rotate 0 360 360 1000
-       time 0.05 0.05
-       color 0xfafad2 0xffffff
-       alpha 256 256 16384
        airfriction -10
-       originoffset 0 0 0
-       relativeoriginoffset 10 0 0
+       alpha 256 256 16384
+       color 0xfafad2 0xffffff
        originjitter 3 3 3
-       velocityoffset 0 0 0
+       relativeoriginoffset 10 0 0
+       rotate 0 360 360 1000
+       stretchfactor 1
+       tex 71 74
+       time 0.050000 0.050000
+       trailspacing 10
        velocityjitter 100 100 100
        velocitymultiplier 200
-       //lightcolor 0 0 0
-       trailspacing 10
-       tex 71 74
-
-effect arc_beam // sparks on beam (underwater)
+effect arc_beam
        type spark
-       underwater
-       stretchfactor 1
-       rotate 0 360 360 1000
-       time 0.001 0.001
-       color 0xfafad2 0xffffff
        alpha 256 256 16384
+       color 0xfafad2 0xffffff
        liquidfriction -10
-       originoffset 0 0 0
-       relativeoriginoffset 10 0 0
        originjitter 30 30 30
-       velocityoffset 0 0 0
+       relativeoriginoffset 10 0 0
+       rotate 0 360 360 1000
+       stretchfactor 1
+       tex 71 74
+       time 0.001000 0.001000
+       trailspacing 10
+       underwater
        velocityjitter 100 100 100
        velocitymultiplier 200
-       //lightcolor 0 0 0
-       trailspacing 10
-       tex 71 74
-
-// ARC healing effect
-effect arc_beam_heal // bubble this...
-       type static
-       trailspacing 1500
-       tex 74 74
-       color 0x20FF20 0x40FF40
-       size 0.1 0.1
-       sizeincrease 20
-       alpha 2048 2048 256
-       //time 0.8 0.8
-       airfriction -20
+effect arc_beam_heal
        type smoke
+       airfriction -20
+       alpha 2048 2048 256
+       color 0x20FF20 0x40FF40
        relativeoriginoffset 5 0 0
        relativevelocityoffset 100 0 0
+       sizeincrease 20
+       size 0.100000 0.100000
+       tex 74 74
+       trailspacing 1500
        velocityjitter 3 3 3
        velocitymultiplier 200
-
-effect arc_beam_healimpact // healing "aura"
+effect arc_beam_healimpact
        type smoke
+       alpha 40 40 350
+       color 0x00ff00 0x84c52f
        countabsolute 1
-       tex 33 33
-       size 32 32
+       lightcolor 0 4.4 0
+       lightradiusfade 150
+       lightradius 20
        sizeincrease -1000
-       color 0x00ff00 0x84c52f
-       alpha 40 40 350
+       size 32 32
+       tex 33 33
        velocitymultiplier 44
-       lightradius 20
-       lightradiusfade 150
-       lightcolor 0 4.375 0
-
-effect arc_beam_healimpact // rising "smoke"
+effect arc_beam_healimpact
        type smoke
-       count 15
-       color 0x00ff00 0x84c52f
-       tex 40 40
-       size 0.5 1
-       alpha 200 456 512
        airfriction 3
+       alpha 200 456 512
+       color 0x00ff00 0x84c52f
+       count 15
        gravity -2
-       velocityjitter 120 120 420
        rotate -180 180 -90 90
-
-effect arc_smoke // arc heat smoke  (notunderwater)
-       notunderwater
-       count 2
+       size 0.500000 1
+       tex 40 40
+       velocityjitter 120 120 420
+effect arc_smoke
        type smoke
-       tex 0 8
+       airfriction 1
+       alpha 32 64 48
        color 0x4c453f 0x2a241f
-       size 5 10
+       count 2
+       gravity -0.125000
+       notunderwater
+       rotate 0 360 -180 180
        sizeincrease 10
-       alpha 32 64 48
-       gravity -0.125
-       originjitter 0 0 0
+       size 5 10
+       tex 0 8
        velocityjitter 0 0 16
-       airfriction 1
-       rotate 0 360 -180 180
-
-effect arc_smoke // arc heat bubbles  (underwater)
-       underwater
-       count 2
+effect arc_smoke
        type bubble
-       tex 62 62
-       color 0x404040 0x808080
-       size 0.1 1
        alpha 170 256 64
-       gravity -0.125
-       bounce 1.5
-       liquidfriction 0.25
+       bounce 1.500000
+       color 0x404040 0x808080
+       count 2
+       gravity -0.125000
+       liquidfriction 0.250000
        originjitter 6 6 6
+       size 0.100000 1
+       tex 62 62
+       underwater
        velocityjitter 16 16 16
-
-effect arc_overheat // arc overheat electric bolts
-       tex 43 43
-       count 24
+effect arc_overheat
        type spark
-       color 0xffffff 0x9271fb
-       size 6 12
-       sizeincrease -24
-       alpha 128 128 292
-       gravity -0.4
        airfriction 5
+       alpha 128 128 292
+       color 0xffffff 0x9271fb
+       count 24
+       gravity -0.400000
        liquidfriction 10
-       velocityjitter 256 256 256
        originjitter 10 10 10
-       
-effect arc_overheat_fire // arc overheat bouncing sparks
-       count 1
+       sizeincrease -24
+       size 6 12
+       tex 43 43
+       velocityjitter 256 256 256
+effect arc_overheat_fire
        type spark
-       color 0x4444ff 0xeeeeff
-       size 0.4 1
        alpha 0 256 640
+       bounce 1.500000
+       color 0x4444ff 0xeeeeff
+       count 1
        gravity 1
-       bounce 1.5
-       velocityoffset 0 0 80
-       velocityjitter 92 92 92
-       originjitter 6 6 6
        liquidfriction 5
+       originjitter 6 6 6
+       size 0.400000 1
+       velocityjitter 92 92 92
        velocitymultiplier 80
-
-// yellowflag_touch -- effects for touching the yellow flag
-// used nowhere in code
+       velocityoffset 0 0 80
 effect yellowflag_touch
-count 35
-type spark
-tex 40 40
-color 0xFFFF0F 0xFFFF0F
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// pinkflag_touch -- effects for touching the pink flag
-// used nowhere in code
+       type spark
+       airfriction 3
+       alpha 0 256 556
+       bounce 1.500000
+       color 0xFFFF0F 0xFFFF0F
+       count 35
+       gravity 1
+       originjitter 1 1 1
+       size 1 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect pinkflag_touch
-count 35
-type spark
-tex 40 40
-color 0xFF0FFF 0xFF0FFF
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// neutralflag_touch -- effects for touching the neutral flag
-// used nowhere in code
+       type spark
+       airfriction 3
+       alpha 0 256 556
+       bounce 1.500000
+       color 0xFF0FFF 0xFF0FFF
+       count 35
+       gravity 1
+       originjitter 1 1 1
+       size 1 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect neutralflag_touch
-count 35
-type spark
-tex 40 40
-color 0xFFFFFF 0xFFFFFF
-size 1 3
-alpha 0 256 556
-gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 3
-
-// yellow_pass
-// used nowhere in code
+       type spark
+       airfriction 3
+       alpha 0 256 556
+       bounce 1.500000
+       color 0xFFFFFF 0xFFFFFF
+       count 35
+       gravity 1
+       originjitter 1 1 1
+       size 1 3
+       tex 40 40
+       velocityjitter 300 300 300
+       velocitymultiplier 0.500000
 effect yellow_pass
-trailspacing 64
-color 0xFFFF0F 0xFFFF0F
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+       type static
+       airfriction 5
+       alpha 64 128 64
+       color 0xFFFF0F 0xFFFF0F
+       sizeincrease 2
+       size 2 2
+       tex 32 32
+       trailspacing 64
 effect yellow_pass
-trailspacing 12
-color 0xFFFF0F 0xFFFF0F
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+       type static
+       airfriction 9
+       alpha 32 64 32
+       color 0xFFFF0F 0xFFFF0F
+       sizeincrease 8
+       size 1 1
+       tex 0 8
+       trailspacing 12
+       velocityjitter 64 64 64
 effect yellow_pass
-trailspacing 12
-color 0xFFFF0F 0xFFFF0F
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// pink_pass
-// used nowhere in code
+       type static
+       alpha 256 256 1280
+       color 0xFFFF0F 0xFFFF0F
+       size 4 4
+       trailspacing 12
 effect pink_pass
-trailspacing 64
-color 0xFFFFFF 0xFFFFFF
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+       type static
+       airfriction 5
+       alpha 64 128 64
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease 2
+       size 2 2
+       tex 32 32
+       trailspacing 64
 effect pink_pass
-trailspacing 12
-color 0xFFFFFF 0xFFFFFF
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+       type static
+       airfriction 9
+       alpha 32 64 32
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease 8
+       size 1 1
+       tex 0 8
+       trailspacing 12
+       velocityjitter 64 64 64
 effect pink_pass
-trailspacing 12
-color 0xFFFFFF 0xFFFFFF
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// neutral_pass
-// used nowhere in code
+       type static
+       alpha 256 256 1280
+       color 0xFFFFFF 0xFFFFFF
+       size 4 4
+       trailspacing 12
 effect neutral_pass
-trailspacing 64
-color 0xFFFFFF 0xFFFFFF
-size 2 2
-tex 32 32
-alpha 64 128 64
-airfriction 5
-sizeincrease 2
-type static
+       type static
+       airfriction 5
+       alpha 64 128 64
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease 2
+       size 2 2
+       tex 32 32
+       trailspacing 64
 effect neutral_pass
-trailspacing 12
-color 0xFFFFFF 0xFFFFFF
-size 1 1
-tex 0 8
-alpha 32 64 32
-airfriction 9
-sizeincrease 8
-velocityjitter 64 64 64
-type static
+       type static
+       airfriction 9
+       alpha 32 64 32
+       color 0xFFFFFF 0xFFFFFF
+       sizeincrease 8
+       size 1 1
+       tex 0 8
+       trailspacing 12
+       velocityjitter 64 64 64
 effect neutral_pass
-trailspacing 12
-color 0xFFFFFF 0xFFFFFF
-size 4 4
-//tex 48 55
-alpha 256 256 1280
-type static
-
-// yellow_cap -- yellow team capture effect
+       type static
+       alpha 256 256 1280
+       color 0xFFFFFF 0xFFFFFF
+       size 4 4
+       trailspacing 12
 effect yellow_cap
-count 500
-type spark
-tex 64 64
-color 0xFFFF0F 0xFFFF0F
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+       type spark
+       airfriction 2
+       alpha 0 256 100
+       bounce 1.500000
+       color 0xFFFF0F 0xFFFF0F
+       count 500
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 1000 1000 1500
+       velocitymultiplier 0.500000
 effect yellow_cap
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0xFFFF0F 0xFFFF0F
-
-// pink_cap -- pink team capture effect
+       type smoke
+       alpha 190 190 180
+       color 0xFFFF0F 0xFFFF0F
+       countabsolute 1
+       sizeincrease -80
+       size 150 150
+       tex 65 65
 effect pink_cap
-count 500
-type spark
-tex 64 64
-color 0xFF0FFF 0xFF0FFF
-size 1 1
-alpha 0 256 100
-stretchfactor 2
-//gravity 1
-bounce 1.5
-originjitter 1 1 1
-velocityjitter 1000 1000 1500
-velocitymultiplier 0.5
-airfriction 2
-stretchfactor 0.6
+       type spark
+       airfriction 2
+       alpha 0 256 100
+       bounce 1.500000
+       color 0xFF0FFF 0xFF0FFF
+       count 500
+       originjitter 1 1 1
+       size 1 1
+       stretchfactor 0.600000
+       tex 64 64
+       velocityjitter 1000 1000 1500
+       velocitymultiplier 0.500000
 effect pink_cap
-countabsolute 1
-type smoke
-tex 65 65
-size 150 150
-alpha 190 190 180
-sizeincrease -80
-color 0xFF0FFF 0xFF0FFF
-
-// relic_resistance effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type smoke
+       alpha 190 190 180
+       color 0xFF0FFF 0xFF0FFF
+       countabsolute 1
+       sizeincrease -80
+       size 150 150
+       tex 65 65
 effect relic_resistance
-count 20
-type static
-color 0x00ff80 0x00ff80
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_regeneration effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0x00ff80 0x00ff80
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_regeneration
-count 1
-type static
-color 0x00ffff 0x00ffff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_vempire effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0x00ffff 0x00ffff
+       count 1
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_vampire
-count 20
-type static
-color 0xff00ff 0xff00ff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_ammo effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0xff00ff 0xff00ff
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_ammo
-count 1
-type static
-color 0x80ff00 0x80ff00
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_damage effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0x80ff00 0x80ff00
+       count 1
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_damage
-count 20
-type static
-color 0xff0000 0xff0000
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_splashdamage effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0xff0000 0xff0000
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_ssplashdamage
-count 20
-type static
-color 0xff8000 0xff8000
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_firingspeed effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0xff8000 0xff8000
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_firingspeed
-count 20
-type static
-color 0xffff00 0xffff00
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_disability effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0xffff00 0xffff00
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_disability
-count 20
-type static
-color 0x0000ff 0x0000ff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_disability_curse effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0x0000ff 0x0000ff
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_disability_curse
-count 1
-type static
-color 0x000080 0x000080
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_teamboost effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0x000080 0x000080
+       count 1
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_teamboost
-count 20
-type static
-color 0xffffff 0xffffff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_teamboost_boost effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0xffffff 0xffffff
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_teamboost_boost
-count 1
-type static
-color 0x808080 0x808080
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_speed effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0x808080 0x808080
+       count 1
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_speed
-count 1
-type static
-color 0x80ffff 0x80ffff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_jump effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0x80ffff 0x80ffff
+       count 1
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_jump
-count 20
-type static
-color 0xffff80 0xffff80
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_flight effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0xffff80 0xffff80
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_flight
-count 1
-type static
-color 0x8080ff 0x8080ff
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_radioactive effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0x8080ff 0x8080ff
+       count 1
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_radioactive
-count 20
-type static
-color 0x00ff00 0x00ff00
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_resurrection effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0x00ff00 0x00ff00
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_resurrection
-count 20
-type static
-color 0xff0080 0xff0080
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// relic_vengeance effect, used by the relics mutator
-// used in qcsrc/server/mutators/relics.qc: pointparticles(particleeffectnum(mdl), e.origin, '0 0 0', 1);
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0xff0080 0xff0080
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect relic_vengeance
-count 20
-type static
-color 0xff8080 0xff8080
-size 1.5 1.5
-alpha 128 256 256
-gravity -0.1
-airfriction 0.2
-liquidfriction 0.8
-originjitter 8 8 32
-velocityjitter 64 64 32
-
-// rocketminsta laser trail - red
+       type static
+       airfriction 0.200000
+       alpha 128 256 256
+       color 0xff8080 0xff8080
+       count 20
+       gravity -0.100000
+       liquidfriction 0.800000
+       originjitter 8 8 32
+       size 1.500000 1.500000
+       velocityjitter 64 64 32
 effect rocketminsta_laser_red
-trailspacing 2
-type static
-color 0xFF0F0F 0xFF0F0F
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+       type static
+       alpha 256 256 968
+       color 0xFF0F0F 0xFF0F0F
+       lightcolor 1.5 3 6
+       lightradius 90
+       size 3 3
+       tex 38 38
+       trailspacing 2
+       velocitymultiplier -0.100000
 effect rocketminsta_laser_red
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xFF0F0F 0xFF0F0F
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// rocketminsta laser trail - blue
+       type snow
+       airfriction 12
+       alpha 444 512 1866
+       bounce 1
+       color 0xFF0F0F 0xFF0F0F
+       count 1.500000
+       originjitter 1 1 1
+       sizeincrease -20
+       size 2 4
+       tex 42 42
+       trailspacing 12
+       velocityjitter 50 50 50
+       velocityoffset 0 0 15
 effect rocketminsta_laser_blue
-trailspacing 2
-type static
-color 0x0F0FFF 0x0F0FFF
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+       type static
+       alpha 256 256 968
+       color 0x0F0FFF 0x0F0FFF
+       lightcolor 1.5 3 6
+       lightradius 90
+       size 3 3
+       tex 38 38
+       trailspacing 2
+       velocitymultiplier -0.100000
 effect rocketminsta_laser_blue
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0x0F0FFF 0x0F0FFF
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// rocketminsta laser trail - yellow
+       type snow
+       airfriction 12
+       alpha 444 512 1866
+       bounce 1
+       color 0x0F0FFF 0x0F0FFF
+       count 1.500000
+       originjitter 1 1 1
+       sizeincrease -20
+       size 2 4
+       tex 42 42
+       trailspacing 12
+       velocityjitter 50 50 50
+       velocityoffset 0 0 15
 effect rocketminsta_laser_yellow
-trailspacing 2
-type static
-color 0xFFFF0F 0xFFFF0F
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+       type static
+       alpha 256 256 968
+       color 0xFFFF0F 0xFFFF0F
+       lightcolor 1.5 3 6
+       lightradius 90
+       size 3 3
+       tex 38 38
+       trailspacing 2
+       velocitymultiplier -0.100000
 effect rocketminsta_laser_yellow
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xFFFF0F 0xFFFF0F
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// rocketminsta laser trail - pink
+       type snow
+       airfriction 12
+       alpha 444 512 1866
+       bounce 1
+       color 0xFFFF0F 0xFFFF0F
+       count 1.500000
+       originjitter 1 1 1
+       sizeincrease -20
+       size 2 4
+       tex 42 42
+       trailspacing 12
+       velocityjitter 50 50 50
+       velocityoffset 0 0 15
 effect rocketminsta_laser_pink
-trailspacing 2
-type static
-color 0xFF0FFF 0xFF0FFF
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+       type static
+       alpha 256 256 968
+       color 0xFF0FFF 0xFF0FFF
+       lightcolor 1.5 3 6
+       lightradius 90
+       size 3 3
+       tex 38 38
+       trailspacing 2
+       velocitymultiplier -0.100000
 effect rocketminsta_laser_pink
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xFF0FFF 0xFF0FFF
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
-
-// rocketminsta laser trail - neutral
+       type snow
+       airfriction 12
+       alpha 444 512 1866
+       bounce 1
+       color 0xFF0FFF 0xFF0FFF
+       count 1.500000
+       originjitter 1 1 1
+       sizeincrease -20
+       size 2 4
+       tex 42 42
+       trailspacing 12
+       velocityjitter 50 50 50
+       velocityoffset 0 0 15
 effect rocketminsta_laser_neutral
-trailspacing 2
-type static
-color 0xFFFFFF 0xFFFFFF
-size 3 3
-tex 38 38
-alpha 256 256 968
-//velocityjitter 16 16 16
-lightradius 90
-lighttime 0
-lightcolor 1.5 3 6
-velocitymultiplier -0.1
-// bright sparks
+       type static
+       alpha 256 256 968
+       color 0xFFFFFF 0xFFFFFF
+       lightcolor 1.5 3 6
+       lightradius 90
+       size 3 3
+       tex 38 38
+       trailspacing 2
+       velocitymultiplier -0.100000
 effect rocketminsta_laser_neutral
-trailspacing 12
-count 1.5
-type snow
-tex 42 42
-color 0xFFFFFF 0xFFFFFF
-size 2 4
-sizeincrease -20
-alpha 444 512 1866
-bounce 1
-velocityoffset 0 0 15
-airfriction 12
-originjitter 1 1 1
-velocityjitter 50 50 50
+       type snow
+       airfriction 12
+       alpha 444 512 1866
+       bounce 1
+       color 0xFFFFFF 0xFFFFFF
+       count 1.500000
+       originjitter 1 1 1
+       sizeincrease -20
+       size 2 4
+       tex 42 42
+       trailspacing 12
+       velocityjitter 50 50 50
+       velocityoffset 0 0 15
diff --git a/gfx/hud/default/checkmark.tga b/gfx/hud/default/checkmark.tga
new file mode 100644 (file)
index 0000000..71cbd68
Binary files /dev/null and b/gfx/hud/default/checkmark.tga differ
diff --git a/gfx/hud/default/minigames/qto/board.jpg b/gfx/hud/default/minigames/qto/board.jpg
deleted file mode 100644 (file)
index cf8fe0a..0000000
Binary files a/gfx/hud/default/minigames/qto/board.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/qto/board_alpha.jpg b/gfx/hud/default/minigames/qto/board_alpha.jpg
deleted file mode 100644 (file)
index 44a8708..0000000
Binary files a/gfx/hud/default/minigames/qto/board_alpha.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/qto/icon.jpg b/gfx/hud/default/minigames/qto/icon.jpg
deleted file mode 100644 (file)
index a534f48..0000000
Binary files a/gfx/hud/default/minigames/qto/icon.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/qto/icon_notif.jpg b/gfx/hud/default/minigames/qto/icon_notif.jpg
deleted file mode 100644 (file)
index 90e0e2e..0000000
Binary files a/gfx/hud/default/minigames/qto/icon_notif.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/qto/icon_notif_alpha.jpg b/gfx/hud/default/minigames/qto/icon_notif_alpha.jpg
deleted file mode 100644 (file)
index 040990f..0000000
Binary files a/gfx/hud/default/minigames/qto/icon_notif_alpha.jpg and /dev/null differ
diff --git a/gfx/hud/default/minigames/qto/piece0.tga b/gfx/hud/default/minigames/qto/piece0.tga
deleted file mode 100644 (file)
index fad7dbd..0000000
Binary files a/gfx/hud/default/minigames/qto/piece0.tga and /dev/null differ
diff --git a/gfx/hud/default/minigames/qto/piece1.tga b/gfx/hud/default/minigames/qto/piece1.tga
deleted file mode 100644 (file)
index 80a34c2..0000000
Binary files a/gfx/hud/default/minigames/qto/piece1.tga and /dev/null differ
diff --git a/gfx/hud/default/minigames/snake/board.jpg b/gfx/hud/default/minigames/snake/board.jpg
new file mode 100644 (file)
index 0000000..dfc5c3c
Binary files /dev/null and b/gfx/hud/default/minigames/snake/board.jpg differ
diff --git a/gfx/hud/default/minigames/snake/board_alpha.jpg b/gfx/hud/default/minigames/snake/board_alpha.jpg
new file mode 100644 (file)
index 0000000..44a8708
Binary files /dev/null and b/gfx/hud/default/minigames/snake/board_alpha.jpg differ
diff --git a/gfx/hud/default/minigames/snake/body.tga b/gfx/hud/default/minigames/snake/body.tga
new file mode 100644 (file)
index 0000000..b8064cc
Binary files /dev/null and b/gfx/hud/default/minigames/snake/body.tga differ
diff --git a/gfx/hud/default/minigames/snake/head.tga b/gfx/hud/default/minigames/snake/head.tga
new file mode 100644 (file)
index 0000000..0679f84
Binary files /dev/null and b/gfx/hud/default/minigames/snake/head.tga differ
diff --git a/gfx/hud/default/minigames/snake/icon.jpg b/gfx/hud/default/minigames/snake/icon.jpg
new file mode 100644 (file)
index 0000000..14252ae
Binary files /dev/null and b/gfx/hud/default/minigames/snake/icon.jpg differ
diff --git a/gfx/hud/default/minigames/snake/icon_notif.jpg b/gfx/hud/default/minigames/snake/icon_notif.jpg
new file mode 100644 (file)
index 0000000..988b6db
Binary files /dev/null and b/gfx/hud/default/minigames/snake/icon_notif.jpg differ
diff --git a/gfx/hud/default/minigames/snake/icon_notif_alpha.jpg b/gfx/hud/default/minigames/snake/icon_notif_alpha.jpg
new file mode 100644 (file)
index 0000000..040990f
Binary files /dev/null and b/gfx/hud/default/minigames/snake/icon_notif_alpha.jpg differ
diff --git a/gfx/hud/default/minigames/snake/mouse.tga b/gfx/hud/default/minigames/snake/mouse.tga
new file mode 100644 (file)
index 0000000..eda8ef7
Binary files /dev/null and b/gfx/hud/default/minigames/snake/mouse.tga differ
diff --git a/gfx/hud/default/minigames/snake/tail.tga b/gfx/hud/default/minigames/snake/tail.tga
new file mode 100644 (file)
index 0000000..71a7901
Binary files /dev/null and b/gfx/hud/default/minigames/snake/tail.tga differ
diff --git a/gfx/hud/default/minigames/snake/tongue.tga b/gfx/hud/default/minigames/snake/tongue.tga
new file mode 100644 (file)
index 0000000..9818d4e
Binary files /dev/null and b/gfx/hud/default/minigames/snake/tongue.tga differ
index 9922d7e5674db21aa80098de1f956eb4f8863791..6dfec5088f886a3b229b0185c35f2e6d24a4ff17 100644 (file)
@@ -11,4 +11,11 @@ set sv_minigames_pong_ball_radius   0.03125 "Ball radius relative to the board s
 set sv_minigames_pong_ball_number   1       "Number of balls to be played at once"
 
 set sv_minigames_pong_ai_thinkspeed 0.1     "Seconds between AI actions"
-set sv_minigames_pong_ai_tolerance  0.33    "Distance of the ball relative to the paddle size"
\ No newline at end of file
+set sv_minigames_pong_ai_tolerance  0.33    "Distance of the ball relative to the paddle size"
+
+
+// Snake? Snake! SNAAAAKE!!
+set sv_minigames_snake_wrap 0 "Wrap around the edges of the screen instead of dying on touch"
+set sv_minigames_snake_delay_initial 0.7 "Initial delay between snake movement"
+set sv_minigames_snake_delay_multiplier 50 "Multiplier of incremental of movement speed (player_score / cvar)"
+set sv_minigames_snake_delay_min 0.1 "Minimum delay between snake movement (at fastest rate)"
diff --git a/mod/client/main.qc b/mod/client/main.qc
deleted file mode 100644 (file)
index d84239c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-REGISTER_MUTATOR(mutator_mod, cvar("g_mod"));
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsString) {
-    ret_string = strcat(ret_string, ":mod");
-}
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsPrettyString) {
-    ret_string = strcat(ret_string, ", Mod");
-}
diff --git a/mod/client/progs.inc b/mod/client/progs.inc
deleted file mode 100644 (file)
index ae91a9e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#if BUILD_MOD
-#include "main.qc"
-#endif
diff --git a/mod/menu/main.qc b/mod/menu/main.qc
deleted file mode 100644 (file)
index d84239c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-REGISTER_MUTATOR(mutator_mod, cvar("g_mod"));
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsString) {
-    ret_string = strcat(ret_string, ":mod");
-}
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsPrettyString) {
-    ret_string = strcat(ret_string, ", Mod");
-}
diff --git a/mod/menu/progs.inc b/mod/menu/progs.inc
deleted file mode 100644 (file)
index ae91a9e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#if BUILD_MOD
-#include "main.qc"
-#endif
diff --git a/mod/server/main.qc b/mod/server/main.qc
deleted file mode 100644 (file)
index d84239c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-REGISTER_MUTATOR(mutator_mod, cvar("g_mod"));
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsString) {
-    ret_string = strcat(ret_string, ":mod");
-}
-
-MUTATOR_HOOKFUNCTION(mutator_mod, BuildMutatorsPrettyString) {
-    ret_string = strcat(ret_string, ", Mod");
-}
diff --git a/mod/server/progs.inc b/mod/server/progs.inc
deleted file mode 100644 (file)
index ae91a9e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#if BUILD_MOD
-#include "main.qc"
-#endif
index 9d961c0ad636036bfd440a91ecdddbb2f83dc75b..2cb6c3e7d90431937bab6a1246f001f40b05e2e6 100644 (file)
@@ -102,6 +102,7 @@ set g_monsters_spawnshieldtime 2
 set g_monsters_typefrag 1
 set g_monsters_target_range 2000
 set g_monsters_target_infront 0
+set g_monsters_target_infront_range 0.3
 set g_monsters_attack_range 120
 set g_monsters_respawn 1
 set g_monsters_respawn_delay 20
index 3300476bfc9dfaa99738d9d9c37599ff87a585a8..5eaa0ad17f6641181b6df34bdb28229694c97c2e 100644 (file)
@@ -398,7 +398,7 @@ set g_breakablehook_owner 0 "allow owner to break their own hook"
 // ===========
 //  multijump
 // ===========
-seta cl_multijump 1 "allow multijump mutator"
+seta cl_multijump 0 "allow multijump mutator"
 set g_multijump 0      "Number of multiple jumps to allow (jumping again in the air), -1 allows for infinite jumps"
 set g_multijump_add 0  "0 = make the current z velocity equal to jumpvelocity, 1 = add jumpvelocity to the current z velocity"
 set g_multijump_speed -999999  "Minimum vertical speed a player must have in order to jump again"
index 1005ab57ae69af66e3940fd3830f7731ffc48eca..44b22f3bd518ca6a42b159876525939eb073139d 100644 (file)
Binary files a/particles/hook_blue.tga and b/particles/hook_blue.tga differ
index 8bfdad9d14beb231bb53023214a6858ed52a2208..502b94cb846c22dc1411b331136c240dde86c996 100644 (file)
Binary files a/particles/hook_pink.tga and b/particles/hook_pink.tga differ
index 570ea2d672cb52ea43f115e2590056c82d5b6019..8c992573a0596721ff900998ecf32785221fd2ee 100644 (file)
Binary files a/particles/hook_red.tga and b/particles/hook_red.tga differ
index c60f07028bcb85afa97b8d94bcd1451e9ce2cb72..5ee54ffead807a3e8d40484974e7c11aa72f94ac 100644 (file)
Binary files a/particles/hook_white.tga and b/particles/hook_white.tga differ
index 47f3c64a6136c73b2472eb461a0418038b877c37..c305c5de31281011d8cafa79a5fee7fe53f13c1b 100644 (file)
Binary files a/particles/hook_yellow.tga and b/particles/hook_yellow.tga differ
index 58d1b1f81d058263aa59c1ddd779f758c72b7e21..e9fe5628940d9597fd5843533b54bced13066ae0 100644 (file)
@@ -38,6 +38,7 @@ set g_physics_xonotic_accelerate 15
 set g_physics_xonotic_stopspeed 100
 set g_physics_xonotic_airaccelerate 2
 set g_physics_xonotic_airstopaccelerate 3
+set g_physics_xonotic_track_canjump 0
 
 // ========
 //  Nexuiz
@@ -65,6 +66,7 @@ set g_physics_nexuiz_accelerate 8
 set g_physics_nexuiz_stopspeed 100
 set g_physics_nexuiz_airaccelerate 5.5
 set g_physics_nexuiz_airstopaccelerate 0
+set g_physics_nexuiz_track_canjump 0
 
 // =======
 //  Quake
@@ -92,6 +94,7 @@ set g_physics_quake_accelerate 10
 set g_physics_quake_stopspeed 100
 set g_physics_quake_airaccelerate 106.66666666666666666666
 set g_physics_quake_airstopaccelerate 0
+set g_physics_quake_track_canjump 1
 
 // ========
 //  Warsow
@@ -119,6 +122,7 @@ set g_physics_warsow_accelerate 15
 set g_physics_warsow_stopspeed 100
 set g_physics_warsow_airaccelerate 1
 set g_physics_warsow_airstopaccelerate 2.5
+set g_physics_warsow_track_canjump 0
 
 // ========
 //  DeFrag
@@ -146,6 +150,7 @@ set g_physics_defrag_accelerate 15
 set g_physics_defrag_stopspeed 100
 set g_physics_defrag_airaccelerate 1
 set g_physics_defrag_airstopaccelerate 2.5
+set g_physics_defrag_track_canjump 0
 
 // =========
 //  Quake 3
@@ -173,6 +178,7 @@ set g_physics_quake3_accelerate 10
 set g_physics_quake3_stopspeed 100
 set g_physics_quake3_airaccelerate 1
 set g_physics_quake3_airstopaccelerate 0
+set g_physics_quake3_track_canjump 1
 
 // ========
 //  Vecxis
@@ -200,6 +206,7 @@ set g_physics_vecxis_accelerate 5.5
 set g_physics_vecxis_stopspeed 100
 set g_physics_vecxis_airaccelerate 5.5
 set g_physics_vecxis_airstopaccelerate 0
+set g_physics_vecxis_track_canjump 0
 
 // =========
 //  Quake 2
@@ -227,6 +234,7 @@ set g_physics_quake2_accelerate 10
 set g_physics_quake2_stopspeed 100
 set g_physics_quake2_airaccelerate 1
 set g_physics_quake2_airstopaccelerate 0
+set g_physics_quake2_track_canjump 1
 
 // =======
 //  Bones
@@ -254,3 +262,4 @@ set g_physics_bones_accelerate 15
 set g_physics_bones_stopspeed 100
 set g_physics_bones_airaccelerate 1
 set g_physics_bones_airstopaccelerate 2.5
+set g_physics_bones_track_canjump 0
index 9734cfc6f6ccc1180a9925105814321f1d5ed69f..e4bbad3d48630aa95c9f3463fdd1d327c7323a12 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 400
+sv_track_canjump 0
index 5f65d66d8ab36e6b6e2349174c15431ea20e6e3f..ee44b5547a052717cde7f28fb0f52063e638c65f 100644 (file)
@@ -33,3 +33,4 @@ sv_jumpspeedcap_min 0 // need predicting? (it should already be in CSQC predicti
 sv_jumpspeedcap_max 0.35
 sv_jumpspeedcap_max_disable_on_ramps 1
 g_teleport_maxspeed 0
+sv_track_canjump 0
index f107158720dc50d26d0dcc014a5a4eb23ae8ddbe..6aac341780e7573cbe580b714e62b747d61e6612 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 3553a94a7e587a415a24613aaf735392622e6a53..90eaa49c1223cd4bacf7aa7e228dc4670f88240b 100644 (file)
@@ -42,3 +42,4 @@ sv_jumpspeedcap_min 0 // need predicting? (it should already be in CSQC predicti
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 1
 g_teleport_maxspeed 0
+sv_track_canjump 0
index e4aef4440d6b5b173e141962d3e429077216ab31..03081fdab7554b9c5118b795ac8b86987ff966a6 100644 (file)
@@ -42,3 +42,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 1
 g_teleport_maxspeed 0
+sv_track_canjump 0
index eda92ac6930431893efd7865b83f26d45efecffc..ef213a70f9d356226b401c0779752d85d69c7157 100644 (file)
@@ -37,3 +37,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max 0.38
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index cd76c2fe39f557fd6bb50133fddc8dad880dc1e6..51c49d7832dbf0197ca6a2ab5d456389ce675ebf 100644 (file)
@@ -35,3 +35,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 6c99b307f00f74d41e90e6d95b5db96dcacb2e20..0ce33aa95132362f57bb28eeec904c6549bed91e 100644 (file)
@@ -35,3 +35,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 65a6a4b6fc40b9a67fc91d4936cee4095e32ebd2..08711fd5b0f6905b33ff2688261f0e0543611922 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 833a67dce383f608a8051938cdffa905d55f3d4d..092985cae51a00a87a76cf26a78519c9f5d3f127 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 31380c973828580dc2fe523cac5715e59e8ab020..c6d9bef4b912d82e5200691d82a3fb55627b4d88 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index f3a85e50b7cf4d03556fd315f7b731b5d4125ec6..5e0ee6ae0c6f265690c3783be05c3d10f35a1d19 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 60071e1844026fb1bb9fb04e695d19247295f33b..d129a2db05ebada4a9698aeafcfedbb9456ac2d9 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index dd984bb310c1a8c2299df157edc8b751e20d05d5..8a52299763d537423fb2012f6a9ed304c969ef0e 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 827bbc55c16501e6ee64e509b4313f8612a0d3c4..4df3f211ebe490134394e21d60a35a0b739fae6b 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index f8d43c4f2ece249c7fe52776ce6bae5c7577a535..3e905428f76d52f1183cde4fc116ccabc0268afa 100644 (file)
@@ -43,3 +43,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 1
 g_teleport_maxspeed 0
+sv_track_canjump 0
index c26745629677cf209b65c223eb60d5abfd6a9436..448e087f46f20c1d0287dfd29c9a605a93266fcc 100644 (file)
@@ -35,3 +35,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 05e2f1456cdd5152935fe084e730f717069dc4cd..124c50660a1046ca8bf9ce7245a4d9579a0ff71c 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 9b953e32e8b78b8852f663ed4e55668da55a1b1a..580f6257fa65f2bde52c74983f72492e45456f2f 100644 (file)
@@ -35,3 +35,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index eed1c7409008447be660d6b84b73e57da536d11f..6f00896b671b4b542115d6270c96b4bac7d08c20 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 320
+sv_track_canjump 0
index 8dff0edd9df5d208440a721a04fce1e236a5722a..31963e9feee4dc1dc6691514a081bde9d3765c7f 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 634b6083ee6c910a69442de8430c8251e2781bb7..82463859835480526e90bbae65db204238344fd7 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 8019089bf216f7eb5749c8d12064a494ca0f7edd..6858892e3b3ad27b1c8a8e8d4257c7a650e269c6 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 7d66b3716d987f96d48687973d7c09cfc7f1011d..50101d73d43165843ecf32f08b55fb33aff8fb2d 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index 1dbb14a90fb4f87d31359ee48ee84ea32ae11231..c4c3535a7f9ac1c74d3daa7a7c7645f4daaa9e27 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
index f2f989d7580295a9ea237701d240ab7084dc7bb0..331723ec9317539cbc2b2e4bdc139a99b52abb94 100644 (file)
@@ -34,3 +34,4 @@ sv_jumpspeedcap_min ""
 sv_jumpspeedcap_max ""
 sv_jumpspeedcap_max_disable_on_ramps 0
 g_teleport_maxspeed 0
+sv_track_canjump 0
diff --git a/qcsrc/.gitignore b/qcsrc/.gitignore
new file mode 100644 (file)
index 0000000..5ccff1a
--- /dev/null
@@ -0,0 +1 @@
+html/
diff --git a/qcsrc/Doxyfile b/qcsrc/Doxyfile
new file mode 100644 (file)
index 0000000..f177a27
--- /dev/null
@@ -0,0 +1,2384 @@
+# Doxyfile 1.8.10
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "Xonotic"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
+# in the documentation. The maximum height of the logo should not exceed 55
+# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
+# the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES    = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = YES
+
+# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
+# page for each member. If set to NO, the documentation of a member will be part
+# of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note: For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      = qc=C qh=C inc=C
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# If one adds a struct or class to a group and this option is enabled, then also
+# any nested class or struct is added to the same group. By default this option
+# is disabled and one has to add nested compounds explicitly via \ingroup.
+# The default value is: NO.
+
+GROUP_NESTED_COMPOUNDS = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = YES
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO,
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. If set to YES, local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO, only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO, these classes will be included in the various overviews. This option
+# has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO, these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO, these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES, upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES, the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
+# append additional text to a page's title, such as Class Reference. If set to
+# YES the compound reference will be hidden.
+# The default value is: NO.
+
+HIDE_COMPOUND_REFERENCE= NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO, the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
+# list. This list is created by putting \todo commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
+# list. This list is created by putting \test commands in the documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES, the
+# list will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO, doxygen will only warn about wrong or incomplete
+# parameter documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  =
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories.
+#
+# Note that for custom extensions or not directly supported extensions you also
+# need to set EXTENSION_MAPPING for the extension otherwise the files are not
+# read by doxygen.
+#
+# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
+# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
+# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
+# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd,
+# *.vhdl, *.ucf, *.qsf, *.as and *.js.
+
+FILE_PATTERNS          = *.qc *.qh *.inc
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        = _
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefore more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the style sheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to YES can help to show when doxygen was last run and thus if the
+# documentation is up to date.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler (hhc.exe). If non-empty,
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the master .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated
+# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer (doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. The package can be specified just
+# by its name or with the correct syntax as to be used with the LaTeX
+# \usepackage command. To get the times font for instance you can specify :
+# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
+# To use the option intlimits with the amsmath package you can specify:
+# EXTRA_PACKAGES=[intlimits]{amsmath}
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
+# string, for the replacement values of the other commands the user is referred
+# to HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# LaTeX style sheets that are included after the standard style sheets created
+# by doxygen. Using this option one can overrule certain style aspects. Doxygen
+# will copy the style sheet files to the output directory.
+# Note: The order of the extra style sheet files is of importance (e.g. the last
+# style sheet in the list overrules the setting of the previous ones in the
+# list).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_STYLESHEET =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES, to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
+# with syntax highlighting in the RTF output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_SOURCE_CODE        = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR             =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see http://autogen.sf.net) file that captures the
+# structure of the code including all documentation. Note that this feature is
+# still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO, the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
+# in the source code. If set to NO, only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES, the include files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
+# the class index. If set to NO, only the inherited external classes will be
+# listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = NO
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 2
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command. Disabling a call graph can be
+# accomplished by means of the command \hidecallgraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command. Disabling a caller graph can be
+# accomplished by means of the command \hidecallergraph.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# http://www.graphviz.org/)).
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
+# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
+# png:gdiplus:gdiplus.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = svg
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = YES
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+
+PLANTUML_JAR_PATH      =
+
+# When using plantuml, the specified paths are searched for files specified by
+# the !include statement in a plantuml block.
+
+PLANTUML_INCLUDE_PATH  =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 500
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
index 143f53249b43f3b79f5e9a7cb323e6237ffac117..51440d4a3c90da83d77f8e57033c7e2287c188d6 100644 (file)
@@ -2,58 +2,57 @@ SCM := $(shell if [ -d .svn ]; then echo svn; elif [ -d ../.git ]; then echo git
 PERL ?= perl
 QCCFLAGS_WATERMARK ?= -DWATERMARK='"$(shell git describe)"'
 QCC ?= gmqcc
-
 QCCVERSIONFILE := qccversion.$(shell (cd server && $(QCC) --version) > qccversion.txt && git hash-object qccversion.txt)
 
 # We eventually need to get rid of these.
 QCCFLAGS_WTFS ?= \
        -Wno-field-redeclared
 
-QCCFLAGS ?= \
-       -std=gmqcc \
-       -O3 -flno \
-       -Werror -fno-bail-on-werror -Wall \
-       -fftepp -fftepp-predefs -Wcpp -futf8 -frelaxed-switch -freturn-assignments \
-       $(QCCFLAGS_WTFS) \
-       $(QCCFLAGS_FEATURES) \
-       $(QCCFLAGS_EXTRA) $(QCCFLAGS_WATERMARK)
-
 QCCFLAGS_FEATURES ?= \
        -DVEHICLES_ENABLED=1 \
        -DVEHICLES_USE_ODE=0 \
        -DBUILD_MOD=$(BUILD_MOD)
 
+QCCFLAGS ?= \
+       -std=gmqcc \
+       -O3 \
+       -Werror -Wall -Wcpp \
+       $(QCCFLAGS_WTFS) \
+       -fftepp -flno -futf8 -fno-bail-on-werror -fftepp-predefs \
+       -frelaxed-switch -freturn-assignments \
+       $(QCCFLAGS_WATERMARK) \
+       $(QCCFLAGS_FEATURES) \
+       $(QCCFLAGS_EXTRA)
+
 # xonotic build system overrides this by command line argument to turn off the update-cvarcount step
 XON_BUILDSYSTEM =
 
-all: qc
 .PHONY: all
+all: qc
 
 .PHONY: qc
 qc: ../menu.dat ../progs.dat ../csprogs.dat
 
 .PHONY: clean
 clean:
-       rm -f ../progs.dat ../menu.dat ../csprogs.dat server/precache-for-csqc.inc
+       rm -f ../progs.dat ../menu.dat ../csprogs.dat
 
 $(QCCVERSIONFILE):
        $(RM) qccversion.*
        echo This file intentionally left blank. > $@
 
-FILES_CSPROGS = $(shell find client common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
+FILES_CSPROGS = $(shell find client lib common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
 ../csprogs.dat: $(FILES_CSPROGS) $(QCCVERSIONFILE)
        @echo make[1]: Entering directory \`$(PWD)/client\'
        cd client && $(QCC) $(QCCFLAGS) -DCSQC
 
-server/precache-for-csqc.inc: $(FILES_CSPROGS)
-       sh collect-precache.sh
-
-FILES_PROGS = $(shell find server common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
-../progs.dat: $(FILES_PROGS) $(QCCVERSIONFILE) server/precache-for-csqc.inc
+FILES_PROGS = $(shell find server lib common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm)
+../progs.dat: $(FILES_PROGS) $(QCCVERSIONFILE)
        @echo make[1]: Entering directory \`$(PWD)/server\'
        cd server && $(QCC) $(QCCFLAGS) -DSVQC
 
-FILES_MENU = $(shell find menu common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm)
+FILES_MENU = $(shell find menu lib common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm)
 ../menu.dat: $(FILES_MENU) $(QCCVERSIONFILE)
        @echo make[1]: Entering directory \`$(PWD)/menu\'
        cd menu && $(QCC) $(QCCFLAGS) -DMENUQC
index e758fdb7a7d5f211de3dc67531cc1aa2d121c506..0fe1c616fd687d4eb9adecfcf2fa8f62086f52f7 100644 (file)
@@ -8,4 +8,7 @@
 
 #include "../dpdefs/csprogsdefs.qh"
 
+#include "../common/models/all.qh"
+#include "../common/sounds/all.qh"
+
 #endif
index 19e51cedc6b98f2611c274476fba9cc0430300d2..b7b7bb5c6e5d992c2a8c20ea1e9f8c8bce7332f2 100644 (file)
@@ -9,12 +9,13 @@ bool announcer_1min;
 bool announcer_5min;
 void Announcer_Countdown()
 {
+       SELFPARAM();
        float starttime = getstatf(STAT_GAMESTARTTIME);
        float roundstarttime = getstatf(STAT_ROUNDSTARTTIME);
        if(roundstarttime == -1)
        {
                Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
-               remove(self);
+               remove(this);
                return;
        }
        if(roundstarttime >= starttime)
@@ -29,7 +30,7 @@ void Announcer_Countdown()
        {
                Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_BEGIN);
                Local_Notification(MSG_MULTI, MULTI_COUNTDOWN_BEGIN);
-               remove(self);
+               remove(this);
                return;
        }
        else // countdown is still going
@@ -46,7 +47,7 @@ void Announcer_Countdown()
                        Local_Notification(MSG_ANNCE, Announcer_PickNumber(CNT_GAMESTART, countdown_rounded));
                }
 
-               self.nextthink = (starttime - (countdown - 1));
+               this.nextthink = (starttime - (countdown - 1));
        }
 }
 
index 2d6093868cc1ea496e5822880e0c69f5900c4f00..88cd246ff106fe5246ad3de4b721ced2e1fd80bf 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "../../common/command/generic.qh"
 
-void DrawDebugModel()
+void DrawDebugModel(entity this)
 {
        if(time - floor(time) > 0.5)
        {
@@ -174,7 +174,7 @@ void LocalCommand_debugmodel(int request, int argc)
 
                        debugmodel_entity = spawn();
                        precache_model(modelname);
-                       setmodel(debugmodel_entity, modelname);
+                       _setmodel(debugmodel_entity, modelname);
                        setorigin(debugmodel_entity, view_origin);
                        debugmodel_entity.angles = view_angles;
                        debugmodel_entity.draw = DrawDebugModel;
index 3b8901cf37695abafb9873d6daf55fd561c14a0b..34301d8063dc50501381721eaf01040ad7ebc51a 100644 (file)
@@ -4,7 +4,6 @@
 #include "../common/movetypes/movetypes.qh"
 
 .float alpha;
-bool cpicon_precached;
 .int count;
 .float pain_finished;
 
@@ -21,194 +20,180 @@ bool cpicon_precached;
 
 .entity icon_realmodel;
 
-void cpicon_precache()
+void cpicon_draw(entity this)
 {
-       if(cpicon_precached)
-               return; // already precached
+       if(time < this.move_time) { return; }
 
-       precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
-       precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
-       precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
-       precache_model("models/onslaught/controlpoint_icon.md3");
-
-       cpicon_precached = true;
-}
-
-void cpicon_draw()
-{
-       if(time < self.move_time) { return; }
-
-       if(self.cp_bob_dmg_z > 0)
-               self.cp_bob_dmg_z = self.cp_bob_dmg_z - 3 * frametime;
+       if(this.cp_bob_dmg_z > 0)
+               this.cp_bob_dmg_z = this.cp_bob_dmg_z - 3 * frametime;
        else
-               self.cp_bob_dmg_z = 0;
-       self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd));
-       self.cp_bob_spd = self.cp_bob_spd + 1.875 * frametime;
-       self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
+               this.cp_bob_dmg_z = 0;
+       this.cp_bob_origin_z = 4 * PI * (1 - cos(this.cp_bob_spd));
+       this.cp_bob_spd = this.cp_bob_spd + 1.875 * frametime;
+       this.colormod = '1 1 1' * (2 - bound(0, (this.pain_finished - time) / 10, 1));
 
-       if(!self.iscaptured) self.alpha = self.health / self.max_health;
+       if(!this.iscaptured) this.alpha = this.health / this.max_health;
 
-       if(self.iscaptured)
+       if(this.iscaptured)
        {
-               if (self.punchangle_x > 0)
+               if (this.punchangle_x > 0)
                {
-                       self.punchangle_x = self.punchangle_x - 60 * frametime;
-                       if (self.punchangle_x < 0)
-                               self.punchangle_x = 0;
+                       this.punchangle_x = this.punchangle_x - 60 * frametime;
+                       if (this.punchangle_x < 0)
+                               this.punchangle_x = 0;
                }
-               else if (self.punchangle_x < 0)
+               else if (this.punchangle_x < 0)
                {
-                       self.punchangle_x = self.punchangle_x + 60 * frametime;
-                       if (self.punchangle_x > 0)
-                               self.punchangle_x = 0;
+                       this.punchangle_x = this.punchangle_x + 60 * frametime;
+                       if (this.punchangle_x > 0)
+                               this.punchangle_x = 0;
                }
 
-               if (self.punchangle_y > 0)
+               if (this.punchangle_y > 0)
                {
-                       self.punchangle_y = self.punchangle_y - 60 * frametime;
-                       if (self.punchangle_y < 0)
-                               self.punchangle_y = 0;
+                       this.punchangle_y = this.punchangle_y - 60 * frametime;
+                       if (this.punchangle_y < 0)
+                               this.punchangle_y = 0;
                }
-               else if (self.punchangle_y < 0)
+               else if (this.punchangle_y < 0)
                {
-                       self.punchangle_y = self.punchangle_y + 60 * frametime;
-                       if (self.punchangle_y > 0)
-                               self.punchangle_y = 0;
+                       this.punchangle_y = this.punchangle_y + 60 * frametime;
+                       if (this.punchangle_y > 0)
+                               this.punchangle_y = 0;
                }
 
-               if (self.punchangle_z > 0)
+               if (this.punchangle_z > 0)
                {
-                       self.punchangle_z = self.punchangle_z - 60 * frametime;
-                       if (self.punchangle_z < 0)
-                               self.punchangle_z = 0;
+                       this.punchangle_z = this.punchangle_z - 60 * frametime;
+                       if (this.punchangle_z < 0)
+                               this.punchangle_z = 0;
                }
-               else if (self.punchangle_z < 0)
+               else if (this.punchangle_z < 0)
                {
-                       self.punchangle_z = self.punchangle_z + 60 * frametime;
-                       if (self.punchangle_z > 0)
-                               self.punchangle_z = 0;
+                       this.punchangle_z = this.punchangle_z + 60 * frametime;
+                       if (this.punchangle_z > 0)
+                               this.punchangle_z = 0;
                }
 
-               self.angles_x = self.punchangle_x;
-               self.angles_y = self.punchangle_y + self.move_angles_y;
-               self.angles_z = self.punchangle_z;
-               self.move_angles_y = self.move_angles_y + 45 * frametime;
+               this.angles_x = this.punchangle_x;
+               this.angles_y = this.punchangle_y + this.move_angles_y;
+               this.angles_z = this.punchangle_z;
+               this.move_angles_y = this.move_angles_y + 45 * frametime;
        }
 
-       setorigin(self, self.cp_origin + self.cp_bob_origin + self.cp_bob_dmg);
+       setorigin(this, this.cp_origin + this.cp_bob_origin + this.cp_bob_dmg);
 }
 
-void cpicon_damage(float hp)
+void cpicon_damage(entity this, float hp)
 {
-       if(!self.iscaptured) { return; }
+       if(!this.iscaptured) { return; }
 
-       if(hp < self.max_health * 0.25)
-               setmodel(self, "models/onslaught/controlpoint_icon_dmg3.md3");
-       else if(hp < self.max_health * 0.50)
-               setmodel(self, "models/onslaught/controlpoint_icon_dmg2.md3");
-       else if(hp < self.max_health * 0.75)
-               setmodel(self, "models/onslaught/controlpoint_icon_dmg1.md3");
-       else if(hp <= self.max_health || hp >= self.max_health)
-               setmodel(self, "models/onslaught/controlpoint_icon.md3");
+       if(hp < this.max_health * 0.25)
+               setmodel(this, MDL_ONS_CP3);
+       else if(hp < this.max_health * 0.50)
+               setmodel(this, MDL_ONS_CP2);
+       else if(hp < this.max_health * 0.75)
+               setmodel(this, MDL_ONS_CP1);
+       else if(hp <= this.max_health || hp >= this.max_health)
+               setmodel(this, MDL_ONS_CP);
 
-       self.punchangle = (2 * randomvec() - '1 1 1') * 45;
+       this.punchangle = (2 * randomvec() - '1 1 1') * 45;
 
-       self.cp_bob_dmg_z = (2 * random() - 1) * 15;
-       self.pain_finished = time + 1;
-       self.colormod = '2 2 2';
+       this.cp_bob_dmg_z = (2 * random() - 1) * 15;
+       this.pain_finished = time + 1;
+       this.colormod = '2 2 2';
 
-       setsize(self, CPICON_MIN, CPICON_MAX);
+       setsize(this, CPICON_MIN, CPICON_MAX);
 }
 
-void cpicon_construct()
+void cpicon_construct(entity this)
 {
-       self.netname = "Control Point Icon";
+       this.netname = "Control Point Icon";
 
-       setmodel(self, "models/onslaught/controlpoint_icon.md3");
-       setsize(self, CPICON_MIN, CPICON_MAX);
+       setmodel(this, MDL_ONS_CP);
+       setsize(this, CPICON_MIN, CPICON_MAX);
 
-       if(self.icon_realmodel == world)
+       if(this.icon_realmodel == world)
        {
-               self.icon_realmodel = spawn();
-               setmodel(self.icon_realmodel, "null");
-               setorigin(self.icon_realmodel, self.origin);
-               setsize(self.icon_realmodel, CPICON_MIN, CPICON_MAX);
-               self.icon_realmodel.movetype = MOVETYPE_NOCLIP;
-               self.icon_realmodel.solid = SOLID_NOT;
-               self.icon_realmodel.move_origin = self.icon_realmodel.origin;
+               this.icon_realmodel = spawn();
+               setmodel(this.icon_realmodel, MDL_Null);
+               setorigin(this.icon_realmodel, this.origin);
+               setsize(this.icon_realmodel, CPICON_MIN, CPICON_MAX);
+               this.icon_realmodel.movetype = MOVETYPE_NOCLIP;
+               this.icon_realmodel.solid = SOLID_NOT;
+               this.icon_realmodel.move_origin = this.icon_realmodel.origin;
        }
 
-       if(self.iscaptured) { self.icon_realmodel.solid = SOLID_BBOX; }
-
-       self.move_movetype      = MOVETYPE_NOCLIP;
-       self.solid                      = SOLID_NOT;
-       self.movetype           = MOVETYPE_NOCLIP;
-       self.move_origin        = self.origin;
-       self.move_time          = time;
-       self.drawmask           = MASK_NORMAL;
-       self.alpha                      = 1;
-       self.draw                       = cpicon_draw;
-       self.cp_origin          = self.origin;
-       self.cp_bob_origin      = '0 0 0.1';
-       self.cp_bob_spd         = 0;
+       if(this.iscaptured) { this.icon_realmodel.solid = SOLID_BBOX; }
+
+       this.move_movetype      = MOVETYPE_NOCLIP;
+       this.solid                      = SOLID_NOT;
+       this.movetype           = MOVETYPE_NOCLIP;
+       this.move_origin        = this.origin;
+       this.move_time          = time;
+       this.drawmask           = MASK_NORMAL;
+       this.alpha                      = 1;
+       this.draw                       = cpicon_draw;
+       this.cp_origin          = this.origin;
+       this.cp_bob_origin      = '0 0 0.1';
+       this.cp_bob_spd         = 0;
 }
 
 .vector glowmod;
-void cpicon_changeteam()
+void cpicon_changeteam(entity this)
 {
-       if(self.team)
+       if(this.team)
        {
-               self.glowmod = Team_ColorRGB(self.team - 1);
-               self.teamradar_color = Team_ColorRGB(self.team - 1);
-               self.colormap = 1024 + (self.team - 1) * 17;
+               this.glowmod = Team_ColorRGB(this.team - 1);
+               this.teamradar_color = Team_ColorRGB(this.team - 1);
+               this.colormap = 1024 + (this.team - 1) * 17;
        }
        else
        {
-               self.colormap = 1024;
-               self.glowmod = '1 1 0';
-               self.teamradar_color = '1 1 0';
+               this.colormap = 1024;
+               this.glowmod = '1 1 0';
+               this.teamradar_color = '1 1 0';
        }
 }
 
-void ent_cpicon()
+void ent_cpicon(entity this)
 {
        int sf = ReadByte();
 
        if(sf & CPSF_SETUP)
        {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-               setorigin(self, self.origin);
-
-               self.health = ReadByte();
-               self.max_health = ReadByte();
-               self.count = ReadByte();
-               self.team = ReadByte();
-               self.iscaptured = ReadByte();
-
-               if(!self.count)
-                       self.count = (self.health - self.max_health) * frametime;
-
-               cpicon_changeteam();
-               cpicon_precache();
-               cpicon_construct();
+               this.origin_x = ReadCoord();
+               this.origin_y = ReadCoord();
+               this.origin_z = ReadCoord();
+               setorigin(this, this.origin);
+
+               this.health = ReadByte();
+               this.max_health = ReadByte();
+               this.count = ReadByte();
+               this.team = ReadByte();
+               this.iscaptured = ReadByte();
+
+               if(!this.count)
+                       this.count = (this.health - this.max_health) * frametime;
+
+               cpicon_changeteam(this);
+               cpicon_construct(this);
        }
 
        if(sf & CPSF_STATUS)
        {
                int _tmp = ReadByte();
-               if(_tmp != self.team)
+               if(_tmp != this.team)
                {
-                       self.team = _tmp;
-                       cpicon_changeteam();
+                       this.team = _tmp;
+                       cpicon_changeteam(this);
                }
 
                _tmp = ReadByte();
 
-               if(_tmp != self.health)
-                       cpicon_damage(_tmp);
+               if(_tmp != this.health)
+                       cpicon_damage(this, _tmp);
 
-               self.health = _tmp;
+               this.health = _tmp;
        }
 }
index 8469b5226fc36ef3f0efc15310c9732b0f654552..31485519d4eefee415115cd3098d03fc80d821cd 100644 (file)
@@ -7,7 +7,6 @@ const vector CPICON_MAX = '32 32 25';
 const int CPSF_STATUS = 4;
 const int CPSF_SETUP = 8;
 
-void ent_cpicon();
-void cpicon_precache();
+void ent_cpicon(entity this);
 
 #endif
index d8c44d660c022dc49d5cf5f481fd4aedfde2bc94..8d1f7e76fb3c77b90c74d7f4d5420cc8d2b4ffb5 100644 (file)
@@ -1,4 +1,3 @@
-#include "csqcmodel_hooks.qh"
 #include "_all.qh"
 
 #include "gibs.qh"
@@ -8,9 +7,10 @@
 
 #include "../common/animdecide.qh"
 #include "../common/csqcmodel_settings.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
 #include "../common/teams.qh"
 #include "../common/triggers/trigger/viewloc.qh"
+#include "../common/viewloc.qh"
 
 #include "mutators/events.qh"
 
@@ -31,7 +31,7 @@ void CSQCModel_Hook_PreDraw(bool isplayer);
 .int lodmodelindex1;
 .int lodmodelindex2;
 void CSQCPlayer_LOD_Apply(void)
-{
+{SELFPARAM();
        // LOD model loading
        if(self.lodmodelindex0 != self.modelindex)
        {
@@ -51,7 +51,7 @@ void CSQCPlayer_LOD_Apply(void)
                if(fexists(s))
                {
                        precache_model(s);
-                       setmodel(self, s);
+                       _setmodel(self, s);
                        if(self.modelindex)
                                self.lodmodelindex1 = self.modelindex;
                }
@@ -60,12 +60,12 @@ void CSQCPlayer_LOD_Apply(void)
                if(fexists(s))
                {
                        precache_model(s);
-                       setmodel(self, s);
+                       _setmodel(self, s);
                        if(self.modelindex)
                                self.lodmodelindex2 = self.modelindex;
                }
 
-               setmodel(self, modelname); // make everything normal again
+               _setmodel(self, modelname); // make everything normal again
                setsize(self, mi, ma);
        }
 
@@ -120,14 +120,14 @@ int forceplayermodels_goodmodelindex;
 .vector old_glowmod;
 
 void CSQCPlayer_ModelAppearance_PreUpdate(void)
-{
+{SELFPARAM();
        self.model = self.forceplayermodels_savemodel;
        self.modelindex = self.forceplayermodels_savemodelindex;
        self.skin = self.forceplayermodels_saveskin;
        self.colormap = self.forceplayermodels_savecolormap;
 }
 void CSQCPlayer_ModelAppearance_PostUpdate(void)
-{
+{SELFPARAM();
        self.forceplayermodels_savemodel = self.model;
        self.forceplayermodels_savemodelindex = self.modelindex;
        self.forceplayermodels_saveskin = self.skin;
@@ -142,7 +142,7 @@ void CSQCPlayer_ModelAppearance_PostUpdate(void)
        }
 }
 void CSQCPlayer_ModelAppearance_Apply(bool islocalplayer)
-{
+{SELFPARAM();
        // FORCEMODEL
        // which one is ALWAYS good?
        if (!forceplayermodels_goodmodel)
@@ -150,7 +150,7 @@ void CSQCPlayer_ModelAppearance_Apply(bool islocalplayer)
                entity e;
                e = spawn();
                precache_model(cvar_defstring("_cl_playermodel"));
-               setmodel(e, cvar_defstring("_cl_playermodel"));
+               _setmodel(e, cvar_defstring("_cl_playermodel"));
                forceplayermodels_goodmodel = e.model;
                forceplayermodels_goodmodelindex = e.modelindex;
                remove(e);
@@ -181,7 +181,7 @@ void CSQCPlayer_ModelAppearance_Apply(bool islocalplayer)
                // only if this failed, find it out on our own
                entity e;
                e = spawn();
-               setmodel(e, autocvar__cl_playermodel); // this is harmless, see below
+               _setmodel(e, autocvar__cl_playermodel); // this is harmless, see below
                forceplayermodels_modelisgoodmodel = fexists(e.model);
                forceplayermodels_model = e.model;
                forceplayermodels_modelindex = e.modelindex;
@@ -193,7 +193,7 @@ void CSQCPlayer_ModelAppearance_Apply(bool islocalplayer)
        {
                entity e;
                e = spawn();
-               setmodel(e, autocvar_cl_forcemyplayermodel); // this is harmless, see below
+               _setmodel(e, autocvar_cl_forcemyplayermodel); // this is harmless, see below
                forceplayermodels_myisgoodmodel = fexists(e.model);
                forceplayermodels_mymodel = e.model;
                forceplayermodels_mymodelindex = e.modelindex;
@@ -325,7 +325,7 @@ void CSQCPlayer_ModelAppearance_Apply(bool islocalplayer)
 
 #define IS_DEAD_FRAME(f) ((f) == 0 || (f) == 1)
 void CSQCPlayer_FallbackFrame_PreUpdate(void)
-{
+{SELFPARAM();
        self.frame = self.csqcmodel_saveframe;
        self.frame2 = self.csqcmodel_saveframe2;
 #ifdef CSQCMODEL_HAVE_TWO_FRAMES
@@ -334,7 +334,7 @@ void CSQCPlayer_FallbackFrame_PreUpdate(void)
 #endif
 }
 void CSQCPlayer_FallbackFrame_PostUpdate(bool isnew)
-{
+{SELFPARAM();
        self.csqcmodel_saveframe = self.frame;
        self.csqcmodel_saveframe2 = self.frame2;
 #ifdef CSQCMODEL_HAVE_TWO_FRAMES
@@ -360,11 +360,11 @@ void CSQCPlayer_FallbackFrame_PostUpdate(bool isnew)
        self.csqcmodel_isdead = IS_DEAD_FRAME(self.frame);
 }
 void CSQCPlayer_AnimDecide_PostUpdate(bool isnew)
-{
+{SELFPARAM();
        self.csqcmodel_isdead = !!(self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
 }
 int CSQCPlayer_FallbackFrame(int f)
-{
+{SELFPARAM();
        if(frameduration(self.modelindex, f) > 0)
                return f; // goooooood
        if(frameduration(self.modelindex, 1) <= 0)
@@ -384,7 +384,7 @@ int CSQCPlayer_FallbackFrame(int f)
        return f;
 }
 void CSQCPlayer_FallbackFrame_Apply(void)
-{
+{SELFPARAM();
        self.frame = CSQCPlayer_FallbackFrame(self.frame);
        self.frame2 = CSQCPlayer_FallbackFrame(self.frame2);
 #ifdef CSQCMODEL_HAVE_TWO_FRAMES
@@ -398,15 +398,11 @@ void CSQCPlayer_FallbackFrame_Apply(void)
 .int tag_entity_lastmodelindex;
 .int tag_index;
 void CSQCModel_AutoTagIndex_Apply(void)
-{
+{SELFPARAM();
        if(self.tag_entity && wasfreed(self.tag_entity))
                self.tag_entity = world;
 
-       if(self.viewloc && wasfreed(self.viewloc))
-               self.viewloc = world;
-
-       if(self.viewloc.entnum != self.tag_networkviewloc)
-               self.viewloc = findfloat(world, entnum, self.tag_networkviewloc);
+       viewloc_SetTags();
 
        MUTATOR_CALLHOOK(TagIndex_Update, self);
 
@@ -423,10 +419,7 @@ void CSQCModel_AutoTagIndex_Apply(void)
                // recursive predraw call to fix issues with forcemodels and LOD if bone indexes mismatch
                if(self.tag_entity.classname == "csqcmodel")
                {
-                       entity oldself = self;
-                       self = self.tag_entity;
-                       CSQCModel_Hook_PreDraw((self.entnum >= 1 && self.entnum <= maxclients));
-                       self = oldself;
+                       WITH(entity, self, self.tag_entity, CSQCModel_Hook_PreDraw((self.entnum >= 1 && self.entnum <= maxclients)));
                }
 
                if(self.tag_entity.modelindex != self.tag_entity_lastmodelindex)
@@ -498,14 +491,16 @@ const int MF_TRACER2 =  64; // orange split trail
 const int MF_TRACER3 = 128; // purple trail
 .int csqcmodel_effects;
 .int csqcmodel_modelflags;
+.int csqcmodel_traileffect;
 void CSQCModel_Effects_PreUpdate(void)
-{
+{SELFPARAM();
        self.effects = self.csqcmodel_effects;
        self.modelflags = self.csqcmodel_modelflags;
+       self.traileffect = self.csqcmodel_traileffect;
 }
 void Reset_ArcBeam(void);
 void CSQCModel_Effects_PostUpdate(void)
-{
+{SELFPARAM();
        if (self == csqcplayer) {
                if (self.csqcmodel_teleported) {
                        Reset_ArcBeam();
@@ -513,22 +508,24 @@ void CSQCModel_Effects_PostUpdate(void)
        }
        self.csqcmodel_effects = self.effects;
        self.csqcmodel_modelflags = self.modelflags;
+       self.csqcmodel_traileffect = self.traileffect;
        self.effects = 0;
        self.modelflags = 0;
        if(self.csqcmodel_teleported)
-               Projectile_ResetTrail(self.origin);
+               Projectile_ResetTrail(self, self.origin);
 }
 .int snd_looping;
 void CSQCModel_Effects_Apply(void)
-{
+{SELFPARAM();
        int eff = self.csqcmodel_effects & ~CSQCMODEL_EF_RESPAWNGHOST;
+       int tref = self.csqcmodel_traileffect;
 
        self.renderflags &= ~(RF_DEPTHHACK | RF_ADDITIVE | RF_FULLBRIGHT | EF_NOSHADOW | RF_USEAXIS);
        self.effects = 0;
        self.traileffect = 0;
 
        if(eff & EF_BRIGHTFIELD)
-               self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA);
+               tref = EFFECT_TR_NEXUIZPLASMA.m_id;
        // ignoring EF_MUZZLEFLASH
        if(eff & EF_BRIGHTLIGHT)
                adddynamiclight(self.origin, 400, '3 3 3');
@@ -562,29 +559,31 @@ void CSQCModel_Effects_Apply(void)
                self.renderflags |= RF_DYNAMICMODELLIGHT;
        // ignoring EF_UNUSED18, EF_UNUSED19, EF_RESTARTANIM_BIT, EF_TELEPORT_BIT, EF_LOWPRECISION
        if(self.csqcmodel_modelflags & MF_ROCKET)
-               self.traileffect = particleeffectnum(EFFECT_TR_ROCKET);
+               tref = EFFECT_TR_ROCKET.m_id;
        if(self.csqcmodel_modelflags & MF_GRENADE)
-               self.traileffect = particleeffectnum(EFFECT_TR_GRENADE);
+               tref = EFFECT_TR_GRENADE.m_id;
        if(self.csqcmodel_modelflags & MF_GIB)
-               self.traileffect = particleeffectnum(EFFECT_TR_BLOOD);
+               tref = EFFECT_TR_BLOOD.m_id;
        if(self.csqcmodel_modelflags & MF_ROTATE)
        {
                self.renderflags |= RF_USEAXIS;
                makevectors(self.angles + '0 100 0' * fmod(time, 3.6));
        }
        if(self.csqcmodel_modelflags & MF_TRACER)
-               self.traileffect = particleeffectnum(EFFECT_TR_WIZSPIKE);
+               tref = EFFECT_TR_WIZSPIKE.m_id;
        if(self.csqcmodel_modelflags & MF_ZOMGIB)
-               self.traileffect = particleeffectnum(EFFECT_TR_SLIGHTBLOOD);
+               tref = EFFECT_TR_SLIGHTBLOOD.m_id;
        if(self.csqcmodel_modelflags & MF_TRACER2)
-               self.traileffect = particleeffectnum(EFFECT_TR_KNIGHTSPIKE);
+               tref = EFFECT_TR_KNIGHTSPIKE.m_id;
        if(self.csqcmodel_modelflags & MF_TRACER3)
-               self.traileffect = particleeffectnum(EFFECT_TR_VORESPIKE);
+               tref = EFFECT_TR_VORESPIKE.m_id;
+
+       self.traileffect = tref;
 
        if(self.drawmask)
-               Projectile_DrawTrail(self.origin);
+               Projectile_DrawTrail(self, self.origin);
        else
-               Projectile_ResetTrail(self.origin);
+               Projectile_ResetTrail(self, self.origin);
 
        if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST)
                self.renderflags |= RF_ADDITIVE;
@@ -594,7 +593,7 @@ void CSQCModel_Effects_Apply(void)
        {
                if(!self.snd_looping)
                {
-                       sound(self, CH_TRIGGER_SINGLE, "misc/jetpack_fly.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+                       sound(self, CH_TRIGGER_SINGLE, SND_JETPACK_FLY, VOL_BASE, autocvar_g_jetpack_attenuation);
                        self.snd_looping = CH_TRIGGER_SINGLE;
                }
        }
@@ -602,17 +601,12 @@ void CSQCModel_Effects_Apply(void)
        {
                if(self.snd_looping)
                {
-                       sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+                       sound(self, self.snd_looping, SND_Null, VOL_BASE, autocvar_g_jetpack_attenuation);
                        self.snd_looping = 0;
                }
        }
 }
 
-void CSQCPlayer_Precache()
-{
-       precache_sound("misc/jetpack_fly.wav");
-}
-
 // general functions
 .int csqcmodel_predraw_run;
 .int anim_frame;
@@ -625,7 +619,7 @@ void CSQCPlayer_Precache()
 .int anim_saveframe2time;
 .int anim_prev_pmove_flags;
 void CSQCModel_Hook_PreDraw(bool isplayer)
-{
+{SELFPARAM();
        if(self.csqcmodel_predraw_run == framecount)
                return;
        self.csqcmodel_predraw_run = framecount;
@@ -724,7 +718,7 @@ void CSQCModel_Hook_PreDraw(bool isplayer)
 }
 
 void CSQCModel_Hook_PreUpdate(bool isnew, bool isplayer, bool islocalplayer)
-{
+{SELFPARAM();
        // interpolate v_angle
        self.iflags |= IFLAG_V_ANGLE_X;
        // revert to values from server
@@ -738,7 +732,7 @@ void CSQCModel_Hook_PreUpdate(bool isnew, bool isplayer, bool islocalplayer)
 }
 
 void CSQCModel_Hook_PostUpdate(bool isnew, bool isplayer, bool islocalplayer)
-{
+{SELFPARAM();
        // is it a player model? (shared state)
        self.isplayermodel = (substring(self.model, 0, 14) == "models/player/" || substring(self.model, 0, 17) == "models/ok_player/" || (substring(self.model, 0, 16) == "models/monsters/" && (self.entnum >= 1 && self.entnum <= maxclients)));
 
diff --git a/qcsrc/client/csqcmodel_hooks.qh b/qcsrc/client/csqcmodel_hooks.qh
deleted file mode 100644 (file)
index 8995880..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef CSQCMODEL_HOOKS
-#define CSQCMODEL_HOOKS
-
-void CSQCPlayer_Precache();
-
-#endif
index 32d236fba4db7a23194ec99e26cc08b38e331e65..7ef7f996bd1e22f93a7c0d07b1650952bbf05974 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "../common/constants.qh"
 #include "../common/deathtypes.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
 #include "../common/movetypes/movetypes.qh"
 #include "../common/util.qh"
 
@@ -20,7 +20,7 @@
 .bool isplayermodel;
 
 void DamageEffect_Think()
-{
+{SELFPARAM();
        // if particle distribution is enabled, slow ticrate by total number of damages
        if(autocvar_cl_damageeffect_distribute)
                self.nextthink = time + autocvar_cl_damageeffect_ticrate * self.owner.total_damages;
@@ -53,7 +53,7 @@ void DamageEffect_Think()
 }
 
 void DamageEffect(vector hitorg, float thedamage, int type, int specnum)
-{
+{SELFPARAM();
        // particle effects for players and objects damaged by weapons (eg: flames coming out of victims shot with rockets)
 
        int nearestbone = 0;
@@ -113,7 +113,7 @@ void DamageEffect(vector hitorg, float thedamage, int type, int specnum)
        }
 
        e = spawn();
-       setmodel(e, "null"); // necessary to attach and read origin
+       setmodel(e, MDL_Null); // necessary to attach and read origin
        setattachment(e, self, gettaginfo_name); // attach to the given bone
        e.classname = "damage";
        e.owner = self;
@@ -125,14 +125,11 @@ void DamageEffect(vector hitorg, float thedamage, int type, int specnum)
 }
 
 void Ent_DamageInfo(float isNew)
-{
+{SELFPARAM();
        float thedamage, rad, edge, thisdmg;
        bool hitplayer = false;
        int species, forcemul;
        vector force, thisforce;
-       entity oldself;
-
-       oldself = self;
 
        w_deathtype = ReadShort();
        w_issilent = (w_deathtype & 0x8000);
@@ -159,8 +156,9 @@ void Ent_DamageInfo(float isNew)
        else
                forcemul = 1;
 
-       for(self = findradius(w_org, rad + MAX_DAMAGEEXTRARADIUS); self; self = self.chain)
+       for(entity e = findradius(w_org, rad + MAX_DAMAGEEXTRARADIUS); e; e = e.chain)
        {
+               setself(e);
                // attached ents suck
                if(self.tag_entity)
                        continue;
@@ -211,8 +209,7 @@ void Ent_DamageInfo(float isNew)
                if(self.isplayermodel)
                        hitplayer = true; // this impact damaged a player
        }
-
-       self = oldself;
+       setself(this);
 
        if(DEATH_ISVEHICLE(w_deathtype))
        {
@@ -231,35 +228,33 @@ void Ent_DamageInfo(float isNew)
 
                        // spiderbot
                        case DEATH_VH_SPID_MINIGUN:
-                               string _snd;
-                               _snd = W_Sound(strcat("ric", ftos(1 + rint(random() * 2))));
-                               sound(self, CH_SHOTS, _snd, VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTEN_NORM);
                                pointparticles(particleeffectnum(EFFECT_SPIDERBOT_MINIGUN_IMPACT), self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_SPID_ROCKET:
-                               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
                                pointparticles(particleeffectnum(EFFECT_SPIDERBOT_ROCKET_EXPLODE), self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_SPID_DEATH:
-                               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_MIN);
+                               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_MIN);
                                pointparticles(particleeffectnum(EFFECT_EXPLOSION_BIG), self.origin, w_backoff * 1000, 1);
                                break;
 
                        case DEATH_VH_WAKI_GUN:
-                               sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_NORM);
                                pointparticles(particleeffectnum(EFFECT_RACER_IMPACT), self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_WAKI_ROCKET:
-                               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
                                pointparticles(particleeffectnum(EFFECT_RACER_ROCKET_EXPLODE), self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_WAKI_DEATH:
-                               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_MIN);
+                               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_MIN);
                                pointparticles(particleeffectnum(EFFECT_EXPLOSION_BIG), self.origin, w_backoff * 1000, 1);
                                break;
 
                        case DEATH_VH_RAPT_CANNON:
-                               sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_NORM);
                                pointparticles(particleeffectnum(EFFECT_RAPTOR_CANNON_IMPACT), self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_RAPT_FRAGMENT:
@@ -271,19 +266,19 @@ void Ent_DamageInfo(float isNew)
                                        ang = vectoangles(vel);
                                        RaptorCBShellfragToss(w_org, vel, ang + '0 0 1' * (120 * i));
                                }
-                               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
                                pointparticles(particleeffectnum(EFFECT_RAPTOR_BOMB_SPREAD), self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_RAPT_BOMB:
-                               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
                                pointparticles(particleeffectnum(EFFECT_RAPTOR_BOMB_IMPACT), self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_RAPT_DEATH:
-                               sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTEN_MIN);
+                               sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_MIN);
                                pointparticles(particleeffectnum(EFFECT_EXPLOSION_BIG), self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_BUMB_GUN:
-                               sound(self, CH_SHOTS, W_Sound("fireball_impact2"), VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_FIREBALL_IMPACT2, VOL_BASE, ATTEN_NORM);
                                pointparticles(particleeffectnum(EFFECT_BIGPLASMA_IMPACT), self.origin, w_backoff * 1000, 1);
                                break;
                }
@@ -292,7 +287,6 @@ void Ent_DamageInfo(float isNew)
 
        if(DEATH_ISTURRET(w_deathtype))
        {
-               string _snd;
                traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world);
                if(trace_plane_normal != '0 0 0')
                        w_backoff = trace_plane_normal;
@@ -304,38 +298,36 @@ void Ent_DamageInfo(float isNew)
                switch(w_deathtype)
                {
                         case DEATH_TURRET_EWHEEL:
-                               sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTEN_MIN);
+                               sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_MIN);
                                pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), self.origin, w_backoff * 1000, 1);
                                break;
 
                         case DEATH_TURRET_FLAC:
                                pointparticles(particleeffectnum(EFFECT_HAGAR_EXPLODE), w_org, '0 0 0', 1);
-                               _snd = W_Sound(strcat("hagexp", ftos(1 + rint(random() * 2))));
-                               sound(self, CH_SHOTS, _snd, VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_HAGEXP_RANDOM(), VOL_BASE, ATTEN_NORM);
                                break;
 
                         case DEATH_TURRET_MLRS:
                         case DEATH_TURRET_HK:
                         case DEATH_TURRET_WALK_ROCKET:
                         case DEATH_TURRET_HELLION:
-                               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_MIN);
+                               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_MIN);
                                pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, w_backoff * 1000, 1);
                                break;
 
                         case DEATH_TURRET_MACHINEGUN:
                         case DEATH_TURRET_WALK_GUN:
-                               _snd = W_Sound(strcat("ric", ftos(1 + rint(random() * 2))));
-                               sound(self, CH_SHOTS, _snd, VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTEN_NORM);
                                pointparticles(particleeffectnum(EFFECT_MACHINEGUN_IMPACT), self.origin, w_backoff * 1000, 1);
                                break;
 
                         case DEATH_TURRET_PLASMA:
-                               sound(self, CH_SHOTS, W_Sound("electro_impact"), VOL_BASE, ATTEN_MIN);
+                               sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_MIN);
                                pointparticles(particleeffectnum(EFFECT_ELECTRO_IMPACT), self.origin, w_backoff * 1000, 1);
                                break;
 
                         case DEATH_TURRET_WALK_MELEE:
-                               sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTEN_MIN);
+                               sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTEN_MIN);
                                pointparticles(particleeffectnum(EFFECT_TE_SPARK), self.origin, w_backoff * 1000, 1);
                                break;
 
@@ -363,6 +355,8 @@ void Ent_DamageInfo(float isNew)
                        w_backoff = -1 * normalize(force);
                setorigin(self, w_org + w_backoff * 2); // for sound() calls
 
-               if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)) { WEP_ACTION(hitwep, WR_IMPACTEFFECT); }
+               if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)) {
+                       Weapon w = get_weaponinfo(hitwep); w.wr_impacteffect(w);
+               }
        }
 }
index 80ccc441bcf01cf0188f4be4cf7b0bd9a7d4205e..eed682785e0ec2ee8877f4aa71546c6843c20be4 100644 (file)
@@ -1,37 +1,9 @@
 #include "generator.qh"
 
-bool generator_precached;
 .int count;
 .float max_health;
 
-void generator_precache()
-{
-       if(generator_precached)
-               return; // already precached
-
-       precache_model("models/onslaught/generator.md3");
-       precache_model("models/onslaught/generator_dead.md3");
-       precache_model("models/onslaught/generator_dmg1.md3");
-       precache_model("models/onslaught/generator_dmg2.md3");
-       precache_model("models/onslaught/generator_dmg3.md3");
-       precache_model("models/onslaught/generator_dmg4.md3");
-       precache_model("models/onslaught/generator_dmg5.md3");
-       precache_model("models/onslaught/generator_dmg6.md3");
-       precache_model("models/onslaught/generator_dmg7.md3");
-       precache_model("models/onslaught/generator_dmg8.md3");
-       precache_model("models/onslaught/generator_dmg9.md3");
-       precache_model("models/onslaught/generator_dead.md3");
-
-       precache_model("models/onslaught/ons_ray.md3");
-       precache_sound("onslaught/shockwave.wav");
-       precache_sound(W_Sound("grenade_impact"));
-       precache_sound(W_Sound("rocket_impact"));
-       precache_sound("onslaught/electricity_explode.wav");
-
-       generator_precached = true;
-}
-
-void ons_generator_ray_draw()
+void ons_generator_ray_draw(entity this)
 {
        if(time < self.move_time)
                return;
@@ -58,7 +30,7 @@ void ons_generator_ray_spawn(vector org)
        entity e;
        e = spawn();
        e.classname = "ons_ray";
-       setmodel(e, "models/onslaught/ons_ray.md3");
+       setmodel(e, MDL_ONS_RAY);
        setorigin(e, org);
        e.angles = randomvec() * 360;
        e.move_origin = org;
@@ -70,7 +42,7 @@ void ons_generator_ray_spawn(vector org)
        e.draw = ons_generator_ray_draw;
 }
 
-void generator_draw()
+void generator_draw(entity this)
 {
        if(time < self.move_time)
                return;
@@ -82,7 +54,7 @@ void generator_draw()
                if(random() < 0.01)
                {
                        pointparticles(particleeffectnum(EFFECT_ELECTRO_BALLEXPLODE), self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
-                       sound(self, CH_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_TRIGGER, SND_ONS_ELECTRICITY_EXPLODE, VOL_BASE, ATTEN_NORM);
                }
                else
                        pointparticles(particleeffectnum(EFFECT_ONS_GENERATOR_DAMAGED), self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
@@ -101,7 +73,7 @@ void generator_draw()
        // White shockwave
        if(self.count==40||self.count==20)
        {
-               sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTEN_NORM);
+               sound(self, CH_TRIGGER, SND_ONS_SHOCKWAVE, VOL_BASE, ATTEN_NORM);
                pointparticles(particleeffectnum(EFFECT_ELECTRO_COMBO), self.origin, '0 0 0', 6);
        }
 
@@ -122,7 +94,7 @@ void generator_draw()
        if(random() < 0.25)
        {
                te_explosion(self.origin);
-               sound(self, CH_TRIGGER, W_Sound("grenade_impact"), VOL_BASE, ATTEN_NORM);
+               sound(self, CH_TRIGGER, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
        }
 
        // Particles
@@ -135,7 +107,7 @@ void generator_draw()
                org = self.origin;
                te_explosion(org);
                pointparticles(particleeffectnum(EFFECT_ONS_GENERATOR_EXPLODE2), org, '0 0 0', 1);
-               sound(self, CH_TRIGGER, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+               sound(self, CH_TRIGGER, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
        }
 
        self.move_time = time + 0.05;
@@ -144,40 +116,40 @@ void generator_draw()
 }
 
 void generator_damage(float hp)
-{
+{SELFPARAM();
        if(hp <= 0)
-               setmodel(self, "models/onslaught/generator_dead.md3");
+               setmodel(self, MDL_ONS_GEN_DEAD);
        else if(hp < self.max_health * 0.10)
-               setmodel(self, "models/onslaught/generator_dmg9.md3");
+               setmodel(self, MDL_ONS_GEN9);
        else if(hp < self.max_health * 0.20)
-               setmodel(self, "models/onslaught/generator_dmg8.md3");
+               setmodel(self, MDL_ONS_GEN8);
        else if(hp < self.max_health * 0.30)
-               setmodel(self, "models/onslaught/generator_dmg7.md3");
+               setmodel(self, MDL_ONS_GEN7);
        else if(hp < self.max_health * 0.40)
-               setmodel(self, "models/onslaught/generator_dmg6.md3");
+               setmodel(self, MDL_ONS_GEN6);
        else if(hp < self.max_health * 0.50)
-               setmodel(self, "models/onslaught/generator_dmg5.md3");
+               setmodel(self, MDL_ONS_GEN5);
        else if(hp < self.max_health * 0.60)
-               setmodel(self, "models/onslaught/generator_dmg4.md3");
+               setmodel(self, MDL_ONS_GEN4);
        else if(hp < self.max_health * 0.70)
-               setmodel(self, "models/onslaught/generator_dmg3.md3");
+               setmodel(self, MDL_ONS_GEN3);
        else if(hp < self.max_health * 0.80)
-               setmodel(self, "models/onslaught/generator_dmg2.md3");
+               setmodel(self, MDL_ONS_GEN2);
        else if(hp < self.max_health * 0.90)
-               setmodel(self, "models/onslaught/generator_dmg1.md3");
+               setmodel(self, MDL_ONS_GEN1);
        else if(hp <= self.max_health || hp >= self.max_health)
-               setmodel(self, "models/onslaught/generator.md3");
+               setmodel(self, MDL_ONS_GEN);
 
        setsize(self, GENERATOR_MIN, GENERATOR_MAX);
 }
 
 void generator_construct()
-{
+{SELFPARAM();
        self.netname = "Generator";
        self.classname = "onslaught_generator";
 
        setorigin(self, self.origin);
-       setmodel(self, "models/onslaught/generator.md3");
+       setmodel(self, MDL_ONS_GEN);
        setsize(self, GENERATOR_MIN, GENERATOR_MAX);
 
        self.move_movetype      = MOVETYPE_NOCLIP;
@@ -192,7 +164,7 @@ void generator_construct()
 
 .vector glowmod;
 void generator_changeteam()
-{
+{SELFPARAM();
        if(self.team)
        {
                self.glowmod = Team_ColorRGB(self.team - 1);
@@ -208,7 +180,7 @@ void generator_changeteam()
 }
 
 void ent_generator()
-{
+{SELFPARAM();
        int sf = ReadByte();
 
        if(sf & GSF_SETUP)
@@ -227,7 +199,6 @@ void ent_generator()
                        self.count = 40;
 
                generator_changeteam();
-               generator_precache();
                generator_construct();
        }
 
index e4e1611f31273ca1d7dda2173f72405d733ab3c4..744bc5589f47a39edba81e1bf1fe78dbc215d617 100644 (file)
@@ -7,5 +7,4 @@ const int GSF_STATUS = 4;
 const int GSF_SETUP = 8;
 
 void ent_generator();
-void generator_precache();
 #endif
index b59cd4ff3d50c4d4b80a1722e3a02953ec9bb9ee..360f7b5c361bdb6b99435575f8dfb5553e6de855 100644 (file)
@@ -13,7 +13,7 @@
 .float gravity;
 
 void Gib_Delete()
-{
+{SELFPARAM();
        remove(self);
 }
 
@@ -42,9 +42,9 @@ void Gib_setmodel(entity gib, string mdlname, int specnum)
                        if(specnum != SPECIES_ROBOT_SOLID || mdlname == "models/gibs/chunk.mdl")
                        {
                                if(mdlname == "models/gibs/bloodyskull.md3")
-                                       setmodel(gib, "models/gibs/robo.md3");
+                                       setmodel(gib, MDL_GIB_ROBO);
                                else
-                                       setmodel(gib, strcat("models/gibs/robo", ftos(floor(random() * 8) + 1), ".md3"));
+                                       setmodel(gib, MDL_GIB_ROBO_RANDOM());
                                if(specnum == SPECIES_ROBOT_SHINY)
                                {
                                        gib.skin = 1;
@@ -54,7 +54,7 @@ void Gib_setmodel(entity gib, string mdlname, int specnum)
                                break;
                        }
                default:
-                       setmodel(gib, mdlname);
+                       _setmodel(gib, mdlname);
                        gib.skin = specnum;
                        break;
        }
@@ -75,7 +75,7 @@ void SUB_RemoveOnNoImpact()
 }
 
 void Gib_Touch()
-{
+{SELFPARAM();
        // TODO maybe bounce of walls, make more gibs, etc.
 
        if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
@@ -85,13 +85,13 @@ void Gib_Touch()
        }
 
        if(!self.silent)
-               sound(self, CH_PAIN, strcat("misc/gib_splat0", ftos(floor(prandom() * 4 + 1)), ".wav"), VOL_BASE, ATTEN_NORM);
+               sound(self, CH_PAIN, SND_GIB_SPLAT_RANDOM(), VOL_BASE, ATTEN_NORM);
        pointparticles(_particleeffectnum(strcat(species_prefix(self.cnt), "blood")), self.origin + '0 0 1', '0 0 30', 10);
 
        Gib_Delete();
 }
 
-void Gib_Draw()
+void Gib_Draw(entity this)
 {
        vector oldorg;
        oldorg = self.origin;
@@ -164,7 +164,7 @@ void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector
 }
 
 void Ent_GibSplash(bool isNew)
-{
+{SELFPARAM();
        int amount, type, specnum;
        vector org, vel;
        string specstr;
@@ -218,7 +218,7 @@ void Ent_GibSplash(bool isNew)
        {
                case 0x01:
                        if(!issilent)
-                               sound (self, CH_PAIN, "misc/gib.wav", VOL_BASE, ATTEN_NORM);
+                               sound (self, CH_PAIN, SND_GIB, VOL_BASE, ATTEN_NORM);
 
                        if(prandom() < amount)
                                TossGib ("models/gibs/eye.md3", org, org, vel, prandomvec() * 150, specnum, 0, issilent);
@@ -272,31 +272,3 @@ void Ent_GibSplash(bool isNew)
                        break;
        }
 }
-
-void GibSplash_Precache()
-{
-       precache_model("models/gibs/chunk.mdl");
-       precache_model("models/gibs/leg1.md3");
-       precache_model("models/gibs/leg2.md3");
-       precache_model("models/gibs/chest.md3");
-       precache_model("models/gibs/smallchest.md3");
-       precache_model("models/gibs/arm.md3");
-       precache_model("models/gibs/bloodyskull.md3");
-       precache_model("models/gibs/eye.md3");
-
-       precache_model("models/gibs/robo.md3");
-       precache_model("models/gibs/robo1.md3");
-       precache_model("models/gibs/robo2.md3");
-       precache_model("models/gibs/robo3.md3");
-       precache_model("models/gibs/robo4.md3");
-       precache_model("models/gibs/robo5.md3");
-       precache_model("models/gibs/robo6.md3");
-       precache_model("models/gibs/robo7.md3");
-       precache_model("models/gibs/robo8.md3");
-
-       precache_sound ("misc/gib.wav");
-    precache_sound ("misc/gib_splat01.wav");
-    precache_sound ("misc/gib_splat02.wav");
-    precache_sound ("misc/gib_splat03.wav");
-    precache_sound ("misc/gib_splat04.wav");
-}
index b33a1a5e061bf1416e11085bd812a899a0ca2e88..f4b60948af7cf0a103c19da8645e18317e7178cf 100644 (file)
@@ -17,11 +17,10 @@ void SUB_RemoveOnNoImpact();
 
 void Gib_Touch();
 
-void Gib_Draw();
+void Gib_Draw(entity this);
 
 void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector vrand, int specnum, bool destroyontouch, bool issilent);
 
 void Ent_GibSplash(bool isNew);
 
-void GibSplash_Precache();
 #endif
index a30ab73c16e357a3972d923c87a43aa5a6623bc4..07123f06b5ec278b9bb1d609a7e9e8d195032836 100644 (file)
@@ -31,7 +31,7 @@ void Draw_GrapplingHook_trace_callback(vector start, vector hit, vector end)
 }
 
 class(Hook) .float teleport_time;
-void Draw_GrapplingHook()
+void Draw_GrapplingHook(entity this)
 {
        vector a, b, atrans;
        string tex;
@@ -44,7 +44,7 @@ void Draw_GrapplingHook()
        if(self.teleport_time)
        if(time > self.teleport_time)
        {
-               sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM); // safeguard
+               sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM); // safeguard
                self.teleport_time = 0;
        }
 
@@ -167,12 +167,12 @@ void Draw_GrapplingHook()
 }
 
 void Remove_GrapplingHook()
-{
-       sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+       sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
 }
 
 void Ent_ReadHook(float bIsNew, float type)
-{
+{SELFPARAM();
        self.HookType = type;
 
        int sf = ReadByte();
@@ -224,11 +224,11 @@ void Ent_ReadHook(float bIsNew, float type)
                        default:
                        case ENT_CLIENT_HOOK:
                                // for the model
-                               setmodel(self, "models/hook.md3");
+                               setmodel(self, MDL_HOOK);
                                self.drawmask = MASK_NORMAL;
                                break;
                        case ENT_CLIENT_ARC_BEAM:
-                               sound (self, CH_SHOTS_SINGLE, W_Sound("lgbeam_fly"), VOL_BASE, ATTEN_NORM);
+                               sound (self, CH_SHOTS_SINGLE, SND_LGBEAM_FLY, VOL_BASE, ATTEN_NORM);
                                break;
                }
        }
@@ -236,10 +236,4 @@ void Ent_ReadHook(float bIsNew, float type)
        self.teleport_time = time + 10;
 }
 
-void Hook_Precache()
-{
-       precache_sound(W_Sound("lgbeam_fly"));
-       precache_model("models/hook.md3");
-}
-
 // TODO: hook: temporarily transform self.origin for drawing the model along warpzones!
index 8401dce049a43cd1c90accf3c6e3c30471da7946..e513ed6afa4451ee0271a1bc33d15716b869edfc 100644 (file)
@@ -2,7 +2,6 @@
 #define HOOK_H
 
 void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg);
-void Hook_Precache();
 
 void Ent_ReadHook(float bIsNew, float type);
 
index eb50ebc094090437a069d5a7fcc87ae368b583b0..dbae62cbdef08c40cde94676b407e014673e5169 100644 (file)
@@ -9,13 +9,14 @@
 
 #include "../dpdefs/keycodes.qh"
 
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
 #include "../common/constants.qh"
 #include "../common/deathtypes.qh"
 #include "../common/items/all.qc"
 #include "../common/mapinfo.qh"
-#include "../common/nades.qh"
+#include "../common/nades/all.qh"
 
+#include "../common/mutators/mutator/waypoints/all.qh"
 #include "../server/mutators/gamemode_ctf.qh"
 
 #include "../common/stats.qh"
@@ -334,7 +335,7 @@ void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theA
 
 // Weapon icons (#0)
 //
-entity weaponorder[WEP_MAXCOUNT];
+entity weaponorder[Weapons_MAX];
 void weaponorder_swap(int i, int j, entity pass)
 {
        entity h = weaponorder[i];
@@ -352,7 +353,7 @@ int weaponorder_cmp(int i, int j, entity pass)
 }
 
 void HUD_Weapons(void)
-{
+{SELFPARAM();
        // declarations
        WepSet weapons_stat = WepSet_GetFromStat();
        int i;
@@ -413,14 +414,14 @@ void HUD_Weapons(void)
                weapon_cnt = 0;
                for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                {
-                       self = get_weaponinfo(i);
+                       setself(get_weaponinfo(i));
                        if(self.impulse >= 0)
                        {
                                weaponorder[weapon_cnt] = self;
                                ++weapon_cnt;
                        }
                }
-               for(i = weapon_cnt; i < WEP_MAXCOUNT; ++i)
+               for(i = weapon_cnt; i < Weapons_MAX; ++i)
                        weaponorder[i] = world;
                heapsort(weapon_cnt, weaponorder_swap, weaponorder_cmp, world);
 
@@ -441,7 +442,7 @@ void HUD_Weapons(void)
                if(cvar("wep_add"))
                {
                        weapons_stat = '0 0 0';
-                       float countw = 1 + floor((floor(time * cvar("wep_add"))) % WEP_COUNT);
+                       float countw = 1 + floor((floor(time * cvar("wep_add"))) % (Weapons_COUNT - 1));
                        for(i = WEP_FIRST; i <= countw; ++i)
                                weapons_stat |= WepSet_FromWeapon(i);
                }
@@ -472,7 +473,15 @@ void HUD_Weapons(void)
                vector padded_panel_size = panel_size - '2 2 0' * panel_bg_padding;
 
                // get the all-weapons layout
-               vector table_size = HUD_GetTableSize_BestItemAR(WEP_COUNT, padded_panel_size, aspect);
+               int nHidden = 0;
+               WepSet weapons_stat = WepSet_GetFromStat();
+               for (int i = WEP_FIRST; i <= WEP_LAST; ++i) {
+                       WepSet weapons_wep = WepSet_FromWeapon(i);
+                       if (weapons_stat & weapons_wep) continue;
+                       Weapon w = get_weaponinfo(i);
+                       if (w.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1;
+               }
+               vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, padded_panel_size, aspect);
                columns = table_size.x;
                rows = table_size.y;
                weapon_size.x = padded_panel_size.x / columns;
@@ -527,7 +536,7 @@ void HUD_Weapons(void)
                        panel_pos.y += (old_panel_size.y - panel_size.y) / 2;
        }
        else
-               weapon_count = WEP_COUNT;
+               weapon_count = (Weapons_COUNT - 1);
 
        // animation for fading in/out the panel respectively when not in use
        if(!autocvar__hud_configure)
@@ -632,7 +641,7 @@ void HUD_Weapons(void)
 
        if(!rows) // if rows is > 0 onlyowned code has already updated these vars
        {
-               vector table_size = HUD_GetTableSize_BestItemAR(WEP_COUNT, panel_size, aspect);
+               vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1), panel_size, aspect);
                columns = table_size.x;
                rows = table_size.y;
                weapon_size.x = panel_size.x / columns;
@@ -673,7 +682,7 @@ void HUD_Weapons(void)
        for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
        {
                // retrieve information about the current weapon to be drawn
-               self = weaponorder[i];
+               setself(weaponorder[i]);
                weapon_id = self.impulse;
                isCurrent = (self.weapon == switchweapon);
 
@@ -850,8 +859,8 @@ void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expan
        float bonusNades    = getstatf(STAT_NADE_BONUS);
        float bonusProgress = getstatf(STAT_NADE_BONUS_SCORE);
        float bonusType     = getstati(STAT_NADE_BONUS_TYPE);
-       vector nadeColor    = NADES[bonusType].m_color;
-       string nadeIcon     = NADES[bonusType].m_icon;
+       vector nadeColor    = Nades[bonusType].m_color;
+       string nadeIcon     = Nades[bonusType].m_icon;
 
        vector iconPos, textPos;
 
@@ -1275,7 +1284,7 @@ void HUD_Powerups()
        if(superTime)
                addPowerupItem("Superweapons", "superweapons", autocvar_hud_progressbar_superweapons_color, superTime, 30);
 
-       FOREACH(BUFFS, it.m_itemid & allBuffs, LAMBDA(
+       FOREACH(Buffs, it.m_itemid & allBuffs, LAMBDA(
                addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, getstatf(STAT_BUFF_TIME) - time, 99), 60);
        ));
 
@@ -2232,8 +2241,8 @@ void HUD_Radar(void)
                                drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
                        }
                }
-
-               draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm, tm.teamradar_color, panel_fg_alpha);
+               entity icon = RadarIcons[tm.teamradar_icon];
+               draw_teamradar_icon(tm.origin, icon, tm, spritelookupcolor(tm, icon.netname, tm.teamradar_color), panel_fg_alpha);
        }
        for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
        {
@@ -4456,7 +4465,7 @@ void HUD_CenterPrint (void)
                        reset_centerprint_messages();
                if (time > hud_configure_cp_generation_time)
                {
-                       if(HUD_PANEL(CENTERPRINT) == highlightedPanel)
+                       if(highlightedPanel == HUD_PANEL(CENTERPRINT))
                        {
                                float r;
                                r = random();
@@ -4791,18 +4800,18 @@ void HUD_Main (void)
 
        // cache the panel order into the panel_order array
        if(autocvar__hud_panelorder != hud_panelorder_prev) {
-               for(i = 0; i < HUD_PANEL_NUM; ++i)
+               for(i = 0; i < hud_panels_COUNT; ++i)
                        panel_order[i] = -1;
                string s = "";
                int p_num;
                bool warning = false;
                int argc = tokenize_console(autocvar__hud_panelorder);
-               if (argc > HUD_PANEL_NUM)
+               if (argc > hud_panels_COUNT)
                        warning = true;
                //first detect wrong/missing panel numbers
-               for(i = 0; i < HUD_PANEL_NUM; ++i) {
+               for(i = 0; i < hud_panels_COUNT; ++i) {
                        p_num = stoi(argv(i));
-                       if (p_num >= 0 && p_num < HUD_PANEL_NUM) { //correct panel number?
+                       if (p_num >= 0 && p_num < hud_panels_COUNT) { //correct panel number?
                                if (panel_order[p_num] == -1) //found for the first time?
                                        s = strcat(s, ftos(p_num), " ");
                                panel_order[p_num] = 1; //mark as found
@@ -4810,7 +4819,7 @@ void HUD_Main (void)
                        else
                                warning = true;
                }
-               for(i = 0; i < HUD_PANEL_NUM; ++i) {
+               for(i = 0; i < hud_panels_COUNT; ++i) {
                        if (panel_order[i] == -1) {
                                warning = true;
                                s = strcat(s, ftos(i), " "); //add missing panel number
@@ -4826,15 +4835,15 @@ void HUD_Main (void)
 
                //now properly set panel_order
                tokenize_console(s);
-               for(i = 0; i < HUD_PANEL_NUM; ++i) {
+               for(i = 0; i < hud_panels_COUNT; ++i) {
                        panel_order[i] = stof(argv(i));
                }
        }
 
        hud_draw_maximized = 0;
        // draw panels in the order specified by panel_order array
-       for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
-               HUD_Panel_Draw(hud_panel[panel_order[i]]);
+       for(i = hud_panels_COUNT - 1; i >= 0; --i)
+               HUD_Panel_Draw(hud_panels[panel_order[i]]);
 
        hud_draw_maximized = 1; // panels that may be maximized must check this var
        // draw maximized panels on top
index d30eea145de3c29e86281185819f3732f4344bb0..224b3fbe09de952c31bca79898d525eca73db2f8 100644 (file)
@@ -3,13 +3,21 @@
 
 #include "../common/weapons/all.qh"
 
-const int HUD_PANEL_MAX = 24;
-entity hud_panel[HUD_PANEL_MAX];
-const int HUD_PANEL_FIRST = 0;
-int HUD_PANEL_NUM;
-int HUD_PANEL_LAST;
+REGISTRY(hud_panels, 24)
+REGISTER_REGISTRY(Registerhud_panels)
 
-int panel_order[HUD_PANEL_MAX];
+#define REGISTER_HUD_PANEL(id, draw_func, name, showflags) \
+       void draw_func(); \
+       REGISTER(Registerhud_panels, HUD_PANEL, hud_panels, id, m_id, new(hud_panel)) { \
+               this.panel_id = this.m_id; \
+               this.panel_draw = draw_func; \
+               this.panel_name = #name; \
+               this.panel_showflags = showflags; \
+       }
+
+#define HUD_PANEL(NAME) HUD_PANEL_##NAME
+
+int panel_order[hud_panels_MAX];
 string hud_panelorder_prev;
 
 bool hud_draw_maximized;
@@ -46,7 +54,7 @@ float highlightedAction; // 0 = nothing, 1 = move, 2 = resize
 
 const float BORDER_MULTIPLIER = 0.25;
 float scoreboard_bottom;
-int weapon_accuracy[WEP_MAXCOUNT];
+int weapon_accuracy[Weapons_MAX];
 
 int complain_weapon;
 string complain_weapon_name;
@@ -156,55 +164,31 @@ int prev_p_health, prev_p_armor;
 
 void HUD_ItemsTime();
 
-#define HUD_PANELS(HUD_PANEL) \
-       HUD_PANEL(WEAPONS      , HUD_Weapons      , weapons,        PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(AMMO         , HUD_Ammo         , ammo,           PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(POWERUPS     , HUD_Powerups     , powerups,       PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(HEALTHARMOR  , HUD_HealthArmor  , healtharmor,    PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(NOTIFY       , HUD_Notify       , notify,         PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(TIMER        , HUD_Timer        , timer,          PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(RADAR        , HUD_Radar        , radar,          PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(SCORE        , HUD_Score        , score,          PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(RACETIMER    , HUD_RaceTimer    , racetimer,      PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(VOTE         , HUD_Vote         , vote,           PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(MODICONS     , HUD_ModIcons     , modicons,       PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(PRESSEDKEYS  , HUD_PressedKeys  , pressedkeys,    PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(CHAT         , HUD_Chat         , chat,           PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(ENGINEINFO   , HUD_EngineInfo   , engineinfo,     PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(INFOMESSAGES , HUD_InfoMessages , infomessages,   PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(PHYSICS      , HUD_Physics      , physics,        PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(CENTERPRINT  , HUD_CenterPrint  , centerprint,    PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(MINIGAME_BOARD, HUD_MinigameBoard ,minigameboard, PANEL_SHOW_MINIGAME ) \
-       HUD_PANEL(MINIGAME_STATUS,HUD_MinigameStatus,minigamestatus,PANEL_SHOW_MINIGAME ) \
-       HUD_PANEL(MINIGAME_HELP,  HUD_MinigameHelp  ,minigamehelp,  PANEL_SHOW_MINIGAME ) \
-       HUD_PANEL(MINIGAME_MENU,  HUD_MinigameMenu  ,minigamemenu,  PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(MAPVOTE      ,  MapVote_Draw      ,mapvote,       PANEL_SHOW_ALWAYS   ) \
-       HUD_PANEL(ITEMSTIME    ,  HUD_ItemsTime     ,itemstime,     PANEL_SHOW_MAINGAME ) \
-       HUD_PANEL(QUICKMENU    , HUD_QuickMenu    , quickmenu,      PANEL_SHOW_MAINGAME ) \
-       // always add new panels to the end of list
-
-
-#define HUD_PANEL(NAME, draw_func, name, showflags)                                                                                                                                                    \
-       int HUD_PANEL_##NAME;                                                                                                                                                                                   \
-       void draw_func(void);                                                                                                                                                                                   \
-       void RegisterHUD_Panel_##NAME() {                                                                                                                                                               \
-               HUD_PANEL_LAST = HUD_PANEL_##NAME = HUD_PANEL_NUM;                                                                                                                      \
-               entity hud_panelent = spawn();                                                                                                                                                          \
-               hud_panel[HUD_PANEL_##NAME] = hud_panelent;                                                                                                                             \
-               hud_panelent.classname = "hud_panel";                                                                                                                                           \
-               hud_panelent.panel_name = #name;                                                                                                                                                        \
-               hud_panelent.panel_id = HUD_PANEL_##NAME;                                                                                                                                       \
-               hud_panelent.panel_draw = draw_func;                                                                                                                                            \
-               hud_panelent.panel_showflags = showflags;                                                                                                                                       \
-               HUD_PANEL_NUM++;                                                                                                                                                                                        \
-       }                                                                                                                                                                                                                               \
-       ACCUMULATE_FUNCTION(RegisterHUD_Panels, RegisterHUD_Panel_##NAME);
-
-HUD_PANELS(HUD_PANEL)
-#undef HUD_PANEL
-
-#define HUD_PANEL(NAME) hud_panel[HUD_PANEL_##NAME]
-
+REGISTER_HUD_PANEL(WEAPONS,         HUD_Weapons,        weapons,        PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(AMMO,            HUD_Ammo,           ammo,           PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(POWERUPS,        HUD_Powerups,       powerups,       PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(HEALTHARMOR,     HUD_HealthArmor,    healtharmor,    PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(NOTIFY,          HUD_Notify,         notify,         PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(TIMER,           HUD_Timer,          timer,          PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(RADAR,           HUD_Radar,          radar,          PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(SCORE,           HUD_Score,          score,          PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(RACETIMER,       HUD_RaceTimer,      racetimer,      PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(VOTE,            HUD_Vote,           vote,           PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(MODICONS,        HUD_ModIcons,       modicons,       PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(PRESSEDKEYS,     HUD_PressedKeys,    pressedkeys,    PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(CHAT,            HUD_Chat,           chat,           PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(ENGINEINFO,      HUD_EngineInfo,     engineinfo,     PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(INFOMESSAGES,    HUD_InfoMessages,   infomessages,   PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(PHYSICS,         HUD_Physics,        physics,        PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(CENTERPRINT,     HUD_CenterPrint,    centerprint,    PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(MINIGAME_BOARD,  HUD_MinigameBoard,  minigameboard,  PANEL_SHOW_MINIGAME)
+REGISTER_HUD_PANEL(MINIGAME_STATUS, HUD_MinigameStatus, minigamestatus, PANEL_SHOW_MINIGAME)
+REGISTER_HUD_PANEL(MINIGAME_HELP,   HUD_MinigameHelp,   minigamehelp,   PANEL_SHOW_MINIGAME)
+REGISTER_HUD_PANEL(MINIGAME_MENU,   HUD_MinigameMenu,   minigamemenu,   PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(MAPVOTE,         MapVote_Draw,       mapvote,        PANEL_SHOW_ALWAYS  )
+REGISTER_HUD_PANEL(ITEMSTIME,       HUD_ItemsTime,      itemstime,      PANEL_SHOW_MAINGAME)
+REGISTER_HUD_PANEL(QUICKMENU,       HUD_QuickMenu,      quickmenu,      PANEL_SHOW_MAINGAME)
+// always add new panels to the end of list
 
 // Because calling lots of functions in QC apparently cuts fps in half on many machines:
 // ----------------------
index 0216a43b087b6b0352148f12ac95ba41a8cc1a7d..2cdb9fcf4de9105cd47c8e1cf5994ba58459eacb 100644 (file)
@@ -59,10 +59,9 @@ void HUD_Panel_ExportCfg(string cfgname)
                HUD_Write("\n");
 
                // common cvars for all panels
-               int i;
-               for (i = 0; i < HUD_PANEL_NUM; ++i)
+               for (int i = 0; i < hud_panels_COUNT; ++i)
                {
-                       panel = hud_panel[i];
+                       panel = hud_panels[i];
 
                        HUD_Write_PanelCvar_n("");
                        HUD_Write_PanelCvar_q("_pos");
@@ -73,7 +72,7 @@ void HUD_Panel_ExportCfg(string cfgname)
                        HUD_Write_PanelCvar_q("_bg_alpha");
                        HUD_Write_PanelCvar_q("_bg_border");
                        HUD_Write_PanelCvar_q("_bg_padding");
-                       switch(i) {
+                       switch(panel) {
                                case HUD_PANEL_WEAPONS:
                                        HUD_Write_PanelCvar_q("_accuracy");
                                        HUD_Write_PanelCvar_q("_label");
@@ -240,8 +239,8 @@ vector HUD_Panel_CheckMove(vector myPos, vector mySize)
        vector myCenter, targCenter;
        vector myTarget = myPos;
        int i;
-       for (i = 0; i < HUD_PANEL_NUM; ++i) {
-               panel = hud_panel[i];
+       for (i = 0; i < hud_panels_COUNT; ++i) {
+               panel = hud_panels[i];
                if(panel == HUD_PANEL(MAPVOTE)) continue;
                if(panel == highlightedPanel) continue;
                HUD_Panel_UpdatePosSize();
@@ -337,8 +336,8 @@ vector HUD_Panel_CheckResize(vector mySize, vector resizeorigin) {
        vector dist;
        float ratio = mySize.x/mySize.y;
        int i;
-       for (i = 0; i < HUD_PANEL_NUM; ++i) {
-               panel = hud_panel[i];
+       for (i = 0; i < hud_panels_COUNT; ++i) {
+               panel = hud_panels[i];
                if(panel == HUD_PANEL(MAPVOTE)) continue;
                if(panel == highlightedPanel) continue;
                HUD_Panel_UpdatePosSize();
@@ -639,7 +638,7 @@ void HUD_Panel_Arrow_Action(float nPrimary)
 }
 
 void HUD_Panel_EnableMenu();
-entity tab_panels[HUD_PANEL_MAX];
+entity tab_panels[hud_panels_MAX];
 entity tab_panel;
 vector tab_panel_pos;
 float tab_backward;
@@ -647,7 +646,7 @@ void HUD_Panel_FirstInDrawQ(float id);
 void reset_tab_panels()
 {
        int i;
-       for(i = 0; i < HUD_PANEL_NUM; ++i)
+       for(i = 0; i < hud_panels_COUNT; ++i)
                tab_panels[i] = world;
 }
 float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
@@ -788,9 +787,9 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
                k=0;
                while(++k)
                {
-                       for(i = 0; i < HUD_PANEL_NUM; ++i)
+                       for(i = 0; i < hud_panels_COUNT; ++i)
                        {
-                               panel = hud_panel[i];
+                               panel = hud_panels[i];
                                if(panel == HUD_PANEL(MAPVOTE))
                                        continue;
                                if (panel == tab_panels[i] || panel == starting_panel)
@@ -934,12 +933,12 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
 float HUD_Panel_Check_Mouse_Pos(float allow_move)
 {
        int i, j = 0;
-       while(j < HUD_PANEL_NUM)
+       while(j < hud_panels_COUNT)
        {
                i = panel_order[j];
                j += 1;
 
-               panel = hud_panel[i];
+               panel = hud_panels[i];
                if(panel == HUD_PANEL(MAPVOTE)) continue;
                HUD_Panel_UpdatePosSize();
 
@@ -980,7 +979,7 @@ void HUD_Panel_FirstInDrawQ(float id)
        int i;
        int place = -1;
        // find out where in the array our current id is, save into place
-       for(i = 0; i < HUD_PANEL_NUM; ++i)
+       for(i = 0; i < hud_panels_COUNT; ++i)
        {
                if(panel_order[i] == id)
                {
@@ -990,7 +989,7 @@ void HUD_Panel_FirstInDrawQ(float id)
        }
        // place last if we didn't find a place for it yet (probably new panel, or screwed up cvar)
        if(place == -1)
-               place = HUD_PANEL_NUM - 1;
+               place = hud_panels_COUNT - 1;
 
        // move all ids up by one step in the array until "place"
        for(i = place; i > 0; --i)
@@ -1002,7 +1001,7 @@ void HUD_Panel_FirstInDrawQ(float id)
 
        // let's save them into the cvar by some strcat trickery
        string s = "";
-       for(i = 0; i < HUD_PANEL_NUM; ++i)
+       for(i = 0; i < hud_panels_COUNT; ++i)
        {
                s = strcat(s, ftos(panel_order[i]), " ");
        }
@@ -1016,12 +1015,12 @@ void HUD_Panel_Highlight(float allow_move)
 {
        int i, j = 0;
 
-       while(j < HUD_PANEL_NUM)
+       while(j < hud_panels_COUNT)
        {
                i = panel_order[j];
                j += 1;
 
-               panel = hud_panel[i];
+               panel = hud_panels[i];
                if(panel == HUD_PANEL(MAPVOTE))
                        continue;
                HUD_Panel_UpdatePosSize();
@@ -1031,7 +1030,7 @@ void HUD_Panel_Highlight(float allow_move)
                // move
                if(allow_move && mousepos.x > panel_pos.x && mousepos.y > panel_pos.y && mousepos.x < panel_pos.x + panel_size.x && mousepos.y < panel_pos.y + panel_size.y)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 1;
                        panel_click_distance = mousepos - panel_pos;
@@ -1040,7 +1039,7 @@ void HUD_Panel_Highlight(float allow_move)
                // resize from topleft border
                else if(mousepos.x >= panel_pos.x - border && mousepos.y >= panel_pos.y - border && mousepos.x <= panel_pos.x + 0.5 * panel_size.x && mousepos.y <= panel_pos.y + 0.5 * panel_size.y)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 2;
                        resizeCorner = 1;
@@ -1051,7 +1050,7 @@ void HUD_Panel_Highlight(float allow_move)
                // resize from topright border
                else if(mousepos.x >= panel_pos.x + 0.5 * panel_size.x && mousepos.y >= panel_pos.y - border && mousepos.x <= panel_pos.x + panel_size.x + border && mousepos.y <= panel_pos.y + 0.5 * panel_size.y)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 2;
                        resizeCorner = 2;
@@ -1063,7 +1062,7 @@ void HUD_Panel_Highlight(float allow_move)
                // resize from bottomleft border
                else if(mousepos.x >= panel_pos.x - border && mousepos.y >= panel_pos.y + 0.5 * panel_size.y && mousepos.x <= panel_pos.x + 0.5 * panel_size.x && mousepos.y <= panel_pos.y + panel_size.y + border)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 2;
                        resizeCorner = 3;
@@ -1075,7 +1074,7 @@ void HUD_Panel_Highlight(float allow_move)
                // resize from bottomright border
                else if(mousepos.x >= panel_pos.x + 0.5 * panel_size.x && mousepos.y >= panel_pos.y + 0.5 * panel_size.y && mousepos.x <= panel_pos.x + panel_size.x + border && mousepos.y <= panel_pos.y + panel_size.y + border)
                {
-                       highlightedPanel = hud_panel[i];
+                       highlightedPanel = hud_panels[i];
                        HUD_Panel_FirstInDrawQ(i);
                        highlightedAction = 2;
                        resizeCorner = 4;
@@ -1249,8 +1248,8 @@ void HUD_Configure_Frame()
                        if(autocvar_hud_cursormode)
                                setcursormode(1);
                        hudShiftState = 0;
-                       for(i = HUD_PANEL_NUM - 1; i >= 0; --i)
-                               hud_panel[panel_order[i]].update_time = time;
+                       for(i = hud_panels_COUNT - 1; i >= 0; --i)
+                               hud_panels[panel_order[i]].update_time = time;
                }
 
                // NOTE this check is necessary because _menu_alpha isn't updated the frame the menu gets enabled
index f5b6d54a9b32bd8df2fe39d95591981d124a28c7..93c4103a9cd993ae2fdc7c45e050bd7e887ce2c3 100644 (file)
@@ -3,7 +3,7 @@
 
 #include "hook.qh"
 
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
 
 #include "../csqcmodellib/cl_model.qh"
 #include "../csqcmodellib/interpolate.qh"
@@ -21,7 +21,7 @@ class(Laser) .float alpha;
 class(Laser) .float scale; // scaling factor of the thickness
 class(Laser) .float modelscale; // scaling factor of the dlight
 
-void Draw_Laser()
+void Draw_Laser(entity this)
 {
        if(!self.state)
                return;
index 31e0256d3062d8cdf802b027c46156356c1c6a8d..ff9fe0f7f96c7e190319df7984794693867ef55b 100644 (file)
@@ -2,7 +2,6 @@
 #include "_all.qh"
 
 #include "controlpoint.qh"
-#include "csqcmodel_hooks.qh"
 #include "damage.qh"
 #include "effects.qh"
 #include "generator.qh"
 
 #include "weapons/projectile.qh"
 
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
 #include "../common/deathtypes.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
 #include "../common/mapinfo.qh"
 #include "../common/monsters/all.qh"
-#include "../common/nades.qh"
+#include "../common/nades/all.qh"
 #include "../common/net_notice.qh"
 #include "../common/notifications.qh"
 #include "../common/stats.qh"
@@ -49,7 +48,6 @@
 #include "../common/triggers/include.qh"
 
 #include "../common/turrets/cl_turrets.qh"
-#include "../common/turrets/turrets.qh"
 
 #include "../warpzonelib/client.qh"
 
@@ -83,6 +81,8 @@ void menu_sub_null()
 {
 }
 
+void draw_null(entity this) { }
+
 string forcefog;
 void ConsoleCommand_macro_init();
 void CSQC_Init(void)
@@ -125,7 +125,7 @@ void CSQC_Init(void)
        registercvar("cl_jumpspeedcap_min", "");
        registercvar("cl_jumpspeedcap_max", "");
 
-       registercvar("cl_multijump", "1");
+       registercvar("cl_multijump", "0");
 
        registercvar("cl_spawn_near_teammate", "1");
 
@@ -148,24 +148,13 @@ void CSQC_Init(void)
 
        // needs to be done so early because of the constants they create
        static_init();
-       CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
-       CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
-
-       initialize_minigames();
 
        // precaches
-       precache_model("null");
-       precache_sound("misc/hit.wav");
-       precache_sound("misc/typehit.wav");
 
-       generator_precache();
        Projectile_Precache();
-       Hook_Precache();
-       GibSplash_Precache();
        Tuba_Precache();
-       CSQCPlayer_Precache();
 
        if(autocvar_cl_reticle)
        {
@@ -304,7 +293,7 @@ float SetTeam(entity o, int Team)
 }
 
 void Playerchecker_Think()
-{
+{SELFPARAM();
     int i;
        entity e;
        for(i = 0; i < maxclients; ++i)
@@ -398,34 +387,32 @@ float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
 // BEGIN OPTIONAL CSQC FUNCTIONS
 
 void Ent_RemoveEntCS()
-{
-       entcs_receiver[self.sv_entnum] = world;
+{SELFPARAM();
+       entcs_receiver[self.sv_entnum] = NULL;
 }
 void Ent_ReadEntCS()
-{
-    int sf;
+{SELFPARAM();
        InterpolateOrigin_Undo();
-
        self.classname = "entcs_receiver";
-       sf = ReadByte();
+       int sf = ReadByte();
 
-       if(sf & 1)
+       if(sf & BIT(0))
                self.sv_entnum = ReadByte();
-       if(sf & 2)
+       if (sf & BIT(1))
        {
                self.origin_x = ReadShort();
                self.origin_y = ReadShort();
                self.origin_z = ReadShort();
                setorigin(self, self.origin);
        }
-       if(sf & 4)
+       if (sf & BIT(2))
        {
                self.angles_y = ReadByte() * 360.0 / 256;
                self.angles_x = self.angles_z = 0;
        }
-       if(sf & 8)
+       if (sf & BIT(3))
                self.healthvalue = ReadByte() * 10;
-       if(sf & 16)
+       if (sf & BIT(4))
                self.armorvalue = ReadByte() * 10;
 
        entcs_receiver[self.sv_entnum] = self;
@@ -438,7 +425,7 @@ void Ent_ReadEntCS()
 void Ent_Remove();
 
 void Ent_RemovePlayerScore()
-{
+{SELFPARAM();
        if(self.owner) {
                SetTeam(self.owner, -1);
                self.owner.gotscores = 0;
@@ -449,7 +436,7 @@ void Ent_RemovePlayerScore()
 }
 
 void Ent_ReadPlayerScore()
-{
+{SELFPARAM();
        int i, n;
        bool isNew;
        entity o;
@@ -507,7 +494,7 @@ void Ent_ReadPlayerScore()
 }
 
 void Ent_ReadTeamScore()
-{
+{SELFPARAM();
        int i;
        entity o;
 
@@ -698,13 +685,13 @@ void Ent_ReadAccuracy(void)
        }
 }
 
-void Spawn_Draw(void)
+void Spawn_Draw(entity this)
 {
-       pointparticles(self.cnt, self.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1));
+       pointparticles(this.cnt, this.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1));
 }
 
 void Ent_ReadSpawnPoint(float is_new) // entity for spawnpoint
-{
+{SELFPARAM();
        float teamnum = (ReadByte() - 1);
        vector spn_origin;
        spn_origin.x = ReadShort();
@@ -750,7 +737,7 @@ void Ent_ReadSpawnPoint(float is_new) // entity for spawnpoint
 }
 
 void Ent_ReadSpawnEvent(float is_new)
-{
+{SELFPARAM();
        // If entnum is 0, ONLY do the local spawn actions
        // this way the server can disable the sending of
        // spawn origin or such to clients if wanted.
@@ -779,7 +766,7 @@ void Ent_ReadSpawnEvent(float is_new)
                        }
                        if(autocvar_cl_spawn_event_sound)
                        {
-                               sound(self, CH_TRIGGER, "misc/spawn.wav", VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_TRIGGER, SND_SPAWN, VOL_BASE, ATTEN_NORM);
                        }
                }
        }
@@ -806,16 +793,14 @@ void Ent_RadarLink();
 void Ent_Init();
 void Ent_ScoresInfo();
 void CSQC_Ent_Update(float bIsNewEntity)
-{
-       float t;
-       float savetime;
-       t = ReadByte();
+{SELFPARAM();
+       int t = ReadByte();
 
        if(autocvar_developer_csqcentities)
                LOG_INFOF("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
 
        // set up the "time" global for received entities to be correct for interpolation purposes
-       savetime = time;
+       float savetime = time;
        if(servertime)
        {
                time = servertime;
@@ -832,7 +817,6 @@ void CSQC_Ent_Update(float bIsNewEntity)
        {
                if(t != self.enttype || bIsNewEntity)
                {
-                       //print("A CSQC entity changed its type!\n");
                        LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
                        Ent_Remove();
                        clearentity(self);
@@ -849,6 +833,13 @@ void CSQC_Ent_Update(float bIsNewEntity)
        }
 #endif
        self.enttype = t;
+       bool done = false;
+       FOREACH(LinkedEntities, it.m_id == t, LAMBDA(
+               it.m_read(self, bIsNewEntity);
+               done = true;
+               break;
+       ));
+       if (!done)
        switch(t)
        {
                case ENT_CLIENT_MUTATOR: {
@@ -888,14 +879,13 @@ void CSQC_Ent_Update(float bIsNewEntity)
                case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
                case ENT_CLIENT_TURRET: ent_turret(); break;
                case ENT_CLIENT_GENERATOR: ent_generator(); break;
-               case ENT_CLIENT_CONTROLPOINT_ICON: ent_cpicon(); break;
+               case ENT_CLIENT_CONTROLPOINT_ICON: ent_cpicon(this); break;
                case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
                case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
                case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
                case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break;
                case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
                case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); break;
-               case ENT_CLIENT_HEALING_ORB: ent_healer(); break;
                case ENT_CLIENT_MINIGAME: ent_read_minigame(); break;
                case ENT_CLIENT_VIEWLOC: ent_viewloc(); break;
                case ENT_CLIENT_VIEWLOC_TRIGGER: ent_viewloc_trigger(); break;
@@ -924,7 +914,7 @@ void CSQC_Ent_Update(float bIsNewEntity)
 // used when an entity changes its type. For an entity that someone interacts
 // with others, make sure it can no longer do so.
 void Ent_Remove()
-{
+{SELFPARAM();
        if(self.entremove)
                self.entremove();
 
@@ -936,19 +926,19 @@ void Ent_Remove()
 
        if(self.snd_looping > 0)
        {
-               sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+               sound(self, self.snd_looping, SND_Null, VOL_BASE, autocvar_g_jetpack_attenuation);
                self.snd_looping = 0;
        }
 
        self.enttype = 0;
        self.classname = "";
-       self.draw = menu_sub_null;
+       self.draw = draw_null;
        self.entremove = menu_sub_null;
        // TODO possibly set more stuff to defaults
 }
 // CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed.  Essentially call remove(self) as well.
 void CSQC_Ent_Remove()
-{
+{SELFPARAM();
        if(autocvar_developer_csqcentities)
                LOG_INFOF("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype);
 
@@ -985,7 +975,7 @@ void CSQC_Parse_Print(string strMessage)
        if(autocvar_developer_csqcentities)
                LOG_INFOF("CSQC_Parse_Print(\"%s\")\n", strMessage);
 
-       LOG_INFO(ColorTranslateRGB(strMessage));
+       print(ColorTranslateRGB(strMessage));
 }
 
 // CSQC_Parse_CenterPrint : Provides the centerprint_hud string in the first parameter that the server provided.
@@ -1011,7 +1001,7 @@ void Fog_Force()
 
 void Gamemode_Init();
 void Ent_ScoresInfo()
-{
+{SELFPARAM();
     int i;
        self.classname = "ent_client_scores_info";
        gametype = ReadInt24_t();
@@ -1035,7 +1025,7 @@ void Ent_ScoresInfo()
 }
 
 void Ent_Init()
-{
+{SELFPARAM();
        self.classname = "ent_client_init";
 
        nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th
@@ -1275,7 +1265,7 @@ void Net_WeaponComplain()
 // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
 // You must ALWAYS first acquire the temporary ID, which is sent as a byte.
 // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
-float CSQC_Parse_TempEntity()
+bool CSQC_Parse_TempEntity()
 {
        // Acquire TE ID
        int nTEID = ReadByte();
@@ -1283,6 +1273,10 @@ float CSQC_Parse_TempEntity()
        if (autocvar_developer_csqcentities)
                LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
 
+       FOREACH(TempEntities, it.m_id == nTEID, LAMBDA(
+               it.m_read(NULL, true);
+               return true;
+       ));
        switch (nTEID)
        {
                case TE_CSQC_MUTATOR:
index c8de3afdc93522a7542ce65b66e9558921688522..d403984d38a08bcac4073496dee4e320310ac14e 100644 (file)
@@ -91,8 +91,8 @@ entity teamslots[17];    // 17 teams (including "spectator team")
 .float ready;
 .float eliminated;
 
-.void(void) draw;
-.void(void) draw2d;
+.void(entity) draw;
+.void(entity) draw2d;
 .void(void) entremove;
 float drawframetime;
 vector view_origin, view_forward, view_right, view_up;
index 3511c743f05b7478a6436c884775742962532b72..945f312ab29a29592806145c248229b94c1fcf92 100644 (file)
@@ -630,8 +630,6 @@ void GameTypeVote_ReadOption(int i)
 
 void MapVote_Init()
 {
-       precache_sound ("misc/invshot.wav");
-
        mv_active = 1;
        if(autocvar_hud_cursormode) { setcursormode(1); }
        else { mv_mousepos = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; }
index c44fbe4dca452dfe702d72e96135a04212284a78..a10062a9f758c21c795824c464b9d2097102eab9 100644 (file)
@@ -5,7 +5,7 @@
 .float scale;
 .float alpha;
 
-void ModelEffect_Draw()
+void ModelEffect_Draw(entity this)
 {
        self.angles = self.angles + frametime * self.avelocity;
        setorigin(self, self.origin + frametime * self.velocity);
@@ -25,7 +25,7 @@ void ModelEffect_Draw()
 }
 
 void Ent_ModelEffect(bool isNew)
-{
+{SELFPARAM();
        self.classname = "modeleffect_spawner";
 
        int f = ReadByte();
index 22998f09d689d14c2951969493479c3811ccbbb6..d4b98e0a5928c6a87f802bfc07aaa534a97f00cb 100644 (file)
@@ -7,7 +7,7 @@ class(ModelEffect) .float lifetime, fadetime;
 class(ModelEffect) .float teleport_time;
 class(ModelEffect) .float scale1, scale2;
 
-void ModelEffect_Draw();
+void ModelEffect_Draw(entity this);
 
 void Ent_ModelEffect(bool isNew);
 #endif
index fe2e3fd33ffb6f915b06e160b171d88927ffd116..a79e0b4712eef8ade9c5573967e5833a61629128 100644 (file)
@@ -64,13 +64,13 @@ MUTATOR_HOOKABLE(CSQC_Ent_Update, EV_CSQC_Ent_Update);
 
 /** Called when a projectile is linked with CSQC */
 #define EV_Ent_Projectile(i, o) \
-    /** entity id */ i(entity, self) \
+    /** entity id */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(Ent_Projectile, EV_Ent_Projectile);
 
 /** Called when a projectile's properties are being modified */
 #define EV_EditProjectile(i, o) \
-    /** entity id */ i(entity, self) \
+    /** entity id */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(EditProjectile, EV_EditProjectile);
 
@@ -79,25 +79,25 @@ MUTATOR_HOOKABLE(PrecacheProjectiles, EV_NO_ARGS);
 
 /** Called when updating the attached tags index */
 #define EV_TagIndex_Update(i, o) \
-    /** entity id */ i(entity, self) \
+    /** entity id */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(TagIndex_Update, EV_TagIndex_Update);
 
 /** Called when setting the attached tags */
 #define EV_TagIndex_Apply(i, o) \
-    /** entity id */ i(entity, self) \
+    /** entity id */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(TagIndex_Apply, EV_TagIndex_Apply);
 
 /** Called when setting up skeleton bones */
 #define EV_Skeleton_CheckBones(i, o) \
-    /** entity id */ i(entity, self) \
+    /** entity id */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(Skeleton_CheckBones, EV_Skeleton_CheckBones);
 
 /** Called when setting up bones from the loaded model */
 #define EV_Skeleton_CheckModel(i, o) \
-    /** entity id */ i(entity, self) \
+    /** entity id */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(Skeleton_CheckModel, EV_Skeleton_CheckModel);
 
@@ -125,7 +125,7 @@ MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
 
 /** Called checking if 3rd person mode should be forced on */
 #define EV_WantEventchase(i, o) \
-    /** entity id */ i(entity, self) \
+    /** entity id */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(WantEventchase, EV_WantEventchase);
 
index 791313f50408de88ed712a9bd60d90b2a3c3cd3e..06cd72523dafe02c7da53b33db59e35837fc2b6c 100644 (file)
@@ -14,7 +14,7 @@ class(PointParticles) .float volume;
 class(PointParticles) .float absolute; // 1 = count per second is absolute, 2 = only spawn at toggle
 class(PointParticles) .vector movedir; // trace direction
 
-void Draw_PointParticles();
+void Draw_PointParticles(entity this);
 
 void Ent_PointParticles_Remove();
 
index 00f9543717f39c5f19c5c6e09cd7667d2f99e620..584a1978015222c3e4604cec92bb2b2666706e29 100644 (file)
@@ -107,7 +107,7 @@ void free_skeleton_from_frames(entity e)
 }
 
 void skeleton_from_frames(entity e, float is_dead)
-{
+{SELFPARAM();
        float m = e.modelindex;
        if(!e.skeletonindex)
        {
diff --git a/qcsrc/client/progs.inc b/qcsrc/client/progs.inc
new file mode 100644 (file)
index 0000000..ec5c318
--- /dev/null
@@ -0,0 +1,80 @@
+#include "../common/util-pre.qh"
+#include "../dpdefs/csprogsdefs.qh"
+#include "../common/util-post.qh"
+
+#include "../lib/_all.inc"
+
+#include "announcer.qc"
+#include "bgmscript.qc"
+#include "controlpoint.qc"
+#include "csqcmodel_hooks.qc"
+#include "damage.qc"
+#include "effects.qc"
+#include "generator.qc"
+#include "gibs.qc"
+#include "hook.qc"
+#include "hud.qc"
+#include "hud_config.qc"
+#include "main.qc"
+#include "mapvoting.qc"
+#include "miscfunctions.qc"
+#include "modeleffects.qc"
+#include "movelib.qc"
+#include "particles.qc"
+#include "player_skeleton.qc"
+#include "rubble.qc"
+#include "scoreboard.qc"
+#include "shownames.qc"
+#include "teamradar.qc"
+#include "tuba.qc"
+#include "t_items.qc"
+#include "view.qc"
+#include "wall.qc"
+
+#include "command/all.qc"
+
+#include "weapons/projectile.qc" // TODO
+
+#include "../common/animdecide.qc"
+#include "../common/effects/effects.qc"
+#include "../common/effects/effectinfo.qc"
+#include "../common/mapinfo.qc"
+#include "../common/movetypes/include.qc"
+#include "../common/net_notice.qc"
+#include "../common/notifications.qc"
+#include "../common/physics.qc"
+#include "../common/playerstats.qc"
+#include "../common/util.qc"
+
+#include "../common/viewloc.qc"
+
+#include "../common/minigames/minigames.qc"
+#include "../common/minigames/cl_minigames.qc"
+
+#include "../common/buffs/all.qc"
+#include "../common/items/all.qc"
+#include "../common/monsters/all.qc"
+#include "../common/mutators/all.qc"
+#include "../common/nades/all.qc"
+#include "../common/turrets/all.qc"
+#include "../common/vehicles/all.qc"
+#include "../common/weapons/all.qc"
+
+#include "../common/turrets/cl_turrets.qc"
+
+#include "../common/triggers/include.qc"
+
+#include "../csqcmodellib/cl_model.qc"
+#include "../csqcmodellib/cl_player.qc"
+#include "../csqcmodellib/interpolate.qc"
+
+#include "../server/mutators/mutator_multijump.qc"
+
+#include "../warpzonelib/anglestransform.qc"
+#include "../warpzonelib/client.qc"
+#include "../warpzonelib/common.qc"
+#include "../warpzonelib/util_server.qc"
+
+#if BUILD_MOD
+#include "../../mod/client/progs.inc"
+#endif
index 5066696022308653a84774cbd84fc16494ef3d71..8a3c0360f784e7eb6fc0b46afba635321b890b3a 100644 (file)
@@ -1,79 +1,2 @@
 ../../csprogs.dat
-
-../common/util-pre.qh
-../dpdefs/csprogsdefs.qh
-../common/util-post.qh
-
-../lib/_all.inc
-
-announcer.qc
-bgmscript.qc
-controlpoint.qc
-csqcmodel_hooks.qc
-damage.qc
-effects.qc
-generator.qc
-gibs.qc
-hook.qc
-hud.qc
-hud_config.qc
-main.qc
-mapvoting.qc
-miscfunctions.qc
-modeleffects.qc
-movelib.qc
-particles.qc
-player_skeleton.qc
-rubble.qc
-scoreboard.qc
-shownames.qc
-teamradar.qc
-tuba.qc
-t_items.qc
-view.qc
-wall.qc
-
-command/all.qc
-
-weapons/projectile.qc // TODO
-
-../common/animdecide.qc
-../common/buffs.qc
-../common/effects.qc
-../common/mapinfo.qc
-../common/movetypes/include.qc
-../common/nades.qc
-../common/net_notice.qc
-../common/notifications.qc
-../common/physics.qc
-../common/playerstats.qc
-../common/util.qc
-
-../common/viewloc.qc
-
-../common/minigames/minigames.qc
-../common/minigames/cl_minigames.qc
-
-../common/items/all.qc
-../common/monsters/all.qc
-../common/mutators/all.qc
-../common/vehicles/all.qc
-../common/weapons/all.qc
-
-../common/turrets/cl_turrets.qc
-../common/turrets/turrets.qc
-
-../common/triggers/include.qc
-
-../csqcmodellib/cl_model.qc
-../csqcmodellib/cl_player.qc
-../csqcmodellib/interpolate.qc
-
-../server/mutators/mutator_multijump.qc
-
-../warpzonelib/anglestransform.qc
-../warpzonelib/client.qc
-../warpzonelib/common.qc
-../warpzonelib/util_server.qc
-
-../../mod/client/progs.inc
+progs.inc
index 4846532636e3191526bbe913641656796aae26e4..5f896beea56bcafca0b9d35deca04654c4ad71b3 100644 (file)
@@ -117,7 +117,7 @@ bool QuickMenu_Open(string mode, string submenu)
                        {
                                if(argv(1) == "")
                                        continue;
-                               QuickMenu_Buffer_Set(QM_TAG_TITLE, argv(0)); 
+                               QuickMenu_Buffer_Set(QM_TAG_TITLE, argv(0));
                                ++QuickMenu_Buffer_Size;
                                QuickMenu_Buffer_Set(QM_TAG_COMMAND, argv(1));
                        }
@@ -173,7 +173,7 @@ bool QuickMenu_Open(string mode, string submenu)
                setcursormode(1);
        hudShiftState = 0;
 
-       QuickMenu_TimeOut = time + autocvar_hud_panel_quickmenu_time;
+       QuickMenu_TimeOut = ((autocvar_hud_panel_quickmenu_time > 0) ? time + autocvar_hud_panel_quickmenu_time : 0);
        return true;
 }
 
@@ -357,7 +357,7 @@ bool QuickMenu_Page_Load(string target_submenu, int new_page)
                QuickMenu_Close();
                return false;
        }
-       QuickMenu_TimeOut = time + autocvar_hud_panel_quickmenu_time;
+       QuickMenu_TimeOut = ((autocvar_hud_panel_quickmenu_time > 0) ? time + autocvar_hud_panel_quickmenu_time : 0);
        return true;
 }
 
@@ -380,7 +380,7 @@ bool QuickMenu_ActionForNumber(int num)
        if (QuickMenu_Page_Command[num] != "")
        {
                localcmd(strcat("\n", QuickMenu_Page_Command[num], "\n"));
-               QuickMenu_TimeOut = time + autocvar_hud_panel_quickmenu_time;
+               QuickMenu_TimeOut = ((autocvar_hud_panel_quickmenu_time > 0) ? time + autocvar_hud_panel_quickmenu_time : 0);
                return true;
        }
        if (QuickMenu_Page_Description[num] != "")
@@ -586,6 +586,7 @@ void HUD_QuickMenu(void)
                //if(!autocvar_hud_panel_quickmenu) return;
                if(!hud_panel_quickmenu) return;
 
+               if(QuickMenu_TimeOut)
                if(time > QuickMenu_TimeOut)
                {
                        QuickMenu_Close();
@@ -799,7 +800,7 @@ void QuickMenu_Default(string target_submenu)
                QUICKMENU_ENTRY_TC(CTX(_("QMCMD^killed flag, icon")), "say_team %s; g_waypointsprite_team_here_p", "killed flagcarrier (l:%y^7)", CTX(_("QMCMD^killed flagcarrier (l:%y^7)")))
                QUICKMENU_ENTRY_TC(CTX(_("QMCMD^dropped flag, icon")), "say_team %s; g_waypointsprite_team_here_d", "dropped flag (l:%d^7)", CTX(_("QMCMD^dropped flag (l:%d^7)")))
                QUICKMENU_ENTRY_TC(CTX(_("QMCMD^drop gun, icon")), "say_team %s; g_waypointsprite_team_here; wait; dropweapon", "dropped gun %w^7 (l:%l^7)", CTX(_("QMCMD^dropped gun %w^7 (l:%l^7)")))
-               QUICKMENU_ENTRY_TC(CTX(_("QMCMD^drop flag/key, icon")), "say_team %s; g_waypointsprite_team_here; wait; +use", "dropped flag/key %w^7 (l:%l^7)", CTX(_("QMCMD^dropped flag/key %w^7 (l:%l^7)")))
+               QUICKMENU_ENTRY_TC(CTX(_("QMCMD^drop flag/key, icon")), "say_team %s; g_waypointsprite_team_here; wait; use", "dropped flag/key %w^7 (l:%l^7)", CTX(_("QMCMD^dropped flag/key %w^7 (l:%l^7)")))
        QUICKMENU_SMENU(CTX(_("QMCMD^Team chat")), "Team chat")
        }
 
index 4e32c0c45490fc9451c17504c5bafb7483368701..5af2e235070f7c5d7b63f2fc3d30353f0f206cfd 100644 (file)
@@ -3,15 +3,12 @@
 // LordHavoc: rewrote this file, it was really bad code
 
 void RubbleLimit(string cname, float limit, void() deleteproc)
-{
+{SELFPARAM();
        entity e;
        entity oldest;
-       entity oldself;
        float c;
        float oldesttime;
 
-       oldself = self;
-
        // remove rubble of the same type if it's at the limit
        // remove multiple rubble if the limit has been decreased
        while(1)
@@ -42,9 +39,7 @@ void RubbleLimit(string cname, float limit, void() deleteproc)
                        break;
 
                // delete this oldest one and search again
-               self = oldest;
-               deleteproc();
-               self = oldself;
+               WITH(entity, self, oldest, deleteproc());
        }
 }
 
index da5a7b2a771ab9cdb85a5101be323089fb21d9f7..a1d9a50dcd5aeb1943a3fc896cd0d46e440e07bc 100644 (file)
@@ -975,7 +975,7 @@ float HUD_WouldDrawScoreboard() {
 
 float average_accuracy;
 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
-{
+{SELFPARAM();
        WepSet weapons_stat = WepSet_GetFromStat();
        WepSet weapons_inmap = WepSet_GetFromStat_InMap();
        float initial_posx = pos.x;
@@ -984,7 +984,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
        int disownedcnt = 0;
        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
        {
-               self = get_weaponinfo(i);
+               setself(get_weaponinfo(i));
                if(!self.weapon)
                        continue;
 
@@ -994,13 +994,13 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
                        ++disownedcnt;
        }
 
-       int weapon_cnt = WEP_COUNT - disownedcnt;
+       int weapon_cnt = (Weapons_COUNT - 1) - disownedcnt;
 
        if(weapon_cnt <= 0)
                return pos;
 
        int rows;
-       if(autocvar_scoreboard_accuracy_doublerows && weapon_cnt >= floor(WEP_COUNT * 0.5))
+       if(autocvar_scoreboard_accuracy_doublerows && weapon_cnt >= floor((Weapons_COUNT - 1) * 0.5))
                rows = 2;
        else
                rows = 1;
@@ -1052,7 +1052,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
        int column;
        for(i = WEP_FIRST, column = 0; i <= WEP_LAST; ++i)
        {
-               self = get_weaponinfo(i);
+               setself(get_weaponinfo(i));
                if (!self.weapon)
                        continue;
                weapon_stats = weapon_accuracy[i-WEP_FIRST];
index 3981b29eb85fdca9f6f9384cb321b2308a1917c2..4e43a9662469377c2f2c383c47bddb5cf5b6b5ae 100644 (file)
@@ -1,6 +1,6 @@
 #include "_all.qh"
 
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
 #include "../common/movetypes/movetypes.qh"
 #include "../common/util.qh"
 #include "../common/weapons/all.qh"
index ab6129e782cd214de6e72b33d7731b6ef7960962..7623e9df86dd8d3ad637e0a9768321a7392c17e1 100644 (file)
@@ -132,10 +132,10 @@ void draw_teamradar_player(vector coord3d, vector pangles, vector rgb)
        R_EndPolygon();
 }
 
-void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a)
+void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb, float a)
 {
        coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(coord));
-       drawpic(coord - '4 4 0', strcat("gfx/teamradar_icon_", ftos(icon)), '8 8 0', rgb, a, 0);
+       drawpic(coord - '4 4 0', strcat("gfx/teamradar_icon_", ftos(icon.m_radaricon)), '8 8 0', rgb, a, 0);
 
        if(pingdata)
        {
@@ -202,7 +202,7 @@ void teamradar_loadcvars()
 // radar links
 
 void Ent_RadarLink()
-{
+{SELFPARAM();
        int sendflags = ReadByte();
 
        InterpolateOrigin_Undo();
index 8aefc0fad1bea52f62a739dca70ce404ed383a20..78ef5ee714e93f17c41841e8716368c1bc370179 100644 (file)
@@ -41,7 +41,7 @@ void draw_teamradar_background(float fg);
 
 void draw_teamradar_player(vector coord3d, vector pangles, vector rgb);
 
-void draw_teamradar_icon(vector coord, float icon, entity pingdata, vector rgb, float a);
+void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb, float a);
 
 void draw_teamradar_link(vector start, vector end, int colors);
 
index b95dd99e324773ab5f437e5ddcc7a5fe446aae48..91ccbba5c853e7d1d7367e1da60c0f404cefefca 100644 (file)
@@ -65,12 +65,12 @@ void tubasound(entity e, bool restart)
                if (restart) {
                        snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note);
                }
-               sound(e, CH_TUBA_SINGLE, snd1, e.tuba_volume, e.tuba_attenuate * autocvar_g_balance_tuba_attenuation);
+               _sound(e, CH_TUBA_SINGLE, snd1, e.tuba_volume, e.tuba_attenuate * autocvar_g_balance_tuba_attenuation);
        }
 }
 
 void Ent_TubaNote_Think()
-{
+{SELFPARAM();
        float f = autocvar_g_balance_tuba_fadetime;
        if (f > 0) {
                self.tuba_volume -= frametime * self.tuba_volume_initial / f;
@@ -79,9 +79,9 @@ void Ent_TubaNote_Think()
        }
        self.nextthink = time;
        if (self.tuba_volume <= 0) {
-               sound(self, CH_TUBA_SINGLE, "misc/null.wav", 0, 0);
+               sound(self, CH_TUBA_SINGLE, SND_Null, 0, 0);
                if (self.enemy) {
-                       sound(self.enemy, CH_TUBA_SINGLE, "misc/null.wav", 0, 0);
+                       sound(self.enemy, CH_TUBA_SINGLE, SND_Null, 0, 0);
                        remove(self.enemy);
                }
                remove(self);
@@ -91,7 +91,7 @@ void Ent_TubaNote_Think()
 }
 
 void Ent_TubaNote_UpdateSound()
-{
+{SELFPARAM();
        self.enemy.tuba_volume = bound(0, VOL_BASE * autocvar_g_balance_tuba_volume, 1);
        self.enemy.tuba_volume_initial = self.enemy.tuba_volume;
        self.enemy.note = self.note;
@@ -100,13 +100,13 @@ void Ent_TubaNote_UpdateSound()
 }
 
 void Ent_TubaNote_StopSound()
-{
+{SELFPARAM();
        self.enemy.nextthink = time;
        self.enemy = world;
 }
 
 void Ent_TubaNote(bool isNew)
-{
+{SELFPARAM();
        bool upd = false;
        int f = ReadByte();
        if (f & 1) {
index 701eb9f1e7419bb5328bcdd6e0651bd94b86e1c0..3bb5585f35931ce09cd01f96c4be1741f725fd82 100644 (file)
@@ -12,7 +12,7 @@
 
 #include "../common/constants.qh"
 #include "../common/mapinfo.qh"
-#include "../common/nades.qh"
+#include "../common/nades/all.qh"
 #include "../common/stats.qh"
 #include "../common/triggers/target/music.qh"
 #include "../common/teams.qh"
@@ -27,7 +27,7 @@
 
 entity porto;
 vector polyline[16];
-void Porto_Draw()
+void Porto_Draw(entity this)
 {
        vector p, dir, ang, q, nextdir;
        float portal_number, portal1_idx;
@@ -321,6 +321,7 @@ float TrueAimCheck()
        {
                case WEP_TUBA.m_id: // no aim
                case WEP_PORTO.m_id: // shoots from eye
+               case WEP_NEXBALL.m_id: // shoots from eye
                case WEP_HOOK.m_id: // no trueaim
                case WEP_MORTAR.m_id: // toss curve
                        return SHOTTYPE_HITWORLD;
@@ -427,7 +428,7 @@ vector liquidcolor_prev;
 float eventchase_current_distance;
 float eventchase_running;
 bool WantEventchase()
-{
+{SELFPARAM();
        if(autocvar_cl_orthoview)
                return false;
        if(intermission)
@@ -440,7 +441,7 @@ bool WantEventchase()
                        return true;
                if(MUTATOR_CALLHOOK(WantEventchase, self))
                        return true;
-               if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_PORTO.m_id)))
+               if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_NEXBALL.m_id)))
                        return true;
                if(autocvar_cl_eventchase_death && (getstati(STAT_HEALTH) <= 0))
                {
@@ -517,7 +518,7 @@ void UpdateHitsound()
                        // todo: avoid very long and very short sounds from wave stretching using different sound files? seems unnecessary
                        // todo: normalize sound pressure levels? seems unnecessary
 
-                       sound7(world, CH_INFO, "misc/hit.wav", VOL_BASE, ATTN_NONE, pitch_shift * 100, 0);
+                       sound7(world, CH_INFO, SND(HIT), VOL_BASE, ATTN_NONE, pitch_shift * 100, 0);
                }
                unaccounted_damage = 0;
                hitsound_time_prev = time;
@@ -527,13 +528,13 @@ void UpdateHitsound()
        float typehit_time = getstatf(STAT_TYPEHIT_TIME);
        if (COMPARE_INCREASING(typehit_time, typehit_time_prev) > autocvar_cl_hitsound_antispam_time)
        {
-               sound(world, CH_INFO, "misc/typehit.wav", VOL_BASE, ATTN_NONE);
+               sound(world, CH_INFO, SND_TYPEHIT, VOL_BASE, ATTN_NONE);
                typehit_time_prev = typehit_time;
        }
 }
 
 void UpdateCrosshair()
-{
+{SELFPARAM();
        static float rainbow_last_flicker;
     static vector rainbow_prev_color;
        entity e = self;
@@ -560,7 +561,7 @@ void UpdateCrosshair()
                        CSQC_common_hud();
 
        // crosshair goes VERY LAST
-       if(!scoreboard_active && !camera_active && intermission != 2 && 
+       if(!scoreboard_active && !camera_active && intermission != 2 &&
                spectatee_status != -1 && hud == HUD_NORMAL && !csqcplayer.viewloc &&
                !HUD_MinigameMenu_IsOpened() )
        {
@@ -1022,11 +1023,10 @@ int lasthud;
 float vh_notice_time;
 void WaypointSprite_Load();
 void CSQC_UpdateView(float w, float h)
-{
+{SELFPARAM();
        entity e;
        float fov;
        float f;
-       int i;
        vector vf_size, vf_min;
        float a;
 
@@ -1077,8 +1077,7 @@ void CSQC_UpdateView(float w, float h)
        if(myteam != prev_myteam)
        {
                myteamcolors = colormapPaletteColor(myteam, 1);
-               for(i = 0; i < HUD_PANEL_NUM; ++i)
-                       hud_panel[i].update_time = time;
+               FOREACH(hud_panels, true, LAMBDA(it.update_time = time));
                prev_myteam = myteam;
        }
 
@@ -1466,11 +1465,9 @@ void CSQC_UpdateView(float w, float h)
           mousepos = mousepos*0.5 + getmousepos();
         */
 
-       e = self;
-       for(self = world; (self = nextent(self)); )
-               if(self.draw)
-                       self.draw();
-       self = e;
+       for(entity e = NULL; (e = nextent(e)); ) if (e.draw) {
+               WITH(entity, self, e, e.draw(e));
+       }
 
        addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS);
        renderscene();
@@ -1533,6 +1530,7 @@ void CSQC_UpdateView(float w, float h)
 
        if(autocvar_cl_reticle)
        {
+               Weapon wep = get_weaponinfo(activeweapon);
                // Draw the aiming reticle for weapons that use it
                // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
                // It must be a persisted float for fading out to work properly (you let go of the zoom button for
@@ -1542,7 +1540,7 @@ void CSQC_UpdateView(float w, float h)
                        // no zoom reticle while dead
                        reticle_type = 0;
                }
-               else if(WEP_ACTION(activeweapon, WR_ZOOMRETICLE) && autocvar_cl_reticle_weapon)
+               else if(wep.wr_zoomreticle(wep) && autocvar_cl_reticle_weapon)
                {
                        if(reticle_image != "") { reticle_type = 2; }
                        else { reticle_type = 0; }
@@ -1805,11 +1803,9 @@ void CSQC_UpdateView(float w, float h)
          } else */
 
        // draw 2D entities
-       e = self;
-       for(self = world; (self = nextent(self)); )
-               if(self.draw2d)
-                       self.draw2d();
-       self = e;
+       for (entity e = NULL; (e = nextent(e)); ) if (e.draw2d) {
+               WITH(entity, self, e, e.draw2d(e));
+       }
        Draw_ShowNames_All();
 
        scoreboard_active = HUD_WouldDrawScoreboard();
@@ -1863,8 +1859,10 @@ void CSQC_UpdateView(float w, float h)
     if(hud && !intermission)
     if(hud == HUD_BUMBLEBEE_GUN)
        CSQC_BUMBLE_GUN_HUD();
-    else
-               VEH_ACTION(hud, VR_HUD);
+    else {
+       Vehicle info = get_vehicleinfo(hud);
+               info.vr_hud(info);
+       }
 
        cl_notice_run();
 
index 92c142435636a8113f973e486f3ec8ec406a084b..f17b54a5caa7bf0f877593c1cd1a811d148fcb46 100644 (file)
@@ -12,7 +12,7 @@
 .vector movedir;
 
 void Ent_Wall_PreDraw()
-{
+{SELFPARAM();
        if (self.inactive)
        {
                self.alpha = 0;
@@ -51,7 +51,7 @@ void Ent_Wall_PreDraw()
                self.drawmask = MASK_NORMAL;
 }
 
-void Ent_Wall_Draw()
+void Ent_Wall_Draw(entity this)
 {
        float f;
        var .vector fld;
@@ -110,14 +110,14 @@ void Ent_Wall_Draw()
 }
 
 void Ent_Wall_Remove()
-{
+{SELFPARAM();
        if(self.bgmscript)
                strunzone(self.bgmscript);
        self.bgmscript = string_null;
 }
 
 void Ent_Wall()
-{
+{SELFPARAM();
        int f;
        var .vector fld;
 
index 04c0dce24f84326303bf3e57638da5e8329f2f67..f44355fc284092de6498b94cbccc2eef03e5deb9 100644 (file)
@@ -16,7 +16,7 @@ class(Wall) .vector saved;
 .float fade_start, fade_end, fade_vertical_offset;
 .float default_solid;
 
-void Ent_Wall_Draw();
+void Ent_Wall_Draw(entity this);
 
 void Ent_Wall_Remove();
 
index 668228b649828dae983f200969d209a477b633d0..22443043d2ae4b699e0360a466c8c7518dd8c6a8 100644 (file)
@@ -5,7 +5,7 @@
 #include "../main.qh"
 
 #include "../../common/constants.qh"
-#include "../../common/nades.qh"
+#include "../../common/nades/all.qh"
 #include "../../common/movetypes/movetypes.qh"
 #include "../../common/util.qh"
 
 .vector colormod;
 
 void SUB_Stop()
-{
+{SELFPARAM();
        self.move_velocity = self.move_avelocity = '0 0 0';
        self.move_movetype = MOVETYPE_NONE;
 }
 
-void Projectile_ResetTrail(vector to)
+void Projectile_ResetTrail(entity this, vector to)
 {
-       self.trail_oldorigin = to;
-       self.trail_oldtime = time;
+       this.trail_oldorigin = to;
+       this.trail_oldtime = time;
 }
 
-void Projectile_DrawTrail(vector to)
+void Projectile_DrawTrail(entity this, vector to)
 {
-       vector from;
-       float t0;
-
-       from = self.trail_oldorigin;
-       t0 = self.trail_oldtime;
-       self.trail_oldorigin = to;
-       self.trail_oldtime = time;
+       vector from = this.trail_oldorigin;
+       // float t0 = this.trail_oldtime;
+       this.trail_oldorigin = to;
+       this.trail_oldtime = time;
 
        // force the effect even for stationary firemine
-       if(self.cnt == PROJECTILE_FIREMINE)
+       if(this.cnt == PROJECTILE_FIREMINE)
                if(from == to)
                        from.z += 1;
 
-       if (self.traileffect)
+       if (this.traileffect)
        {
-               particles_alphamin = particles_alphamax = particles_fade = sqrt(self.alpha);
-               boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE | PARTICLES_DRAWASTRAIL);
+               particles_alphamin = particles_alphamax = particles_fade = sqrt(this.alpha);
+               boxparticles(particleeffectnum(Effects[this.traileffect]), this, from, to, this.velocity, this.velocity, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE | PARTICLES_DRAWASTRAIL);
        }
 }
 
-void Projectile_Draw()
+void Projectile_Draw(entity this)
 {
        vector rot;
        vector trailorigin;
@@ -114,7 +111,7 @@ void Projectile_Draw()
                                break;
                }
 
-               if(Nade_FromProjectile(self.cnt) != NADE_TYPE_NULL)
+               if(Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
                        rot = self.avelocity;
 
                self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime)));
@@ -142,13 +139,13 @@ void Projectile_Draw()
                        break;
        }
 
-       if(Nade_FromProjectile(self.cnt) != NADE_TYPE_NULL)
+       if(Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
                trailorigin += v_up * 4;
 
        if(drawn)
-               Projectile_DrawTrail(trailorigin);
+               Projectile_DrawTrail(self, trailorigin);
        else
-               Projectile_ResetTrail(trailorigin);
+               Projectile_ResetTrail(self, trailorigin);
 
        self.drawmask = 0;
 
@@ -166,25 +163,25 @@ void Projectile_Draw()
 }
 
 void loopsound(entity e, int ch, string samp, float vol, float attn)
-{
+{SELFPARAM();
        if(self.silent)
                return;
 
-       sound(e, ch, samp, vol, attn);
+       _sound(e, ch, samp, vol, attn);
        e.snd_looping = ch;
 }
 
 void Ent_RemoveProjectile()
-{
+{SELFPARAM();
        if(self.count & 0x80)
        {
                tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self);
-               Projectile_DrawTrail(trace_endpos);
+               Projectile_DrawTrail(self, trace_endpos);
        }
 }
 
 void Ent_Projectile()
-{
+{SELFPARAM();
        int f;
 
        // projectile properties:
@@ -270,9 +267,6 @@ void Ent_Projectile()
 
        if(f & 2)
        {
-               string rm_suffix = strcat("rocketminsta_laser_", Static_Team_ColorName_Lower(self.team));
-               if(_particleeffectnum(rm_suffix) < 0 || Team_TeamToNumber(self.team) == -1) { rm_suffix = "TR_NEXUIZPLASMA"; }
-
                self.cnt = ReadByte();
 
                self.silent = (self.cnt & 0x80);
@@ -280,56 +274,57 @@ void Ent_Projectile()
 
                self.scale = 1;
                self.traileffect = 0;
-               switch(self.cnt)
-               {
-                       case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
-                       case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum(EFFECT_TR_ROCKET); self.scale = 2; break;
-                       case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum(EFFECT_TR_CRYLINKPLASMA); break;
-                       case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum(EFFECT_TR_CRYLINKPLASMA); break;
-                       case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
-                       case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_GRENADE); break;
-                       case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_GRENADE); break;
-                       case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum(EFFECT_TR_GRENADE); break;
-                       case PROJECTILE_BLASTER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(EFFECT_NULL); break;
-                       case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(EFFECT_NULL); break;
-                       case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_WIZSPIKE); self.scale = 4; break;
-                       case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_WIZSPIKE); self.scale = 4; break;
-                       case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum(EFFECT_TR_KNIGHTSPIKE); break;
-                       case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum(EFFECT_HAGAR_ROCKET); self.scale = 0.75; break;
-                       case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum(EFFECT_HAGAR_ROCKET); self.scale = 0.75; break;
-                       case PROJECTILE_NAPALM_FOUNTAIN: //self.model = ""; self.modelindex = 0; self.traileffect = _particleeffectnum("torch_small"); break;
-                       case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum(EFFECT_FIREBALL); break; // particle effect is good enough
-                       case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum(EFFECT_FIREMINE); break; // particle effect is good enough
-                       case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum(EFFECT_TR_ROCKET); break;
-                       case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum(EFFECT_FLAC_TRAIL); break;
-                       case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum(EFFECT_SEEKER_TRAIL); break;
-
-                       case PROJECTILE_MAGE_SPIKE: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum(EFFECT_TR_VORESPIKE); break;
-                       case PROJECTILE_SHAMBLER_LIGHTNING: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
-
-                       case PROJECTILE_RAPTORBOMB:    setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(EFFECT_NULL); break;
-                       case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3");     self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(EFFECT_NULL); break;
-                       case PROJECTILE_RAPTORCANNON:  setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum(EFFECT_TR_CRYLINKPLASMA); break;
-
-                       case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum(EFFECT_SPIDERBOT_ROCKET_TRAIL); break;
-                       case PROJECTILE_WAKIROCKET:   setmodel(self, "models/vehicles/rocket01.md3");  self.traileffect = particleeffectnum(EFFECT_RACER_ROCKET_TRAIL); break;
-                       case PROJECTILE_WAKICANNON:   setmodel(self, "models/laser.mdl");  self.traileffect = particleeffectnum(EFFECT_NULL); break;
-
-                       case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
-                       case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum(EFFECT_TR_NEXUIZPLASMA); break;
-
-                       case PROJECTILE_RPC: setmodel(self, W_Model("ok_rocket"));self.traileffect = particleeffectnum(EFFECT_TR_ROCKET); break;
-
-                       case PROJECTILE_ROCKETMINSTA_LASER: setmodel(self, "models/elaser.mdl");self.traileffect = _particleeffectnum(rm_suffix); break;
-
+               switch (self.cnt) {
+#define CASE(id) case PROJECTILE_##id: setmodel(self, MDL_PROJECTILE_##id);
+                       CASE(ELECTRO)            self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+                       CASE(ROCKET)             self.traileffect = EFFECT_TR_ROCKET.m_id; self.scale = 2; break;
+                       CASE(CRYLINK)            self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+                       CASE(CRYLINK_BOUNCING)   self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+                       CASE(ELECTRO_BEAM)       self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+                       CASE(GRENADE)            self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+                       CASE(GRENADE_BOUNCING)   self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+                       CASE(MINE)               self.traileffect = EFFECT_TR_GRENADE.m_id; break;
+                       CASE(BLASTER)            self.traileffect = EFFECT_Null.m_id; break;
+                       CASE(HLAC)               self.traileffect = EFFECT_Null.m_id; break;
+                       CASE(PORTO_RED)          self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+                       CASE(PORTO_BLUE)         self.traileffect = EFFECT_TR_WIZSPIKE.m_id; self.scale = 4; break;
+                       CASE(HOOKBOMB)           self.traileffect = EFFECT_TR_KNIGHTSPIKE.m_id; break;
+                       CASE(HAGAR)              self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+                       CASE(HAGAR_BOUNCING)     self.traileffect = EFFECT_HAGAR_ROCKET.m_id; self.scale = 0.75; break;
+                       CASE(NAPALM_FOUNTAIN)    // fallthrough // sself.modelindex = 0; self.traileffect = _particleeffectnum("torch_small"); break;
+                       CASE(FIREBALL)           self.modelindex = 0; self.traileffect = EFFECT_FIREBALL.m_id; break; // particle effect is good enough
+                       CASE(FIREMINE)           self.modelindex = 0; self.traileffect = EFFECT_FIREMINE.m_id; break; // particle effect is good enough
+                       CASE(TAG)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+                       CASE(FLAC)               self.scale = 0.4; self.traileffect = EFFECT_FLAC_TRAIL.m_id; break;
+                       CASE(SEEKER)             self.traileffect = EFFECT_SEEKER_TRAIL.m_id; break;
+
+                       CASE(MAGE_SPIKE)         self.traileffect = EFFECT_TR_VORESPIKE.m_id; break;
+                       CASE(SHAMBLER_LIGHTNING) self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+                       CASE(RAPTORBOMB)         self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+                       CASE(RAPTORBOMBLET)      self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = EFFECT_Null.m_id; break;
+                       CASE(RAPTORCANNON)       self.traileffect = EFFECT_TR_CRYLINKPLASMA.m_id; break;
+
+                       CASE(SPIDERROCKET)       self.traileffect = EFFECT_SPIDERBOT_ROCKET_TRAIL.m_id; break;
+                       CASE(WAKIROCKET)         self.traileffect = EFFECT_RACER_ROCKET_TRAIL.m_id; break;
+                       CASE(WAKICANNON)         self.traileffect = EFFECT_Null.m_id; break;
+
+                       CASE(BUMBLE_GUN)         self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+                       CASE(BUMBLE_BEAM)        self.traileffect = EFFECT_TR_NEXUIZPLASMA.m_id; break;
+
+                       CASE(RPC)                self.traileffect = EFFECT_TR_ROCKET.m_id; break;
+
+                       CASE(ROCKETMINSTA_LASER) self.traileffect = EFFECT_ROCKETMINSTA_LASER(self.team).m_id; break;
+#undef CASE
                        default:
                                if(MUTATOR_CALLHOOK(Ent_Projectile, self))
                                        break;
 
-                               if (Nade_FromProjectile(self.cnt) != NADE_TYPE_NULL)
+                               if (Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
                                {
-                                       setmodel(self, W_Model("v_ok_grenade.md3"));
-                                       self.traileffect = _particleeffectnum(Nade_TrailEffect(self.cnt, self.team));
+                                       setmodel(self, MDL_PROJECTILE_NADE);
+                                       entity trail = Nade_TrailEffect(self.cnt, self.team);
+                                       if (trail.eent_eff_name) self.traileffect = trail.m_id;
                                        break;
                                }
                                error("Received invalid CSQC projectile, can't work with this!");
@@ -347,7 +342,7 @@ void Ent_Projectile()
                {
                        case PROJECTILE_ELECTRO:
                                // only new engines support sound moving with object
-                               loopsound(self, CH_SHOTS_SINGLE, W_Sound("electro_fly"), VOL_BASE, ATTEN_NORM);
+                               loopsound(self, CH_SHOTS_SINGLE, SND(ELECTRO_FLY), VOL_BASE, ATTEN_NORM);
                                self.mins = '0 0 -4';
                                self.maxs = '0 0 -4';
                                self.move_movetype = MOVETYPE_BOUNCE;
@@ -357,7 +352,7 @@ void Ent_Projectile()
                                break;
                        case PROJECTILE_RPC:
                        case PROJECTILE_ROCKET:
-                               loopsound(self, CH_SHOTS_SINGLE, W_Sound("rocket_fly"), VOL_BASE, ATTEN_NORM);
+                               loopsound(self, CH_SHOTS_SINGLE, SND(ROCKET_FLY), VOL_BASE, ATTEN_NORM);
                                self.mins = '-3 -3 -3';
                                self.maxs = '3 3 3';
                                break;
@@ -405,12 +400,12 @@ void Ent_Projectile()
                                break;
                        case PROJECTILE_NAPALM_FOUNTAIN:
                        case PROJECTILE_FIREBALL:
-                               loopsound(self, CH_SHOTS_SINGLE, W_Sound("fireball_fly2"), VOL_BASE, ATTEN_NORM);
+                               loopsound(self, CH_SHOTS_SINGLE, SND(FIREBALL_FLY2), VOL_BASE, ATTEN_NORM);
                                self.mins = '-16 -16 -16';
                                self.maxs = '16 16 16';
                                break;
                        case PROJECTILE_FIREMINE:
-                               loopsound(self, CH_SHOTS_SINGLE, W_Sound("fireball_fly"), VOL_BASE, ATTEN_NORM);
+                               loopsound(self, CH_SHOTS_SINGLE, SND(FIREBALL_FLY), VOL_BASE, ATTEN_NORM);
                                self.move_movetype = MOVETYPE_BOUNCE;
                                self.move_touch = func_null;
                                self.mins = '-4 -4 -4';
@@ -425,7 +420,7 @@ void Ent_Projectile()
                                self.maxs = '2 2 2';
                                break;
                        case PROJECTILE_SEEKER:
-                               loopsound(self, CH_SHOTS_SINGLE, W_Sound("tag_rocket_fly"), VOL_BASE, ATTEN_NORM);
+                               loopsound(self, CH_SHOTS_SINGLE, SND(TAG_ROCKET_FLY), VOL_BASE, ATTEN_NORM);
                                self.mins = '-4 -4 -4';
                                self.maxs = '4 4 4';
                                break;
@@ -438,17 +433,17 @@ void Ent_Projectile()
             case PROJECTILE_RAPTORCANNON:
                                break;
             case PROJECTILE_SPIDERROCKET:
-                loopsound(self, CH_SHOTS_SINGLE, W_Sound("tag_rocket_fly"), VOL_BASE, ATTEN_NORM);
+                loopsound(self, CH_SHOTS_SINGLE, SND(TAG_ROCKET_FLY), VOL_BASE, ATTEN_NORM);
                                break;
             case PROJECTILE_WAKIROCKET:
-                loopsound(self, CH_SHOTS_SINGLE, W_Sound("tag_rocket_fly"), VOL_BASE, ATTEN_NORM);
+                loopsound(self, CH_SHOTS_SINGLE, SND(TAG_ROCKET_FLY), VOL_BASE, ATTEN_NORM);
                                break;
             /*
             case PROJECTILE_WAKICANNON:
                                break;
                        case PROJECTILE_BUMBLE_GUN:
                                // only new engines support sound moving with object
-                               loopsound(self, CH_SHOTS_SINGLE, W_Sound("electro_fly"), VOL_BASE, ATTEN_NORM);
+                               loopsound(self, CH_SHOTS_SINGLE, SND(ELECTRO_FLY), VOL_BASE, ATTEN_NORM);
                                self.mins = '0 0 -4';
                                self.maxs = '0 0 -4';
                                self.move_movetype = MOVETYPE_BOUNCE;
@@ -461,7 +456,7 @@ void Ent_Projectile()
                                break;
                }
 
-               if(Nade_FromProjectile(self.cnt) != NADE_TYPE_NULL)
+               if(Nade_FromProjectile(self.cnt) != NADE_TYPE_Null)
                {
                        entity nade_type = Nade_FromProjectile(self.cnt);
                        self.mins = '-16 -16 -16';
@@ -508,27 +503,5 @@ void Ent_Projectile()
 
 void Projectile_Precache()
 {
-       precache_model("models/ebomb.mdl");
-       precache_model("models/elaser.mdl");
-       precache_model("models/grenademodel.md3");
-       precache_model("models/mine.md3");
-       precache_model("models/hagarmissile.mdl");
-       precache_model("models/hlac_bullet.md3");
-       precache_model("models/laser.mdl");
-       precache_model("models/plasmatrail.mdl");
-       precache_model("models/rocket.md3");
-       precache_model("models/tagrocket.md3");
-       precache_model("models/tracer.mdl");
-       precache_model("models/sphere/sphere.md3");
-
-       precache_model(W_Model("v_ok_grenade.md3"));
-       precache_model(W_Model("ok_rocket.md3"));
-
-       precache_sound(W_Sound("electro_fly"));
-       precache_sound(W_Sound("rocket_fly"));
-       precache_sound(W_Sound("fireball_fly"));
-       precache_sound(W_Sound("fireball_fly2"));
-       precache_sound(W_Sound("tag_rocket_fly"));
-
        MUTATOR_CALLHOOK(PrecacheProjectiles);
 }
index 67e08c224bfd6f2a5f35dd8f3354c36e7d79be07..dd289817ec15b034e01d1a3b89ec13cc51227dac 100644 (file)
@@ -19,11 +19,11 @@ class(Projectile) .bool silent;
 
 void SUB_Stop();
 
-void Projectile_ResetTrail(vector to);
+void Projectile_ResetTrail(entity this, vector to);
 
-void Projectile_DrawTrail(vector to);
+void Projectile_DrawTrail(entity this, vector to);
 
-void Projectile_Draw();
+void Projectile_Draw(entity this);
 
 void loopsound(entity e, int ch, string samp, float vol, float attn);
 
diff --git a/qcsrc/collect-precache.sh b/qcsrc/collect-precache.sh
deleted file mode 100755 (executable)
index 302220c..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-{
-       grep -h '\<precache_model *( *"' client/* | grep -v "//NO_SV_PRECACHE"
-       grep -h '\<precache_sound *( *"' client/* | grep -v "//NO_SV_PRECACHE"
-} > server/precache-for-csqc.inc
-
index 5c2caa6a7f04c7d8c6a3a9b60040b95e035602ee..0db1a6afdfea74ce714a72b538901783bb3e06bb 100644 (file)
@@ -12,7 +12,7 @@
 
 bool monsters_animoverride(entity e)
 {
-       int monster_id = 0;
+       Monster monster_id = NULL;
        for(int i = MON_FIRST; i <= MON_LAST; ++i)
        {
                entity mon = get_monsterinfo(i);
@@ -20,14 +20,14 @@ bool monsters_animoverride(entity e)
                //if(substring(e.model, 0, strlen(mon.model) - 4) == substring(mon.model, 0, strlen(mon.model) - 4))
                if(e.model == mon.model)
                {
-                       monster_id = i;
+                       monster_id = mon;
                        break;
                }
        }
 
        if(!monster_id) { return false; }
 
-       MON_ACTION(monster_id, MR_ANIM);
+       monster_id.mr_anim(monster_id);
 
        vector none = '0 0 0';
        e.anim_duckwalk = e.anim_walk;
diff --git a/qcsrc/common/buffs.qc b/qcsrc/common/buffs.qc
deleted file mode 100644 (file)
index 612255d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "../client/defs.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "../dpdefs/dpextensions.qh"
-#endif
-#include "buffs.qh"
-
diff --git a/qcsrc/common/buffs.qh b/qcsrc/common/buffs.qh
deleted file mode 100644 (file)
index f1ef589..0000000
+++ /dev/null
@@ -1,192 +0,0 @@
-#ifndef BUFFS_H
-#define BUFFS_H
-// Welcome to the stuff behind the scenes
-// Below, you will find the list of buffs
-// Add new buffs here!
-// Note: Buffs also need spawnfuncs, which are set below
-
-#include "teams.qh"
-#include "util.qh"
-
-void RegisterBuffs();
-const int BUFFS_MAX = 16;
-entity BUFFS[BUFFS_MAX], BUFFS_first, BUFFS_last;
-int BUFFS_COUNT;
-#define REGISTER_BUFF(id) \
-    REGISTER(RegisterBuffs, BUFF, BUFFS, BUFFS_COUNT, id, m_id, NEW(Buff)); \
-    REGISTER_INIT_POST(BUFF, id) { \
-        this.netname = this.m_name; \
-        this.m_itemid = BIT(this.m_id - 1); \
-        this.m_sprite = strzone(strcat("buff-", this.m_name)); \
-    } \
-    REGISTER_INIT(BUFF, id)
-REGISTER_REGISTRY(RegisterBuffs)
-
-#include "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, "")
-       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));
-       }
-#ifdef SVQC
-       METHOD(Buff, m_time, float(entity));
-       float Buff_m_time(entity this) { return cvar(strcat("g_buffs_", this.netname, "_time")); }
-#endif
-ENDCLASS(Buff)
-
-REGISTER_BUFF(NULL);
-
-REGISTER_BUFF(AMMO) {
-       this.m_prettyName = _("Ammo");
-       this.m_name = "ammo";
-       this.m_skin = 3;
-       this.m_color = '0.76 1 0.1';
-}
-
-REGISTER_BUFF(RESISTANCE) {
-       this.m_prettyName = _("Resistance");
-       this.m_name = "resistance";
-       this.m_skin = 0;
-       this.m_color = '0.36 1 0.07';
-}
-
-REGISTER_BUFF(SPEED) {
-       this.m_prettyName = _("Speed");
-       this.m_name = "speed";
-       this.m_skin = 9;
-       this.m_color = '0.1 1 0.84';
-}
-
-REGISTER_BUFF(MEDIC) {
-       this.m_prettyName = _("Medic");
-       this.m_name = "medic";
-       this.m_skin = 1;
-       this.m_color = '1 0.12 0';
-}
-
-REGISTER_BUFF(BASH) {
-       this.m_prettyName = _("Bash");
-       this.m_name = "bash";
-       this.m_skin = 5;
-       this.m_color = '1 0.39 0';
-}
-
-REGISTER_BUFF(VAMPIRE) {
-       this.m_prettyName = _("Vampire");
-       this.m_name = "vampire";
-       this.m_skin = 2;
-       this.m_color = '1 0 0.24';
-}
-
-REGISTER_BUFF(DISABILITY) {
-       this.m_prettyName = _("Disability");
-       this.m_name = "disability";
-       this.m_skin = 7;
-       this.m_color = '0.94 0.3 1';
-}
-
-REGISTER_BUFF(VENGEANCE) {
-       this.m_prettyName = _("Vengeance");
-       this.m_name = "vengeance";
-       this.m_skin = 15;
-       this.m_color = '1 0.23 0.61';
-}
-
-REGISTER_BUFF(JUMP) {
-       this.m_prettyName = _("Jump");
-       this.m_name = "jump";
-       this.m_skin = 10;
-       this.m_color = '0.24 0.78 1';
-}
-
-REGISTER_BUFF(FLIGHT) {
-       this.m_prettyName = _("Flight");
-       this.m_name = "flight";
-       this.m_skin = 11;
-       this.m_color = '0.33 0.56 1';
-}
-
-REGISTER_BUFF(INVISIBLE) {
-       this.m_prettyName = _("Invisible");
-       this.m_name = "invisible";
-       this.m_skin = 12;
-       this.m_color = '0.5 0.5 1';
-}
-
-REGISTER_BUFF(INFERNO) {
-       this.m_prettyName = _("Inferno");
-       this.m_name = "inferno";
-       this.m_skin = 16;
-       this.m_color = '1 0.62 0';
-}
-
-REGISTER_BUFF(SWAPPER) {
-       this.m_prettyName = _("Swapper");
-       this.m_name = "swapper";
-       this.m_skin = 17;
-       this.m_color = '0.63 0.36 1';
-}
-
-REGISTER_BUFF(MAGNET) {
-       this.m_prettyName = _("Magnet");
-       this.m_name = "magnet";
-       this.m_skin = 18;
-       this.m_color = '1 0.95 0.18';
-}
-
-#ifdef SVQC
-.int buffs;
-void buff_Init(entity ent);
-void buff_Init_Compat(entity ent, entity replacement);
-
-#define BUFF_SPAWNFUNC(e, b, t) void spawnfunc_item_buff_##e() { \
-       self.buffs = b.m_itemid; \
-       self.team = t; \
-       buff_Init(self); \
-}
-#define BUFF_SPAWNFUNCS(e, b)                       \
-               BUFF_SPAWNFUNC(e,           b,  0)          \
-               BUFF_SPAWNFUNC(e##_team1,   b,  NUM_TEAM_1) \
-               BUFF_SPAWNFUNC(e##_team2,   b,  NUM_TEAM_2) \
-               BUFF_SPAWNFUNC(e##_team3,   b,  NUM_TEAM_3) \
-               BUFF_SPAWNFUNC(e##_team4,   b,  NUM_TEAM_4)
-#define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r) void spawnfunc_item_##o() { buff_Init_Compat(self, r); }
-
-BUFF_SPAWNFUNCS(resistance,            BUFF_RESISTANCE)
-BUFF_SPAWNFUNCS(ammo,                  BUFF_AMMO)
-BUFF_SPAWNFUNCS(speed,                 BUFF_SPEED)
-BUFF_SPAWNFUNCS(medic,                 BUFF_MEDIC)
-BUFF_SPAWNFUNCS(bash,                  BUFF_BASH)
-BUFF_SPAWNFUNCS(vampire,               BUFF_VAMPIRE)
-BUFF_SPAWNFUNCS(disability,            BUFF_DISABILITY)
-BUFF_SPAWNFUNCS(vengeance,             BUFF_VENGEANCE)
-BUFF_SPAWNFUNCS(jump,                  BUFF_JUMP)
-BUFF_SPAWNFUNCS(flight,                        BUFF_FLIGHT)
-BUFF_SPAWNFUNCS(invisible,             BUFF_INVISIBLE)
-BUFF_SPAWNFUNCS(inferno,               BUFF_INFERNO)
-BUFF_SPAWNFUNCS(swapper,               BUFF_SWAPPER)
-BUFF_SPAWNFUNCS(magnet,                        BUFF_MAGNET)
-BUFF_SPAWNFUNCS(random,                        BUFF_NULL)
-
-BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler,    BUFF_MEDIC)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(resistance, BUFF_RESISTANCE)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(scout,      BUFF_SPEED)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(ammoregen,  BUFF_AMMO)
-
-// actually Q3
-BUFF_SPAWNFUNC_Q3TA_COMPAT(haste,      BUFF_SPEED)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(invis,      BUFF_INVISIBLE)
-BUFF_SPAWNFUNC_Q3TA_COMPAT(medic,      BUFF_MEDIC)
-
-#undef BUFF_SPAWNFUNC
-#undef BUFF_SPAWNFUNC_Q3TA_COMPAT
-#undef BUFF_SPAWNFUNCS
-#endif
-
-#endif
diff --git a/qcsrc/common/buffs/all.inc b/qcsrc/common/buffs/all.inc
new file mode 100644 (file)
index 0000000..25fa722
--- /dev/null
@@ -0,0 +1,118 @@
+REGISTER_BUFF(AMMO) {
+    this.m_prettyName = _("Ammo");
+    this.m_name = "ammo";
+    this.m_skin = 3;
+    this.m_color = '0.76 1 0.1';
+}
+BUFF_SPAWNFUNCS(ammo, BUFF_AMMO)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(ammoregen, BUFF_AMMO)
+
+REGISTER_BUFF(RESISTANCE) {
+    this.m_prettyName = _("Resistance");
+    this.m_name = "resistance";
+    this.m_skin = 0;
+    this.m_color = '0.36 1 0.07';
+}
+BUFF_SPAWNFUNCS(resistance, BUFF_RESISTANCE)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(resistance, BUFF_RESISTANCE)
+
+REGISTER_BUFF(SPEED) {
+    this.m_prettyName = _("Speed");
+    this.m_name = "speed";
+    this.m_skin = 9;
+    this.m_color = '0.1 1 0.84';
+}
+BUFF_SPAWNFUNCS(speed, BUFF_SPEED)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(haste, BUFF_SPEED)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(scout, BUFF_SPEED)
+
+REGISTER_BUFF(MEDIC) {
+    this.m_prettyName = _("Medic");
+    this.m_name = "medic";
+    this.m_skin = 1;
+    this.m_color = '1 0.12 0';
+}
+BUFF_SPAWNFUNCS(medic, BUFF_MEDIC)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler, BUFF_MEDIC)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(medic, BUFF_MEDIC)
+
+REGISTER_BUFF(BASH) {
+    this.m_prettyName = _("Bash");
+    this.m_name = "bash";
+    this.m_skin = 5;
+    this.m_color = '1 0.39 0';
+}
+BUFF_SPAWNFUNCS(bash, BUFF_BASH)
+
+REGISTER_BUFF(VAMPIRE) {
+    this.m_prettyName = _("Vampire");
+    this.m_name = "vampire";
+    this.m_skin = 2;
+    this.m_color = '1 0 0.24';
+}
+BUFF_SPAWNFUNCS(vampire, BUFF_VAMPIRE)
+
+REGISTER_BUFF(DISABILITY) {
+    this.m_prettyName = _("Disability");
+    this.m_name = "disability";
+    this.m_skin = 7;
+    this.m_color = '0.94 0.3 1';
+}
+BUFF_SPAWNFUNCS(disability, BUFF_DISABILITY)
+
+REGISTER_BUFF(VENGEANCE) {
+    this.m_prettyName = _("Vengeance");
+    this.m_name = "vengeance";
+    this.m_skin = 15;
+    this.m_color = '1 0.23 0.61';
+}
+BUFF_SPAWNFUNCS(vengeance, BUFF_VENGEANCE)
+
+REGISTER_BUFF(JUMP) {
+    this.m_prettyName = _("Jump");
+    this.m_name = "jump";
+    this.m_skin = 10;
+    this.m_color = '0.24 0.78 1';
+}
+BUFF_SPAWNFUNCS(jump, BUFF_JUMP)
+
+REGISTER_BUFF(FLIGHT) {
+    this.m_prettyName = _("Flight");
+    this.m_name = "flight";
+    this.m_skin = 11;
+    this.m_color = '0.33 0.56 1';
+}
+BUFF_SPAWNFUNCS(flight, BUFF_FLIGHT)
+
+REGISTER_BUFF(INVISIBLE) {
+    this.m_prettyName = _("Invisible");
+    this.m_name = "invisible";
+    this.m_skin = 12;
+    this.m_color = '0.5 0.5 1';
+}
+BUFF_SPAWNFUNCS(invisible, BUFF_INVISIBLE)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(invis, BUFF_INVISIBLE)
+
+REGISTER_BUFF(INFERNO) {
+    this.m_prettyName = _("Inferno");
+    this.m_name = "inferno";
+    this.m_skin = 16;
+    this.m_color = '1 0.62 0';
+}
+BUFF_SPAWNFUNCS(inferno, BUFF_INFERNO)
+
+REGISTER_BUFF(SWAPPER) {
+    this.m_prettyName = _("Swapper");
+    this.m_name = "swapper";
+    this.m_skin = 17;
+    this.m_color = '0.63 0.36 1';
+}
+BUFF_SPAWNFUNCS(swapper, BUFF_SWAPPER)
+
+REGISTER_BUFF(MAGNET) {
+    this.m_prettyName = _("Magnet");
+    this.m_name = "magnet";
+    this.m_skin = 18;
+    this.m_color = '1 0.95 0.18';
+}
+BUFF_SPAWNFUNCS(magnet, BUFF_MAGNET)
diff --git a/qcsrc/common/buffs/all.qc b/qcsrc/common/buffs/all.qc
new file mode 100644 (file)
index 0000000..190c627
--- /dev/null
@@ -0,0 +1,10 @@
+#if defined(CSQC)
+       #include "../../dpdefs/csprogsdefs.qh"
+       #include "../../client/defs.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+       #include "../../dpdefs/progsdefs.qh"
+    #include "../../dpdefs/dpextensions.qh"
+#endif
+#include "all.qh"
+
diff --git a/qcsrc/common/buffs/all.qh b/qcsrc/common/buffs/all.qh
new file mode 100644 (file)
index 0000000..7099034
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef BUFFS_ALL_H
+#define BUFFS_ALL_H
+// Welcome to the stuff behind the scenes
+// Below, you will find the list of buffs
+// Add new buffs here!
+// Note: Buffs also need spawnfuncs, which are set below
+
+#include "../teams.qh"
+#include "../util.qh"
+
+REGISTRY(Buffs, BIT(4))
+REGISTER_REGISTRY(RegisterBuffs)
+
+#define REGISTER_BUFF(id) \
+    REGISTER(RegisterBuffs, BUFF, Buffs, id, m_id, NEW(Buff)); \
+    REGISTER_INIT_POST(BUFF, id) { \
+        this.netname = this.m_name; \
+        this.m_itemid = BIT(this.m_id - 1); \
+        this.m_sprite = strzone(strcat("buff-", this.m_name)); \
+    } \
+    REGISTER_INIT(BUFF, id)
+
+#include "../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, "")
+       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));
+       }
+#ifdef SVQC
+       METHOD(Buff, m_time, float(entity));
+       float Buff_m_time(entity this) { return cvar(strcat("g_buffs_", this.netname, "_time")); }
+#endif
+ENDCLASS(Buff)
+
+#ifdef SVQC
+       .int buffs;
+       void buff_Init(entity ent);
+       void buff_Init_Compat(entity ent, entity replacement);
+       #define BUFF_SPAWNFUNC(e, b, t) spawnfunc(item_buff_##e) { \
+               self.buffs = b.m_itemid; \
+               self.team = t; \
+               buff_Init(self); \
+       }
+       #define BUFF_SPAWNFUNCS(e, b)                       \
+                       BUFF_SPAWNFUNC(e,           b,  0)          \
+                       BUFF_SPAWNFUNC(e##_team1,   b,  NUM_TEAM_1) \
+                       BUFF_SPAWNFUNC(e##_team2,   b,  NUM_TEAM_2) \
+                       BUFF_SPAWNFUNC(e##_team3,   b,  NUM_TEAM_3) \
+                       BUFF_SPAWNFUNC(e##_team4,   b,  NUM_TEAM_4)
+       #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r) spawnfunc(item_##o) { buff_Init_Compat(self, r); }
+#else
+       #define BUFF_SPAWNFUNC(e, b, t)
+       #define BUFF_SPAWNFUNCS(e, b)
+       #define BUFF_SPAWNFUNC_Q3TA_COMPAT(o, r)
+#endif
+
+REGISTER_BUFF(Null);
+BUFF_SPAWNFUNCS(random, BUFF_Null)
+
+#include "all.inc"
+
+#endif
index 0c8f85816f124f2668255db78a3872a8bb81b033..20826f64e21f74853743cd7e757da8a3f4031552 100644 (file)
@@ -240,6 +240,49 @@ void GenericCommand_dumpcommands(float request)
        }
 }
 
+#ifndef MENUQC
+void effectinfo_dump(int fh, bool alsoprint);
+#endif
+void GenericCommand_dumpeffectinfo(float request)
+{
+    switch (request) {
+        case CMD_REQUEST_COMMAND: {
+            #ifndef MENUQC
+            string filename = argv(1);
+                       bool alsoprint = false;
+            if (filename == "") {
+                filename = "effectinfo_dump.txt";
+                alsoprint = false;
+            } else if (filename == "-") {
+                filename = "effectinfo_dump.txt";
+                alsoprint = true;
+            }
+            int fh = fopen(filename, FILE_WRITE);
+            if (fh >= 0) {
+               effectinfo_dump(fh, alsoprint);
+                LOG_INFOF("Dumping effectinfo... File located at ^2data/data/%s^7.\n", filename);
+                               LOG_INFOF("Reload with ^2cl_particles_reloadeffects data/%s^7.\n", filename);
+                fclose(fh);
+            } else {
+                LOG_WARNINGF("Could not open file '%s'!\n", filename);
+            }
+            #else
+            LOG_INFO(_("Effectinfo dump command only works with cl_cmd and sv_cmd.\n"));
+            #endif
+            return;
+        }
+        default:
+        case CMD_REQUEST_USAGE: {
+            LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpeffectinfo [filename]"));
+            LOG_INFO("  Where 'filename' is the file to write (default is effectinfo_dump.txt),\n");
+            LOG_INFO("  if supplied with '-' output to console as well as default,\n");
+            LOG_INFO("  if left blank, it will only write to default.\n");
+            return;
+        }
+    }
+}
+STATIC_INIT(dumpeffectinfo) { localcmd("alias dumpeffectinfo \"qc_cmd_svcl dumpeffectinfo ${* ?}\"\n"); }
+
 void GenericCommand_dumpitems(float request)
 {
        switch(request)
@@ -722,6 +765,7 @@ void GenericCommand_(float request)
 #define GENERIC_COMMANDS(request,arguments,command) \
        GENERIC_COMMAND("addtolist", GenericCommand_addtolist(request, arguments), "Add a string to a cvar") \
        GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \
+       GENERIC_COMMAND("dumpeffectinfo", GenericCommand_dumpeffectinfo(request), "Dump all effectinfo to effectinfo_dump.txt") \
        GENERIC_COMMAND("dumpitems", GenericCommand_dumpitems(request), "Dump all items to the console") \
        GENERIC_COMMAND("dumpnotifs", GenericCommand_dumpnotifs(request), "Dump all notifications into notifications_dump.txt") \
        GENERIC_COMMAND("dumpturrets", GenericCommand_dumpturrets(request), "Dump all turrets into turrets_dump.txt") \
index fe04e910cff4782d6e482abb74866eedc083330f..a4329ad44553606563046f207ec3666ab1471d81 100644 (file)
@@ -127,7 +127,6 @@ const int ENT_CLIENT_EFFECT = 74;
 const int ENT_CLIENT_MINIGAME = 75;
 const int ENT_CLIENT_VIEWLOC = 78;
 const int ENT_CLIENT_VIEWLOC_TRIGGER = 79;
-const int ENT_CLIENT_HEALING_ORB = 80;
 
 const int ENT_CLIENT_MUTATOR = TE_CSQC_MUTATOR; // 99
 
@@ -135,20 +134,6 @@ const int SPRITERULE_DEFAULT = 0;
 const int SPRITERULE_TEAMPLAY = 1;
 const int SPRITERULE_SPECTATOR = 2;
 
-const int RADARICON_NONE = 0;
-const int RADARICON_FLAG = 1;
-const int RADARICON_FLAGCARRIER = 1;
-const int RADARICON_HERE = 1; // TODO make these 3 and 4, and make images for them
-const int RADARICON_DANGER = 1;
-const int RADARICON_WAYPOINT = 1;
-const int RADARICON_HELPME = 1;
-const int RADARICON_CONTROLPOINT = 1;
-const int RADARICON_GENERATOR = 1;
-const int RADARICON_OBJECTIVE = 1;
-const int RADARICON_DOMPOINT = 1;
-const int RADARICON_POWERUP = 1;
-const int RADARICON_TAGGED = 1;
-
 ///////////////////////////
 // keys pressed
 const int KEY_FORWARD = 1;
index e11604aae3da6b8e2847cb05891bc8c5e40b815d..256142759d622b44fd4baa21ddb0d5537120fb49 100644 (file)
@@ -59,6 +59,7 @@
                CSQCMODEL_PROPERTY(512, float, ReadApproxPastTime, WriteApproxPastTime, anim_upper_time) \
        CSQCMODEL_ENDIF \
        CSQCMODEL_PROPERTY(1024, float, ReadAngle, WriteAngle, v_angle_x) \
+       CSQCMODEL_PROPERTY(2048, int, ReadByte, WriteByte, traileffect) \
        CSQCMODEL_PROPERTY_SCALED(4096, float, ReadByte, WriteByte, scale, 16, 0, 255) \
        CSQCMODEL_PROPERTY(8192, int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
        CSQCMODEL_PROPERTY(16384, TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME)
@@ -86,8 +87,8 @@
 //vector PL_CROUCH_VIEW_OFS  = ...;
 
 #ifdef SVQC
-# define CSQCMODEL_AUTOINIT() CSQCModel_LinkEntity()
-# define CSQCMODEL_AUTOUPDATE() CSQCModel_CheckUpdate()
+# define CSQCMODEL_AUTOINIT(e) CSQCModel_LinkEntity(e)
+# define CSQCMODEL_AUTOUPDATE(e) CSQCModel_CheckUpdate(e)
 #endif
 
 #define CSQCMODEL_EF_RESPAWNGHOST EF_SELECTABLE
index b9c215f907b5fe28e53c121337829cc9bd2fc450..c1e8bd2218f0c7787f4e327106649ad0632c868a 100644 (file)
@@ -104,7 +104,7 @@ entity deathtypes[DT_MAX];
                if (msg_death_by != NO_MSG) \
                        deathent.death_msgmurder = msg_multi_notifs[msg_death_by - 1]; \
        } \
-       ACCUMULATE_FUNCTION(RegisterDeathtypes, RegisterDeathtype_##name);
+       ACCUMULATE_FUNCTION(RegisterDeathtypes, RegisterDeathtype_##name)
 
 DEATHTYPES
 #undef DEATHTYPE
diff --git a/qcsrc/common/effects.inc b/qcsrc/common/effects.inc
deleted file mode 100644 (file)
index 8cd4d49..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-// Global list of effects, networked to CSQC by ID to save bandwidth and to use client particle numbers (allows mismatching effectinfos to some degree)
-// Not too concerned about the order of this list, just keep the weapon effects together!
-
-// EFFECT(istrail, EFFECT_NAME,     "effectinfo_string")
-EFFECT(0, EXPLOSION_SMALL,          "explosion_small")
-EFFECT(0, EXPLOSION_MEDIUM,         "explosion_medium")
-EFFECT(0, EXPLOSION_BIG,            "explosion_big")
-
-EFFECT(0, SMOKE_SMALL,              "smoke_small")
-EFFECT(0, SMOKE_LARGE,              "smoke_large")
-
-
-
-EFFECT(0, BLASTER_IMPACT,           "laser_impact")
-EFFECT(0, BLASTER_MUZZLEFLASH,      "laser_muzzleflash")
-
-EFFECT(0, SHOTGUN_IMPACT,           "shotgun_impact")
-EFFECT(0, SHOTGUN_MUZZLEFLASH,      "shotgun_muzzleflash")
-
-EFFECT(0, ARC_BEAM,                 "arc_beam")
-EFFECT(0, ARC_BEAM_HEAL,            "arc_beam_heal")
-EFFECT(0, ARC_BEAM_HEAL_IMPACT,     "arc_beam_healimpact")
-EFFECT(0, ARC_BEAM_HEAL_IMPACT2,    "healray_impact")
-EFFECT(0, ARC_LIGHTNING,            "arc_lightning")
-EFFECT(0, ARC_LIGHTNING2,           "electro_lightning")
-
-EFFECT(0, MACHINEGUN_IMPACT,        "machinegun_impact")
-EFFECT(0, MACHINEGUN_MUZZLEFLASH,   "uzi_muzzleflash")
-
-EFFECT(0, GRENADE_EXPLODE,          "grenade_explode")
-EFFECT(0, GRENADE_MUZZLEFLASH,      "grenadelauncher_muzzleflash")
-
-EFFECT(0, ELECTRO_BALLEXPLODE,      "electro_ballexplode")
-EFFECT(0, ELECTRO_COMBO,            "electro_combo")
-EFFECT(0, ELECTRO_IMPACT,           "electro_impact")
-EFFECT(0, ELECTRO_MUZZLEFLASH,      "electro_muzzleflash")
-
-EFFECT(0, CRYLINK_IMPACT,           "crylink_impactbig")
-EFFECT(0, CRYLINK_IMPACT2,          "crylink_impact")
-EFFECT(0, CRYLINK_JOINEXPLODE,      "crylink_joinexplode")
-EFFECT(0, CRYLINK_MUZZLEFLASH,      "crylink_muzzleflash")
-
-EFFECT(0, VORTEX_BEAM,              "nex_beam")
-EFFECT(0, VORTEX_BEAM_OLD,          "TE_TEI_G3")
-EFFECT(0, VORTEX_IMPACT,            "nex_impact")
-EFFECT(0, VORTEX_MUZZLEFLASH,       "nex_muzzleflash")
-
-EFFECT(1, VAPORIZER_RED,            "TE_TEI_G3RED")
-EFFECT(1, VAPORIZER_RED_HIT,        "TE_TEI_G3RED_HIT")
-EFFECT(1, VAPORIZER_BLUE,           "TE_TEI_G3BLUE")
-EFFECT(1, VAPORIZER_BLUE_HIT,       "TE_TEI_G3BLUE_HIT")
-EFFECT(1, VAPORIZER_YELLOW,         "TE_TEI_G3YELLOW")
-EFFECT(1, VAPORIZER_YELLOW_HIT,     "TE_TEI_G3YELLOW_HIT")
-EFFECT(1, VAPORIZER_PINK,           "TE_TEI_G3PINK")
-EFFECT(1, VAPORIZER_PINK_HIT,       "TE_TEI_G3PINK_HIT")
-EFFECT(1, VAPORIZER_NEUTRAL,        "TE_TEI_G3")
-EFFECT(1, VAPORIZER_NEUTRAL_HIT,    "TE_TEI_G3_HIT")
-
-EFFECT(0, RIFLE_IMPACT,             "machinegun_impact")
-EFFECT(0, RIFLE_MUZZLEFLASH,        "rifle_muzzleflash")
-EFFECT(1, RIFLE,                    "tr_rifle")
-EFFECT(1, RIFLE_WEAK,               "tr_rifle_weak")
-
-EFFECT(0, HAGAR_BOUNCE,             "hagar_bounce")
-EFFECT(0, HAGAR_EXPLODE,            "hagar_explode")
-EFFECT(0, HAGAR_MUZZLEFLASH,        "hagar_muzzleflash")
-EFFECT(1, HAGAR_ROCKET,             "tr_hagar")
-
-EFFECT(0, ROCKET_EXPLODE,           "rocket_explode")
-EFFECT(0, ROCKET_GUIDE,             "rocket_guide")
-EFFECT(0, ROCKET_MUZZLEFLASH,       "rocketlauncher_muzzleflash")
-
-EFFECT(0, HOOK_EXPLODE,             "hookbomb_explode")
-EFFECT(0, HOOK_IMPACT,              "grapple_impact")
-EFFECT(0, HOOK_MUZZLEFLASH,         "grapple_muzzleflash")
-
-EFFECT(0, SEEKER_MUZZLEFLASH,       "seeker_muzzleflash")
-
-EFFECT(0, FLAK_BOUNCE,              "flak_bounce")
-
-EFFECT(1, FIREBALL,                 "fireball")
-EFFECT(0, FIREBALL_BFGDAMAGE,       "fireball_bfgdamage")
-EFFECT(0, FIREBALL_EXPLODE,         "fireball_explode")
-EFFECT(0, FIREBALL_LASER,           "fireball_laser")
-EFFECT(0, FIREBALL_MUZZLEFLASH,     "fireball_muzzleflash")
-EFFECT(0, FIREBALL_PRE_MUZZLEFLASH, "fireball_preattack_muzzleflash")
-
-
-
-EFFECT(0, RAPTOR_CANNON_IMPACT,     "raptor_cannon_impact")
-EFFECT(0, RAPTOR_BOMB_IMPACT,       "raptor_bomb_impact")
-EFFECT(0, RAPTOR_BOMB_SPREAD,       "raptor_bomb_spread")
-EFFECT(0, RAPTOR_MUZZLEFLASH,       "raptor_cannon_muzzleflash")
-
-EFFECT(0, RACER_BOOSTER,            "wakizashi_booster_smoke")
-EFFECT(0, RACER_IMPACT,             "wakizashi_gun_impact")
-EFFECT(0, RACER_MUZZLEFLASH,        "wakizashi_gun_muzzleflash")
-EFFECT(0, RACER_ROCKETLAUNCH,       "wakizashi_rocket_launch")
-EFFECT(0, RACER_ROCKET_EXPLODE,     "wakizashi_rocket_launch")
-EFFECT(1, RACER_ROCKET_TRAIL,       "wakizashi_rocket_thrust")
-
-EFFECT(0, SPIDERBOT_ROCKETLAUNCH,   "spiderbot_rocket_launch")
-EFFECT(1, SPIDERBOT_ROCKET_TRAIL,   "spiderbot_rocket_thrust")
-EFFECT(0, SPIDERBOT_ROCKET_EXPLODE, "spiderbot_rocket_explode")
-EFFECT(0, SPIDERBOT_MINIGUN_IMPACT, "spiderbot_minigun_impact")
-EFFECT(0, SPIDERBOT_MINIGUN_MUZZLEFLASH,    "spiderbot_minigun_muzzleflash")
-
-EFFECT(0, BUMBLEBEE_HEAL_MUZZLEFLASH,   "healray_muzzleflash")
-EFFECT(0, BUMBLEBEE_HEAL_IMPACT,   "healray_impact")
-
-EFFECT(0, BIGPLASMA_IMPACT,         "bigplasma_impact")
-EFFECT(0, BIGPLASMA_MUZZLEFLASH,    "bigplasma_muzzleflash")
-
-EFFECT(0, TELEPORT,                 "teleport")
-
-EFFECT(0, SPAWNPOINT_RED,           "spawn_point_red")
-EFFECT(0, SPAWN_RED,                "spawn_event_red")
-EFFECT(0, SPAWNPOINT_BLUE,          "spawn_point_blue")
-EFFECT(0, SPAWN_BLUE,               "spawn_event_blue")
-EFFECT(0, SPAWNPOINT_YELLOW,        "spawn_point_yellow")
-EFFECT(0, SPAWN_YELLOW,             "spawn_event_yellow")
-EFFECT(0, SPAWNPOINT_PINK,          "spawn_point_pink")
-EFFECT(0, SPAWN_PINK,               "spawn_event_pink")
-EFFECT(0, SPAWNPOINT_NEUTRAL,       "spawn_point_neutral")
-EFFECT(0, SPAWN_NEUTRAL,            "spawn_event_neutral")
-
-EFFECT(0, NADE_RED_EXPLODE,         "nade_red_explode")
-EFFECT(0, NADE_BLUE_EXPLODE,        "nade_blue_explode")
-EFFECT(0, NADE_YELLOW_EXPLODE,      "nade_yellow_explode")
-EFFECT(0, NADE_PINK_EXPLODE,        "nade_pink_explode")
-EFFECT(0, NADE_NEUTRAL_EXPLODE,     "nade_neutral_explode")
-
-EFFECT(0, ICEORGLASS,               "iceorglass")
-EFFECT(0, ICEFIELD,                 "icefield")
-EFFECT(0, FIREFIELD,                "firefield")
-EFFECT(0, HEALING,                  "healing_fx")
-EFFECT(1, LASER_BEAM_FAST,          "nex242_misc_laser_beam_fast")
-EFFECT(0, RESPAWN_GHOST,            "respawn_ghost")
-
-EFFECT(0, FLAG_RED_TOUCH,           "redflag_touch")
-EFFECT(0, FLAG_BLUE_TOUCH,          "blueflag_touch")
-EFFECT(0, FLAG_YELLOW_TOUCH,        "yellowflag_touch")
-EFFECT(0, FLAG_PINK_TOUCH,          "pinkflag_touch")
-EFFECT(0, FLAG_NEUTRAL_TOUCH,       "neutralflag_touch")
-EFFECT(1, RED_PASS,                 "red_pass")
-EFFECT(1, BLUE_PASS,                "blue_pass")
-EFFECT(1, YELLOW_PASS,              "yellow_pass")
-EFFECT(1, PINK_PASS,                "pink_pass")
-EFFECT(1, NEUTRAL_PASS,             "neutral_pass")
-EFFECT(0, RED_CAP,                  "red_cap")
-EFFECT(0, BLUE_CAP,                 "blue_cap")
-EFFECT(0, YELLOW_CAP,               "yellow_cap")
-EFFECT(0, PINK_CAP,                 "pink_cap")
-
-EFFECT(0, ITEM_PICKUP,              "item_pickup")
-EFFECT(0, ITEM_RESPAWN,             "item_respawn")
-
-EFFECT(0, ONS_GENERATOR_DAMAGED,    "torch_small")
-EFFECT(0, ONS_GENERATOR_GIB,        "onslaught_generator_gib_explode")
-EFFECT(0, ONS_GENERATOR_EXPLODE,    "onslaught_generator_smallexplosion")
-EFFECT(0, ONS_GENERATOR_EXPLODE2,   "onslaught_generator_finalexplosion")
-
-
-
-EFFECT(0, LASER_DEADLY,             "laser_deadly")
-EFFECT(1, FLAC_TRAIL,               "TR_SEEKER")
-EFFECT(1, SEEKER_TRAIL,             "TR_SEEKER")
-EFFECT(1, FIREMINE,                 "firemine")
-EFFECT(0, BALL_SPARKS,              "kaball_sparks")
-EFFECT(0, ELECTRIC_SPARKS,          "electricity_sparks")
-EFFECT(0, SPARKS,                   "sparks")
-EFFECT(0, RAGE,                     "rage")
-EFFECT(0, SMOKING,                  "smoking")
-EFFECT(0, SMOKE_RING,               "smoke_ring")
-EFFECT(0, JUMPPAD,                  "jumppad_activate")
-EFFECT(1, BULLET,                   "tr_bullet")
-EFFECT(0, EF_FLAME,                 "EF_FLAME")
-EFFECT(0, EF_STARDUST,              "EF_STARDUST")
-EFFECT(0, TE_EXPLOSION,             "TE_EXPLOSION")
-EFFECT(1, TR_NEXUIZPLASMA,          "TR_NEXUIZPLASMA")
-EFFECT(1, TR_CRYLINKPLASMA,         "TR_CRYLINKPLASMA")
-EFFECT(1, TR_ROCKET,                "TR_ROCKET")
-EFFECT(1, TR_GRENADE,               "TR_GRENADE")
-EFFECT(1, TR_BLOOD,                 "TR_BLOOD")
-EFFECT(1, TR_WIZSPIKE,              "TR_WIZSPIKE")
-EFFECT(1, TR_SLIGHTBLOOD,           "TR_SLIGHTBLOOD")
-EFFECT(1, TR_KNIGHTSPIKE,           "TR_KNIGHTSPIKE")
-EFFECT(1, TR_VORESPIKE,             "TR_VORESPIKE")
-EFFECT(0, TE_SPARK,                 "TE_SPARK")
diff --git a/qcsrc/common/effects.qc b/qcsrc/common/effects.qc
deleted file mode 100644 (file)
index e170702..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifdef CSQC
-void Read_Effect(bool is_new)
-{
-#if EFFECTS_COUNT >= 255
-       int net_name = ReadShort();
-#else
-       int net_name = ReadByte();
-#endif
-
-       entity eff = effects_ent[net_name];
-
-       vector v, vel = '0 0 0';
-       int eff_cnt = 1;
-       bool eff_trail = eff.eent_eff_trail;
-       v_x = ReadCoord();
-       v_y = ReadCoord();
-       v_z = ReadCoord();
-
-       bool use_vel = ReadByte();
-       if(use_vel)
-       {
-               vel_x = ReadCoord();
-               vel_y = ReadCoord();
-               vel_z = ReadCoord();
-       }
-
-       if(!eff_trail)
-               eff_cnt = ReadByte();
-
-       if(is_new)
-       {
-               if(eff_trail)
-                       WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel);
-               else
-                       pointparticles(particleeffectnum(eff), v, vel, eff_cnt);
-       }
-}
-#endif
-
-#ifdef SVQC
-bool Net_Write_Effect(entity client, int sf)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_EFFECT);
-#if EFFECTS_COUNT >= 255
-       WriteShort(MSG_ENTITY, self.m_id);
-#else
-       WriteByte(MSG_ENTITY, self.m_id);
-#endif
-       WriteCoord(MSG_ENTITY, self.eent_net_location_x);
-       WriteCoord(MSG_ENTITY, self.eent_net_location_y);
-       WriteCoord(MSG_ENTITY, self.eent_net_location_z);
-
-       // attempt to save a tiny bit more bandwidth by not sending velocity if it isn't set
-       if(self.eent_net_velocity)
-       {
-               WriteByte(MSG_ENTITY, true);
-               WriteCoord(MSG_ENTITY, self.eent_net_velocity_x);
-               WriteCoord(MSG_ENTITY, self.eent_net_velocity_y);
-               WriteCoord(MSG_ENTITY, self.eent_net_velocity_z);
-       }
-       else { WriteByte(MSG_ENTITY, false); }
-
-       if(!self.eent_eff_trail) { WriteByte(MSG_ENTITY, self.eent_net_count); }
-       return true;
-}
-
-void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
-{
-       if(!eff) { return; }
-       if(!eff.eent_eff_trail && !eff_cnt) { return; } // effect has no count!
-       entity net_eff = spawn();
-       net_eff.owner = eff;
-       net_eff.classname = "net_effect";
-       //net_eff.eent_broadcast = broadcast;
-       net_eff.m_id = eff.m_id;
-       net_eff.eent_net_velocity = eff_vel;
-       net_eff.eent_net_location = eff_loc;
-       net_eff.eent_net_count = eff_cnt;
-       net_eff.eent_eff_trail = eff.eent_eff_trail;
-
-       net_eff.think = SUB_Remove;
-       net_eff.nextthink = time + 0.2; // don't need to keep this long
-
-       Net_LinkEntity(net_eff, false, 0, Net_Write_Effect);
-}
-
-void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
-{
-       // problem with this is, we might not have all the available effects for it
-       FOREACH(effects_ent, it.eent_eff_name == eff_name, LAMBDA(
-               Send_Effect(it, eff_loc, eff_vel, eff_cnt);
-               return;
-       ));
-       // revert to engine handling
-       pointparticles(_particleeffectnum(eff_name), eff_loc, eff_vel, eff_cnt);
-}
-#endif
diff --git a/qcsrc/common/effects.qh b/qcsrc/common/effects.qh
deleted file mode 100644 (file)
index b72eab2..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef P_EFFECTS_H
-#define P_EFFECTS_H
-
-#ifdef CSQC
-void Read_Effect(bool is_new);
-#elif defined(SVQC)
-void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt);
-void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt);
-#endif
-
-#define particleeffectnum(e) _particleeffectnum(e.eent_eff_name)
-
-void RegisterEffects();
-const int MAX_EFFECTS = 512;
-entity effects_ent[MAX_EFFECTS], effects_ent_first, effects_ent_last;
-int EFFECT_COUNT;
-
-#define EFFECT(istrail, name, realname) \
-    REGISTER(RegisterEffects, EFFECT, effects_ent, EFFECT_COUNT, name, m_id, Create_Effect_Entity(realname, istrail));
-REGISTER_REGISTRY(RegisterEffects)
-
-.int m_id;
-.string eent_eff_name;
-.int eent_eff_trail;
-
-.vector eent_net_location;
-.vector eent_net_velocity;
-.int eent_net_count;
-
-entity Create_Effect_Entity(string eff_name, bool eff_trail)
-{
-       entity this = new(effect_entity);
-       this.eent_eff_name = eff_name;
-       this.eent_eff_trail = eff_trail;
-       return this;
-}
-
-void RegisterEffects_First()
-{
-    #ifdef SVQC
-    #define dedi (server_is_dedicated ? "a dedicated " : "")
-    #else
-    #define dedi ""
-    #endif
-
-    LOG_TRACEF("Beginning effect initialization on %s%s program...\n", dedi, PROGNAME);
-    #undef dedi
-}
-
-void RegisterEffects_Done()
-{
-    LOG_TRACE("Effects initialization successful!\n");
-}
-
-// NOW we actually activate the declarations
-ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_First);
-EFFECT(0, NULL, string_null)
-#include "effects.inc"
-ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_Done);
-
-#endif
diff --git a/qcsrc/common/effects/effectinfo.inc b/qcsrc/common/effects/effectinfo.inc
new file mode 100644 (file)
index 0000000..7a0fc66
--- /dev/null
@@ -0,0 +1,8733 @@
+// item respawn effect
+DEF(TE_WIZSPIKE);
+// flare particle and light
+SUB(TE_WIZSPIKE) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x63F2EA";
+       MY(color_max) = "0x63f2EA";
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '0.4 0.9 0.9';
+       MY(lightradiusfade) = 200;
+       MY(lightradius) = 200;
+       MY(size_min) = 20;
+       MY(size_max) = 20;
+       MY(type) = "static";
+}
+// cloud of particles which expand rapidly and then slow to form a ball
+SUB(TE_WIZSPIKE) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x63F2EA";
+       MY(color_max) = "0x63f2EA";
+       MY(count) = 50;
+       MY(liquidfriction) = 2;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+}
+
+// laser impact
+DEF(TE_KNIGHTSPIKE);
+// decal
+SUB(TE_KNIGHTSPIKE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '4.0 0.2 0.2';
+       MY(lightradiusfade) = 1000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(TE_KNIGHTSPIKE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xFF2010";
+       MY(color_max) = "0xFF2010";
+       MY(countabsolute) = 1;
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 39;
+       MY(tex_max) = 39;
+       MY(type) = "static";
+}
+// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect
+SUB(TE_KNIGHTSPIKE) {
+       MY(airfriction) = 6;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x800000";
+       MY(color_max) = "0xFF8020";
+       MY(count) = 128;
+       MY(liquidfriction) = 6;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(type) = "spark";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+// machinegun bullet impact
+DEF(TE_SPIKE);
+// bullet impact decal
+SUB(TE_SPIKE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '6.0 6.0 6.0';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 56;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(TE_SPIKE) {
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x101010";
+       MY(color_max) = "0x101010";
+       MY(count) = 4;
+       MY(sizeincrease) = 3;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// dust/smoke staying at the impact
+SUB(TE_SPIKE) {
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x505050";
+       MY(color_max) = "0x505050";
+       MY(count) = 0.500000;
+       MY(sizeincrease) = 4;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+}
+// bouncing sparks
+SUB(TE_SPIKE) {
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 10;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// electro combo explosion
+DEF(TE_SPIKEQUAD);
+// decal
+SUB(TE_SPIKEQUAD) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '2.0 2.5 3.0';
+       MY(lightradiusfade) = 200;
+       MY(lightradius) = 400;
+       MY(originjitter) = '34.0 34.0 34.0';
+       MY(size_min) = 64;
+       MY(size_max) = 64;
+       MY(tex_min) = 59;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(TE_SPIKEQUAD) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x80C0FF";
+       MY(color_max) = "0x80C0FF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 48;
+       MY(size_max) = 48;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "static";
+}
+// large sparks
+SUB(TE_SPIKEQUAD) {
+       MY(airfriction) = 4;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x2030FF";
+       MY(color_max) = "0x80C0FF";
+       MY(count) = 10;
+       MY(liquidfriction) = 16;
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(type) = "static";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+
+// quake effect
+DEF(TE_SUPERSPIKE);
+// decal
+SUB(TE_SUPERSPIKE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '6.0 6.0 6.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 56;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(TE_SUPERSPIKE) {
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x101010";
+       MY(color_max) = "0x101010";
+       MY(count) = 4;
+       MY(sizeincrease) = 3;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// dust/smoke staying at the impact
+SUB(TE_SUPERSPIKE) {
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x505050";
+       MY(color_max) = "0x505050";
+       MY(count) = 0.500000;
+       MY(sizeincrease) = 4;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+}
+// sparks that disappear on impact
+SUB(TE_SUPERSPIKE) {
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 15;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// quake effect
+DEF(TE_SUPERSPIKEQUAD);
+// decal
+SUB(TE_SUPERSPIKEQUAD) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '0.2 0.2 1.5';
+       MY(lightradiusfade) = 500;
+       MY(lightradius) = 100;
+       MY(originjitter) = '6.0 6.0 6.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 56;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(TE_SUPERSPIKEQUAD) {
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x101010";
+       MY(color_max) = "0x101010";
+       MY(count) = 4;
+       MY(sizeincrease) = 3;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// dust/smoke staying at the impact
+SUB(TE_SUPERSPIKEQUAD) {
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x505050";
+       MY(color_max) = "0x505050";
+       MY(count) = 0.500000;
+       MY(sizeincrease) = 4;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+}
+// sparks that disappear on impact
+SUB(TE_SUPERSPIKEQUAD) {
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 15;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// shotgun pellet impact
+DEF(TE_GUNSHOT);
+// decal
+SUB(TE_GUNSHOT) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '6.0 6.0 6.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 56;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(TE_GUNSHOT) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x101010";
+       MY(color_max) = "0x101010";
+       MY(count) = 0.800000;
+       MY(sizeincrease) = 3;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// dust/smoke staying at the impact
+SUB(TE_GUNSHOT) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x505050";
+       MY(color_max) = "0x505050";
+       MY(count) = 0.200000;
+       MY(sizeincrease) = 4;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+}
+// bouncing sparks
+SUB(TE_GUNSHOT) {
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 2.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// crylink impact effect
+DEF(TE_GUNSHOTQUAD);
+// decal
+SUB(TE_GUNSHOTQUAD) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '12.0 12.0 12.0';
+       MY(size_min) = 8;
+       MY(size_max) = 8;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "decal";
+}
+// purple flare effect
+SUB(TE_GUNSHOTQUAD) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x504060";
+       MY(color_max) = "0x504060";
+       MY(countabsolute) = 1;
+       MY(size_min) = 8;
+       MY(size_max) = 8;
+       MY(tex_min) = 39;
+       MY(tex_max) = 39;
+       MY(type) = "static";
+}
+// purple sparks
+SUB(TE_GUNSHOTQUAD) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 384;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xA040C0";
+       MY(color_max) = "0xFFFFFF";
+       MY(count) = 6;
+       MY(gravity) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(type) = "spark";
+       MY(velocityjitter) = '128.0 128.0 128.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// mortar/hagar explosion (smaller than rocket)
+DEF(TE_EXPLOSION);
+// decal
+SUB(TE_EXPLOSION) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '4.0 2.0 0.5';
+       MY(lightradiusfade) = 300;
+       MY(lightradius) = 150;
+       MY(originjitter) = '40.0 40.0 40.0';
+       MY(size_min) = 48;
+       MY(size_max) = 48;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(TE_EXPLOSION) {
+       MY(alpha_min) = 192;
+       MY(alpha_max) = 192;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x404040";
+       MY(countabsolute) = 1;
+       MY(size_min) = 48;
+       MY(size_max) = 48;
+       MY(tex_min) = 35;
+       MY(tex_max) = 37;
+       MY(type) = "static";
+}
+// fire effect which expands then slows
+SUB(TE_EXPLOSION) {
+       MY(airfriction) = 4;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x902010";
+       MY(color_max) = "0xFFD080";
+       MY(count) = 64;
+       MY(liquidfriction) = 4;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// underwater bubbles
+SUB(TE_EXPLOSION) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 16;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// bouncing sparks
+SUB(TE_EXPLOSION) {
+       MY(airfriction) = 0.200000;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 384;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x903010";
+       MY(color_max) = "0xFFD030";
+       MY(count) = 16;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(type) = "spark";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// quake effect
+DEF(TE_EXPLOSIONQUAD);
+// decal
+SUB(TE_EXPLOSIONQUAD) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '4.0 2.0 8.0';
+       MY(lightradiusfade) = 700;
+       MY(lightradius) = 350;
+       MY(originjitter) = '40.0 40.0 40.0';
+       MY(size_min) = 48;
+       MY(size_max) = 48;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// smoke cloud
+SUB(TE_EXPLOSIONQUAD) {
+       MY(alpha_min) = 32;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 16;
+       MY(notunderwater) = true;
+       MY(size_min) = 12;
+       MY(size_max) = 12;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '48.0 48.0 48.0';
+}
+// underwater bubbles
+SUB(TE_EXPLOSIONQUAD) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 16;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// sparks which go through walls
+SUB(TE_EXPLOSIONQUAD) {
+       MY(airfriction) = 0.200000;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x903010";
+       MY(color_max) = "0xFFD030";
+       MY(count) = 64;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(type) = "spark";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// quake effect
+DEF(TE_TAREXPLOSION);
+// decal
+SUB(TE_TAREXPLOSION) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '1.6 0.8 2.0';
+       MY(lightradiusfade) = 1200;
+       MY(lightradius) = 600;
+       MY(originjitter) = '40.0 40.0 40.0';
+       MY(size_min) = 48;
+       MY(size_max) = 48;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// smoke cloud
+SUB(TE_TAREXPLOSION) {
+       MY(alpha_min) = 32;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 16;
+       MY(notunderwater) = true;
+       MY(size_min) = 12;
+       MY(size_max) = 12;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '48.0 48.0 48.0';
+}
+// underwater bubbles
+SUB(TE_TAREXPLOSION) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 16;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// sparks which go through walls
+SUB(TE_TAREXPLOSION) {
+       MY(airfriction) = 0.200000;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x903010";
+       MY(color_max) = "0xFFD030";
+       MY(count) = 64;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(type) = "spark";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// bloody impact effect indicating damage
+DEF(TE_BLOOD);
+SUB(TE_BLOOD) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(count) = 0.167000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 8;
+       MY(size_max) = 8;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 1;
+}
+
+// sparks (quake effect)
+DEF(TE_SPARK);
+SUB(TE_SPARK) {
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.600000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 1;
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// vortex impact
+DEF(TE_PLASMABURN);
+// decal
+SUB(TE_PLASMABURN) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '1.0 1.0 1.0';
+       MY(lightradiusfade) = 400;
+       MY(lightradius) = 200;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(TE_PLASMABURN) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x80C0FF";
+       MY(color_max) = "0x80C0FF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 8;
+       MY(size_max) = 8;
+       MY(tex_min) = 37;
+       MY(tex_max) = 37;
+       MY(type) = "static";
+}
+// small sparks which form a sphere as they slow down
+SUB(TE_PLASMABURN) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(bounce) = 2;
+       MY(color_min) = "0x2030FF";
+       MY(color_max) = "0x80C0FF";
+       MY(count) = 128;
+       MY(liquidfriction) = 8;
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(type) = "spark";
+       MY(velocityjitter) = '128.0 128.0 128.0';
+}
+
+// quake effect
+DEF(TE_SMALLFLASH);
+SUB(TE_SMALLFLASH) {
+       MY(lightcolor) = '2.0 2.0 2.0';
+       MY(lightradiusfade) = 1000;
+       MY(lightradius) = 200;
+}
+
+// quake effect
+DEF(TE_FLAMEJET);
+SUB(TE_FLAMEJET) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 384;
+       MY(bounce) = 1.100000;
+       MY(color_min) = "0x6f0f00";
+       MY(color_max) = "0xe3974f";
+       MY(count) = 0.500000;
+       MY(gravity) = -1;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '128.0 128.0 128.0';
+       MY(velocitymultiplier) = 1;
+}
+
+// quake effect
+DEF(TE_LAVASPLASH);
+SUB(TE_LAVASPLASH) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x6f0f00";
+       MY(color_max) = "0xe3974f";
+       MY(count) = 32;
+       MY(gravity) = 0.050000;
+       MY(originjitter) = '128.0 128.0 32.0';
+       MY(originoffset) = '0.0 0.0 32.0';
+       MY(size_min) = 12;
+       MY(size_max) = 12;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '128.0 128.0 0.0';
+       MY(velocityoffset) = '0.0 0.0 256.0';
+}
+
+// player teleport effect
+DEF(TE_TELEPORT);
+SUB(TE_TELEPORT) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0xA0A0A0";
+       MY(color_max) = "0xFFFFFF";
+       MY(count) = 56;
+       MY(liquidfriction) = 4;
+       MY(originjitter) = '16.0 16.0 28.0';
+       MY(originoffset) = '0.0 0.0 28.0';
+       MY(size_min) = 10;
+       MY(size_max) = 10;
+       MY(type) = "static";
+       MY(velocityjitter) = '0.0 0.0 256.0';
+}
+
+// vortex beam
+DEF(TE_TEI_G3);
+SUB(TE_TEI_G3) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0xFFFFFF";
+       MY(color_max) = "0xFFFFFF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+SUB(TE_TEI_G3) {
+       MY(airfriction) = -4;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(trailspacing) = 4;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '8.0 8.0 8.0';
+}
+
+// smoke effect
+DEF(TE_TEI_SMOKE);
+SUB(TE_TEI_SMOKE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 0.167000;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 1;
+}
+
+// rocket explosion (bigger than mortar and hagar)
+DEF(TE_TEI_BIGEXPLOSION);
+// decal
+SUB(TE_TEI_BIGEXPLOSION) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '4.0 2.0 0.5';
+       MY(lightradiusfade) = 500;
+       MY(lightradius) = 500;
+       MY(originjitter) = '40.0 40.0 40.0';
+       MY(size_min) = 72;
+       MY(size_max) = 72;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(TE_TEI_BIGEXPLOSION) {
+       MY(alpha_min) = 192;
+       MY(alpha_max) = 192;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x404040";
+       MY(countabsolute) = 1;
+       MY(size_min) = 72;
+       MY(size_max) = 72;
+       MY(tex_min) = 35;
+       MY(tex_max) = 37;
+       MY(type) = "static";
+}
+// fire effect
+SUB(TE_TEI_BIGEXPLOSION) {
+       MY(airfriction) = 4;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x902010";
+       MY(color_max) = "0xFFD080";
+       MY(count) = 128;
+       MY(liquidfriction) = 4;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// underwater bubbles
+SUB(TE_TEI_BIGEXPLOSION) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 32;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// bouncing sparks
+SUB(TE_TEI_BIGEXPLOSION) {
+       MY(airfriction) = 0.200000;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 384;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x903010";
+       MY(color_max) = "0xFFD030";
+       MY(count) = 64;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(type) = "spark";
+       MY(velocityjitter) = '384.0 384.0 384.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// electro explosion
+DEF(TE_TEI_PLASMAHIT);
+// decal
+SUB(TE_TEI_PLASMAHIT) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '2.4 4.8 8.0';
+       MY(lightradiusfade) = 600;
+       MY(lightradius) = 200;
+       MY(originjitter) = '20.0 20.0 20.0';
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 59;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(TE_TEI_PLASMAHIT) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x80C0FF";
+       MY(color_max) = "0x80C0FF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "static";
+}
+// cloud of bouncing sparks
+SUB(TE_TEI_PLASMAHIT) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x2030FF";
+       MY(color_max) = "0x80C0FF";
+       MY(count) = 0.500000;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(type) = "spark";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+
+// bloody impact effect indicating damage
+DEF(blood);
+SUB(blood) {
+       MY(airfriction) = 0.400000;
+       MY(alpha_min) = 1560;
+       MY(alpha_max) = 2560;
+       MY(alpha_fade) = 7000;
+       MY(blend) = "invmod";
+       MY(bounce) = -1;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFFF";
+       MY(count) = 0.400000;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 5;
+       MY(size_max) = 11;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(stainsize_min) = 1;
+       MY(stainsize_max) = 2;
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(stretchfactor) = 20;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "spark";
+       MY(velocityjitter) = '99.0 99.0 55.0';
+}
+//blood mist
+SUB(blood) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(blend) = "invmod";
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x420000";
+       MY(countabsolute) = 1;
+       MY(originjitter) = '11.0 11.0 11.0';
+       MY(sizeincrease) = 20;
+       MY(size_min) = 25;
+       MY(size_max) = 30;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "alphastatic";
+}
+
+// player teleport effect
+DEF(teleport);
+SUB(teleport) {
+       MY(airfriction) = 2;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 100;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x807aff";
+       MY(color_max) = "0x4463d5";
+       MY(count) = 500;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(stretchfactor) = 0.600000;
+       MY(tex_min) = 64;
+       MY(tex_max) = 64;
+       MY(type) = "spark";
+       MY(velocityjitter) = '1000.0 1000.0 1500.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+SUB(teleport) {
+       MY(alpha_min) = 190;
+       MY(alpha_max) = 190;
+       MY(alpha_fade) = 180;
+       MY(color_min) = "0x807aff";
+       MY(color_max) = "0x4463d5";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = -80;
+       MY(size_min) = 150;
+       MY(size_max) = 150;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "smoke";
+}
+
+// normal super gory blood trail (used by gibs)
+DEF(TR_BLOOD);
+SUB(TR_BLOOD) {
+       MY(airfriction) = -2;
+       MY(alpha_min) = 384;
+       MY(alpha_max) = 984;
+       MY(alpha_fade) = 1492;
+       MY(blend) = "invmod";
+       MY(bounce) = -1;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFF";
+       MY(gravity) = 0.400000;
+       MY(liquidfriction) = 1;
+       MY(sizeincrease) = -5;
+       MY(size_min) = 4;
+       MY(size_max) = 19;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(stainsize_min) = 1;
+       MY(stainsize_max) = 2;
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(stretchfactor) = 7;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 20;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = -0.100000;
+}
+// splash around gib
+SUB(TR_BLOOD) {
+       MY(alpha_min) = 684;
+       MY(alpha_max) = 684;
+       MY(alpha_fade) = 7492;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFF";
+       MY(sizeincrease) = 500;
+       MY(size_min) = 4;
+       MY(size_max) = 6;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 42;
+       MY(type) = "blood";
+}
+
+// thinner blood trail (used by quake zombies)
+DEF(TR_SLIGHTBLOOD);
+SUB(TR_SLIGHTBLOOD) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 384;
+       MY(alpha_max) = 384;
+       MY(alpha_fade) = 192;
+       MY(bounce) = -1;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFF";
+       MY(liquidfriction) = 4;
+       MY(size_min) = 8;
+       MY(size_max) = 8;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 64;
+       MY(type) = "blood";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+// func_stardust effect, used in some maps to indicate teleporters
+DEF(EF_STARDUST);
+SUB(EF_STARDUST) {
+       MY(airfriction) = 0.200000;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0xfff368";
+       MY(color_max) = "0xfff368";
+       MY(count) = 37.500000;
+       MY(gravity) = -0.100000;
+       MY(liquidfriction) = 0.800000;
+       MY(originjitter) = '16.0 16.0 64.0';
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 0.0';
+}
+
+// flare particle and light
+DEF(item_respawn);
+SUB(item_respawn) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x63F2EA";
+       MY(color_max) = "0x63f2EA";
+       MY(countabsolute) = 1;
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(type) = "static";
+}
+// cloud of particles which expand rapidly and then slow to form a ball
+SUB(item_respawn) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1280;
+       MY(color_min) = "0x63F2EA";
+       MY(color_max) = "0x63f2EA";
+       MY(count) = 128;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+DEF(jumppad_activate);
+SUB(jumppad_activate) {
+       MY(lightcolor) = '2.0 2.0 2.0';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+}
+
+DEF(laser_muzzleflash);
+// glow and light
+SUB(laser_muzzleflash) {
+       MY(airfriction) = 10;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 6280;
+       MY(color_min) = "0xcc0000";
+       MY(color_max) = "0xff0000";
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '3.0 0.1 0.1';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(sizeincrease) = -100;
+       MY(size_min) = 10;
+       MY(size_max) = 15;
+       MY(stretchfactor) = 2;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "smoke";
+}
+// electricity
+SUB(laser_muzzleflash) {
+       MY(airfriction) = 10;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 6280;
+       MY(color_min) = "0xb44215";
+       MY(color_max) = "0xff0000";
+       MY(count) = 3;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = 4000;
+       MY(spin_max) = -4000;
+       MY(sizeincrease) = -100;
+       MY(size_min) = 5;
+       MY(size_max) = 7;
+       MY(stretchfactor) = 2.300000;
+       MY(tex_min) = 43;
+       MY(tex_max) = 43;
+       MY(type) = "spark";
+       MY(velocityjitter) = '150.0 150.0 150.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+// fire
+SUB(laser_muzzleflash) {
+       MY(airfriction) = 12;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 6280;
+       MY(color_min) = "0xff4200";
+       MY(color_max) = "0xff0000";
+       MY(count) = 6;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = -100;
+       MY(size_min) = 7;
+       MY(size_max) = 9;
+       MY(stretchfactor) = 2;
+       MY(tex_min) = 8;
+       MY(tex_max) = 15;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(laser_impact);
+// decal
+SUB(laser_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '8.0 0.4 0.4';
+       MY(lightradiusfade) = 500;
+       MY(lightradius) = 200;
+       MY(originjitter) = '14.0 14.0 14.0';
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(laser_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xFF2010";
+       MY(color_max) = "0xFF2010";
+       MY(countabsolute) = 1;
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 39;
+       MY(tex_max) = 39;
+       MY(type) = "static";
+}
+// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect
+SUB(laser_impact) {
+       MY(airfriction) = 6;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x800000";
+       MY(color_max) = "0xFF8020";
+       MY(count) = 128;
+       MY(liquidfriction) = 6;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(type) = "spark";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+SUB(laser_impact) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x800000";
+       MY(color_max) = "0xFF8020";
+       MY(count) = 4;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = 6;
+       MY(size_min) = 12;
+       MY(size_max) = 12;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '16.0 16.0 16.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+
+DEF(shotgun_muzzleflash);
+SUB(shotgun_muzzleflash) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 1.500000;
+       MY(lightcolor) = '2.0 1.5 0.2';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(sizeincrease) = 12;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 0.050000;
+}
+SUB(shotgun_muzzleflash) {
+       MY(airfriction) = 5;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xffdb96";
+       MY(color_max) = "0xff5400";
+       MY(count) = 16;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 10;
+       MY(size_max) = 20;
+       MY(stretchfactor) = 2.500000;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+// shotgun pellet impact
+DEF(shotgun_impact);
+// decal
+SUB(shotgun_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '10.0 10.0 10.0';
+       MY(size_min) = 5;
+       MY(size_max) = 8;
+       MY(tex_min) = 56;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(shotgun_impact) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 550;
+       MY(alpha_fade) = 756;
+       MY(color_min) = "0x473a37";
+       MY(color_max) = "0x0b0a07";
+       MY(count) = 1;
+       MY(notunderwater) = true;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -50;
+       MY(spin_max) = 50;
+       MY(sizeincrease) = 25;
+       MY(size_min) = 10;
+       MY(size_max) = 20;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '150.0 150.0 150.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+// dust/smoke staying at the impact
+SUB(shotgun_impact) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 350;
+       MY(alpha_fade) = 500;
+       MY(bounce) = 6;
+       MY(color_min) = "0x201d1a";
+       MY(color_max) = "0x000000";
+       MY(count) = 0.200000;
+       MY(notunderwater) = true;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -50;
+       MY(spin_max) = 50;
+       MY(sizeincrease) = 74;
+       MY(size_min) = 10;
+       MY(size_max) = 11;
+       MY(tex_min) = 36;
+       MY(tex_max) = 36;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 11.0';
+       MY(velocitymultiplier) = 0.030000;
+}
+// sparks
+SUB(shotgun_impact) {
+       MY(airfriction) = 1.100000;
+       MY(alpha_max) = 356;
+       MY(alpha_fade) = 268;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xFDFFD9";
+       MY(color_max) = "0xFDFFD9";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(notunderwater) = true;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 0.600000;
+       MY(size_max) = 0.600000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '200.0 200.0 200.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(uzi_muzzleflash);
+SUB(uzi_muzzleflash) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 1;
+       MY(gravity) = -0.100000;
+       MY(lightcolor) = '2.0 1.5 0.2';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_max) = 8;
+       MY(type) = "static";
+       MY(velocityjitter) = '1.0 1.0 1.0';
+       MY(velocitymultiplier) = 0.030000;
+}
+SUB(uzi_muzzleflash) {
+       MY(airfriction) = 12;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 6000;
+       MY(color_min) = "0xff9c00";
+       MY(color_max) = "0xffd200";
+       MY(count) = 3;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 0.300000;
+       MY(size_max) = 0.400000;
+       MY(stretchfactor) = 0.150000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '555.0 555.0 555.0';
+       MY(velocitymultiplier) = 3;
+}
+
+DEF(machinegun_impact);
+// decal
+SUB(machinegun_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '6.0 3.6 0.6';
+       MY(lightradiusfade) = 800;
+       MY(lightradius) = 80;
+       MY(originjitter) = '10.0 10.0 10.0';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 56;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(machinegun_impact) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 550;
+       MY(alpha_fade) = 456;
+       MY(color_min) = "0x473a37";
+       MY(color_max) = "0x0b0a07";
+       MY(count) = 1.500000;
+       MY(notunderwater) = true;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -50;
+       MY(spin_max) = 50;
+       MY(sizeincrease) = 15;
+       MY(size_min) = 10;
+       MY(size_max) = 20;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '150.0 150.0 150.0';
+       MY(velocitymultiplier) = 0.100000;
+}
+// dust/smoke staying at the impact
+SUB(machinegun_impact) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 350;
+       MY(alpha_fade) = 500;
+       MY(bounce) = 6;
+       MY(color_min) = "0x201d1a";
+       MY(color_max) = "0x000000";
+       MY(count) = 0.500000;
+       MY(notunderwater) = true;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -50;
+       MY(spin_max) = 50;
+       MY(sizeincrease) = 74;
+       MY(size_min) = 10;
+       MY(size_max) = 11;
+       MY(tex_min) = 36;
+       MY(tex_max) = 36;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 11.0';
+       MY(velocitymultiplier) = 0.030000;
+}
+// debris
+SUB(machinegun_impact) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 550;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.700000;
+       MY(color_min) = "0x63493e";
+       MY(color_max) = "0xffffff";
+       MY(count) = 1;
+       MY(gravity) = 1.400000;
+       MY(notunderwater) = true;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -500;
+       MY(spin_max) = 500;
+       MY(size_min) = 1;
+       MY(size_max) = 5;
+       MY(tex_min) = 66;
+       MY(tex_max) = 68;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '350.0 350.0 350.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+// sparks
+SUB(machinegun_impact) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 168;
+       MY(bounce) = 1;
+       MY(color_min) = "0xFDFFD9";
+       MY(color_max) = "0xFDFFD9";
+       MY(count) = 1;
+       MY(gravity) = 1;
+       MY(notunderwater) = true;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 0.300000;
+       MY(size_max) = 0.300000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '300.0 300.0 300.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(grenadelauncher_muzzleflash);
+SUB(grenadelauncher_muzzleflash) {
+       MY(airfriction) = 12;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 1.500000;
+       MY(lightcolor) = '2.0 1.5 0.2';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '20.0 20.0 20.0';
+       MY(velocitymultiplier) = 0.030000;
+}
+SUB(grenadelauncher_muzzleflash) {
+       MY(airfriction) = 5;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xffdb96";
+       MY(color_max) = "0xff5400";
+       MY(count) = 16;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 10;
+       MY(size_max) = 20;
+       MY(stretchfactor) = 2.500000;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+// mortar trail
+DEF(TR_GRENADE);
+// smoke
+SUB(TR_GRENADE) {
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 400;
+       MY(alpha_fade) = 780;
+       MY(bounce) = 1;
+       MY(color_min) = "0x101010";
+       MY(color_max) = "0x000000";
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 3;
+       MY(size_max) = 2;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 4;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '1.0 1.0 1.0';
+       MY(velocitymultiplier) = -0.020000;
+}
+// fire
+SUB(TR_GRENADE) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 144;
+       MY(alpha_fade) = 988;
+       MY(color_min) = "0xffdf72";
+       MY(color_max) = "0x811200";
+       MY(notunderwater) = true;
+       MY(sizeincrease) = -15;
+       MY(size_min) = 5;
+       MY(size_max) = 2;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 4;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = -1;
+}
+// bubbles
+SUB(TR_GRENADE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 16;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+// hookbomb trail
+DEF(TR_KNIGHTSPIKE);
+// smoke
+SUB(TR_KNIGHTSPIKE) {
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 400;
+       MY(alpha_fade) = 600;
+       MY(bounce) = 1;
+       MY(color_min) = "0x303030";
+       MY(color_max) = "0x000000";
+       MY(gravity) = -0.110000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = 11;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 6;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '3.0 3.0 3.0';
+       MY(velocitymultiplier) = -0.020000;
+}
+// marker
+SUB(TR_KNIGHTSPIKE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 720;
+       MY(color_min) = "0x666666";
+       MY(color_max) = "0x000000";
+       MY(sizeincrease) = -0.100000;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 2;
+       MY(type) = "alphastatic";
+}
+// bubbles
+SUB(TR_KNIGHTSPIKE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 32;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+DEF(grenade_explode);
+// decal
+SUB(grenade_explode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '8.0 4.0 1.0';
+       MY(lightradiusfade) = 400;
+       MY(lightradius) = 250;
+       MY(originjitter) = '26.0 26.0 26.0';
+       MY(size_min) = 48;
+       MY(size_max) = 48;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// fire effect which expands then slows
+SUB(grenade_explode) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 228;
+       MY(alpha_fade) = 356;
+       MY(bounce) = 4.500000;
+       MY(color_min) = "0xe03f00";
+       MY(color_max) = "0x5e0000";
+       MY(count) = 40;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(sizeincrease) = 20;
+       MY(size_min) = 16;
+       MY(size_max) = 26;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// fire effect which make bright dot inside
+SUB(grenade_explode) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 228;
+       MY(alpha_max) = 328;
+       MY(alpha_fade) = 756;
+       MY(bounce) = 1;
+       MY(color_min) = "0xe03f00";
+       MY(color_max) = "0xffdf92";
+       MY(count) = 15;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(sizeincrease) = 40;
+       MY(size_min) = 6;
+       MY(size_max) = 16;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// smoke
+SUB(grenade_explode) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 550;
+       MY(alpha_fade) = 556;
+       MY(bounce) = 6;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 10;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 34;
+       MY(size_min) = 20;
+       MY(size_max) = 40;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// underwater bubbles
+SUB(grenade_explode) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 32;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 3;
+       MY(size_max) = 6;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '196.0 196.0 196.0';
+}
+// underwatershockwave
+SUB(grenade_explode) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 300;
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1500;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(underwater) = true;
+       MY(velocitymultiplier) = 0.300000;
+}
+// bouncing sparks
+SUB(grenade_explode) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 644;
+       MY(alpha_max) = 956;
+       MY(alpha_fade) = 484;
+       MY(bounce) = 1.600000;
+       MY(color_min) = "0xffa35b";
+       MY(color_max) = "0xfff2be";
+       MY(count) = 16;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 1;
+       MY(size_max) = 0.100000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '424.0 424.0 624.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+// debris
+SUB(grenade_explode) {
+       MY(airfriction) = 0.500000;
+       MY(alpha_min) = 644;
+       MY(alpha_max) = 956;
+       MY(alpha_fade) = 684;
+       MY(bounce) = 1.600000;
+       MY(color_min) = "0x6a3d25";
+       MY(color_max) = "0xcac5b4";
+       MY(count) = 12;
+       MY(gravity) = 1.300000;
+       MY(notunderwater) = true;
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -1000;
+       MY(spin_max) = 1000;
+       MY(size_min) = 2;
+       MY(size_max) = 6;
+       MY(tex_min) = 66;
+       MY(tex_max) = 68;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '324.0 324.0 524.0';
+}
+
+DEF(electro_muzzleflash);
+SUB(electro_muzzleflash) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x283880";
+       MY(color_max) = "0x283880";
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '1.5 3.0 6.0';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(sizeincrease) = -10;
+       MY(size_min) = 15;
+       MY(size_max) = 15;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+SUB(electro_muzzleflash) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 110;
+       MY(alpha_max) = 228;
+       MY(alpha_fade) = 2024;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0xD9FDFF";
+       MY(count) = 7;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 5;
+       MY(size_max) = 15;
+       MY(stretchfactor) = 1.500000;
+       MY(tex_min) = 8;
+       MY(tex_max) = 15;
+       MY(type) = "spark";
+       MY(velocityjitter) = '150.0 150.0 150.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+SUB(electro_muzzleflash) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 110;
+       MY(alpha_max) = 228;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0xD9FDFF";
+       MY(count) = 5;
+       MY(gravity) = 1.300000;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 7;
+       MY(size_max) = 6;
+       MY(stretchfactor) = 0.100000;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '350.0 350.0 350.0';
+       MY(velocitymultiplier) = 2.500000;
+}
+
+// electro trail
+DEF(TR_NEXUIZPLASMA);
+// glowing vapor trail
+SUB(TR_NEXUIZPLASMA) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 968;
+       MY(color_min) = "0x283880";
+       MY(color_max) = "0x283880";
+       MY(lightcolor) = '1.5 3.0 6.0';
+       MY(lightradius) = 90;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(trailspacing) = 2;
+       MY(type) = "static";
+       MY(velocitymultiplier) = -0.100000;
+}
+// bright sparks
+SUB(TR_NEXUIZPLASMA) {
+       MY(airfriction) = 12;
+       MY(alpha_min) = 444;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 1866;
+       MY(bounce) = 1;
+       MY(color_min) = "0x629dff";
+       MY(color_max) = "0x0018ff";
+       MY(count) = 1.500000;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = -20;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(tex_min) = 42;
+       MY(tex_max) = 42;
+       MY(trailspacing) = 12;
+       MY(type) = "snow";
+       MY(velocityjitter) = '50.0 50.0 50.0';
+       MY(velocityoffset) = '0.0 0.0 15.0';
+}
+
+DEF(electro_impact);
+// decal
+SUB(electro_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '3.1 4.4 10.0';
+       MY(lightradiusfade) = 250;
+       MY(lightradius) = 250;
+       MY(originjitter) = '17.0 17.0 17.0';
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 59;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// shockwave
+SUB(electro_impact) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 350;
+       MY(color_min) = "0x80C0FF";
+       MY(color_max) = "0x80C0FF";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1000;
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(velocitymultiplier) = 44;
+}
+// flare effect
+SUB(electro_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x80C0FF";
+       MY(color_max) = "0x80C0FF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 12;
+       MY(size_max) = 32;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "static";
+}
+// cloud of bouncing sparks
+SUB(electro_impact) {
+       MY(airfriction) = 6;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(bounce) = 2;
+       MY(color_min) = "0x629dff";
+       MY(color_max) = "0x0018ff";
+       MY(count) = 30;
+       MY(gravity) = -0.300000;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -9999;
+       MY(spin_max) = 9999;
+       MY(sizeincrease) = -50;
+       MY(size_min) = 36;
+       MY(size_max) = 36;
+       MY(tex_min) = 42;
+       MY(tex_max) = 42;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// inner cloud of smoke
+SUB(electro_impact) {
+       MY(airfriction) = 30;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x629dff";
+       MY(color_max) = "0x0018ff";
+       MY(count) = 30;
+       MY(originjitter) = '20.0 20.0 20.0';
+       MY(sizeincrease) = 50;
+       MY(size_min) = 20;
+       MY(size_max) = 24;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '320.0 320.0 320.0';
+}
+
+DEF(electro_ballexplode);
+// decal
+SUB(electro_ballexplode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '3.1 4.4 10.0';
+       MY(lightradiusfade) = 250;
+       MY(lightradius) = 250;
+       MY(originjitter) = '17.0 17.0 17.0';
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 59;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(electro_ballexplode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x80C0FF";
+       MY(color_max) = "0x80C0FF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "static";
+}
+// cloud of bouncing sparks
+SUB(electro_ballexplode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(bounce) = 2;
+       MY(color_min) = "0xFDFFD9";
+       MY(color_max) = "0xFDFFD9";
+       MY(count) = 64;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(stretchfactor) = 0.400000;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// inner cloud of smoke
+SUB(electro_ballexplode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 8;
+       MY(originjitter) = '20.0 20.0 20.0';
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+}
+
+DEF(electro_combo);
+// decal
+SUB(electro_combo) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '4.0 5.0 6.0';
+       MY(lightradiusfade) = 300;
+       MY(lightradius) = 400;
+       MY(originjitter) = '17.0 17.0 17.0';
+       MY(size_min) = 64;
+       MY(size_max) = 64;
+       MY(tex_min) = 59;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(electro_combo) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x80C0FF";
+       MY(color_max) = "0x80C0FF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 48;
+       MY(size_max) = 48;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "static";
+}
+// large sparks
+SUB(electro_combo) {
+       MY(airfriction) = 6;
+       MY(alpha_min) = 156;
+       MY(alpha_max) = 156;
+       MY(alpha_fade) = 156;
+       MY(bounce) = 2;
+       MY(color_min) = "0x2030FF";
+       MY(color_max) = "0x80C0FF";
+       MY(count) = 5;
+       MY(liquidfriction) = 16;
+       MY(sizeincrease) = 50;
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_max) = 7;
+       MY(type) = "static";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+SUB(electro_combo) {
+       MY(alpha_min) = 444;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 700;
+       MY(bounce) = 1.600000;
+       MY(color_min) = "0xa9cacf";
+       MY(color_max) = "0x0054ff";
+       MY(count) = 32;
+       MY(gravity) = 0.300000;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(stretchfactor) = 2;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '312.0 312.0 312.0';
+       MY(velocitymultiplier) = 3;
+}
+// inner cloud of smoke
+SUB(electro_combo) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 0.125000;
+       MY(originjitter) = '20.0 20.0 20.0';
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+}
+// shockwave
+SUB(electro_combo) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 100;
+       MY(color_min) = "0xa9cacf";
+       MY(color_max) = "0x0054ff";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 600;
+       MY(size_min) = 30;
+       MY(size_max) = 30;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(velocitymultiplier) = 0.300000;
+}
+
+DEF(crylink_muzzleflash);
+SUB(crylink_muzzleflash) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 2024;
+       MY(color_min) = "0xdd9cff";
+       MY(color_max) = "0xff0090";
+       MY(count) = 0.500000;
+       MY(lightcolor) = '1.6 0.2 2.0';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(size_min) = 15;
+       MY(size_max) = 20;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "smoke";
+       MY(velocitymultiplier) = 0.010000;
+}
+SUB(crylink_muzzleflash) {
+       MY(airfriction) = 12;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xA080C0";
+       MY(color_max) = "0xA080C0";
+       MY(count) = 5;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(stretchfactor) = 1.500000;
+       MY(tex_min) = 35;
+       MY(tex_max) = 36;
+       MY(type) = "spark";
+       MY(velocityjitter) = '200.0 200.0 200.0';
+       MY(velocitymultiplier) = 0.300000;
+}
+
+DEF(crylink_impact);
+// decal
+SUB(crylink_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '12.0 12.0 12.0';
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "decal";
+}
+// purple flare effect
+SUB(crylink_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x504060";
+       MY(color_max) = "0x504060";
+       MY(countabsolute) = 1;
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 39;
+       MY(tex_max) = 39;
+       MY(type) = "static";
+}
+// purple sparks
+SUB(crylink_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(bounce) = 2;
+       MY(color_min) = "0xA040C0";
+       MY(color_max) = "0xA040C0";
+       MY(count) = 40;
+       MY(size_min) = 6;
+       MY(size_max) = 6;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// purple splash
+SUB(crylink_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0xE070FF";
+       MY(color_max) = "0xE070FF";
+       MY(count) = 1.500000;
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+}
+// purple splash
+SUB(crylink_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xE070FF";
+       MY(color_max) = "0xE070FF";
+       MY(count) = 3;
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(type) = "static";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+DEF(nex_muzzleflash);
+SUB(nex_muzzleflash) {
+       MY(airfriction) = 9;
+       MY(alpha_min) = 328;
+       MY(alpha_max) = 328;
+       MY(alpha_fade) = 4000;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x0072ff";
+       MY(count) = 12;
+       MY(lightcolor) = '2.0 2.5 3.0';
+       MY(lightradiusfade) = 200;
+       MY(lightradius) = 200;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(sizeincrease) = -100;
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(stretchfactor) = 2;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "spark";
+       MY(velocityjitter) = '180.0 180.0 180.0';
+       MY(velocitymultiplier) = 1.400000;
+}
+SUB(nex_muzzleflash) {
+       MY(airfriction) = 9;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0xD9FDFF";
+       MY(count) = 50;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '600.0 600.0 600.0';
+       MY(velocitymultiplier) = 1.500000;
+}
+
+// vortex beam
+DEF(nex_beam);
+SUB(nex_beam) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x1680A0";
+       MY(color_max) = "0x1680A0";
+       MY(sizeincrease) = 2;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(tex_min) = 32;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 64;
+       MY(type) = "static";
+}
+// drifting smoke
+SUB(nex_beam) {
+       MY(airfriction) = 9;
+       MY(alpha_min) = 32;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 32;
+       MY(color_min) = "0x5080A0";
+       MY(color_max) = "0x5080A0";
+       MY(sizeincrease) = 8;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 12;
+       MY(type) = "static";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+}
+// bright core
+SUB(nex_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1280;
+       MY(color_min) = "0x80CDFF";
+       MY(color_max) = "0x80CDFF";
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(trailspacing) = 12;
+       MY(type) = "static";
+}
+// sparks
+SUB(nex_beam) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 80;
+       MY(color_min) = "0x1680A0";
+       MY(color_max) = "0x1680A0";
+       MY(gravity) = -0.010000;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 63;
+       MY(tex_max) = 63;
+       MY(trailspacing) = 16;
+       MY(type) = "snow";
+}
+
+DEF(nex_impact);
+// decal
+SUB(nex_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '4.0 6.0 8.0';
+       MY(lightradiusfade) = 250;
+       MY(lightradius) = 200;
+       MY(originjitter) = '14.0 14.0 14.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "decal";
+}
+// rotating something
+SUB(nex_impact) {
+       MY(alpha_min) = 55;
+       MY(alpha_max) = 55;
+       MY(alpha_fade) = 50;
+       MY(color_min) = "0x1680A0";
+       MY(color_max) = "0x1680A0";
+       MY(count) = 5;
+       MY(startangle_min) = 180;
+       MY(startangle_max) = -180;
+       MY(spin_min) = 500;
+       MY(spin_max) = -500;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 25;
+       MY(size_max) = 28;
+       MY(tex_min) = 46;
+       MY(tex_max) = 46;
+       MY(type) = "smoke";
+}
+// shockwave
+SUB(nex_impact) {
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 50;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x1680A0";
+       MY(color_max) = "0x1680A0";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 900;
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "static";
+}
+// shockwave2
+SUB(nex_impact) {
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 50;
+       MY(alpha_fade) = 100;
+       MY(color_min) = "0x1680A0";
+       MY(color_max) = "0x1680A0";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 500;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "static";
+}
+// flare effect
+SUB(nex_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x80C0FF";
+       MY(color_max) = "0x80C0FF";
+       MY(countabsolute) = 1;
+       MY(size_min) = 8;
+       MY(size_max) = 8;
+       MY(tex_min) = 37;
+       MY(tex_max) = 37;
+       MY(type) = "static";
+}
+// small sparks which glow brightly but live briefly
+SUB(nex_impact) {
+       MY(airfriction) = 9;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 512;
+       MY(bounce) = 2;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0xD9FDFF";
+       MY(count) = 64;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(stretchfactor) = 3;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '600.0 600.0 600.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+// small sparks that live longer
+SUB(nex_impact) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 112;
+       MY(bounce) = 1.600000;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0xD9FDFF";
+       MY(count) = 16;
+       MY(gravity) = 1;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(stretchfactor) = 0.700000;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '300.0 300.0 600.0';
+       MY(velocitymultiplier) = 2.500000;
+}
+
+DEF(hagar_muzzleflash);
+SUB(hagar_muzzleflash) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 2;
+       MY(lightcolor) = '2.0 1.5 0.2';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+SUB(hagar_muzzleflash) {
+       MY(airfriction) = 12;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xff8400";
+       MY(color_max) = "0xff4200";
+       MY(count) = 15;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -400;
+       MY(spin_max) = 400;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(stretchfactor) = 2;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "spark";
+       MY(velocityjitter) = '200.0 200.0 200.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(hagar_bounce);
+SUB(hagar_bounce) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 2;
+       MY(lightcolor) = '2.0 1.5 0.2';
+       MY(lightradiusfade) = 300;
+       MY(lightradius) = 60;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+SUB(hagar_bounce) {
+       MY(airfriction) = 12;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xFFFDD9";
+       MY(color_max) = "0xFFFDD9";
+       MY(count) = 15;
+       MY(gravity) = 1;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '600.0 600.0 600.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(hagar_explode);
+// decal
+SUB(hagar_explode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '8.0 4.0 1.0';
+       MY(lightradiusfade) = 400;
+       MY(lightradius) = 120;
+       MY(originjitter) = '14.0 14.0 14.0';
+       MY(size_min) = 28;
+       MY(size_max) = 38;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// fire effect which make bright dot inside
+SUB(hagar_explode) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 80;
+       MY(alpha_max) = 200;
+       MY(alpha_fade) = 356;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xffe955";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 3.500000;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(sizeincrease) = 5;
+       MY(size_min) = 16;
+       MY(size_max) = 26;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '156.0 156.0 156.0';
+}
+// fire effect which expands then slows
+SUB(hagar_explode) {
+       MY(airfriction) = 12;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 456;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 12;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(sizeincrease) = 15;
+       MY(size_min) = 20;
+       MY(size_max) = 26;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '286.0 286.0 286.0';
+}
+// smoke
+SUB(hagar_explode) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 500;
+       MY(alpha_fade) = 600;
+       MY(bounce) = 2;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 7;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 20;
+       MY(size_max) = 40;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '244.0 244.0 244.0';
+}
+// underwater bubbles
+SUB(hagar_explode) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 16;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// bouncing sparks
+SUB(hagar_explode) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 644;
+       MY(alpha_max) = 956;
+       MY(alpha_fade) = 684;
+       MY(bounce) = 1.600000;
+       MY(color_min) = "0xffa35b";
+       MY(color_max) = "0xfff2be";
+       MY(count) = 4;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 1;
+       MY(size_max) = 0.100000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '224.0 224.0 224.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+DEF(rocketlauncher_muzzleflash);
+SUB(rocketlauncher_muzzleflash) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 10;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(sizeincrease) = 20;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '40.0 40.0 40.0';
+       MY(velocitymultiplier) = -0.130000;
+}
+SUB(rocketlauncher_muzzleflash) {
+       MY(airfriction) = 9;
+       MY(alpha_min) = 10;
+       MY(alpha_max) = 25;
+       MY(alpha_fade) = 20;
+       MY(color_min) = "0xFFFDD9";
+       MY(color_max) = "0xFFFDD9";
+       MY(count) = 6;
+       MY(originjitter) = '3.0 3.0 3.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(tex_min) = 35;
+       MY(tex_max) = 36;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = 0.300000;
+}
+
+// rocket trail
+DEF(TR_ROCKET);
+// smoke
+SUB(TR_ROCKET) {
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 300;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x666666";
+       MY(lightcolor) = '6.0 3.0 1.0';
+       MY(lightradius) = 150;
+       MY(notunderwater) = true;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = 11;
+       MY(size_min) = 3;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 10;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '3.0 3.0 3.0';
+       MY(velocitymultiplier) = -0.020000;
+}
+// fire
+SUB(TR_ROCKET) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 144;
+       MY(alpha_fade) = 588;
+       MY(color_min) = "0xffdf72";
+       MY(color_max) = "0x811200";
+       MY(sizeincrease) = -30;
+       MY(size_min) = 7;
+       MY(size_max) = 7;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 4;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = -1.500000;
+}
+// bubbles
+SUB(TR_ROCKET) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 16;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+       MY(velocitymultiplier) = -0.310000;
+}
+// sparks
+SUB(TR_ROCKET) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 444;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 1866;
+       MY(bounce) = 1;
+       MY(color_min) = "0xFFFDD9";
+       MY(color_max) = "0xFFFDD9";
+       MY(notunderwater) = true;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 0.500000;
+       MY(size_max) = 0.500000;
+       MY(stretchfactor) = 0.300000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(trailspacing) = 20;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = -0.310000;
+}
+
+// rocket explosion (bigger than mortar and hagar)
+DEF(rocket_explode);
+SUB(rocket_explode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '8.0 4.0 1.0';
+       MY(lightradiusfade) = 750;
+       MY(lightradius) = 400;
+       MY(originjitter) = '23.0 23.0 23.0';
+       MY(size_min) = 72;
+       MY(size_max) = 72;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// fire effect
+SUB(rocket_explode) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 32;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(sizeincrease) = 45;
+       MY(size_min) = 33;
+       MY(size_max) = 44;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// fire effect 2
+SUB(rocket_explode) {
+       MY(airfriction) = 19;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 612;
+       MY(bounce) = 2.500000;
+       MY(color_min) = "0xea691b";
+       MY(color_max) = "0xeed05a";
+       MY(count) = 14;
+       MY(liquidfriction) = 19;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(sizeincrease) = 55;
+       MY(size_min) = 33;
+       MY(size_max) = 44;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '912.0 912.0 912.0';
+}
+// smoke
+SUB(rocket_explode) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 450;
+       MY(alpha_fade) = 456;
+       MY(bounce) = 2;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 32;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 44;
+       MY(size_min) = 20;
+       MY(size_max) = 40;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '444.0 444.0 444.0';
+}
+// underwater bubbles
+SUB(rocket_explode) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 32;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// underwatershockwave
+SUB(rocket_explode) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 300;
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1900;
+       MY(size_min) = 30;
+       MY(size_max) = 30;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(underwater) = true;
+       MY(velocitymultiplier) = 0.300000;
+}
+// bouncing sparks
+SUB(rocket_explode) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 644;
+       MY(alpha_max) = 956;
+       MY(alpha_fade) = 484;
+       MY(bounce) = 1.600000;
+       MY(color_min) = "0xffa35b";
+       MY(color_max) = "0xfff2be";
+       MY(count) = 16;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 1;
+       MY(size_max) = 0.100000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '424.0 424.0 624.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+// debris
+SUB(rocket_explode) {
+       MY(airfriction) = 0.500000;
+       MY(alpha_min) = 644;
+       MY(alpha_max) = 956;
+       MY(alpha_fade) = 684;
+       MY(bounce) = 1.600000;
+       MY(color_min) = "0x6a3d25";
+       MY(color_max) = "0xcac5b4";
+       MY(count) = 12;
+       MY(gravity) = 1.300000;
+       MY(notunderwater) = true;
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -1000;
+       MY(spin_max) = 1000;
+       MY(size_min) = 2;
+       MY(size_max) = 6;
+       MY(tex_min) = 66;
+       MY(tex_max) = 68;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '324.0 324.0 524.0';
+}
+
+DEF(grapple_muzzleflash);
+SUB(grapple_muzzleflash) {
+       MY(lightcolor) = '1.0 0.0 0.0';
+       MY(lightradiusfade) = 800;
+       MY(lightradius) = 160;
+}
+
+DEF(grapple_impact);
+SUB(grapple_impact) {
+       MY(lightcolor) = '1.0 0.0 0.0';
+       MY(lightradiusfade) = 800;
+       MY(lightradius) = 160;
+}
+
+DEF(nex242_misc_laser_beam);
+SUB(nex242_misc_laser_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0xff0000";
+       MY(color_max) = "0xff0000";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_beam_end);
+SUB(nex242_misc_laser_beam_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_beam_fast);
+SUB(nex242_misc_laser_beam_fast) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 640;
+       MY(color_min) = "0xff0000";
+       MY(color_max) = "0xff0000";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 0.100000;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_beam_fast_end);
+SUB(nex242_misc_laser_beam_fast_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_green_beam);
+SUB(nex242_misc_laser_green_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x00ff00";
+       MY(color_max) = "0x00ff00";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_green_beam_end);
+SUB(nex242_misc_laser_green_beam_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_blue_beam);
+SUB(nex242_misc_laser_blue_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x0000ff";
+       MY(color_max) = "0x0000ff";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_blue_beam_end);
+SUB(nex242_misc_laser_blue_beam_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_yellow_beam);
+SUB(nex242_misc_laser_yellow_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0xffff00";
+       MY(color_max) = "0xffff00";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_yellow_beam_end);
+SUB(nex242_misc_laser_yellow_beam_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_cyan_beam);
+SUB(nex242_misc_laser_cyan_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x00ffff";
+       MY(color_max) = "0x00ffff";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_cyan_beam_end);
+SUB(nex242_misc_laser_cyan_beam_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_magenta_beam);
+SUB(nex242_misc_laser_magenta_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0xff00ff";
+       MY(color_max) = "0xff00ff";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_magenta_beam_end);
+SUB(nex242_misc_laser_magenta_beam_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_white_beam);
+SUB(nex242_misc_laser_white_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0xffffff";
+       MY(color_max) = "0xffffff";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_white_beam_end);
+SUB(nex242_misc_laser_white_beam_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_black_beam);
+SUB(nex242_misc_laser_black_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x000000";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_black_beam_end);
+SUB(nex242_misc_laser_black_beam_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(nex242_misc_laser_orange_beam);
+SUB(nex242_misc_laser_orange_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0xff6600";
+       MY(color_max) = "0xff6600";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 200;
+       MY(tex_max) = 200;
+       MY(type) = "beam";
+}
+
+DEF(nex242_misc_laser_orange_beam_end);
+SUB(nex242_misc_laser_orange_beam_end) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = -1;
+       MY(color_min) = "0x8f4333";
+       MY(color_max) = "0xfff31b";
+       MY(count) = 0.500000;
+       MY(gravity) = 1;
+       MY(size_min) = 0.400000;
+       MY(size_max) = 0.400000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 100;
+}
+
+// bigger crylink impact effect
+DEF(crylink_impactbig);
+// decal
+SUB(crylink_impactbig) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '12.0 12.0 12.0';
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "decal";
+}
+// purple flare effect
+SUB(crylink_impactbig) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x504060";
+       MY(color_max) = "0x504060";
+       MY(countabsolute) = 1;
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 39;
+       MY(tex_max) = 39;
+       MY(type) = "static";
+}
+// purple sparks
+SUB(crylink_impactbig) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(bounce) = 2;
+       MY(color_min) = "0xA040C0";
+       MY(color_max) = "0xA040C0";
+       MY(count) = 40;
+       MY(size_min) = 6;
+       MY(size_max) = 6;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// purple splash
+SUB(crylink_impactbig) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0xE070FF";
+       MY(color_max) = "0xE070FF";
+       MY(count) = 1.500000;
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+}
+// purple splash
+SUB(crylink_impactbig) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xE070FF";
+       MY(color_max) = "0xE070FF";
+       MY(count) = 3;
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(type) = "static";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+#include "effectinfo_gentle.inc"
+
+DEF(laser_deadly);
+// decal
+SUB(laser_deadly) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '6.0 6.0 6.0';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 56;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// dust/smoke drifting away from the impact
+SUB(laser_deadly) {
+       MY(airfriction) = 7;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0xFFFFFF";
+       MY(color_max) = "0xFFFFFF";
+       MY(count) = 0.025000;
+       MY(liquidfriction) = 16;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = 2;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '15.0 15.0 15.0';
+       MY(velocitymultiplier) = 20;
+}
+// sparks
+SUB(laser_deadly) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 768;
+       MY(bounce) = 1;
+       MY(color_min) = "0xFDFFD9";
+       MY(color_max) = "0xFDFFD9";
+       MY(count) = 0.025000;
+       MY(gravity) = 1;
+       MY(notunderwater) = true;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 0.600000;
+       MY(size_max) = 0.600000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = 100;
+}
+
+DEF(torch_small);
+// fire
+SUB(torch_small) {
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 8;
+       MY(gravity) = -0.500000;
+       MY(originjitter) = '5.0 5.0 5.0';
+       MY(sizeincrease) = -1;
+       MY(size_min) = 1;
+       MY(size_max) = 11;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '1.0 1.0 50.0';
+}
+// smoke
+SUB(torch_small) {
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 4;
+       MY(gravity) = -0.300000;
+       MY(originjitter) = '3.0 3.0 3.0';
+       MY(sizeincrease) = 5;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+DEF(fountain01);
+SUB(fountain01) {
+       MY(alpha_max) = 100;
+       MY(alpha_fade) = 100;
+       MY(bounce) = 1;
+       MY(color_min) = "0x7cbaff";
+       MY(color_max) = "0xcfd1ff";
+       MY(count) = 16;
+       MY(gravity) = 0.600000;
+       MY(originjitter) = '5.0 5.0 5.0';
+       MY(sizeincrease) = 20;
+       MY(size_min) = 10;
+       MY(size_max) = 15;
+       MY(tex_max) = 8;
+       MY(type) = "snow";
+       MY(velocityjitter) = '81.0 81.0 150.0';
+       MY(velocitymultiplier) = 2;
+}
+
+DEF(hookbomb_explode);
+// decal
+SUB(hookbomb_explode) {
+       MY(airfriction) = 10;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x807aff";
+       MY(color_max) = "0x4463d5";
+       MY(count) = 25;
+       MY(originjitter) = '10.0 10.0 10.0';
+       MY(sizeincrease) = -160;
+       MY(size_min) = 150;
+       MY(size_max) = 200;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "static";
+       MY(velocityjitter) = '550.0 550.0 550.0';
+}
+// decal in the air
+SUB(hookbomb_explode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 265;
+       MY(alpha_fade) = 100;
+       MY(color_min) = "0x807aff";
+       MY(color_max) = "0x4463d5";
+       MY(countabsolute) = 3;
+       MY(originoffset) = '0.0 0.0 6.0';
+       MY(sizeincrease) = -60;
+       MY(size_min) = 160;
+       MY(size_max) = 200;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "static";
+}
+// decal on the ground
+SUB(hookbomb_explode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '6.0 6.0 6.0';
+       MY(size_min) = 80;
+       MY(size_max) = 100;
+       MY(tex_min) = 39;
+       MY(tex_max) = 39;
+       MY(type) = "decal";
+}
+// some sparks
+SUB(hookbomb_explode) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 456;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x807aff";
+       MY(color_max) = "0x4463d5";
+       MY(count) = 30;
+       MY(gravity) = 1;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = -60;
+       MY(size_min) = 20;
+       MY(size_max) = 30;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "spark";
+       MY(velocityjitter) = '1900.0 1900.0 1300.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(EF_MGTURRETTRAIL);
+// smoke
+SUB(EF_MGTURRETTRAIL) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 196;
+       MY(alpha_fade) = 768;
+       MY(color_min) = "0xd0d0a0";
+       MY(color_max) = "0xffffff";
+       MY(gravity) = -0.010000;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = -8;
+       MY(size_min) = 5;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 10;
+       MY(type) = "smoke";
+}
+// bubbles
+SUB(EF_MGTURRETTRAIL) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 32;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+DEF(fire_big);
+// fire
+SUB(fire_big) {
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 356;
+       MY(alpha_fade) = 512;
+       MY(bounce) = 2;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 26;
+       MY(gravity) = -0.500000;
+       MY(originjitter) = '33.0 33.0 33.0';
+       MY(sizeincrease) = -3;
+       MY(size_min) = 11;
+       MY(size_max) = 31;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(fire_big) {
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 2;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 11;
+       MY(gravity) = -0.300000;
+       MY(originjitter) = '44.0 44.0 44.0';
+       MY(sizeincrease) = 11;
+       MY(size_min) = 22;
+       MY(size_max) = 33;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+#define flare(name, colormin, colormax) \
+       DEF(name##_flare); \
+       SUB(name##_flare) /* smoke */ { \
+               MY(alpha_min) = 200; \
+               MY(alpha_max) = 256; \
+               MY(alpha_fade) = 160; \
+               MY(bounce) = 1; \
+               MY(color_min) = colormin; \
+               MY(color_max) = colormax; \
+               MY(count) = 10.500000; \
+               MY(gravity) = -0.240000; \
+               MY(originjitter) = '2.0 2.0 0.0'; \
+               MY(sizeincrease) = 11; \
+               MY(size_min) = 1; \
+               MY(size_max) = 11; \
+               MY(tex_max) = 8; \
+               MY(type) = "alphastatic"; \
+               MY(velocityjitter) = '15.0 15.0 30.0'; \
+       }
+
+flare(red,     "0xff0000", "0xdc7171")
+flare(blue, "0x0000ff", "0x7194dc")
+#undef flare
+
+DEF(smoke_ring);
+// smoke
+SUB(smoke_ring) {
+       MY(airfriction) = 3;
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 156;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.100000;
+       MY(color_min) = "0x111111";
+       MY(color_max) = "0x979797";
+       MY(count) = 45;
+       MY(gravity) = 0.100000;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 21;
+       MY(size_min) = 1;
+       MY(size_max) = 11;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '190.0 190.0 50.0';
+}
+
+DEF(smoke_large);
+// smoke
+SUB(smoke_large) {
+       MY(airfriction) = 7;
+       MY(alpha_min) = 140;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 190;
+       MY(bounce) = 1.100000;
+       MY(color_min) = "0x9e895f";
+       MY(color_max) = "0xffd39b";
+       MY(count) = 25;
+       MY(gravity) = -0.150000;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 21;
+       MY(size_min) = 11;
+       MY(size_max) = 21;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '390.0 390.0 390.0';
+}
+
+DEF(sparks);
+SUB(sparks) {
+       MY(airfriction) = 3;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xFFFDD9";
+       MY(color_max) = "0xFFFDD9";
+       MY(count) = 15;
+       MY(gravity) = 1;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 1;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '300.0 300.0 200.0';
+       MY(velocitymultiplier) = 1.500000;
+}
+
+DEF(electricity_sparks);
+SUB(electricity_sparks) {
+       MY(airfriction) = 3;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 556;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x807aff";
+       MY(color_max) = "0x4463d5";
+       MY(count) = 35;
+       MY(gravity) = 1;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 1;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '300.0 300.0 300.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(steam);
+SUB(steam) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 140;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 190;
+       MY(bounce) = 1.100000;
+       MY(color_min) = "0xfffbdf";
+       MY(color_max) = "0xffffff";
+       MY(count) = 1;
+       MY(gravity) = -0.250000;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 7;
+       MY(size_min) = 1;
+       MY(size_max) = 3;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '19.0 19.0 19.0';
+       MY(velocitymultiplier) = 14;
+}
+
+DEF(smoking);
+SUB(smoking) {
+       MY(airfriction) = -1;
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 100;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x292929";
+       MY(color_max) = "0x000000";
+       MY(count) = 10;
+       MY(gravity) = -0.100000;
+       MY(originjitter) = '10.0 10.0 10.0';
+       MY(sizeincrease) = 5;
+       MY(size_min) = 10;
+       MY(size_max) = 40;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '5.0 5.0 20.0';
+}
+
+// golden dust (create it once per second to cover large area in small yellow particles)
+DEF(goldendust);
+SUB(goldendust) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 70;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xff9600";
+       MY(color_max) = "0xffefb8";
+       MY(count) = 25;
+       MY(originjitter) = '500.0 500.0 500.0';
+       MY(sizeincrease) = -0.300000;
+       MY(size_min) = 2;
+       MY(size_max) = 3;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "snow";
+       MY(velocityjitter) = '0.1 0.1 0.1';
+}
+
+DEF(healing_fx);
+SUB(healing_fx) {
+       MY(airfriction) = -0.500000;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 170;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xff0000";
+       MY(color_max) = "0xff0000";
+       MY(count) = 25;
+       MY(gravity) = -0.100000;
+       MY(originjitter) = '5.0 5.0 100.0';
+       MY(sizeincrease) = -0.050000;
+       MY(size_min) = 1;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '50.0 50.0 0.0';
+}
+
+DEF(armorrepair_fx);
+SUB(armorrepair_fx) {
+       MY(airfriction) = -0.500000;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 170;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x00ff00";
+       MY(color_max) = "0x00ff00";
+       MY(count) = 25;
+       MY(gravity) = -0.100000;
+       MY(originjitter) = '5.0 5.0 50.0';
+       MY(sizeincrease) = -0.050000;
+       MY(size_min) = 1;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '50.0 50.0 0.0';
+}
+
+DEF(ammoregen_fx);
+SUB(ammoregen_fx) {
+       MY(airfriction) = -0.500000;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 170;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x0000ff";
+       MY(color_max) = "0x0000ff";
+       MY(count) = 25;
+       MY(gravity) = -0.100000;
+       MY(originjitter) = '5.0 5.0 50.0';
+       MY(sizeincrease) = -0.050000;
+       MY(size_min) = 1;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '50.0 50.0 0.0';
+}
+
+// red-yellow flame like fx
+DEF(rage);
+SUB(rage) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 190;
+       MY(color_min) = "0xff0000";
+       MY(color_max) = "0xff7800";
+       MY(count) = 2.500000;
+       MY(gravity) = -0.060000;
+       MY(originjitter) = '5.0 5.0 5.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 1;
+       MY(size_max) = 3;
+       MY(tex_min) = 35;
+       MY(tex_max) = 36;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '25.0 25.0 25.0';
+}
+
+// pieces of glass or ice falling on the floor
+DEF(iceorglass);
+SUB(iceorglass) {
+       MY(airfriction) = 3;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(bounce) = 2;
+       MY(color_min) = "0xffffff";
+       MY(color_max) = "0xb2d3e6";
+       MY(count) = 15;
+       MY(gravity) = 1.300000;
+       MY(originjitter) = '30.0 30.0 30.0';
+       MY(size_min) = 3;
+       MY(size_max) = 7;
+       MY(tex_min) = 44;
+       MY(tex_max) = 44;
+       MY(time_min) = 1;
+       MY(time_max) = 3;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+}
+
+// cover small area in poison gas, spawn it once per second
+DEF(poisonfield);
+SUB(poisonfield) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 50;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x00ff00";
+       MY(color_max) = "0x7db843";
+       MY(count) = 15;
+       MY(gravity) = -0.010000;
+       MY(originjitter) = '333.0 333.0 50.0';
+       MY(sizeincrease) = 30;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '5.0 5.0 5.0';
+}
+
+// cover small area in icy mist, spawn it once per second
+DEF(icefield);
+SUB(icefield) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 50;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x008aff";
+       MY(color_max) = "0x75e7ff";
+       MY(count) = 10;
+       MY(gravity) = -0.010000;
+       MY(originjitter) = '333.0 333.0 0.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '5.0 5.0 30.0';
+}
+SUB(icefield) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 50;
+       MY(color_min) = "0x008aff";
+       MY(color_max) = "0x75e7ff";
+       MY(count) = 5;
+       MY(gravity) = -0.001000;
+       MY(originjitter) = '333.0 333.0 0.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+}
+
+// cover very small area in flames, spawn it 3 times per second (or more often to get better looking fire at cost of fps hit )
+DEF(firefield);
+// flames that go up
+SUB(firefield) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 100;
+       MY(gravity) = -0.060000;
+       MY(originjitter) = '180.0 180.0 0.0';
+       MY(sizeincrease) = 20;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '5.0 5.0 30.0';
+}
+// flames that stay on the ground
+SUB(firefield) {
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 50;
+       MY(originjitter) = '180.0 180.0 0.0';
+       MY(sizeincrease) = 40;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+}
+// smoke
+SUB(firefield) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 70;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 20;
+       MY(gravity) = -0.020000;
+       MY(originjitter) = '180.0 180.0 0.0';
+       MY(sizeincrease) = 7;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// flamethrower, spawn it as fast as you can  20 times per second or more, it needs direction
+DEF(flamethrower);
+// fast fire
+SUB(flamethrower) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 250;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 3;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '40.0 40.0 11.0';
+       MY(velocitymultiplier) = 30;
+}
+// slow fire
+SUB(flamethrower) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 2.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '40.0 40.0 40.0';
+       MY(velocitymultiplier) = 20;
+}
+// very slow and small fire
+SUB(flamethrower) {
+       MY(airfriction) = 0.300000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 1.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 10;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '30.0 30.0 30.0';
+       MY(velocitymultiplier) = 10;
+}
+// decreasing fire
+SUB(flamethrower) {
+       MY(airfriction) = 0.300000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 2;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = -10;
+       MY(size_min) = 20;
+       MY(size_max) = 30;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '10.0 10.0 10.0';
+       MY(velocitymultiplier) = 15;
+}
+// smoke
+SUB(flamethrower) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 90;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 0.500000;
+       MY(originjitter) = '10.0 10.0 10.0';
+       MY(sizeincrease) = 7;
+       MY(size_min) = 5;
+       MY(size_max) = 15;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocitymultiplier) = 20;
+       MY(velocityoffset) = '0.0 0.0 10.0';
+}
+
+// port-o-launch trail
+DEF(TR_WIZSPIKE);
+// glowing vapor trail
+SUB(TR_WIZSPIKE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 968;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x404040";
+       MY(lightcolor) = '1.5 3.0 6.0';
+       MY(lightradius) = 90;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 4;
+       MY(type) = "static";
+       MY(velocitymultiplier) = -0.100000;
+}
+// bright sparks
+SUB(TR_WIZSPIKE) {
+       MY(airfriction) = 12;
+       MY(alpha_min) = 444;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 1866;
+       MY(bounce) = 1;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x404040";
+       MY(count) = 1.500000;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = -20;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(tex_min) = 42;
+       MY(tex_max) = 42;
+       MY(trailspacing) = 12;
+       MY(type) = "snow";
+       MY(velocityjitter) = '50.0 50.0 50.0';
+       MY(velocityoffset) = '0.0 0.0 15.0';
+}
+
+// TAG trail
+DEF(TR_VORESPIKE);
+// glowing vapor trail
+SUB(TR_VORESPIKE) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 968;
+       MY(color_min) = "0x804000";
+       MY(color_max) = "0x804000";
+       MY(lightcolor) = '1.5 3.0 6.0';
+       MY(lightradius) = 90;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 4;
+       MY(type) = "static";
+       MY(velocitymultiplier) = -0.100000;
+}
+// bright sparks
+SUB(TR_VORESPIKE) {
+       MY(airfriction) = 12;
+       MY(alpha_min) = 444;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 1866;
+       MY(bounce) = 1;
+       MY(color_min) = "0xff8000";
+       MY(color_max) = "0xff8000";
+       MY(count) = 1.500000;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = -20;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(tex_min) = 42;
+       MY(tex_max) = 42;
+       MY(trailspacing) = 12;
+       MY(type) = "snow";
+       MY(velocityjitter) = '50.0 50.0 50.0';
+       MY(velocityoffset) = '0.0 0.0 15.0';
+}
+
+DEF(flac_explode);
+SUB(flac_explode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '8.0 4.0 1.0';
+       MY(lightradiusfade) = 400;
+       MY(lightradius) = 150;
+       MY(originjitter) = '40.0 40.0 40.0';
+       MY(size_min) = 18;
+       MY(size_max) = 28;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// fire effect which make bright dot inside
+SUB(flac_explode) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 456;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xffe955";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 3;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(sizeincrease) = 5;
+       MY(size_min) = 6;
+       MY(size_max) = 16;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '156.0 156.0 156.0';
+}
+// fire effect which expands then slows
+SUB(flac_explode) {
+       MY(airfriction) = 12;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 456;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 6;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(sizeincrease) = 15;
+       MY(size_min) = 10;
+       MY(size_max) = 16;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+// smoke
+SUB(flac_explode) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 500;
+       MY(alpha_max) = 600;
+       MY(alpha_fade) = 556;
+       MY(bounce) = 2;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 5;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 10;
+       MY(size_max) = 20;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '244.0 244.0 244.0';
+}
+// underwater bubbles
+SUB(flac_explode) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 8;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '96.0 96.0 96.0';
+}
+// bouncing sparks
+SUB(flac_explode) {
+       MY(airfriction) = 0.200000;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 384;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x903010";
+       MY(color_max) = "0xFFD030";
+       MY(count) = 4;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+// bullet trail (somewhat like a tracer)
+DEF(tr_bullet);
+SUB(tr_bullet) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 2560;
+       MY(color_min) = "0xff8960";
+       MY(color_max) = "0xff8533";
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(stretchfactor) = 0.200000;
+       MY(tex_min) = 70;
+       MY(tex_max) = 70;
+       MY(trailspacing) = 750;
+       MY(type) = "spark";
+       MY(velocitymultiplier) = 3;
+}
+
+// smoke emitter for small pipes
+DEF(smoking_smallemitter);
+SUB(smoking_smallemitter) {
+       MY(airfriction) = -1;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 100;
+       MY(color_min) = "0x292929";
+       MY(color_max) = "0x000000";
+       MY(count) = 10;
+       MY(gravity) = -0.100000;
+       MY(originjitter) = '10.0 10.0 10.0';
+       MY(sizeincrease) = 20;
+       MY(size_min) = 6;
+       MY(size_max) = 15;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '5.0 5.0 20.0';
+}
+
+// crylink trail
+DEF(TR_CRYLINKPLASMA);
+// plasma smoke
+SUB(TR_CRYLINKPLASMA) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x5522aa";
+       MY(color_max) = "0x6622ff";
+       MY(sizeincrease) = 8;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(tex_min) = 32;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 128;
+       MY(type) = "static";
+       MY(velocityjitter) = '8.0 8.0 8.0';
+       MY(velocitymultiplier) = -0.010000;
+}
+// crylink main trail
+SUB(TR_CRYLINKPLASMA) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 2600;
+       MY(color_min) = "0x5522aa";
+       MY(color_max) = "0x6622ff";
+       MY(sizeincrease) = 15;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 3;
+       MY(tex_max) = 3;
+       MY(trailspacing) = 16;
+       MY(type) = "static";
+       MY(velocityjitter) = '2.0 2.0 2.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+
+DEF(cherryblossom);
+SUB(cherryblossom) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 32;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xb123ff";
+       MY(color_max) = "0xb183ff";
+       MY(count) = 1.500000;
+       MY(gravity) = 0.050000;
+       MY(liquidfriction) = 1;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 1.500000;
+       MY(size_max) = 2;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 0.0';
+}
+
+DEF(alien_blood);
+SUB(alien_blood) {
+       MY(airfriction) = 0.400000;
+       MY(alpha_min) = 1560;
+       MY(alpha_max) = 2560;
+       MY(alpha_fade) = 7000;
+       MY(blend) = "invmod";
+       MY(bounce) = -1;
+       MY(color_min) = "0xDC9BCD";
+       MY(color_max) = "0xDC9BCD";
+       MY(count) = 0.400000;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 5;
+       MY(size_max) = 11;
+       MY(staincolor_min) = "0xDC9BCD";
+       MY(staincolor_max) = "0xDC9BCD";
+       MY(stainsize_min) = 1;
+       MY(stainsize_max) = 2;
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(stretchfactor) = 25;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "spark";
+       MY(velocityjitter) = '99.0 99.0 55.0';
+}
+// blood mist
+SUB(alien_blood) {
+       MY(alpha_min) = 3000;
+       MY(alpha_max) = 5560;
+       MY(alpha_fade) = 12000;
+       MY(blend) = "invmod";
+       MY(color_min) = "0xDC9BCD";
+       MY(color_max) = "0xDC9BCD";
+       MY(countabsolute) = 1;
+       MY(originjitter) = '11.0 11.0 11.0';
+       MY(sizeincrease) = 20;
+       MY(size_min) = 25;
+       MY(size_max) = 30;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "smoke";
+}
+
+DEF(robot_blood);
+SUB(robot_blood) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xff3000";
+       MY(color_max) = "0xff7373";
+       MY(count) = 0.167000;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(tex_min) = 70;
+       MY(tex_max) = 70;
+       MY(type) = "spark";
+       MY(velocityjitter) = '264.0 264.0 264.0';
+       MY(velocityoffset) = '0.0 0.0 100.0';
+}
+// shockwave
+SUB(robot_blood) {
+       MY(alpha_max) = 90;
+       MY(alpha_fade) = 1000;
+       MY(color_min) = "0xff8400";
+       MY(color_max) = "0xffbb72";
+       MY(countabsolute) = 1;
+       MY(originjitter) = '11.0 11.0 11.0';
+       MY(sizeincrease) = 800;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(tex_min) = 74;
+       MY(tex_max) = 74;
+       MY(type) = "smoke";
+}
+// electo sparks
+SUB(robot_blood) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 5120;
+       MY(color_min) = "0xff3000";
+       MY(color_max) = "0xff8585";
+       MY(count) = 0.100000;
+       MY(originjitter) = '41.0 41.0 21.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = 4000;
+       MY(spin_max) = -4000;
+       MY(size_min) = 20;
+       MY(size_max) = 40;
+       MY(tex_min) = 71;
+       MY(tex_max) = 73;
+       MY(type) = "smoke";
+}
+
+DEF(alien_TR_BLOOD);
+SUB(alien_TR_BLOOD) {
+       MY(airfriction) = -2;
+       MY(alpha_min) = 384;
+       MY(alpha_max) = 984;
+       MY(alpha_fade) = 1492;
+       MY(blend) = "invmod";
+       MY(bounce) = -1;
+       MY(color_min) = "0xC080B0";
+       MY(color_max) = "0xC080B0";
+       MY(gravity) = 0.400000;
+       MY(liquidfriction) = 1;
+       MY(sizeincrease) = -5;
+       MY(size_min) = 4;
+       MY(size_max) = 19;
+       MY(staincolor_min) = "0xC080B0";
+       MY(staincolor_max) = "0xC080B0";
+       MY(stainsize_min) = 1;
+       MY(stainsize_max) = 2;
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(stretchfactor) = 7;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 20;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = -0.100000;
+}
+
+// splash around gib
+SUB(TR_BLOOD) {
+       MY(alpha_min) = 684;
+       MY(alpha_max) = 684;
+       MY(alpha_fade) = 7492;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFF";
+       MY(sizeincrease) = 500;
+       MY(size_min) = 4;
+       MY(size_max) = 6;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 42;
+       MY(type) = "blood";
+}
+
+DEF(robot_TR_BLOOD);
+SUB(robot_TR_BLOOD) {
+       MY(airfriction) = -2;
+       MY(alpha_min) = 384;
+       MY(alpha_max) = 984;
+       MY(alpha_fade) = 1892;
+       MY(blend) = "invmod";
+       MY(bounce) = -1;
+       MY(color_min) = "0xC0D890";
+       MY(color_max) = "0xC0D890";
+       MY(gravity) = 0.400000;
+       MY(liquidfriction) = 1;
+       MY(sizeincrease) = -6;
+       MY(size_min) = 4;
+       MY(size_max) = 13;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(stainsize_min) = 1;
+       MY(stainsize_max) = 3;
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(stretchfactor) = 6;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 16;
+       MY(type) = "spark";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = -0.300000;
+}
+// fire
+SUB(robot_TR_BLOOD) {
+       MY(airfriction) = 4;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 900;
+       MY(color_min) = "0x902010";
+       MY(color_max) = "0xff3600";
+       MY(gravity) = -1;
+       MY(liquidfriction) = 4;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 10;
+       MY(size_min) = 5;
+       MY(size_max) = 20;
+       MY(stretchfactor) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 16;
+       MY(type) = "spark";
+       MY(velocityjitter) = '44.0 44.0 44.0';
+}
+// arcs
+SUB(robot_TR_BLOOD) {
+       MY(alpha_min) = 1128;
+       MY(alpha_max) = 1256;
+       MY(alpha_fade) = 44900;
+       MY(color_min) = "0xff3000";
+       MY(color_max) = "0xff8585";
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = 4000;
+       MY(spin_max) = -4000;
+       MY(size_min) = 25;
+       MY(size_max) = 30;
+       MY(tex_min) = 71;
+       MY(tex_max) = 73;
+       MY(trailspacing) = 128;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '44.0 44.0 44.0';
+}
+
+DEF(alien_TR_SLIGHTBLOOD);
+SUB(alien_TR_SLIGHTBLOOD) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 384;
+       MY(alpha_max) = 384;
+       MY(alpha_fade) = 192;
+       MY(bounce) = -1;
+       MY(color_min) = "0xC080B0";
+       MY(color_max) = "0xC080B0";
+       MY(liquidfriction) = 4;
+       MY(size_min) = 80;
+       MY(size_max) = 80;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 64;
+       MY(type) = "blood";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(robot_TR_SLIGHTBLOOD);
+SUB(robot_TR_SLIGHTBLOOD) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 384;
+       MY(alpha_max) = 384;
+       MY(alpha_fade) = 192;
+       MY(bounce) = -1;
+       MY(color_min) = "0xC0D890";
+       MY(color_max) = "0xC0D890";
+       MY(liquidfriction) = 4;
+       MY(size_min) = 8;
+       MY(size_max) = 8;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(trailspacing) = 64;
+       MY(type) = "blood";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(item_pickup);
+// flare particle and light
+SUB(item_pickup) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x63F2EA";
+       MY(color_max) = "0xB0C5C4";
+       MY(countabsolute) = 1;
+       MY(size_min) = 8;
+       MY(size_max) = 16;
+       MY(type) = "static";
+}
+// cloud of particles which expand rapidly and then slow to form a ball
+SUB(item_pickup) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1280;
+       MY(color_min) = "0x63F2EA";
+       MY(color_max) = "0xB0C5C4";
+       MY(count) = 32;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+DEF(bloodshower);
+SUB(bloodshower) {
+       MY(alpha_min) = 156;
+       MY(alpha_max) = 656;
+       MY(alpha_fade) = 1664;
+       MY(blend) = "invmod";
+       MY(bounce) = -1;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFFF";
+       MY(count) = 125;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 8;
+       MY(size_max) = 28;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(stainsize_min) = 1;
+       MY(stainsize_max) = 2;
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(stretchfactor) = 3;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "spark";
+       MY(velocityjitter) = '764.0 764.0 764.0';
+}
+// center blood
+SUB(bloodshower) {
+       MY(alpha_min) = 156;
+       MY(alpha_max) = 656;
+       MY(alpha_fade) = 1664;
+       MY(blend) = "invmod";
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFFF";
+       MY(countabsolute) = 0.100000;
+       MY(originjitter) = '50.0 50.0 50.0';
+       MY(sizeincrease) = 300;
+       MY(size_min) = 1;
+       MY(size_max) = 28;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "smoke";
+}
+
+DEF(alien_bloodshower);
+SUB(alien_bloodshower) {
+       MY(alpha_min) = 156;
+       MY(alpha_max) = 656;
+       MY(alpha_fade) = 1664;
+       MY(blend) = "invmod";
+       MY(bounce) = -1;
+       MY(color_min) = "0xC080B0";
+       MY(color_max) = "0xC080B0";
+       MY(count) = 125;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 8;
+       MY(size_max) = 28;
+       MY(staincolor_min) = "0xC080B0";
+       MY(staincolor_max) = "0xC080B0";
+       MY(stainsize_min) = 1;
+       MY(stainsize_max) = 2;
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(stretchfactor) = 3;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "spark";
+       MY(velocityjitter) = '764.0 764.0 764.0';
+}
+// center blood
+SUB(bloodshower) {
+       MY(alpha_min) = 156;
+       MY(alpha_max) = 656;
+       MY(alpha_fade) = 1664;
+       MY(blend) = "invmod";
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFFF";
+       MY(countabsolute) = 0.100000;
+       MY(originjitter) = '50.0 50.0 50.0';
+       MY(sizeincrease) = 300;
+       MY(size_min) = 1;
+       MY(size_max) = 28;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "smoke";
+}
+
+DEF(robot_bloodshower);
+SUB(robot_bloodshower) {
+       MY(alpha_min) = 156;
+       MY(alpha_max) = 656;
+       MY(alpha_fade) = 1664;
+       MY(blend) = "invmod";
+       MY(bounce) = -1;
+       MY(color_min) = "0xC0D890";
+       MY(color_max) = "0xC0D890";
+       MY(count) = 100;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 8;
+       MY(size_max) = 28;
+       MY(staincolor_min) = "0xC0D890";
+       MY(staincolor_max) = "0xC0D890";
+       MY(stainsize_min) = 1;
+       MY(stainsize_max) = 2;
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(stretchfactor) = 3;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "spark";
+       MY(velocityjitter) = '764.0 764.0 764.0';
+}
+// arc
+SUB(robot_bloodshower) {
+       MY(alpha_min) = 1128;
+       MY(alpha_max) = 1256;
+       MY(alpha_fade) = 4200;
+       MY(color_min) = "0xff3000";
+       MY(color_max) = "0xff8585";
+       MY(count) = 2.500000;
+       MY(originjitter) = '150.0 150.0 150.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = 99;
+       MY(spin_max) = -99;
+       MY(size_min) = 25;
+       MY(size_max) = 40;
+       MY(tex_min) = 71;
+       MY(tex_max) = 73;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '44.0 44.0 44.0';
+}
+// shockwave
+SUB(robot_bloodshower) {
+       MY(alpha_min) = 11;
+       MY(alpha_max) = 125;
+       MY(alpha_fade) = 990;
+       MY(color_min) = "0xff3000";
+       MY(color_max) = "0xff8585";
+       MY(count) = 2.500000;
+       MY(sizeincrease) = 3000;
+       MY(size_min) = 5;
+       MY(size_max) = 50;
+       MY(tex_min) = 74;
+       MY(tex_max) = 74;
+       MY(type) = "smoke";
+}
+
+#define ground_quake(name, colormin, colormax) \
+       DEF(name##_ground_quake); \
+       SUB(name##_ground_quake) /* smoke */ { \
+               MY(airfriction) = 3; \
+               MY(alpha_min) = 100; \
+               MY(alpha_max) = 126; \
+               MY(alpha_fade) = 200; \
+               MY(bounce) = 1.100000; \
+               MY(color_min) = "0x111111"; \
+               MY(color_max) = "0xbbbbbb"; \
+               MY(count) = 90; \
+               MY(gravity) = 0.500000; \
+               MY(notunderwater) = true; \
+               MY(sizeincrease) = 100; \
+               MY(size_min) = 20; \
+               MY(size_max) = 50; \
+               MY(tex_max) = 8; \
+               MY(time_min) = 5; \
+               MY(time_max) = 10; \
+               MY(type) = "smoke"; \
+               MY(velocityjitter) = '190.0 190.0 50.0'; \
+       } \
+       SUB(name##_ground_quake) { \
+               MY(airfriction) = 4; \
+               MY(alpha_min) = 100; \
+               MY(alpha_max) = 126; \
+               MY(alpha_fade) = 200; \
+               MY(bounce) = 1.200000; \
+               MY(color_min) = "0x111111"; \
+               MY(color_max) = "0x979797"; \
+               MY(count) = 40; \
+               MY(gravity) = 0.200000; \
+               MY(notunderwater) = true; \
+               MY(sizeincrease) = 60; \
+               MY(size_min) = 10; \
+               MY(size_max) = 30; \
+               MY(tex_max) = 8; \
+               MY(time_min) = 10; \
+               MY(time_max) = 15; \
+               MY(type) = "smoke"; \
+               MY(velocityjitter) = '190.0 190.0 50.0'; \
+       } \
+       SUB(name##_ground_quake) { \
+               MY(alpha_min) = 200; \
+               MY(alpha_max) = 356; \
+               MY(alpha_fade) = 512; \
+               MY(bounce) = 6; \
+               MY(color_min) = colormin; \
+               MY(color_max) = colormax; \
+               MY(count) = 16; \
+               MY(gravity) = -0.500000; \
+               MY(originjitter) = '33.0 33.0 33.0'; \
+               MY(sizeincrease) = 5; \
+               MY(size_min) = 4; \
+               MY(size_max) = 20; \
+               MY(tex_min) = 48; \
+               MY(tex_max) = 55; \
+               MY(time_min) = 15; \
+               MY(time_max) = 25; \
+               MY(type) = "smoke"; \
+               MY(velocityjitter) = '22.0 22.0 50.0'; \
+       } \
+       SUB(name##_ground_quake) /* smoke */ { \
+               MY(alpha_min) = 200; \
+               MY(alpha_max) = 256; \
+               MY(alpha_fade) = 200; \
+               MY(bounce) = 2; \
+               MY(color_min) = "0x000000"; \
+               MY(color_max) = "0xffffff"; \
+               MY(count) = 11; \
+               MY(gravity) = -0.300000; \
+               MY(originjitter) = '44.0 44.0 44.0'; \
+               MY(sizeincrease) = 11; \
+               MY(size_min) = 22; \
+               MY(size_max) = 33; \
+               MY(tex_max) = 8; \
+               MY(time_min) = 25; \
+               MY(time_max) = 35; \
+               MY(type) = "alphastatic"; \
+               MY(velocityjitter) = '11.0 11.0 50.0'; \
+       } \
+       /**/
+
+ground_quake(red,      "0x9E6A64", "0x91302D")
+ground_quake(blue,     "0x64679E", "0x2D4C91")
+#undef ground_quake
+
+#include "effectinfo_gentle_morphed.inc"
+
+// Team / hit vaporizer effects
+#define TE_TEI_G3(name, colormin1, colormax1, colormin2, colormax2) \
+       DEF(TE_TEI_G3##name); \
+       SUB(TE_TEI_G3##name) { \
+               MY(alpha_min) = 128; \
+               MY(alpha_max) = 128; \
+               MY(alpha_fade) = 256; \
+               MY(color_min) = colormin1; \
+               MY(color_max) = colormax1; \
+               MY(countabsolute) = 1; \
+               MY(size_min) = 4; \
+               MY(size_max) = 4; \
+               MY(tex_min) = 200; \
+               MY(tex_max) = 200; \
+               MY(type) = "beam"; \
+       } \
+       SUB(TE_TEI_G3##name) { \
+               MY(airfriction) = -4; \
+               MY(alpha_min) = 256; \
+               MY(alpha_max) = 256; \
+               MY(alpha_fade) = 512; \
+               MY(color_min) = colormin2; \
+               MY(color_max) = colormax2; \
+               MY(sizeincrease) = 3; \
+               MY(size_min) = 0.300000; \
+               MY(size_max) = 0.300000; \
+               MY(tex_min) = 46; \
+               MY(tex_max) = 46; \
+               MY(trailspacing) = 8; \
+               MY(type) = "smoke"; \
+               MY(velocityjitter) = '3.0 3.0 3.0'; \
+       } \
+       DEF(TE_TEI_G3##name##_HIT); \
+       SUB(TE_TEI_G3##name##_HIT) { \
+               MY(alpha_min) = 128; \
+               MY(alpha_max) = 128; \
+               MY(alpha_fade) = 256; \
+               MY(color_min) = colormin1; \
+               MY(color_max) = colormax1; \
+               MY(countabsolute) = 1; \
+               MY(size_min) = 8; \
+               MY(size_max) = 8; \
+               MY(tex_min) = 200; \
+               MY(tex_max) = 200; \
+               MY(type) = "beam"; \
+       } \
+       SUB(TE_TEI_G3##name##_HIT) /* rings */ { \
+               MY(airfriction) = -4; \
+               MY(alpha_min) = 256; \
+               MY(alpha_max) = 256; \
+               MY(alpha_fade) = 512; \
+               MY(color_min) = "0xFFFFFF"; \
+               MY(color_max) = colormax1; \
+               MY(sizeincrease) = -2; \
+               MY(size_min) = 2; \
+               MY(size_max) = 2; \
+               MY(trailspacing) = 20; \
+               MY(type) = "smoke"; \
+               MY(velocityjitter) = '2.0 2.0 2.0'; \
+       } \
+       SUB(TE_TEI_G3##name##_HIT) { \
+               MY(airfriction) = -4; \
+               MY(alpha_min) = 256; \
+               MY(alpha_max) = 256; \
+               MY(alpha_fade) = 512; \
+               MY(color_min) = colormin1; \
+               MY(color_max) = colormax1; \
+               MY(sizeincrease) = -6; \
+               MY(size_min) = 10; \
+               MY(size_max) = 10; \
+               MY(trailspacing) = 40; \
+               MY(type) = "smoke"; \
+       } \
+       /**/
+TE_TEI_G3(RED, "0xFF0000", "0xFF0011", "0x200000", "0x400000")
+TE_TEI_G3(BLUE, "0x0000FF", "0x1100FF", "0x000020", "0x000040")
+TE_TEI_G3(YELLOW, "0xffff00", "0xffff11", "0x202000", "0x404000")
+TE_TEI_G3(PINK, "0xFF00FF", "0xFF11FF", "0x200020", "0x400040")
+#undef TE_TEI_G3
+
+#include "effectinfo_gentle_particlegibs.inc"
+
+#include "effectinfo_onslaught.inc"
+
+DEF(firemine);
+SUB(firemine) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 250;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 5;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 2;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '10.0 10.0 2.0';
+}
+// slowfire
+SUB(firemine) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 5;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 2;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '10.0 10.0 10.0';
+}
+// very slow and small fire
+SUB(firemine) {
+       MY(airfriction) = 0.300000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 2;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 4;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '8.0 8.0 8.0';
+}
+// decreasing fire
+SUB(firemine) {
+       MY(airfriction) = 0.300000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = -3;
+       MY(size_min) = 5;
+       MY(size_max) = 7;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 4;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '3.0 3.0 3.0';
+}
+// smoke
+SUB(firemine) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 90;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 0.500000;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityoffset) = '0.0 0.0 3.0';
+}
+// fastfire
+SUB(firemine) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1600;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(size_min) = 12;
+       MY(size_max) = 12;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 1;
+       MY(type) = "smoke";
+}
+// light only
+SUB(firemine) {
+       MY(lightcolor) = '2.7 2.7 0.6';
+       MY(lightradiusfade) = 50000;
+       MY(lightradius) = 50;
+       MY(trailspacing) = 16;
+}
+
+DEF(fireball);
+SUB(fireball) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 250;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 2;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '40.0 40.0 11.0';
+}
+// slow fire
+SUB(fireball) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 2;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '40.0 40.0 40.0';
+}
+// very slow and small fire
+SUB(fireball) {
+       MY(airfriction) = 0.300000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 10;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 4;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '30.0 30.0 30.0';
+}
+// decreasing fire
+SUB(fireball) {
+       MY(airfriction) = 0.300000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = -10;
+       MY(size_min) = 20;
+       MY(size_max) = 30;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 4;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '10.0 10.0 10.0';
+}
+// smoke
+SUB(fireball) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 90;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 0.500000;
+       MY(originjitter) = '10.0 10.0 10.0';
+       MY(sizeincrease) = 7;
+       MY(size_min) = 5;
+       MY(size_max) = 15;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityoffset) = '0.0 0.0 10.0';
+}
+// fast fire
+SUB(fireball) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1600;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 0.500000;
+       MY(size_min) = 48;
+       MY(size_max) = 48;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 1;
+       MY(type) = "smoke";
+}
+// light only
+SUB(fireball) {
+       MY(lightcolor) = '2.7 2.7 0.6';
+       MY(lightradiusfade) = 3000;
+       MY(lightradius) = 300;
+       MY(trailspacing) = 16;
+}
+
+DEF(fireball_laser);
+SUB(fireball_laser) {
+       MY(alpha_min) = 192;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 2560;
+       MY(color_min) = "0x800000";
+       MY(color_max) = "0xFF8020";
+       MY(count) = 10;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(stretchfactor) = 0.700000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '1.0 1.0 1.0';
+       MY(velocitymultiplier) = 10;
+}
+
+// rocket explosion (bigger than mortar and hagar)
+DEF(fireball_explode);
+// decal
+SUB(fireball_explode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '4.0 2.0 0.5';
+       MY(lightradiusfade) = 500;
+       MY(lightradius) = 500;
+       MY(originjitter) = '56.0 56.0 56.0';
+       MY(size_min) = 72;
+       MY(size_max) = 72;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// flare effect
+SUB(fireball_explode) {
+       MY(alpha_min) = 192;
+       MY(alpha_max) = 192;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x404040";
+       MY(countabsolute) = 1;
+       MY(size_min) = 72;
+       MY(size_max) = 72;
+       MY(tex_min) = 35;
+       MY(tex_max) = 37;
+       MY(type) = "static";
+}
+// fire effect
+SUB(fireball_explode) {
+       MY(airfriction) = 4;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x902010";
+       MY(color_max) = "0xFFD080";
+       MY(count) = 128;
+       MY(liquidfriction) = 4;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// underwater bubbles
+SUB(fireball_explode) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 32;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '16.0 16.0 16.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// bouncing sparks
+SUB(fireball_explode) {
+       MY(airfriction) = 0.200000;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 384;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x903010";
+       MY(color_max) = "0xFFD030";
+       MY(count) = 64;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(type) = "spark";
+       MY(velocityjitter) = '384.0 384.0 384.0';
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+DEF(fireball_muzzleflash);
+SUB(fireball_muzzleflash) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 2;
+       MY(lightcolor) = '2.0 1.5 0.2';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+SUB(fireball_muzzleflash) {
+       MY(airfriction) = 12;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xFFFDD9";
+       MY(color_max) = "0xFFFDD9";
+       MY(count) = 15;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '300.0 300.0 300.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(fireball_preattack_muzzleflash);
+SUB(fireball_preattack_muzzleflash) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 2;
+       MY(lightcolor) = '2.0 1.5 0.2';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+SUB(fireball_preattack_muzzleflash) {
+       MY(airfriction) = 12;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xFFFDD9";
+       MY(color_max) = "0xFFFDD9";
+       MY(count) = 15;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '300.0 300.0 300.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(fireball_bfgdamage);
+SUB(fireball_bfgdamage) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(count) = 2;
+       MY(lightcolor) = '2.0 1.5 0.2';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+SUB(fireball_bfgdamage) {
+       MY(airfriction) = 12;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xFFFDD9";
+       MY(color_max) = "0xFFFDD9";
+       MY(count) = 15;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '300.0 300.0 300.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+DEF(EF_FLAME);
+// fire
+SUB(EF_FLAME) {
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 356;
+       MY(alpha_fade) = 512;
+       MY(bounce) = 2;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 100;
+       MY(gravity) = -0.500000;
+       MY(originjitter) = '12.0 12.0 34.0';
+       MY(originoffset) = '0.0 0.0 10.0';
+       MY(sizeincrease) = -1;
+       MY(size_min) = 5;
+       MY(size_max) = 21;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(EF_FLAME) {
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 2;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 50;
+       MY(gravity) = -0.300000;
+       MY(originjitter) = '12.0 12.0 34.0';
+       MY(originoffset) = '0.0 0.0 10.0';
+       MY(sizeincrease) = 6;
+       MY(size_min) = 11;
+       MY(size_max) = 15;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 50.0';
+}
+SUB(EF_FLAME) {
+       MY(count) = 0.500000;
+       MY(lightcolor) = '0.9 0.9 0.2';
+       MY(lightradiusfade) = 10000;
+       MY(lightradius) = 200;
+}
+
+// rifle bullet trail (somewhat like a tracer)
+DEF(tr_rifle);
+SUB(tr_rifle) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 2560;
+       MY(color_min) = "0x800000";
+       MY(color_max) = "0xFF8020";
+       MY(size_min) = 1.500000;
+       MY(size_max) = 1.500000;
+       MY(stretchfactor) = 1;
+       MY(trailspacing) = 128;
+       MY(type) = "spark";
+       MY(velocitymultiplier) = 0.700000;
+}
+SUB(tr_rifle) {
+       MY(airfriction) = -4;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 0.400000;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '4.0 4.0 4.0';
+}
+SUB(tr_rifle) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 128;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 32;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+// rocket guiding start
+DEF(rocket_guide);
+// underwater bubbles
+SUB(rocket_guide) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 2;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(size_min) = 1.500000;
+       MY(size_max) = 1.500000;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '48.0 48.0 48.0';
+       MY(velocitymultiplier) = -0.100000;
+}
+// bouncing sparks
+SUB(rocket_guide) {
+       MY(airfriction) = 0.200000;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 984;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x903010";
+       MY(color_max) = "0xFFD030";
+       MY(count) = 8;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(size_min) = 0.300000;
+       MY(size_max) = 0.700000;
+       MY(stretchfactor) = 0.400000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '156.0 156.0 156.0';
+       MY(velocitymultiplier) = -0.300000;
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+SUB(rocket_guide) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 100;
+       MY(alpha_fade) = 500;
+       MY(color_min) = "0x903010";
+       MY(color_max) = "0xFFD030";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 300;
+       MY(size_min) = 10;
+       MY(size_max) = 10;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "smoke";
+}
+
+// gauntlet laser
+DEF(laser_gauntlet);
+SUB(laser_gauntlet) {
+       MY(airfriction) = 10;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 6280;
+       MY(color_min) = "0xb44215";
+       MY(color_max) = "0x880000";
+       MY(count) = 3;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = 4000;
+       MY(spin_max) = -4000;
+       MY(sizeincrease) = -100;
+       MY(size_min) = 7;
+       MY(size_max) = 10;
+       MY(stretchfactor) = 2.300000;
+       MY(tex_min) = 43;
+       MY(tex_max) = 43;
+       MY(type) = "spark";
+       MY(velocityjitter) = '150.0 150.0 150.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+SUB(laser_gauntlet) {
+       MY(airfriction) = 12;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 6280;
+       MY(color_min) = "0xff4200";
+       MY(color_max) = "0xff0000";
+       MY(count) = 6;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = -100;
+       MY(size_min) = 7;
+       MY(size_max) = 9;
+       MY(stretchfactor) = 2;
+       MY(tex_min) = 8;
+       MY(tex_max) = 15;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(laser_gauntletmuzzleflash);
+// glow and light
+SUB(laser_gauntletmuzzleflash) {
+       MY(airfriction) = 10;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 6280;
+       MY(color_min) = "0x220000";
+       MY(color_max) = "0x880000";
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '3.0 0.1 0.1';
+       MY(lightradiusfade) = 500;
+       MY(lightradius) = 150;
+       MY(sizeincrease) = -100;
+       MY(size_min) = 10;
+       MY(size_max) = 15;
+       MY(stretchfactor) = 2;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "smoke";
+}
+// electricity
+SUB(laser_gauntletmuzzleflash) {
+       MY(airfriction) = 10;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 6280;
+       MY(color_min) = "0xb44215";
+       MY(color_max) = "0x880000";
+       MY(count) = 3;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = 4000;
+       MY(spin_max) = -4000;
+       MY(sizeincrease) = -100;
+       MY(size_min) = 7;
+       MY(size_max) = 10;
+       MY(stretchfactor) = 2.300000;
+       MY(tex_min) = 43;
+       MY(tex_max) = 43;
+       MY(type) = "spark";
+       MY(velocityjitter) = '150.0 150.0 150.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+// fire
+SUB(laser_gauntletmuzzleflash) {
+       MY(airfriction) = 12;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 6280;
+       MY(color_min) = "0xff4200";
+       MY(color_max) = "0xff0000";
+       MY(count) = 6;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = -100;
+       MY(size_min) = 7;
+       MY(size_max) = 9;
+       MY(stretchfactor) = 2;
+       MY(tex_min) = 8;
+       MY(tex_max) = 15;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = 0.200000;
+}
+
+// torch flame, spawn it as fast as you can  20 times per second or more, supports direction but not required
+DEF(torchflame);
+// fast fire
+SUB(torchflame) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 250;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 3;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '40.0 40.0 11.0';
+       MY(velocitymultiplier) = 30;
+}
+// slow fire
+SUB(torchflame) {
+       MY(airfriction) = 1.200000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 2.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 20;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '40.0 40.0 40.0';
+       MY(velocitymultiplier) = 20;
+}
+// very slow and small fire
+SUB(torchflame) {
+       MY(airfriction) = 0.300000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 1.500000;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = 10;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '30.0 30.0 30.0';
+       MY(velocitymultiplier) = 10;
+}
+// decreasing fire
+SUB(torchflame) {
+       MY(airfriction) = 0.300000;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 200;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 2;
+       MY(gravity) = -0.060000;
+       MY(sizeincrease) = -10;
+       MY(size_min) = 20;
+       MY(size_max) = 30;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '10.0 10.0 10.0';
+       MY(velocitymultiplier) = 15;
+}
+// smoke
+SUB(torchflame) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 90;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 0.500000;
+       MY(originjitter) = '10.0 10.0 10.0';
+       MY(sizeincrease) = 7;
+       MY(size_min) = 5;
+       MY(size_max) = 15;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocitymultiplier) = 20;
+       MY(velocityoffset) = '0.0 0.0 10.0';
+}
+
+#include "effectinfo_gentle_happy.inc"
+
+DEF(electro_lightning);
+SUB(electro_lightning) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '3.1 4.4 10.0';
+       MY(lightradiusfade) = 500;
+       MY(lightradius) = 50;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(tex_min) = 59;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+SUB(electro_lightning) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 206;
+       MY(alpha_fade) = 1724;
+       MY(color_min) = "0x2030FF";
+       MY(color_max) = "0x80C0FF";
+       MY(count) = 300;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 6;
+       MY(size_max) = 6;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "spark";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 2000;
+}
+SUB(electro_lightning) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 110;
+       MY(alpha_max) = 170;
+       MY(alpha_fade) = 1500;
+       MY(color_min) = "0xDDFDFF";
+       MY(color_max) = "0xFDFDFF";
+       MY(count) = 30;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 2;
+       MY(size_max) = 5;
+       MY(stretchfactor) = 1.500000;
+       MY(tex_min) = 8;
+       MY(tex_max) = 15;
+       MY(type) = "spark";
+       MY(velocityjitter) = '150.0 150.0 150.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+SUB(electro_lightning) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 110;
+       MY(alpha_max) = 170;
+       MY(alpha_fade) = 1500;
+       MY(color_min) = "0xFDFDFF";
+       MY(color_max) = "0xF9FDFF";
+       MY(count) = 50;
+       MY(gravity) = 1.300000;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 2;
+       MY(size_max) = 3;
+       MY(stretchfactor) = 0.100000;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '350.0 350.0 350.0';
+       MY(velocitymultiplier) = 2.500000;
+}
+
+DEF(gauntlet_lightning);
+SUB(gauntlet_lightning) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x280000";
+       MY(color_max) = "0x280000";
+       MY(count) = 300;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(sizeincrease) = 15;
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "spark";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 2000;
+}
+SUB(gauntlet_lightning) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 110;
+       MY(alpha_max) = 228;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xDD0000";
+       MY(color_max) = "0xFD0000";
+       MY(count) = 30;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 2;
+       MY(size_max) = 5;
+       MY(stretchfactor) = 1.500000;
+       MY(tex_min) = 8;
+       MY(tex_max) = 15;
+       MY(type) = "spark";
+       MY(velocityjitter) = '150.0 150.0 150.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+SUB(gauntlet_lightning) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 110;
+       MY(alpha_max) = 228;
+       MY(alpha_fade) = 600;
+       MY(color_min) = "0xFD0000";
+       MY(color_max) = "0xF90000";
+       MY(count) = 50;
+       MY(gravity) = 1.300000;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 2;
+       MY(size_max) = 3;
+       MY(stretchfactor) = 0.100000;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '350.0 350.0 350.0';
+       MY(velocitymultiplier) = 2.500000;
+}
+
+DEF(crylink_joinexplode);
+// decal
+SUB(crylink_joinexplode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(originjitter) = '12.0 12.0 12.0';
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "decal";
+}
+// purple flare effect
+SUB(crylink_joinexplode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x504060";
+       MY(color_max) = "0x504060";
+       MY(countabsolute) = 1;
+       MY(size_min) = 24;
+       MY(size_max) = 24;
+       MY(tex_min) = 39;
+       MY(tex_max) = 39;
+       MY(type) = "static";
+}
+// purple sparks
+SUB(crylink_joinexplode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(bounce) = 2;
+       MY(color_min) = "0xA040C0";
+       MY(color_max) = "0xA040C0";
+       MY(count) = 40;
+       MY(size_min) = 6;
+       MY(size_max) = 6;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// purple splash
+SUB(crylink_joinexplode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0xE070FF";
+       MY(color_max) = "0xE070FF";
+       MY(count) = 1.500000;
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+}
+// purple splash
+SUB(crylink_joinexplode) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0xE070FF";
+       MY(color_max) = "0xE070FF";
+       MY(count) = 3;
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(type) = "static";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+// sparks for keepaway ball touch
+DEF(kaball_sparks);
+SUB(kaball_sparks) {
+       MY(airfriction) = 3;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 556;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0xa9cacf";
+       MY(color_max) = "0x0054ff";
+       MY(count) = 35;
+       MY(gravity) = 1;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 1;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '300.0 300.0 300.0';
+       MY(velocitymultiplier) = 0.500000;
+}
+
+// weak rifle bullet trail (somewhat like a tracer)
+DEF(tr_rifle_weak);
+SUB(tr_rifle_weak) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 2560;
+       MY(color_min) = "0x800000";
+       MY(color_max) = "0xFF8020";
+       MY(size_min) = 1.500000;
+       MY(size_max) = 1.500000;
+       MY(stretchfactor) = 1;
+       MY(trailspacing) = 128;
+       MY(type) = "spark";
+       MY(velocitymultiplier) = 0.700000;
+}
+SUB(tr_rifle_weak) {
+       MY(airfriction) = -4;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x202020";
+       MY(color_max) = "0x404040";
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 0.400000;
+       MY(size_min) = 4;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 48;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '4.0 4.0 4.0';
+}
+SUB(tr_rifle_weak) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 128;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 192;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+// red smoke emiter
+DEF(red_smoke);
+SUB(red_smoke) {
+       MY(airfriction) = -1;
+       MY(alpha_min) = 32;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 32;
+       MY(color_min) = "0xff8866";
+       MY(color_max) = "0x331100";
+       MY(count) = 2;
+       MY(gravity) = -0.007000;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(size_min) = 60;
+       MY(size_max) = 120;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocitymultiplier) = 5;
+}
+
+// pipe smoke emiter
+DEF(pipe_smoke);
+SUB(pipe_smoke) {
+       MY(airfriction) = -1;
+       MY(alpha_min) = 32;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 48;
+       MY(color_min) = "0x999999";
+       MY(color_max) = "0x555555";
+       MY(count) = 2;
+       MY(gravity) = -0.015000;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -180;
+       MY(spin_max) = 180;
+       MY(sizeincrease) = 35;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '0.0 0.0 5.0';
+       MY(velocitymultiplier) = 15;
+}
+
+// seeker missile trail
+DEF(TR_SEEKER);
+SUB(TR_SEEKER) {
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 300;
+       MY(alpha_fade) = 200;
+       MY(bounce) = 1;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x666666";
+       MY(lightcolor) = '6.0 3.0 1.0';
+       MY(lightradius) = 100;
+       MY(notunderwater) = true;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = 11;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 10;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '3.0 3.0 3.0';
+       MY(velocitymultiplier) = -0.020000;
+}
+// fire
+SUB(TR_SEEKER) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 144;
+       MY(alpha_fade) = 588;
+       MY(color_min) = "0xffdf72";
+       MY(color_max) = "0x811200";
+       MY(sizeincrease) = -30;
+       MY(size_min) = 5;
+       MY(size_max) = 5;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 4;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = -1.500000;
+}
+// bubbles
+SUB(TR_SEEKER) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 16;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+       MY(velocitymultiplier) = -0.310000;
+}
+// sparks
+SUB(TR_SEEKER) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 444;
+       MY(alpha_max) = 512;
+       MY(alpha_fade) = 1866;
+       MY(bounce) = 1;
+       MY(color_min) = "0xFFFDD9";
+       MY(color_max) = "0xFFFDD9";
+       MY(notunderwater) = true;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 0.500000;
+       MY(size_max) = 0.500000;
+       MY(stretchfactor) = 0.300000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(trailspacing) = 20;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = -0.310000;
+}
+
+#include "effectinfo_vehicles.inc"
+
+// generic explosion size:big (biggest explosion ever)
+DEF(explosion_big);
+// decal
+SUB(explosion_big) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '8.0 4.0 0.0';
+       MY(lightradiusfade) = 1750;
+       MY(lightradius) = 600;
+       MY(originjitter) = '23.0 23.0 23.0';
+       MY(size_min) = 172;
+       MY(size_max) = 172;
+       MY(tex_min) = 8;
+       MY(tex_max) = 16;
+       MY(type) = "decal";
+}
+// shockwave
+SUB(explosion_big) {
+       MY(alpha_min) = 56;
+       MY(alpha_max) = 56;
+       MY(alpha_fade) = 330;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 4400;
+       MY(size_min) = 72;
+       MY(size_max) = 72;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "static";
+}
+// fire effect
+SUB(explosion_big) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 712;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 64;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '80.0 80.0 80.0';
+       MY(sizeincrease) = 45;
+       MY(size_min) = 133;
+       MY(size_max) = 144;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '2512.0 2512.0 2512.0';
+}
+// fire rays
+SUB(explosion_big) {
+       MY(airfriction) = -5;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 800;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 64;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '40.0 40.0 40.0';
+       MY(sizeincrease) = 45;
+       MY(size_min) = 133;
+       MY(size_max) = 144;
+       MY(stretchfactor) = 10;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "spark";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// smoke
+SUB(explosion_big) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 650;
+       MY(alpha_fade) = 456;
+       MY(color_min) = "0x4F4B46";
+       MY(color_max) = "0x000000";
+       MY(count) = 32;
+       MY(notunderwater) = true;
+       MY(sizeincrease) = 244;
+       MY(size_min) = 50;
+       MY(size_max) = 100;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '3444.0 3444.0 3444.0';
+}
+// bouncing sparks
+SUB(explosion_big) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 644;
+       MY(alpha_max) = 956;
+       MY(alpha_fade) = 1284;
+       MY(color_min) = "0xffa35b";
+       MY(color_max) = "0xfff2be";
+       MY(count) = 34;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '160.0 160.0 160.0';
+       MY(size_min) = 3;
+       MY(size_max) = 4;
+       MY(stretchfactor) = 0.700000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '924.0 924.0 924.0';
+       MY(velocityoffset) = '0.0 0.0 370.0';
+}
+// debris
+SUB(explosion_big) {
+       MY(airfriction) = 0.500000;
+       MY(alpha_min) = 444;
+       MY(alpha_max) = 1356;
+       MY(alpha_fade) = 1184;
+       MY(color_min) = "0xFFFFFF";
+       MY(color_max) = "0xcac5b4";
+       MY(count) = 16;
+       MY(gravity) = 2.300000;
+       MY(notunderwater) = true;
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -1000;
+       MY(spin_max) = 1000;
+       MY(sizeincrease) = -5;
+       MY(size_min) = 10;
+       MY(size_max) = 16;
+       MY(tex_min) = 66;
+       MY(tex_max) = 68;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '1800.0 1800.0 1800.0';
+       MY(velocityoffset) = '0.0 0.0 970.0';
+}
+// underwater bubbles
+SUB(explosion_big) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 32;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '160.0 160.0 160.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '444.0 444.0 444.0';
+}
+// underwatershockwave
+SUB(explosion_big) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 300;
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 2900;
+       MY(size_min) = 30;
+       MY(size_max) = 30;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(underwater) = true;
+       MY(velocitymultiplier) = 0.300000;
+}
+
+// generic explosion size:medium (it leaves rising smoke for a longer time)
+DEF(explosion_medium);
+// shockwave
+SUB(explosion_medium) {
+       MY(alpha_min) = 56;
+       MY(alpha_max) = 56;
+       MY(alpha_fade) = 330;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 2400;
+       MY(size_min) = 72;
+       MY(size_max) = 72;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "static";
+}
+// fire effect
+SUB(explosion_medium) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 712;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 32;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '30.0 30.0 30.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -500;
+       MY(spin_max) = 500;
+       MY(sizeincrease) = 45;
+       MY(size_min) = 133;
+       MY(size_max) = 144;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '1512.0 1512.0 1512.0';
+}
+// fire effect 2
+SUB(explosion_medium) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 612;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 32;
+       MY(gravity) = -2;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '30.0 30.0 30.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -150;
+       MY(spin_max) = 150;
+       MY(sizeincrease) = 40;
+       MY(size_min) = 73;
+       MY(size_max) = 94;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '1512.0 1512.0 1512.0';
+}
+// fire rays
+SUB(explosion_medium) {
+       MY(airfriction) = -3;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 800;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 14;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '40.0 40.0 40.0';
+       MY(sizeincrease) = 40;
+       MY(size_min) = 43;
+       MY(size_max) = 74;
+       MY(stretchfactor) = 8;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "spark";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// smoke
+SUB(explosion_medium) {
+       MY(airfriction) = 3;
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 650;
+       MY(alpha_fade) = 756;
+       MY(color_min) = "0x4F4B46";
+       MY(color_max) = "0x000000";
+       MY(count) = 5;
+       MY(notunderwater) = true;
+       MY(originjitter) = '100.0 100.0 100.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -20;
+       MY(spin_max) = 20;
+       MY(sizeincrease) = -30;
+       MY(size_min) = 250;
+       MY(size_max) = 300;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '200.0 200.0 200.0';
+}
+// smoke 2
+SUB(explosion_medium) {
+       MY(airfriction) = 3;
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 650;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x4F4B46";
+       MY(color_max) = "0x000000";
+       MY(count) = 10;
+       MY(gravity) = -0.300000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '100.0 100.0 100.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -20;
+       MY(spin_max) = 20;
+       MY(sizeincrease) = 50;
+       MY(size_min) = 50;
+       MY(size_max) = 100;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '500.0 500.0 500.0';
+       MY(velocityoffset) = '0.0 0.0 200.0';
+}
+// smoke rays
+SUB(explosion_medium) {
+       MY(alpha_min) = 140;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 350;
+       MY(color_min) = "0x4F4B46";
+       MY(color_max) = "0x000000";
+       MY(count) = 13;
+       MY(notunderwater) = true;
+       MY(originjitter) = '40.0 40.0 40.0';
+       MY(sizeincrease) = 100;
+       MY(size_min) = 150;
+       MY(size_max) = 200;
+       MY(stretchfactor) = 50;
+       MY(tex_max) = 8;
+       MY(type) = "spark";
+       MY(velocityjitter) = '250.0 250.0 250.0';
+}
+// bouncing sparks
+SUB(explosion_medium) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 644;
+       MY(alpha_max) = 956;
+       MY(alpha_fade) = 984;
+       MY(color_min) = "0xffa35b";
+       MY(color_max) = "0xfff2be";
+       MY(count) = 14;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '100.0 100.0 100.0';
+       MY(size_min) = 2;
+       MY(size_max) = 3;
+       MY(stretchfactor) = 0.700000;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "spark";
+       MY(velocityjitter) = '624.0 624.0 624.0';
+       MY(velocityoffset) = '0.0 0.0 370.0';
+}
+// underwater bubbles
+SUB(explosion_medium) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 32;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '160.0 160.0 160.0';
+       MY(size_min) = 3;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '444.0 444.0 444.0';
+}
+// underwatershockwave
+SUB(explosion_medium) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 300;
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 2900;
+       MY(size_min) = 30;
+       MY(size_max) = 30;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(underwater) = true;
+       MY(velocitymultiplier) = 0.300000;
+}
+
+// generic explosion size:small (its fire only, made to support other explosions)
+DEF(explosion_small);
+// shockwave
+SUB(explosion_small) {
+       MY(alpha_min) = 56;
+       MY(alpha_max) = 56;
+       MY(alpha_fade) = 330;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 2400;
+       MY(size_min) = 22;
+       MY(size_max) = 22;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "static";
+}
+// fire effect
+SUB(explosion_small) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1212;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 16;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -500;
+       MY(spin_max) = 500;
+       MY(sizeincrease) = 45;
+       MY(size_min) = 1;
+       MY(size_max) = 44;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// fire effect 2
+SUB(explosion_small) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 812;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 16;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -150;
+       MY(spin_max) = 150;
+       MY(sizeincrease) = 40;
+       MY(size_min) = 73;
+       MY(size_max) = 94;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "static";
+       MY(velocityjitter) = '912.0 912.0 912.0';
+}
+// fire rays
+SUB(explosion_small) {
+       MY(airfriction) = -3;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 1300;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 14;
+       MY(liquidfriction) = 8;
+       MY(notunderwater) = true;
+       MY(originjitter) = '40.0 40.0 40.0';
+       MY(sizeincrease) = 30;
+       MY(size_min) = 13;
+       MY(size_max) = 54;
+       MY(stretchfactor) = 8;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "spark";
+       MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// underwater bubbles
+SUB(explosion_small) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 32;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '160.0 160.0 160.0';
+       MY(size_min) = 1;
+       MY(size_max) = 3;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// underwatershockwave
+SUB(explosion_small) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 300;
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1200;
+       MY(size_min) = 30;
+       MY(size_max) = 30;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(underwater) = true;
+}
+
+// big smoke ( for spamming on damaged stuff )
+DEF(smoke_big);
+SUB(smoke_big) {
+       MY(airfriction) = 4;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 750;
+       MY(alpha_fade) = 200;
+       MY(color_min) = "0x4F4B46";
+       MY(color_max) = "0x000000";
+       MY(count) = 3;
+       MY(gravity) = -0.500000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '55.0 55.0 55.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -20;
+       MY(spin_max) = 20;
+       MY(sizeincrease) = 15;
+       MY(size_min) = 30;
+       MY(size_max) = 60;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '140.0 140.0 200.0';
+       MY(velocityoffset) = '0.0 0.0 200.0';
+}
+
+// small smoke ( more precise than big one, for spamming on damaged parts like raptors spinner )
+DEF(smoke_small);
+SUB(smoke_small) {
+       MY(airfriction) = 4;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 750;
+       MY(alpha_fade) = 200;
+       MY(color_min) = "0x4F4B46";
+       MY(color_max) = "0x000000";
+       MY(count) = 3;
+       MY(gravity) = -0.500000;
+       MY(notunderwater) = true;
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -20;
+       MY(spin_max) = 20;
+       MY(sizeincrease) = -10;
+       MY(size_min) = 60;
+       MY(size_max) = 100;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '40.0 40.0 400.0';
+       MY(velocityoffset) = '0.0 0.0 200.0';
+}
+
+// metal impact effect
+DEF(impact_metal);
+SUB(impact_metal) {
+       MY(alpha_min) = 25;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 50;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x886666";
+       MY(count) = 1;
+       MY(gravity) = -0.010000;
+       MY(originjitter) = '20.0 20.0 5.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 3;
+       MY(size_max) = 6;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+// sparks
+SUB(impact_metal) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 112;
+       MY(bounce) = 1.800000;
+       MY(color_min) = "0xFFCC22";
+       MY(color_max) = "0xFF4422";
+       MY(count) = 2;
+       MY(gravity) = 1;
+       MY(size_min) = 2;
+       MY(size_max) = 2;
+       MY(stretchfactor) = 0.500000;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '200.0 200.0 300.0';
+       MY(velocitymultiplier) = 2;
+}
+
+// stone impact effect
+DEF(impact_stone);
+SUB(impact_stone) {
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 75;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0xcc9966";
+       MY(count) = 1;
+       MY(gravity) = -0.010000;
+       MY(originjitter) = '20.0 20.0 5.0';
+       MY(sizeincrease) = 15;
+       MY(size_min) = 3;
+       MY(size_max) = 6;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+// debris
+SUB(impact_stone) {
+       MY(airfriction) = 0.500000;
+       MY(alpha_min) = 450;
+       MY(alpha_max) = 750;
+       MY(alpha_fade) = 300;
+       MY(bounce) = 1.200000;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x886644";
+       MY(count) = 1;
+       MY(gravity) = 1.300000;
+       MY(notunderwater) = true;
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -1000;
+       MY(spin_max) = 1000;
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(tex_min) = 66;
+       MY(tex_max) = 68;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '124.0 124.0 324.0';
+}
+
+// wood impact effect
+DEF(impact_wood);
+SUB(impact_wood) {
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 75;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0xcc9966";
+       MY(count) = 1;
+       MY(gravity) = -0.010000;
+       MY(originjitter) = '20.0 20.0 5.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 3;
+       MY(size_max) = 6;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+// sparks
+SUB(impact_wood) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 75;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x221100";
+       MY(color_max) = "0x221100";
+       MY(count) = 2;
+       MY(gravity) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 8;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '180.0 180.0 260.0';
+       MY(velocitymultiplier) = 2;
+}
+
+// flesh impact effect
+DEF(impact_flesh);
+SUB(impact_flesh) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x420000";
+       MY(count) = 0.500000;
+       MY(originjitter) = '11.0 11.0 11.0';
+       MY(size_min) = 8;
+       MY(size_max) = 12;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+// blood splash
+SUB(impact_flesh) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFFF";
+       MY(count) = 0.300000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 6;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '96.0 96.0 96.0';
+       MY(velocitymultiplier) = 5;
+}
+
+// hagar trail
+DEF(tr_hagar);
+// smoke
+SUB(tr_hagar) {
+       MY(alpha_min) = 300;
+       MY(alpha_max) = 400;
+       MY(alpha_fade) = 780;
+       MY(bounce) = 1;
+       MY(color_min) = "0x101010";
+       MY(color_max) = "0x000000";
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 3;
+       MY(size_max) = 2;
+       MY(tex_max) = 8;
+       MY(trailspacing) = 4;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '1.0 1.0 1.0';
+       MY(velocitymultiplier) = -0.020000;
+}
+// fire
+SUB(tr_hagar) {
+       MY(airfriction) = 8;
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 144;
+       MY(alpha_fade) = 988;
+       MY(color_min) = "0xffdf72";
+       MY(color_max) = "0x811200";
+       MY(notunderwater) = true;
+       MY(sizeincrease) = -15;
+       MY(size_min) = 5;
+       MY(size_max) = 2;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(trailspacing) = 4;
+       MY(type) = "static";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = -1;
+}
+// bubbles
+SUB(tr_hagar) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(trailspacing) = 16;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+// laser damage effect
+DEF(damage_laser);
+SUB(damage_laser) {
+       MY(airfriction) = -0.350000;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 16;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x880000";
+       MY(color_max) = "0xff4400";
+       MY(count) = 3;
+       MY(notunderwater) = true;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(startangle_max) = 180;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = 8;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '0.4 0.4 0.6';
+}
+
+// shotgun damage effect, normal blood
+DEF(damage_shotgun);
+SUB(damage_shotgun) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFFF";
+       MY(count) = 0.600000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_shotgun) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x420000";
+       MY(count) = 1;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 8;
+       MY(size_max) = 16;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// shotgun damage effect, alien blood
+DEF(damage_shotgun_alien);
+SUB(damage_shotgun_alien) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xDC9BCD";
+       MY(color_max) = "0xDC9BCD";
+       MY(count) = 0.600000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_shotgun_alien) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x204010";
+       MY(count) = 1;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 8;
+       MY(size_max) = 16;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// shotgun damage effect, robot blood
+DEF(damage_shotgun_robot);
+SUB(damage_shotgun_robot) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xC0D890";
+       MY(color_max) = "0xC0D890";
+       MY(count) = 0.600000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_shotgun_robot) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x301860";
+       MY(count) = 1;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 8;
+       MY(size_max) = 16;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// machinegun damage effect, normal blood
+DEF(damage_uzi);
+SUB(damage_uzi) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFFF";
+       MY(count) = 0.300000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_uzi) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x420000";
+       MY(count) = 1;
+       MY(size_min) = 6;
+       MY(size_max) = 12;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// machinegun damage effect, alien blood
+DEF(damage_uzi_alien);
+SUB(damage_uzi_alien) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xDC9BCD";
+       MY(color_max) = "0xDC9BCD";
+       MY(count) = 0.300000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_uzi_alien) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x204010";
+       MY(count) = 1;
+       MY(size_min) = 6;
+       MY(size_max) = 12;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// machinegun damage effect, robot blood
+DEF(damage_uzi_robot);
+SUB(damage_uzi_robot) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xC0D890";
+       MY(color_max) = "0xC0D890";
+       MY(count) = 0.300000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_uzi_robot) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x301860";
+       MY(count) = 1;
+       MY(size_min) = 6;
+       MY(size_max) = 12;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// minelayer damage effect
+DEF(damage_minelayer);
+SUB(damage_minelayer) {
+       MY(alpha_min) = 512;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 3;
+       MY(gravity) = -0.500000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = -15;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_minelayer) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 2;
+       MY(gravity) = -0.300000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(sizeincrease) = 5;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// mortar damage effect
+DEF(damage_grenadelauncher);
+SUB(damage_grenadelauncher) {
+       MY(alpha_min) = 512;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 3;
+       MY(gravity) = -0.500000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = -15;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_grenadelauncher) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 2;
+       MY(gravity) = -0.300000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(sizeincrease) = 5;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// electro damage effect
+DEF(damage_electro);
+SUB(damage_electro) {
+       MY(airfriction) = -0.500000;
+       MY(alpha_min) = 48;
+       MY(alpha_max) = 8;
+       MY(alpha_fade) = 48;
+       MY(color_min) = "0x66ffff";
+       MY(color_max) = "0x2288ff";
+       MY(count) = 2;
+       MY(gravity) = -0.000100;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '3.0 3.0 3.0';
+       MY(startangle_min) = 180;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = -14;
+       MY(size_min) = 6;
+       MY(size_max) = 10;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "static";
+       MY(velocityjitter) = '8.0 8.0 16.0';
+}
+// plasma smoke
+SUB(damage_electro) {
+       MY(airfriction) = -0.350000;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 16;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x2244ff";
+       MY(color_max) = "0x002266";
+       MY(count) = 4;
+       MY(notunderwater) = true;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(startangle_max) = 180;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = 10;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '0.4 0.4 0.6';
+}
+// bouncing sparks
+SUB(damage_electro) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 768;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 256;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x003090";
+       MY(color_max) = "0x00CCFF";
+       MY(count) = 0.500000;
+       MY(gravity) = 0.200000;
+       MY(liquidfriction) = 0.800000;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(tex_min) = 66;
+       MY(tex_max) = 68;
+       MY(type) = "spark";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+}
+
+// crylink damage effect
+DEF(damage_crylink);
+SUB(damage_crylink) {
+       MY(airfriction) = -0.500000;
+       MY(alpha_min) = 48;
+       MY(alpha_max) = 16;
+       MY(alpha_fade) = 48;
+       MY(color_min) = "0xff44ff";
+       MY(color_max) = "0x9966ff";
+       MY(count) = 2;
+       MY(gravity) = -0.000100;
+       MY(liquidfriction) = 0.800000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '3.0 3.0 3.0';
+       MY(startangle_min) = 180;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = -8;
+       MY(size_min) = 0.500000;
+       MY(size_max) = 1;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(type) = "static";
+       MY(velocityjitter) = '10.0 10.0 20.0';
+}
+// plasma smoke
+SUB(damage_crylink) {
+       MY(airfriction) = -0.350000;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 16;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x8844ff";
+       MY(color_max) = "0x662244";
+       MY(count) = 4;
+       MY(gravity) = 0.001000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(startangle_max) = 180;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = 6;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '0.4 0.4 0.6';
+}
+// floating sparks
+SUB(damage_crylink) {
+       MY(airfriction) = 0.200000;
+       MY(alpha_min) = 192;
+       MY(alpha_max) = 192;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x903090";
+       MY(color_max) = "0xFFD0FF";
+       MY(count) = 0.300000;
+       MY(liquidfriction) = 0.800000;
+       MY(sizeincrease) = -5;
+       MY(size_min) = 0.500000;
+       MY(size_max) = 0.500000;
+       MY(type) = "spark";
+       MY(velocityjitter) = '12.0 12.0 12.0';
+}
+
+// hlac damage effect
+DEF(damage_hlac);
+SUB(damage_hlac) {
+       MY(airfriction) = -0.350000;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 16;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x880000";
+       MY(color_max) = "0xff4400";
+       MY(count) = 3;
+       MY(notunderwater) = true;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(startangle_max) = 180;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = 10;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '0.4 0.4 0.6';
+}
+
+// vortex damage effect
+DEF(damage_nex);
+SUB(damage_nex) {
+       MY(airfriction) = -0.500000;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 8;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0xffffff";
+       MY(color_max) = "0x88ffff";
+       MY(count) = 1;
+       MY(gravity) = -0.000100;
+       MY(liquidfriction) = 0.600000;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(startangle_min) = 180;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = -14;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "static";
+       MY(velocityjitter) = '8.0 8.0 16.0';
+}
+// plasma smoke
+SUB(damage_nex) {
+       MY(airfriction) = -0.350000;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 16;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x6688ff";
+       MY(color_max) = "0x226688";
+       MY(count) = 2;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(startangle_max) = 180;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = 8;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '0.5 0.5 0.8';
+}
+// bouncing sparks
+SUB(damage_nex) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 112;
+       MY(bounce) = 1.600000;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0xD9FDFF";
+       MY(count) = 0.200000;
+       MY(gravity) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(stretchfactor) = 0.700000;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 300.0';
+       MY(velocitymultiplier) = 3;
+}
+
+// vaporizer damage effect
+DEF(damage_minstanex);
+SUB(damage_minstanex) {
+       MY(airfriction) = -0.500000;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 8;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0xffffff";
+       MY(color_max) = "0x88ffff";
+       MY(count) = 2;
+       MY(gravity) = -0.000100;
+       MY(liquidfriction) = 0.600000;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(startangle_min) = 180;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = -14;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(tex_min) = 47;
+       MY(tex_max) = 47;
+       MY(type) = "static";
+       MY(velocityjitter) = '8.0 8.0 16.0';
+}
+// plasma smoke
+SUB(damage_minstanex) {
+       MY(airfriction) = -0.350000;
+       MY(alpha_min) = 64;
+       MY(alpha_max) = 16;
+       MY(alpha_fade) = 64;
+       MY(color_min) = "0x6688ff";
+       MY(color_max) = "0x226688";
+       MY(count) = 4;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(startangle_max) = 180;
+       MY(spin_min) = -30;
+       MY(spin_max) = 30;
+       MY(sizeincrease) = 8;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '0.5 0.5 0.8';
+}
+// bouncing sparks
+SUB(damage_minstanex) {
+       MY(airfriction) = 2;
+       MY(alpha_min) = 255;
+       MY(alpha_max) = 255;
+       MY(alpha_fade) = 112;
+       MY(bounce) = 1.600000;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0xD9FDFF";
+       MY(count) = 0.200000;
+       MY(gravity) = 1;
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(stretchfactor) = 0.700000;
+       MY(tex_min) = 41;
+       MY(tex_max) = 41;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 300.0';
+       MY(velocitymultiplier) = 3;
+}
+
+// rifle damage effect, normal blood
+DEF(damage_rifle);
+SUB(damage_rifle) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xA8FFFF";
+       MY(color_max) = "0xA8FFFFF";
+       MY(count) = 0.300000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_rifle) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x420000";
+       MY(count) = 1;
+       MY(size_min) = 6;
+       MY(size_max) = 12;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// rifle damage effect, alien blood
+DEF(damage_rifle_alien);
+SUB(damage_rifle_alien) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xDC9BCD";
+       MY(color_max) = "0xDC9BCD";
+       MY(count) = 0.300000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_rifle_alien) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x204010";
+       MY(count) = 1;
+       MY(size_min) = 6;
+       MY(size_max) = 12;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// rifle damage effect, robot blood
+DEF(damage_rifle_robot);
+SUB(damage_rifle_robot) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = -1;
+       MY(color_min) = "0xC0D890";
+       MY(color_max) = "0xC0D890";
+       MY(count) = 0.300000;
+       MY(liquidfriction) = 4;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(staincolor_min) = "0x808080";
+       MY(staincolor_max) = "0x808080";
+       MY(staintex_min) = 16;
+       MY(staintex_max) = 24;
+       MY(tex_min) = 24;
+       MY(tex_max) = 32;
+       MY(type) = "blood";
+       MY(velocityjitter) = '32.0 32.0 32.0';
+       MY(velocitymultiplier) = 5;
+}
+// blood mist
+SUB(damage_rifle_robot) {
+       MY(alpha_min) = 100;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 400;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x301860";
+       MY(count) = 1;
+       MY(size_min) = 6;
+       MY(size_max) = 12;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+}
+
+// seeker damage effect
+DEF(damage_seeker);
+SUB(damage_seeker) {
+       MY(alpha_min) = 512;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x8f0c00";
+       MY(color_max) = "0xff2200";
+       MY(count) = 3;
+       MY(gravity) = -0.300000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = -10;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_seeker) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 2;
+       MY(gravity) = -0.300000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// hagar damage effect
+DEF(damage_hagar);
+SUB(damage_hagar) {
+       MY(alpha_min) = 512;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x8f0c00";
+       MY(color_max) = "0xff3a00";
+       MY(count) = 3;
+       MY(gravity) = -0.300000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = -10;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_hagar) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 2;
+       MY(gravity) = -0.300000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 2;
+       MY(size_max) = 4;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// fireball damage effect
+DEF(damage_fireball);
+SUB(damage_fireball) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 16;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x8f0d00";
+       MY(color_max) = "0xff5a00";
+       MY(count) = 4;
+       MY(gravity) = -0.500000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '8.0 8.0 8.0';
+       MY(sizeincrease) = -10;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '22.0 22.0 50.0';
+}
+// smoke
+SUB(damage_fireball) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 4;
+       MY(gravity) = -0.300000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '6.0 6.0 6.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// rocketlauncher damage effect
+DEF(damage_rocketlauncher);
+SUB(damage_rocketlauncher) {
+       MY(alpha_min) = 512;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x8f0c00";
+       MY(color_max) = "0xff2a00";
+       MY(count) = 3;
+       MY(gravity) = -0.700000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(sizeincrease) = -10;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '22.0 22.0 30.0';
+}
+// smoke
+SUB(damage_rocketlauncher) {
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 32;
+       MY(alpha_fade) = 128;
+       MY(color_min) = "0x000000";
+       MY(color_max) = "0x111111";
+       MY(count) = 3;
+       MY(gravity) = -0.300000;
+       MY(notunderwater) = true;
+       MY(originjitter) = '4.0 4.0 4.0';
+       MY(sizeincrease) = 10;
+       MY(size_min) = 4;
+       MY(size_max) = 8;
+       MY(tex_max) = 8;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '11.0 11.0 50.0';
+}
+
+// fireflies
+DEF(fireflies);
+SUB(fireflies) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 70;
+       MY(bounce) = -1;
+       MY(color_min) = "0xff9600";
+       MY(color_max) = "0xffefb8";
+       MY(count) = 1;
+       MY(originjitter) = '32.0 32.0 32.0';
+       MY(originoffset) = '8.0 8.0 8.0';
+       MY(sizeincrease) = -0.300000;
+       MY(size_min) = 2;
+       MY(size_max) = 3;
+       MY(tex_min) = 38;
+       MY(tex_max) = 38;
+       MY(time_min) = 1;
+       MY(time_max) = 2;
+       MY(type) = "static";
+       MY(velocityjitter) = '64.0 64.0 64.0';
+       MY(velocityoffset) = '2.0 2.0 2.0';
+}
+
+DEF(healray_muzzleflash);
+SUB(healray_muzzleflash) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x283880";
+       MY(color_max) = "0x283880";
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '1.5 3.0 6.0';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(sizeincrease) = -10;
+       MY(size_min) = 20;
+       MY(size_max) = 20;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+SUB(healray_muzzleflash) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 150;
+       MY(alpha_fade) = 1924;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0x00f0ff";
+       MY(count) = 22;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = 3;
+       MY(size_min) = 1;
+       MY(size_max) = 15;
+       MY(stretchfactor) = 3.900000;
+       MY(tex_min) = 71;
+       MY(tex_max) = 73;
+       MY(type) = "spark";
+       MY(velocityjitter) = '150.0 150.0 150.0';
+       MY(velocitymultiplier) = 0.400000;
+}
+SUB(healray_muzzleflash) {
+       MY(alpha_min) = 110;
+       MY(alpha_max) = 228;
+       MY(alpha_fade) = 4024;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0x00f0ff";
+       MY(count) = 4;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 1;
+       MY(size_max) = 1;
+       MY(stretchfactor) = 0.200000;
+       MY(tex_min) = 70;
+       MY(tex_max) = 70;
+       MY(type) = "spark";
+       MY(velocityjitter) = '650.0 650.0 650.0';
+       MY(velocitymultiplier) = 1.100000;
+}
+
+DEF(healray_impact);
+SUB(healray_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(color_min) = "0xd800ff";
+       MY(color_max) = "0xd800ff";
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '0.0 4.4 0.0';
+       MY(lightradiusfade) = 450;
+       MY(lightradius) = 125;
+       MY(originjitter) = '17.0 17.0 17.0';
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 59;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// shockwave
+SUB(healray_impact) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 350;
+       MY(color_min) = "0x00ff00";
+       MY(color_max) = "0x84c52f";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1400;
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(velocitymultiplier) = 44;
+}
+// cloud of bouncing sparks
+SUB(healray_impact) {
+       MY(airfriction) = 6;
+       MY(alpha_min) = 156;
+       MY(alpha_max) = 300;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x00ff00";
+       MY(color_max) = "0x84c52f";
+       MY(count) = 30;
+       MY(gravity) = 2;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(tex_min) = 70;
+       MY(tex_max) = 70;
+       MY(type) = "spark";
+       MY(velocityjitter) = '1112.0 1112.0 1112.0';
+}
+// inner cloud of smoke
+SUB(healray_impact) {
+       MY(airfriction) = 3;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 456;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x00ff00";
+       MY(color_max) = "0x84c52f";
+       MY(count) = 15;
+       MY(gravity) = -2;
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -90;
+       MY(spin_max) = 90;
+       MY(size_min) = 2;
+       MY(size_max) = 3;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '120.0 120.0 420.0';
+}
+
+DEF(bigplasma_muzzleflash);
+SUB(bigplasma_muzzleflash) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 812;
+       MY(color_min) = "0x283880";
+       MY(color_max) = "0x283880";
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '1.5 3.0 6.0';
+       MY(lightradiusfade) = 2000;
+       MY(lightradius) = 200;
+       MY(originjitter) = '1.5 1.5 1.5';
+       MY(sizeincrease) = -10;
+       MY(size_min) = 50;
+       MY(size_max) = 50;
+       MY(tex_min) = 65;
+       MY(tex_max) = 65;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '6.0 6.0 6.0';
+       MY(velocitymultiplier) = 0.010000;
+}
+SUB(bigplasma_muzzleflash) {
+       MY(alpha_min) = 56;
+       MY(alpha_max) = 56;
+       MY(alpha_fade) = 1112;
+       MY(color_min) = "0x00f0ff";
+       MY(color_max) = "0x00f0ff";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 300;
+       MY(size_min) = 20;
+       MY(size_max) = 20;
+       MY(tex_min) = 74;
+       MY(tex_max) = 74;
+       MY(type) = "smoke";
+}
+SUB(bigplasma_muzzleflash) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 50;
+       MY(alpha_max) = 150;
+       MY(alpha_fade) = 1924;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0x00f0ff";
+       MY(count) = 14;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(sizeincrease) = 135;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(stretchfactor) = 1.900000;
+       MY(tex_min) = 51;
+       MY(tex_max) = 55;
+       MY(type) = "spark";
+       MY(velocityjitter) = '350.0 350.0 350.0';
+       MY(velocitymultiplier) = 0.400000;
+}
+SUB(bigplasma_muzzleflash) {
+       MY(alpha_min) = 110;
+       MY(alpha_max) = 228;
+       MY(alpha_fade) = 4024;
+       MY(color_min) = "0xD9FDFF";
+       MY(color_max) = "0x00f0ff";
+       MY(count) = 4;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 20;
+       MY(size_max) = 20;
+       MY(stretchfactor) = 0.200000;
+       MY(tex_min) = 70;
+       MY(tex_max) = 70;
+       MY(type) = "spark";
+       MY(velocityjitter) = '650.0 650.0 650.0';
+       MY(velocitymultiplier) = 1.100000;
+}
+
+DEF(bigplasma_impact);
+SUB(bigplasma_impact) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '3.1 4.4 10.0';
+       MY(lightradiusfade) = 450;
+       MY(lightradius) = 125;
+       MY(originjitter) = '17.0 17.0 17.0';
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 59;
+       MY(tex_max) = 59;
+       MY(type) = "decal";
+}
+// shockwave
+SUB(bigplasma_impact) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 350;
+       MY(color_min) = "0x80C0FF";
+       MY(color_max) = "0x80C0FF";
+       MY(countabsolute) = 1;
+       MY(sizeincrease) = 1400;
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(velocitymultiplier) = 44;
+}
+// cloud of bouncing sparks
+SUB(bigplasma_impact) {
+       MY(airfriction) = 6;
+       MY(alpha_min) = 156;
+       MY(alpha_max) = 300;
+       MY(alpha_fade) = 1024;
+       MY(color_min) = "0x629dff";
+       MY(color_max) = "0x0018ff";
+       MY(count) = 30;
+       MY(gravity) = 2;
+       MY(originjitter) = '1.0 1.0 1.0';
+       MY(size_min) = 1;
+       MY(size_max) = 2;
+       MY(tex_min) = 70;
+       MY(tex_max) = 70;
+       MY(type) = "spark";
+       MY(velocityjitter) = '1512.0 1512.0 1512.0';
+}
+// inner cloud of smoke
+SUB(bigplasma_impact) {
+       MY(airfriction) = 30;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 456;
+       MY(alpha_fade) = 1512;
+       MY(color_min) = "0x629dff";
+       MY(color_max) = "0x0018ff";
+       MY(count) = 15;
+       MY(originjitter) = '20.0 20.0 20.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -9;
+       MY(spin_max) = 9;
+       MY(sizeincrease) = 555;
+       MY(size_min) = 20;
+       MY(size_max) = 24;
+       MY(tex_min) = 48;
+       MY(tex_max) = 55;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '320.0 320.0 320.0';
+}
+// smoke
+SUB(bigplasma_impact) {
+       MY(airfriction) = 0.040000;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 328;
+       MY(alpha_fade) = 390;
+       MY(blend) = "alpha";
+       MY(color_min) = "0x222222";
+       MY(color_max) = "0x000000";
+       MY(count) = 16;
+       MY(gravity) = 0.400000;
+       MY(originjitter) = '80.0 80.0 10.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = 2;
+       MY(spin_max) = -2;
+       MY(sizeincrease) = 30;
+       MY(size_min) = 60;
+       MY(size_max) = 30;
+       MY(tex_max) = 7;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '100.0 100.0 200.0';
+       MY(velocityoffset) = '0.0 0.0 180.0';
+}
+// smoke in the middle
+SUB(bigplasma_impact) {
+       MY(airfriction) = 0.040000;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 328;
+       MY(alpha_fade) = 310;
+       MY(color_min) = "0x222222";
+       MY(color_max) = "0x000000";
+       MY(count) = 10;
+       MY(gravity) = -0.200000;
+       MY(originjitter) = '80.0 80.0 80.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = 20;
+       MY(spin_max) = -20;
+       MY(sizeincrease) = -10;
+       MY(size_min) = 60;
+       MY(size_max) = 70;
+       MY(tex_max) = 7;
+       MY(type) = "alphastatic";
+       MY(velocityjitter) = '10.0 10.0 10.0';
+}
+
+#include "effectinfo_ctf.inc"
+
+// spawn_point -- team idle spawn point effect
+#define spawn_point(name, color) \
+       DEF(spawn_point_##name); \
+       SUB(spawn_point_##name) { \
+               MY(airfriction) = 0.200000; \
+               MY(alpha_min) = 64; \
+               MY(alpha_max) = 128; \
+               MY(alpha_fade) = 128; \
+               MY(color_min) = color; \
+               MY(color_max) = color; \
+               MY(count) = 37.500000; \
+               MY(gravity) = -0.100000; \
+               MY(liquidfriction) = 0.800000; \
+               MY(originjitter) = '16.0 16.0 64.0'; \
+               MY(size_min) = 1; \
+               MY(size_max) = 2; \
+               MY(type) = "static"; \
+               MY(velocityjitter) = '32.0 32.0 0.0'; \
+       }
+
+spawn_point(red,               "0xFF0F0F")
+spawn_point(blue,              "0x0F0FFF")
+spawn_point(yellow,    "0xFFFF0F")
+spawn_point(pink,              "0xFF0FFF")
+spawn_point(neutral,   "0xFFFFFF")
+#undef spawn_point
+
+// spawn_event -- team spawning effect
+#define spawn_event(name, color) \
+       DEF(spawn_event_##name); \
+       SUB(spawn_event_##name) { \
+               MY(airfriction) = 2; \
+               MY(alpha_max) = 256; \
+               MY(alpha_fade) = 256; \
+               MY(bounce) = 1; \
+               MY(color_min) = color; \
+               MY(color_max) = color; \
+               MY(count) = 100; \
+               MY(originjitter) = '1.0 1.0 1.0'; \
+               MY(size_min) = 1; \
+               MY(size_max) = 1; \
+               MY(stretchfactor) = 0.600000; \
+               MY(tex_min) = 64; \
+               MY(tex_max) = 64; \
+               MY(type) = "spark"; \
+               MY(velocityjitter) = '500.0 500.0 500.0'; \
+               MY(velocitymultiplier) = 0.100000; \
+       } \
+       SUB(spawn_event_##name) { \
+               MY(alpha_min) = 190; \
+               MY(alpha_max) = 190; \
+               MY(alpha_fade) = 180; \
+               MY(color_min) = color; \
+               MY(color_max) = color; \
+               MY(countabsolute) = 1; \
+               MY(sizeincrease) = -80; \
+               MY(size_min) = 100; \
+               MY(size_max) = 100; \
+               MY(tex_min) = 65; \
+               MY(tex_max) = 65; \
+               MY(type) = "smoke"; \
+       } \
+       /**/
+
+spawn_event(red,               "0xFF0F0F")
+spawn_event(blue,              "0x0F0FFF")
+spawn_event(yellow,    "0xFFFF0F")
+spawn_event(pink,              "0xFF0FFF")
+spawn_event(neutral,   "0xFFFFFF")
+#undef spawn_event
+
+#include "effectinfo_nades.inc"
+
+DEF(shockwave_attack);
+// electricity
+SUB(shockwave_attack) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 4096;
+       MY(alpha_max) = 4096;
+       MY(alpha_fade) = 20000;
+       MY(color_min) = "0xb44215";
+       MY(color_max) = "0xff0000";
+       MY(count) = 1;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = 4000;
+       MY(spin_max) = -4000;
+       MY(sizeincrease) = 1.500000;
+       MY(size_min) = 5;
+       MY(size_max) = 7;
+       MY(stretchfactor) = 2.300000;
+       MY(tex_min) = 43;
+       MY(tex_max) = 43;
+       MY(type) = "spark";
+       MY(velocityjitter) = '10.0 10.0 10.0';
+       MY(velocitymultiplier) = 10;
+}
+// fire
+SUB(shockwave_attack) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 4096;
+       MY(alpha_max) = 4096;
+       MY(alpha_fade) = 20000;
+       MY(color_min) = "0xff4200";
+       MY(color_max) = "0xff0000";
+       MY(count) = 1;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(sizeincrease) = 1.500000;
+       MY(size_min) = 7;
+       MY(size_max) = 9;
+       MY(stretchfactor) = 2;
+       MY(tex_min) = 8;
+       MY(tex_max) = 15;
+       MY(type) = "spark";
+       MY(velocityjitter) = '10.0 10.0 10.0';
+       MY(velocitymultiplier) = 10;
+}
+
+DEF(arc_lightning);
+// impact decal
+SUB(arc_lightning) {
+       MY(alpha_min) = 32;
+       MY(alpha_max) = 32;
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '3.1 4.4 10.0';
+       MY(lightradiusfade) = 200;
+       MY(lightradius) = 50;
+       MY(originjitter) = '2.0 2.0 2.0';
+       MY(size_min) = 16;
+       MY(size_max) = 16;
+       MY(tex_min) = 16;
+       MY(tex_max) = 32;
+       MY(type) = "decal";
+}
+// impact sparks
+SUB(arc_lightning) {
+       MY(airfriction) = 110;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0xDDFDFF";
+       MY(color_max) = "0xFDFDFF";
+       MY(count) = 100;
+       MY(originjitter) = '20.0 20.0 20.0';
+       MY(startangle_max) = 360;
+       MY(spin_min) = -36000;
+       MY(spin_max) = 36000;
+       MY(sizeincrease) = -5;
+       MY(size_max) = 5;
+       MY(stretchfactor) = 1;
+       MY(tex_min) = 71;
+       MY(tex_max) = 74;
+       MY(type) = "static";
+       MY(velocityjitter) = '250.0 250.0 250.0';
+       MY(velocitymultiplier) = 100;
+}
+// impact sparks (underwater)
+SUB(arc_lightning) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0xDDFDFF";
+       MY(color_max) = "0xFDFDFF";
+       MY(count) = 100;
+       MY(liquidfriction) = 5;
+       MY(orientation) = "spark";
+       MY(originjitter) = '20.0 20.0 20.0';
+       MY(startangle_max) = 360;
+       MY(spin_min) = -36000;
+       MY(spin_max) = 36000;
+       MY(sizeincrease) = -5;
+       MY(size_max) = 5;
+       MY(stretchfactor) = 1;
+       MY(tex_min) = 71;
+       MY(tex_max) = 74;
+       MY(type) = "static";
+       MY(underwater) = true;
+       MY(velocityjitter) = '250.0 250.0 250.0';
+       MY(velocitymultiplier) = 20;
+}
+
+DEF(arc_beam);
+// sparks on beam
+SUB(arc_beam) {
+       MY(airfriction) = -10;
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 16384;
+       MY(color_min) = "0xfafad2";
+       MY(color_max) = "0xffffff";
+       MY(originjitter) = '3.0 3.0 3.0';
+       MY(relativeoriginoffset) = '10.0 0.0 0.0';
+       MY(startangle_max) = 360;
+       MY(spin_min) = 360;
+       MY(spin_max) = 1000;
+       MY(stretchfactor) = 1;
+       MY(tex_min) = 71;
+       MY(tex_max) = 74;
+       MY(time_min) = 0.050000;
+       MY(time_max) = 0.050000;
+       MY(trailspacing) = 10;
+       MY(type) = "spark";
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = 200;
+}
+// sparks on beam (underwater)
+SUB(arc_beam) {
+       MY(alpha_min) = 256;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 16384;
+       MY(color_min) = "0xfafad2";
+       MY(color_max) = "0xffffff";
+       MY(liquidfriction) = -10;
+       MY(originjitter) = '30.0 30.0 30.0';
+       MY(relativeoriginoffset) = '10.0 0.0 0.0';
+       MY(startangle_max) = 360;
+       MY(spin_min) = 360;
+       MY(spin_max) = 1000;
+       MY(stretchfactor) = 1;
+       MY(tex_min) = 71;
+       MY(tex_max) = 74;
+       MY(time_min) = 0.001000;
+       MY(time_max) = 0.001000;
+       MY(trailspacing) = 10;
+       MY(type) = "spark";
+       MY(underwater) = true;
+       MY(velocityjitter) = '100.0 100.0 100.0';
+       MY(velocitymultiplier) = 200;
+}
+
+DEF(arc_beam_heal);
+// bubble this...
+SUB(arc_beam_heal) {
+       MY(airfriction) = -20;
+       MY(alpha_min) = 2048;
+       MY(alpha_max) = 2048;
+       MY(alpha_fade) = 256;
+       MY(color_min) = "0x20FF20";
+       MY(color_max) = "0x40FF40";
+       MY(relativeoriginoffset) = '5.0 0.0 0.0';
+       MY(relativevelocityoffset) = '100.0 0.0 0.0';
+       MY(sizeincrease) = 20;
+       MY(size_min) = 0.100000;
+       MY(size_max) = 0.100000;
+       MY(tex_min) = 74;
+       MY(tex_max) = 74;
+       MY(trailspacing) = 1500;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '3.0 3.0 3.0';
+       MY(velocitymultiplier) = 200;
+}
+
+DEF(arc_beam_healimpact);
+// healing "aura"
+SUB(arc_beam_healimpact) {
+       MY(alpha_min) = 40;
+       MY(alpha_max) = 40;
+       MY(alpha_fade) = 350;
+       MY(color_min) = "0x00ff00";
+       MY(color_max) = "0x84c52f";
+       MY(countabsolute) = 1;
+       MY(lightcolor) = '0.0 4.4 0.0';
+       MY(lightradiusfade) = 150;
+       MY(lightradius) = 20;
+       MY(sizeincrease) = -1000;
+       MY(size_min) = 32;
+       MY(size_max) = 32;
+       MY(tex_min) = 33;
+       MY(tex_max) = 33;
+       MY(type) = "smoke";
+       MY(velocitymultiplier) = 44;
+}
+// rising "smoke"
+SUB(arc_beam_healimpact) {
+       MY(airfriction) = 3;
+       MY(alpha_min) = 200;
+       MY(alpha_max) = 456;
+       MY(alpha_fade) = 512;
+       MY(color_min) = "0x00ff00";
+       MY(color_max) = "0x84c52f";
+       MY(count) = 15;
+       MY(gravity) = -2;
+       MY(startangle_min) = -180;
+       MY(startangle_max) = 180;
+       MY(spin_min) = -90;
+       MY(spin_max) = 90;
+       MY(size_min) = 0.500000;
+       MY(size_max) = 1;
+       MY(tex_min) = 40;
+       MY(tex_max) = 40;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '120.0 120.0 420.0';
+}
+
+DEF(arc_smoke);
+// arc heat smoke  (notunderwater)
+SUB(arc_smoke) {
+       MY(airfriction) = 1;
+       MY(alpha_min) = 32;
+       MY(alpha_max) = 64;
+       MY(alpha_fade) = 48;
+       MY(color_min) = "0x4c453f";
+       MY(color_max) = "0x2a241f";
+       MY(count) = 2;
+       MY(gravity) = -0.125000;
+       MY(notunderwater) = true;
+       MY(startangle_max) = 360;
+       MY(spin_min) = -180;
+       MY(spin_max) = 180;
+       MY(sizeincrease) = 10;
+       MY(size_min) = 5;
+       MY(size_max) = 10;
+       MY(tex_max) = 8;
+       MY(type) = "smoke";
+       MY(velocityjitter) = '0.0 0.0 16.0';
+}
+// arc heat bubbles  (underwater)
+SUB(arc_smoke) {
+       MY(alpha_min) = 170;
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 64;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x404040";
+       MY(color_max) = "0x808080";
+       MY(count) = 2;
+       MY(gravity) = -0.125000;
+       MY(liquidfriction) = 0.250000;
+       MY(originjitter) = '6.0 6.0 6.0';
+       MY(size_min) = 0.100000;
+       MY(size_max) = 1;
+       MY(tex_min) = 62;
+       MY(tex_max) = 62;
+       MY(type) = "bubble";
+       MY(underwater) = true;
+       MY(velocityjitter) = '16.0 16.0 16.0';
+}
+
+DEF(arc_overheat);
+// arc overheat electric bolts
+SUB(arc_overheat) {
+       MY(airfriction) = 5;
+       MY(alpha_min) = 128;
+       MY(alpha_max) = 128;
+       MY(alpha_fade) = 292;
+       MY(color_min) = "0xffffff";
+       MY(color_max) = "0x9271fb";
+       MY(count) = 24;
+       MY(gravity) = -0.400000;
+       MY(liquidfriction) = 10;
+       MY(originjitter) = '10.0 10.0 10.0';
+       MY(sizeincrease) = -24;
+       MY(size_min) = 6;
+       MY(size_max) = 12;
+       MY(tex_min) = 43;
+       MY(tex_max) = 43;
+       MY(type) = "spark";
+       MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+DEF(arc_overheat_fire);
+// arc overheat bouncing sparks
+SUB(arc_overheat_fire) {
+       MY(alpha_max) = 256;
+       MY(alpha_fade) = 640;
+       MY(bounce) = 1.500000;
+       MY(color_min) = "0x4444ff";
+       MY(color_max) = "0xeeeeff";
+       MY(count) = 1;
+       MY(gravity) = 1;
+       MY(liquidfriction) = 5;
+       MY(originjitter) = '6.0 6.0 6.0';
+       MY(size_min) = 0.400000;
+       MY(size_max) = 1;
+       MY(type) = "spark";
+       MY(velocityjitter) = '92.0 92.0 92.0';
+       MY(velocitymultiplier) = 80;
+       MY(velocityoffset) = '0.0 0.0 80.0';
+}
+
+#include "effectinfo_buffs.inc"
+
+#include "effectinfo_instagib.inc"
diff --git a/qcsrc/common/effects/effectinfo.qc b/qcsrc/common/effects/effectinfo.qc
new file mode 100644 (file)
index 0000000..731903b
--- /dev/null
@@ -0,0 +1,303 @@
+#define EFFECTINFO_PARSER(on) \
+    on(type,                                        MY(type) \
+    ,{ ASSERT(n == 1 && "type");                    MY(type) = strzone(argv(1)); \
+    }, sprintf(" %s",                               (MY(type)) \
+    )) \
+    on(airfriction,                                 MY(airfriction) \
+    ,{ ASSERT(n == 1 && "airfriction");             MY(airfriction) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(airfriction)) \
+    )) \
+    on(alpha,                                       MY(alpha_min) ||                    MY(alpha_max) ||                MY(alpha_fade) \
+    ,{ ASSERT(n == 3 && "alpha");                   MY(alpha_min) = stof(argv(1));      MY(alpha_max) = stof(argv(2));  MY(alpha_fade) = stof(argv(3)); \
+    }, sprintf(" %s %s %s",                         ftos(MY(alpha_min)),                ftos(MY(alpha_max)),            ftos(MY(alpha_fade)) \
+    )) \
+    on(blend,                                       MY(blend) \
+    ,{ ASSERT(n == 1 && "blend");                   MY(blend) = strzone(argv(1)); \
+    }, sprintf(" %s",                               (MY(blend)) \
+    )) \
+    on(bounce,                                      MY(bounce) \
+    ,{ ASSERT(n == 1 && "bounce");                  MY(bounce) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(bounce)) \
+    )) \
+    on(color,                                       MY(color_min) ||                    MY(color_max) \
+    ,{ ASSERT(n == 2 && "color");                   MY(color_min) = strzone(argv(1));   MY(color_max) = strzone(argv(2)); \
+    }, sprintf(" %s %s",                            (MY(color_min)),                    (MY(color_max)) \
+    )) \
+    on(countabsolute,                               MY(countabsolute) \
+    ,{ ASSERT(n == 1 && "countabsolute");           MY(countabsolute) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(countabsolute)) \
+    )) \
+    on(count,                                       MY(count) \
+    ,{ ASSERT(n == 1 && "count");                   MY(count) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(count)) \
+    )) \
+    on(gravity,                                     MY(gravity) \
+    ,{ ASSERT(n == 1 && "gravity");                 MY(gravity) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(gravity)) \
+    )) \
+    on(lightcolor,                                  MY(lightcolor) \
+    ,{ ASSERT(n == 3 && "lightcolor");              MY(lightcolor) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+    }, sprintf(" %v",                               (MY(lightcolor)) \
+    )) \
+    on(lightradiusfade,                             MY(lightradiusfade) \
+    ,{ ASSERT(n == 1 && "lightradiusfade");         MY(lightradiusfade) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(lightradiusfade)) \
+    )) \
+    on(lightradius,                                 MY(lightradius) \
+    ,{ ASSERT(n == 1 && "lightradius");             MY(lightradius) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(lightradius)) \
+    )) \
+    on(lighttime,                                   MY(lighttime) \
+    ,{ ASSERT(n == 1 && "lighttime");               MY(lighttime) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(lighttime)) \
+    )) \
+    on(liquidfriction,                              MY(liquidfriction) \
+    ,{ ASSERT(n == 1 && "liquidfriction");          MY(liquidfriction) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(liquidfriction)) \
+    )) \
+    on(notunderwater,                               MY(notunderwater) \
+    ,{ ASSERT(n == 0 && "notunderwater");           MY(notunderwater) = true; \
+    }, "" \
+    ) \
+    on(orientation,                                 MY(orientation) \
+    ,{ ASSERT(n == 1 && "orientation");             MY(orientation) = strzone(argv(1)); \
+    }, sprintf(" %s",                               (MY(orientation)) \
+    )) \
+    on(originjitter,                                MY(originjitter) \
+    ,{ ASSERT(n == 3 && "originjitter");            MY(originjitter) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+    }, sprintf(" %v",                               (MY(originjitter)) \
+    )) \
+    on(originoffset,                                MY(originoffset) \
+    ,{ ASSERT(n == 3 && "originoffset");            MY(originoffset) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+    }, sprintf(" %v",                               (MY(originoffset)) \
+    )) \
+    on(relativeoriginoffset,                        MY(relativeoriginoffset) \
+    ,{ ASSERT(n == 3 && "relativeoriginoffset");    MY(relativeoriginoffset) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+    }, sprintf(" %v",                               (MY(relativeoriginoffset)) \
+    )) \
+    on(relativevelocityoffset,                      MY(relativevelocityoffset) \
+    ,{ ASSERT(n == 3 && "relativevelocityoffset");  MY(relativevelocityoffset) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+    }, sprintf(" %v",                               (MY(relativevelocityoffset)) \
+    )) \
+    on(rotate,                                      MY(startangle_min) ||               MY(startangle_max) ||               MY(spin_min) ||                 MY(spin_max) \
+    ,{ ASSERT(n == 4 && "rotate");                  MY(startangle_min) = stof(argv(1)); MY(startangle_max) = stof(argv(2)); MY(spin_min) = stof(argv(3));   MY(spin_max) = stof(argv(4)); \
+    }, sprintf(" %s %s %s %s",                      ftos(MY(startangle_min)),           ftos(MY(startangle_max)),           ftos(MY(spin_min)),             ftos(MY(spin_max)) \
+    )) \
+    on(sizeincrease,                                MY(sizeincrease) \
+    ,{ ASSERT(n == 1 && "sizeincrease");            MY(sizeincrease) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(sizeincrease)) \
+    )) \
+    on(size,                                        MY(size_min) ||                     MY(size_max) \
+    ,{ ASSERT(n == 2 && "size");                    MY(size_min) = stof(argv(1));       MY(size_max) = stof(argv(2)); \
+    }, sprintf(" %s %s",                            ftos(MY(size_min)),                 ftos(MY(size_max)) \
+    )) \
+    on(staincolor,                                  MY(staincolor_min) ||                   MY(staincolor_max) \
+    ,{ ASSERT(n == 2 && "staincolor");              MY(staincolor_min) = strzone(argv(1));  MY(staincolor_max) = strzone(argv(2)); \
+    }, sprintf(" %s %s",                            (MY(staincolor_min)),                   (MY(staincolor_max)) \
+    )) \
+    on(stainsize,                                   MY(stainsize_min) ||                MY(stainsize_max) \
+    ,{ ASSERT(n == 2 && "stainsize");               MY(stainsize_min) = stof(argv(1));  MY(stainsize_max) = stof(argv(2)); \
+    }, sprintf(" %s %s",                            ftos(MY(stainsize_min)),            ftos(MY(stainsize_max)) \
+    )) \
+    on(staintex,                                    MY(staintex_min) ||                 MY(staintex_max) \
+    ,{ ASSERT(n == 2 && "staintex");                MY(staintex_min) = stof(argv(1));   MY(staintex_max) = stof(argv(2)); \
+    }, sprintf(" %s %s",                            ftos(MY(staintex_min)),             ftos(MY(staintex_max)) \
+    )) \
+    on(stretchfactor,                               MY(stretchfactor) \
+    ,{ ASSERT(n == 1 && "stretchfactor");           MY(stretchfactor) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(stretchfactor)) \
+    )) \
+    on(tex,                                         MY(tex_min) ||                      MY(tex_max) \
+    ,{ ASSERT(n == 2 && "tex");                     MY(tex_min) = stof(argv(1));        MY(tex_max) = stof(argv(2)); \
+    }, sprintf(" %s %s",                            ftos(MY(tex_min)),                  ftos(MY(tex_max)) \
+    )) \
+    on(time,                                        MY(time_min) ||                     MY(time_max) \
+    ,{ ASSERT(n == 2 && "time");                    MY(time_min) = stof(argv(1));       MY(time_max) = stof(argv(2)); \
+    }, sprintf(" %s %s",                            ftos(MY(time_min)),                 ftos(MY(time_max)) \
+    )) \
+    on(trailspacing,                                MY(trailspacing) \
+    ,{ ASSERT(n == 1 && "trailspacing");            MY(trailspacing) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(trailspacing)) \
+    )) \
+    on(underwater,                                  MY(underwater) \
+    ,{ ASSERT(n == 0 && "underwater");              MY(underwater) = true; \
+    }, "" \
+    ) \
+    on(velocityjitter,                              MY(velocityjitter) \
+    ,{ ASSERT(n == 3 && "velocityjitter");          MY(velocityjitter) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+    }, sprintf(" %v",                               (MY(velocityjitter)) \
+    )) \
+    on(velocitymultiplier,                          MY(velocitymultiplier) \
+    ,{ ASSERT(n == 1 && "velocitymultiplier");      MY(velocitymultiplier) = stof(argv(1)); \
+    }, sprintf(" %s",                               ftos(MY(velocitymultiplier)) \
+    )) \
+    on(velocityoffset,                              MY(velocityoffset) \
+    ,{ ASSERT(n == 3 && "velocityoffset");          MY(velocityoffset) = vec3(stof(argv(1)), stof(argv(2)), stof(argv(3))); \
+    }, sprintf(" %v",                               (MY(velocityoffset)) \
+    )) \
+    /**/
+
+CLASS(EffectInfo, Object)
+    ATTRIB(EffectInfo, effectinfo_name, string, string_null)
+    CONSTRUCTOR(EffectInfo, string s) {
+        CONSTRUCT(EffectInfo);
+        this.effectinfo_name = s;
+    }
+
+    #define FIELDS(MY) \
+    MY(airfriction, float, 0) \
+    MY(alpha_min, float, 0) \
+    MY(alpha_max, float, 0) \
+    MY(alpha_fade, float, 0) \
+    MY(blend, string, string_null) \
+    MY(bounce, float, 0) \
+    MY(color_min, string, string_null) \
+    MY(color_max, string, string_null) \
+    MY(countabsolute, float, 0) \
+    MY(count, float, 0) \
+    MY(gravity, float, 0) \
+    MY(lightcolor, vector, '0 0 0') \
+    MY(lightradiusfade, float, 0) \
+    MY(lightradius, float, 0) \
+    MY(lighttime, float, 0) \
+    MY(liquidfriction, float, 0) \
+    MY(notunderwater, bool, false) \
+    MY(orientation, string, string_null) \
+    MY(originjitter, vector, '0 0 0') \
+    MY(originoffset, vector, '0 0 0') \
+    MY(relativeoriginoffset, vector, '0 0 0') \
+    MY(relativevelocityoffset, vector, '0 0 0') \
+    MY(startangle_min, float, 0) \
+    MY(startangle_max, float, 0) \
+    MY(spin_min, float, 0) \
+    MY(spin_max, float, 0) \
+    MY(sizeincrease, float, 0) \
+    MY(size_min, float, 0) \
+    MY(size_max, float, 0) \
+    MY(staincolor_min, string, string_null) \
+    MY(staincolor_max, string, string_null) \
+    MY(stainsize_min, float, 0) \
+    MY(stainsize_max, float, 0) \
+    MY(staintex_min, float, 0) \
+    MY(staintex_max, float, 0) \
+    MY(stretchfactor, float, 0) \
+    MY(tex_min, float, 0) \
+    MY(tex_max, float, 0) \
+    MY(time_min, float, 0) \
+    MY(time_max, float, 0) \
+    MY(trailspacing, float, 0) \
+    MY(type, string, string_null) \
+    MY(underwater, bool, false) \
+    MY(velocityjitter, vector, '0 0 0') \
+    MY(velocitymultiplier, float, 0) \
+    MY(velocityoffset, vector, '0 0 0') \
+    /**/
+
+    #define MY(f, type, val) ATTRIB(EffectInfo, effectinfo_##f, type, val)
+    FIELDS(MY)
+    #undef MY
+
+    METHOD(EffectInfo, describe, string(EffectInfo this)) {
+        string s = sprintf("SUB(%s) {\n", this.effectinfo_name);
+        #define str_bool(it) (it ? "true" : "false")
+        #define str_float(it) ftos(it)
+        #define str_vector(it) vtos(it)
+        #define str_string(it) strcat("\"", it, "\"")
+        #define p(f, type, default) if (this.effectinfo_##f) { s = strcat(s, "\t", "MY("#f") = ", str_##type(this.effectinfo_##f), ";\n"); }
+        FIELDS(p)
+        #undef p
+        #undef MY
+        return strcat(s, "}\n");
+    }
+
+    METHOD(EffectInfo, dump, string(EffectInfo this)) {
+        string s = sprintf("effect %s\n", this.effectinfo_name);
+        #define MY(f) this.effectinfo_##f
+        #define p(k, isset, parse, unparse) if (isset) { s = strcat(s, "\t", #k, unparse, "\n"); }
+        EFFECTINFO_PARSER(p)
+        #undef p
+        #undef MY
+        return s;
+    }
+
+    #undef FIELDS
+ENDCLASS(EffectInfo)
+
+CLASS(EffectInfoGroup, Object)
+    ATTRIBARRAY(EffectInfoGroup, children, EffectInfo, 16)
+    ATTRIB(EffectInfoGroup, children_count, int, 0)
+ENDCLASS(EffectInfoGroup)
+
+void effectinfo_read()
+{
+    int fh = fopen("effectinfo.txt", FILE_READ);
+    EffectInfo info = NULL;
+    for (string line; (line = fgets(fh)); ) {
+        int n = tokenize_console(line);
+        if (n == 0) continue;
+        n--;
+        string k = argv(0);
+        if (k == "effect") {
+            ASSERT(n == 1);
+            info = NEW(EffectInfo, strzone(argv(1)));
+            continue;
+        }
+        ASSERT(info != NULL);
+        switch (k) {
+            #define MY(f) info.effectinfo_##f
+            #define p(k, isset, parse, unparse) case #k: parse break;
+            EFFECTINFO_PARSER(p)
+            #undef p
+            #undef MY
+            default:
+                LOG_WARNINGF("Unknown property '%s'\n", k);
+                break;
+        }
+    }
+    fclose(fh);
+}
+
+void effectinfo_dump(int fh, bool alsoprint)
+{
+    #define WRITE(s) do { \
+        fputs(fh, s); \
+        if (alsoprint) LOG_INFO(s); \
+    } while (0)
+    WRITE("// ********************************************** //\n");
+    WRITE("// ** WARNING - DO NOT MANUALLY EDIT THIS FILE ** //\n");
+    WRITE("// **                                          ** //\n");
+    WRITE("// **  This file is automatically generated by ** //\n");
+    WRITE("// **  code with the command 'dumpeffectinfo'. ** //\n");
+    WRITE("// **                                          ** //\n");
+    WRITE("// **  If you modify an effect, please         ** //\n");
+    WRITE("// **  regenerate this file with that command. ** //\n");
+    WRITE("// **                                          ** //\n");
+    WRITE("// ********************************************** //\n");
+    WRITE("\n");
+
+    for (EffectInfo it = NULL; (it = findfloat(it, instanceOfEffectInfo, true)); ) {
+        if (it.classname == "vtbl") continue;
+        string s = it.dump(it);
+        WRITE(s);
+    }
+    #undef WRITE
+}
+
+
+REGISTRY(EffectInfos, BIT(9))
+REGISTER_REGISTRY(RegisterEffectInfos)
+#define EFFECTINFO(name) \
+    [[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this) { } \
+    REGISTER(RegisterEffectInfos, EFFECTINFO, EffectInfos, name, m_id, NEW(EffectInfoGroup)) { \
+        effectinfo_##name(this, NULL); \
+    }
+
+#define MY(f) this.effectinfo_##f
+#define DEF(name) EFFECTINFO(name)
+#define SUB(name) \
+    [[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this) { parent = EFFECTINFO_##name; parent.children[parent.children_count++] = this = NEW(EffectInfo, #name); } \
+    [[accumulate]] void effectinfo_##name(EffectInfoGroup parent, EffectInfo this)
+#include "effectinfo.inc"
+#undef MY
+#undef DEF
+#undef SUB
diff --git a/qcsrc/common/effects/effectinfo_buffs.inc b/qcsrc/common/effects/effectinfo_buffs.inc
new file mode 100644 (file)
index 0000000..8ac9041
--- /dev/null
@@ -0,0 +1,305 @@
+DEF(relic_resistance);
+SUB(relic_resistance) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0x00ff80";
+    MY(color_max) = "0x00ff80";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_regeneration);
+SUB(relic_regeneration) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0x00ffff";
+    MY(color_max) = "0x00ffff";
+    MY(count) = 1;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_vampire);
+SUB(relic_vampire) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0xff00ff";
+    MY(color_max) = "0xff00ff";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_ammo);
+SUB(relic_ammo) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0x80ff00";
+    MY(color_max) = "0x80ff00";
+    MY(count) = 1;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_damage);
+SUB(relic_damage) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0xff0000";
+    MY(color_max) = "0xff0000";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_ssplashdamage);
+SUB(relic_ssplashdamage) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0xff8000";
+    MY(color_max) = "0xff8000";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_firingspeed);
+SUB(relic_firingspeed) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0xffff00";
+    MY(color_max) = "0xffff00";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_disability);
+SUB(relic_disability) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0x0000ff";
+    MY(color_max) = "0x0000ff";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_disability_curse);
+SUB(relic_disability_curse) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0x000080";
+    MY(color_max) = "0x000080";
+    MY(count) = 1;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_teamboost);
+SUB(relic_teamboost) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0xffffff";
+    MY(color_max) = "0xffffff";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_teamboost_boost);
+SUB(relic_teamboost_boost) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0x808080";
+    MY(color_max) = "0x808080";
+    MY(count) = 1;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_speed);
+SUB(relic_speed) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0x80ffff";
+    MY(color_max) = "0x80ffff";
+    MY(count) = 1;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_jump);
+SUB(relic_jump) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0xffff80";
+    MY(color_max) = "0xffff80";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_flight);
+SUB(relic_flight) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0x8080ff";
+    MY(color_max) = "0x8080ff";
+    MY(count) = 1;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_radioactive);
+SUB(relic_radioactive) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0x00ff00";
+    MY(color_max) = "0x00ff00";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_resurrection);
+SUB(relic_resurrection) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0xff0080";
+    MY(color_max) = "0xff0080";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
+
+DEF(relic_vengeance);
+SUB(relic_vengeance) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 256;
+    MY(color_min) = "0xff8080";
+    MY(color_max) = "0xff8080";
+    MY(count) = 20;
+    MY(gravity) = -0.100000;
+    MY(liquidfriction) = 0.800000;
+    MY(originjitter) = '8.0 8.0 32.0';
+    MY(size_min) = 1.500000;
+    MY(size_max) = 1.500000;
+    MY(type) = "static";
+    MY(velocityjitter) = '64.0 64.0 32.0';
+}
diff --git a/qcsrc/common/effects/effectinfo_ctf.inc b/qcsrc/common/effects/effectinfo_ctf.inc
new file mode 100644 (file)
index 0000000..5794ad4
--- /dev/null
@@ -0,0 +1,123 @@
+// flag_touch -- effects for touching the flag
+#define flag_touch(name, colormin, colormax) \
+    DEF(name##flag_touch); \
+    SUB(name##flag_touch) { \
+        MY(airfriction) = 3; \
+        MY(alpha_max) = 256; \
+        MY(alpha_fade) = 556; \
+        MY(bounce) = 1.500000; \
+        MY(color_min) = colormin; \
+        MY(color_max) = colormax; \
+        MY(count) = 35; \
+        MY(gravity) = 1; \
+        MY(originjitter) = '1.0 1.0 1.0'; \
+        MY(size_min) = 1; \
+        MY(size_max) = 3; \
+        MY(tex_min) = 40; \
+        MY(tex_max) = 40; \
+        MY(type) = "spark"; \
+        MY(velocityjitter) = '300.0 300.0 300.0'; \
+        MY(velocitymultiplier) = 0.500000; \
+    }
+
+flag_touch(red,     "0xFF0000", "0x970000")
+flag_touch(blue,    "0x0000FF", "0x000097")
+flag_touch(yellow,  "0xFFFF0F", "0xFFFF0F")
+flag_touch(pink,    "0xFF0FFF", "0xFF0FFF")
+flag_touch(neutral, "0xFFFFFF", "0xFFFFFF")
+#undef flag_touch
+
+#define pass(name, colormin, colormax) \
+    DEF(name##_pass); \
+    SUB(name##_pass) { \
+        MY(airfriction) = 5; \
+        MY(alpha_min) = 64; \
+        MY(alpha_max) = 128; \
+        MY(alpha_fade) = 64; \
+        MY(color_min) = colormin; \
+        MY(color_max) = colormax; \
+        MY(sizeincrease) = 2; \
+        MY(size_min) = 2; \
+        MY(size_max) = 2; \
+        MY(tex_min) = 32; \
+        MY(tex_max) = 32; \
+        MY(trailspacing) = 64; \
+        MY(type) = "static"; \
+    } \
+    SUB(name##_pass) { \
+        MY(airfriction) = 9; \
+        MY(alpha_min) = 32; \
+        MY(alpha_max) = 64; \
+        MY(alpha_fade) = 32; \
+        MY(color_min) = colormin; \
+        MY(color_max) = colormax; \
+        MY(sizeincrease) = 8; \
+        MY(size_min) = 1; \
+        MY(size_max) = 1; \
+        MY(tex_max) = 8; \
+        MY(trailspacing) = 12; \
+        MY(type) = "static"; \
+        MY(velocityjitter) = '64.0 64.0 64.0'; \
+    } \
+    SUB(name##_pass) { \
+        MY(alpha_min) = 256; \
+        MY(alpha_max) = 256; \
+        MY(alpha_fade) = 1280; \
+        MY(color_min) = colormin; \
+        MY(color_max) = colormax; \
+        MY(size_min) = 4; \
+        MY(size_max) = 4; \
+        MY(trailspacing) = 12; \
+        MY(type) = "static"; \
+    } \
+    /**/
+
+pass(red,       "0xFF0000", "0x970000")
+pass(blue,      "0x0000FF", "0x000097")
+pass(yellow,    "0xFFFF0F", "0xFFFF0F")
+pass(pink,      "0xFFFFFF", "0xFFFFFF")
+pass(neutral,   "0xFFFFFF", "0xFFFFFF")
+#undef pass
+
+// cap -- team capture effect
+#define cap(name, colormin, colormax) \
+    DEF(name##_cap); \
+    SUB(name##_cap) { \
+        MY(airfriction) = 2; \
+        MY(alpha_max) = 256; \
+        MY(alpha_fade) = 100; \
+        MY(bounce) = 1.500000; \
+        MY(color_min) = colormin; \
+        MY(color_max) = colormax; \
+        MY(count) = 500; \
+        MY(originjitter) = '1.0 1.0 1.0'; \
+        MY(size_min) = 1; \
+        MY(size_max) = 1; \
+        MY(stretchfactor) = 0.600000; \
+        MY(tex_min) = 64; \
+        MY(tex_max) = 64; \
+        MY(type) = "spark"; \
+        MY(velocityjitter) = '1000.0 1000.0 1500.0'; \
+        MY(velocitymultiplier) = 0.500000; \
+    } \
+    SUB(name##_cap) { \
+        MY(alpha_min) = 190; \
+        MY(alpha_max) = 190; \
+        MY(alpha_fade) = 180; \
+        MY(color_min) = colormin; \
+        MY(color_max) = colormax; \
+        MY(countabsolute) = 1; \
+        MY(sizeincrease) = -80; \
+        MY(size_min) = 150; \
+        MY(size_max) = 150; \
+        MY(tex_min) = 65; \
+        MY(tex_max) = 65; \
+        MY(type) = "smoke"; \
+    } \
+    /**/
+
+cap(red,    "0xFF0000", "0x970000")
+cap(blue,   "0x0000FF", "0x000097")
+cap(yellow, "0xFFFF0F", "0xFFFF0F")
+cap(pink,   "0xFF0FFF", "0xFF0FFF")
+#undef cap
diff --git a/qcsrc/common/effects/effectinfo_gentle.inc b/qcsrc/common/effects/effectinfo_gentle.inc
new file mode 100644 (file)
index 0000000..aef1664
--- /dev/null
@@ -0,0 +1,121 @@
+// cl_gentle impact effect indicating damage
+// NOTE: maintained by div0, make your own new effect instead of changing this one without asking!
+DEF(damage_hit);
+SUB(damage_hit) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 128;
+    MY(alpha_fade) = 192;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0x00FFFF";
+    MY(color_max) = "0xFF00FF";
+    MY(count) = 0.500000;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 10;
+    MY(sizeincrease) = -24;
+    MY(size_min) = 16;
+    MY(size_max) = 16;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '256.0 256.0 256.0';
+}
+SUB(damage_hit) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 128;
+    MY(alpha_fade) = 192;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xFF00FF";
+    MY(color_max) = "0xFFFF00";
+    MY(count) = 0.500000;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 10;
+    MY(sizeincrease) = -24;
+    MY(size_min) = 16;
+    MY(size_max) = 16;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '256.0 256.0 256.0';
+}
+SUB(damage_hit) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 128;
+    MY(alpha_fade) = 192;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xFFFF00";
+    MY(color_max) = "0x00FFFF";
+    MY(count) = 0.500000;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 10;
+    MY(sizeincrease) = -24;
+    MY(size_min) = 16;
+    MY(size_max) = 16;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '256.0 256.0 256.0';
+}
+
+// effect for removing player model
+DEF(damage_dissolve);
+// large sparks
+SUB(damage_dissolve) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 128;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0x00FFFF";
+    MY(color_max) = "0xFF00FF";
+    MY(count) = 15;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 6;
+    MY(sizeincrease) = -16;
+    MY(size_min) = 32;
+    MY(size_max) = 32;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '512.0 512.0 512.0';
+}
+SUB(damage_dissolve) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 128;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xFF00FF";
+    MY(color_max) = "0xFFFF00";
+    MY(count) = 15;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 6;
+    MY(sizeincrease) = -16;
+    MY(size_min) = 32;
+    MY(size_max) = 32;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '512.0 512.0 512.0';
+}
+SUB(damage_dissolve) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 128;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xFFFF00";
+    MY(color_max) = "0x00FFFF";
+    MY(count) = 15;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 6;
+    MY(sizeincrease) = -16;
+    MY(size_min) = 32;
+    MY(size_max) = 32;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '512.0 512.0 512.0';
+}
diff --git a/qcsrc/common/effects/effectinfo_gentle_happy.inc b/qcsrc/common/effects/effectinfo_gentle_happy.inc
new file mode 100644 (file)
index 0000000..4afbe00
--- /dev/null
@@ -0,0 +1,119 @@
+// happy death fx for cl_gentle
+DEF(happy_damage_dissolve);
+SUB(happy_damage_dissolve) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 228;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0x00FFFF";
+    MY(color_max) = "0xFF00FF";
+    MY(count) = 15;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 6;
+    MY(sizeincrease) = -10;
+    MY(size_min) = 32;
+    MY(size_max) = 32;
+    MY(tex_min) = 69;
+    MY(tex_max) = 69;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '312.0 312.0 312.0';
+}
+SUB(happy_damage_dissolve) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 228;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xFF00FF";
+    MY(color_max) = "0xFFFF00";
+    MY(count) = 15;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 6;
+    MY(sizeincrease) = -10;
+    MY(size_min) = 32;
+    MY(size_max) = 32;
+    MY(tex_min) = 69;
+    MY(tex_max) = 69;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '312.0 312.0 312.0';
+}
+SUB(happy_damage_dissolve) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 228;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xFFFF00";
+    MY(color_max) = "0x00FFFF";
+    MY(count) = 15;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 6;
+    MY(sizeincrease) = -10;
+    MY(size_min) = 32;
+    MY(size_max) = 32;
+    MY(tex_min) = 69;
+    MY(tex_max) = 69;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '312.0 312.0 312.0';
+}
+
+// happy damage fx for cl_gentle
+DEF(happy_damage_hit);
+SUB(happy_damage_hit) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 128;
+    MY(alpha_fade) = 192;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0x00FFFF";
+    MY(color_max) = "0xFF00FF";
+    MY(count) = 0.100000;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 10;
+    MY(sizeincrease) = -28;
+    MY(size_min) = 26;
+    MY(size_max) = 26;
+    MY(tex_min) = 69;
+    MY(tex_max) = 69;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '156.0 156.0 156.0';
+}
+SUB(happy_damage_hit) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 128;
+    MY(alpha_fade) = 192;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xFF00FF";
+    MY(color_max) = "0xFFFF00";
+    MY(count) = 0.100000;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 10;
+    MY(sizeincrease) = -28;
+    MY(size_min) = 26;
+    MY(size_max) = 26;
+    MY(tex_min) = 69;
+    MY(tex_max) = 69;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '156.0 156.0 156.0';
+}
+SUB(happy_damage_hit) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 128;
+    MY(alpha_fade) = 192;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xFFFF00";
+    MY(color_max) = "0x00FFFF";
+    MY(count) = 0.100000;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 10;
+    MY(sizeincrease) = -28;
+    MY(size_min) = 26;
+    MY(size_max) = 26;
+    MY(tex_min) = 69;
+    MY(tex_max) = 69;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '156.0 156.0 156.0';
+}
diff --git a/qcsrc/common/effects/effectinfo_gentle_morphed.inc b/qcsrc/common/effects/effectinfo_gentle_morphed.inc
new file mode 100644 (file)
index 0000000..c334912
--- /dev/null
@@ -0,0 +1,121 @@
+// cl_gentle impact effect indicating damage
+DEF(morphed_damage_hit);
+SUB(morphed_damage_hit) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 128;
+    MY(alpha_fade) = 292;
+    MY(color_min) = "0xffffff";
+    MY(color_max) = "0x9271fb";
+    MY(count) = 0.500000;
+    MY(gravity) = -0.400000;
+    MY(liquidfriction) = 10;
+    MY(sizeincrease) = -24;
+    MY(size_min) = 14;
+    MY(size_max) = 24;
+    MY(tex_min) = 43;
+    MY(tex_max) = 43;
+    MY(type) = "spark";
+    MY(velocityjitter) = '356.0 356.0 456.0';
+}
+SUB(morphed_damage_hit) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 128;
+    MY(alpha_fade) = 292;
+    MY(color_min) = "0xffffff";
+    MY(color_max) = "0x9271fb";
+    MY(count) = 0.500000;
+    MY(liquidfriction) = 10;
+    MY(originjitter) = '10.0 10.0 10.0';
+    MY(sizeincrease) = -24;
+    MY(size_min) = 24;
+    MY(size_max) = 24;
+    MY(tex_max) = 8;
+    MY(type) = "smoke";
+}
+
+// effect for removing player model
+DEF(morphed_damage_dissolve);
+SUB(morphed_damage_dissolve) {
+    MY(airfriction) = 8;
+    MY(alpha_min) = 456;
+    MY(alpha_max) = 456;
+    MY(alpha_fade) = 1828;
+    MY(color_min) = "0xffffff";
+    MY(color_max) = "0x9271fb";
+    MY(count) = 10;
+    MY(gravity) = -1.900000;
+    MY(liquidfriction) = 6;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -399;
+    MY(spin_max) = -99;
+    MY(sizeincrease) = -16;
+    MY(size_min) = 40;
+    MY(size_max) = 40;
+    MY(tex_min) = 43;
+    MY(tex_max) = 43;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '256.0 256.0 512.0';
+}
+SUB(morphed_damage_dissolve) {
+    MY(airfriction) = 9;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 628;
+    MY(color_min) = "0x7bdbff";
+    MY(color_max) = "0xbed2ff";
+    MY(count) = 2.500000;
+    MY(gravity) = -0.800000;
+    MY(liquidfriction) = 6;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(sizeincrease) = -16;
+    MY(size_min) = 40;
+    MY(size_max) = 40;
+    MY(tex_min) = 43;
+    MY(tex_max) = 43;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '256.0 256.0 512.0';
+}
+SUB(morphed_damage_dissolve) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 156;
+    MY(alpha_max) = 156;
+    MY(alpha_fade) = 128;
+    MY(color_min) = "0xffffff";
+    MY(color_max) = "0x9271fb";
+    MY(count) = 5;
+    MY(liquidfriction) = 6;
+    MY(originjitter) = '22.0 22.0 76.0';
+    MY(sizeincrease) = -16;
+    MY(size_min) = 44;
+    MY(size_max) = 44;
+    MY(tex_min) = 65;
+    MY(tex_max) = 65;
+    MY(type) = "smoke";
+}
+SUB(morphed_damage_dissolve) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 56;
+    MY(alpha_max) = 56;
+    MY(alpha_fade) = 128;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xffffff";
+    MY(color_max) = "0x9271fb";
+    MY(count) = 15;
+    MY(gravity) = 1;
+    MY(liquidfriction) = 6;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = 999;
+    MY(spin_max) = -999;
+    MY(sizeincrease) = -16;
+    MY(size_min) = 32;
+    MY(size_max) = 32;
+    MY(tex_min) = 46;
+    MY(tex_max) = 46;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '400.0 400.0 0.0';
+}
diff --git a/qcsrc/common/effects/effectinfo_gentle_particlegibs.inc b/qcsrc/common/effects/effectinfo_gentle_particlegibs.inc
new file mode 100644 (file)
index 0000000..f01c175
--- /dev/null
@@ -0,0 +1,199 @@
+// cl_gentle impact effect indicating damage
+DEF(particlegibs_damage_hit);
+// core decal
+SUB(particlegibs_damage_hit) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 428;
+    MY(bounce) = -1;
+    MY(color_min) = "0xA8FFFF";
+    MY(color_max) = "0xA8FFFFF";
+    MY(count) = 0.500000;
+    MY(gravity) = 1;
+    MY(liquidfriction) = 6;
+    MY(size_min) = 5;
+    MY(size_max) = 10;
+    MY(staincolor_min) = "0x808080";
+    MY(staincolor_max) = "0x808080";
+    MY(staintex_min) = 16;
+    MY(staintex_max) = 24;
+    MY(tex_max) = 8;
+    MY(type) = "blood";
+    MY(velocityjitter) = '156.0 156.0 212.0';
+}
+// front blood
+SUB(particlegibs_damage_hit) {
+    MY(airfriction) = 1;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 328;
+    MY(bounce) = -1;
+    MY(color_min) = "0xA8FFFF";
+    MY(color_max) = "0xA8FFFFF";
+    MY(count) = 0.100000;
+    MY(gravity) = 0.500000;
+    MY(liquidfriction) = 3;
+    MY(sizeincrease) = -15;
+    MY(size_min) = 10;
+    MY(size_max) = 20;
+    MY(staincolor_min) = "0x808080";
+    MY(staincolor_max) = "0x808080";
+    MY(staintex_min) = 16;
+    MY(staintex_max) = 24;
+    MY(tex_min) = 24;
+    MY(tex_max) = 32;
+    MY(type) = "blood";
+    MY(velocityjitter) = '6.0 6.0 30.0';
+    MY(velocitymultiplier) = -1;
+}
+// back blood
+SUB(particlegibs_damage_hit) {
+    MY(airfriction) = 1;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 328;
+    MY(bounce) = -1;
+    MY(color_min) = "0xA8FFFF";
+    MY(color_max) = "0xA8FFFFF";
+    MY(count) = 0.100000;
+    MY(gravity) = 1;
+    MY(liquidfriction) = 3;
+    MY(originjitter) = '3.0 3.0 3.0';
+    MY(sizeincrease) = 10;
+    MY(size_min) = 5;
+    MY(size_max) = 15;
+    MY(staincolor_min) = "0x808080";
+    MY(staincolor_max) = "0x808080";
+    MY(staintex_min) = 16;
+    MY(staintex_max) = 24;
+    MY(tex_min) = 24;
+    MY(tex_max) = 32;
+    MY(type) = "blood";
+    MY(velocityjitter) = '26.0 26.0 112.0';
+    MY(velocitymultiplier) = 2;
+}
+
+// effect for removing player model
+DEF(particlegibs_damage_dissolve);
+// small core blood no decals
+SUB(particlegibs_damage_dissolve) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 328;
+    MY(color_min) = "0x00ffff";
+    MY(color_max) = "0x82ffff";
+    MY(count) = 32;
+    MY(gravity) = 1;
+    MY(liquidfriction) = 6;
+    MY(originjitter) = '10.0 10.0 25.0';
+    MY(size_min) = 15;
+    MY(size_max) = 20;
+    MY(staincolor_min) = "0x808080";
+    MY(staincolor_max) = "0x808080";
+    MY(staintex_min) = 16;
+    MY(staintex_max) = 24;
+    MY(tex_max) = 8;
+    MY(type) = "blood";
+    MY(velocityjitter) = '256.0 256.0 312.0';
+}
+// core decal
+SUB(particlegibs_damage_dissolve) {
+    MY(airfriction) = 2;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 528;
+    MY(bounce) = -1;
+    MY(color_min) = "0xA8FFFF";
+    MY(color_max) = "0xA8FFFFF";
+    MY(count) = 12;
+    MY(gravity) = 2;
+    MY(liquidfriction) = 6;
+    MY(originjitter) = '10.0 10.0 25.0';
+    MY(size_min) = 20;
+    MY(size_max) = 40;
+    MY(staincolor_min) = "0x808080";
+    MY(staincolor_max) = "0x808080";
+    MY(staintex_min) = 16;
+    MY(staintex_max) = 24;
+    MY(tex_max) = 8;
+    MY(type) = "blood";
+    MY(velocityjitter) = '356.0 356.0 412.0';
+}
+// front blood
+SUB(particlegibs_damage_dissolve) {
+    MY(airfriction) = 1;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 328;
+    MY(bounce) = -1;
+    MY(color_min) = "0xA8FFFF";
+    MY(color_max) = "0xA8FFFFF";
+    MY(count) = 32;
+    MY(gravity) = 0.500000;
+    MY(liquidfriction) = 3;
+    MY(originjitter) = '5.0 5.0 10.0';
+    MY(sizeincrease) = -15;
+    MY(size_min) = 10;
+    MY(size_max) = 20;
+    MY(staincolor_min) = "0x808080";
+    MY(staincolor_max) = "0x808080";
+    MY(staintex_min) = 16;
+    MY(staintex_max) = 24;
+    MY(tex_min) = 24;
+    MY(tex_max) = 32;
+    MY(type) = "blood";
+    MY(velocityjitter) = '56.0 56.0 212.0';
+    MY(velocitymultiplier) = -0.300000;
+}
+// back blood
+SUB(particlegibs_damage_dissolve) {
+    MY(airfriction) = 1;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 328;
+    MY(bounce) = -1;
+    MY(color_min) = "0xA8FFFF";
+    MY(color_max) = "0xA8FFFFF";
+    MY(count) = 32;
+    MY(gravity) = 1;
+    MY(liquidfriction) = 3;
+    MY(originjitter) = '5.0 5.0 10.0';
+    MY(sizeincrease) = 10;
+    MY(size_min) = 5;
+    MY(size_max) = 15;
+    MY(staincolor_min) = "0x808080";
+    MY(staincolor_max) = "0x808080";
+    MY(staintex_min) = 16;
+    MY(staintex_max) = 24;
+    MY(tex_min) = 24;
+    MY(tex_max) = 32;
+    MY(type) = "blood";
+    MY(velocityjitter) = '56.0 56.0 212.0';
+    MY(velocitymultiplier) = 0.500000;
+}
+// small bits
+SUB(particlegibs_damage_dissolve) {
+    MY(airfriction) = 1.500000;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 328;
+    MY(color_min) = "0xA8FFFF";
+    MY(color_max) = "0xA8FFFFF";
+    MY(count) = 75;
+    MY(gravity) = 1;
+    MY(liquidfriction) = 3;
+    MY(originjitter) = '10.0 10.0 25.0';
+    MY(sizeincrease) = 10;
+    MY(size_min) = 1;
+    MY(size_max) = 1;
+    MY(staincolor_min) = "0x808080";
+    MY(staincolor_max) = "0x808080";
+    MY(staintex_min) = 16;
+    MY(staintex_max) = 24;
+    MY(tex_min) = 24;
+    MY(tex_max) = 32;
+    MY(type) = "blood";
+    MY(velocityjitter) = '656.0 656.0 912.0';
+}
diff --git a/qcsrc/common/effects/effectinfo_instagib.inc b/qcsrc/common/effects/effectinfo_instagib.inc
new file mode 100644 (file)
index 0000000..044f252
--- /dev/null
@@ -0,0 +1,46 @@
+#define rocketminsta_laser(name, color) \
+    DEF(rocketminsta_laser_##name); \
+    SUB(rocketminsta_laser_##name) { \
+        MY(alpha_min) = 256; \
+        MY(alpha_max) = 256; \
+        MY(alpha_fade) = 968; \
+        MY(color_min) = color; \
+        MY(color_max) = color; \
+        MY(lightcolor) = '1.5 3.0 6.0'; \
+        MY(lightradius) = 90; \
+        MY(size_min) = 3; \
+        MY(size_max) = 3; \
+        MY(tex_min) = 38; \
+        MY(tex_max) = 38; \
+        MY(trailspacing) = 2; \
+        MY(type) = "static"; \
+        MY(velocitymultiplier) = -0.100000; \
+    } \
+    SUB(rocketminsta_laser_##name) /* bright sparks */ { \
+        MY(airfriction) = 12; \
+        MY(alpha_min) = 444; \
+        MY(alpha_max) = 512; \
+        MY(alpha_fade) = 1866; \
+        MY(bounce) = 1; \
+        MY(color_min) = color; \
+        MY(color_max) = color; \
+        MY(count) = 1.500000; \
+        MY(originjitter) = '1.0 1.0 1.0'; \
+        MY(sizeincrease) = -20; \
+        MY(size_min) = 2; \
+        MY(size_max) = 4; \
+        MY(tex_min) = 42; \
+        MY(tex_max) = 42; \
+        MY(trailspacing) = 12; \
+        MY(type) = "snow"; \
+        MY(velocityjitter) = '50.0 50.0 50.0'; \
+        MY(velocityoffset) = '0.0 0.0 15.0'; \
+    } \
+    /**/
+
+rocketminsta_laser(red,     "0xFF0F0F")
+rocketminsta_laser(blue,    "0x0F0FFF")
+rocketminsta_laser(yellow,  "0xFFFF0F")
+rocketminsta_laser(pink,    "0xFF0FFF")
+rocketminsta_laser(neutral, "0xFFFFFF")
+#undef rocketminsta_laser
diff --git a/qcsrc/common/effects/effectinfo_nades.inc b/qcsrc/common/effects/effectinfo_nades.inc
new file mode 100644 (file)
index 0000000..9c65557
--- /dev/null
@@ -0,0 +1,316 @@
+#define nade(name, colormin1, colormax1, colormin2, colormax2) \
+    DEF(nade_##name); \
+    SUB(nade_##name) { \
+        MY(alpha_min) = 100; \
+        MY(alpha_max) = 100; \
+        MY(alpha_fade) = 250; \
+        MY(color_min) = colormin1; \
+        MY(color_max) = colormax1; \
+        MY(sizeincrease) = -1; \
+        MY(size_min) = 3; \
+        MY(size_max) = 3; \
+        MY(tex_min) = 65; \
+        MY(tex_max) = 65; \
+        MY(trailspacing) = 1; \
+        MY(type) = "smoke"; \
+    } \
+    SUB(nade_##name) /* fire */ { \
+        MY(alpha_min) = 30; \
+        MY(alpha_max) = 30; \
+        MY(alpha_fade) = 150; \
+        MY(color_min) = colormin2; \
+        MY(color_max) = colormax2; \
+        MY(notunderwater) = true; \
+        MY(sizeincrease) = -10; \
+        MY(size_min) = 15; \
+        MY(size_max) = 25; \
+        MY(tex_min) = 65; \
+        MY(tex_max) = 65; \
+        MY(trailspacing) = 8; \
+        MY(type) = "smoke"; \
+    } \
+    SUB(nade_##name) /* bubbles */ { \
+        MY(alpha_min) = 256; \
+        MY(alpha_max) = 256; \
+        MY(alpha_fade) = 256; \
+        MY(bounce) = 1.500000; \
+        MY(color_min) = colormin1; \
+        MY(color_max) = colormax1; \
+        MY(gravity) = -0.125000; \
+        MY(liquidfriction) = 4; \
+        MY(size_min) = 1; \
+        MY(size_max) = 1; \
+        MY(tex_min) = 62; \
+        MY(tex_max) = 62; \
+        MY(trailspacing) = 16; \
+        MY(type) = "bubble"; \
+        MY(underwater) = true; \
+        MY(velocityjitter) = '16.0 16.0 16.0'; \
+    } \
+    /**/
+
+nade(blue,      "0x006cff", "0x0600ff", "0x0600ff", "0x9794ff")
+nade(red,       "0xff0000", "0xff3c00", "0xff0000", "0xffa2a2")
+nade(yellow,    "0xFFFF0F", "0xFFFF0F", "0xFFFF0F", "0xFFFF0F")
+nade(pink,      "0xFF0FFF", "0xFF0FFF", "0xFF0FFF", "0xFF0FFF")
+nade(neutral,   "0xFFFFFF", "0xFFFFFF", "0xFFFFFF", "0xFFFFFF")
+#undef nade
+
+#define nade_burn(name, colormin1, colormax1, colormin2, colormax2) \
+    DEF(nade_##name##_burn); \
+    SUB(nade_##name##_burn) { \
+        MY(alpha_min) = 100; \
+        MY(alpha_max) = 100; \
+        MY(alpha_fade) = 250; \
+        MY(color_min) = colormin1; \
+        MY(color_max) = colormax1; \
+        MY(sizeincrease) = -1; \
+        MY(size_min) = 5; \
+        MY(size_max) = 5; \
+        MY(tex_min) = 65; \
+        MY(tex_max) = 65; \
+        MY(trailspacing) = 1; \
+        MY(type) = "smoke"; \
+    } \
+    SUB(nade_##name##_burn) /* fire */ { \
+        MY(alpha_min) = 200; \
+        MY(alpha_max) = 200; \
+        MY(alpha_fade) = 1000; \
+        MY(color_min) = colormin2; \
+        MY(color_max) = colormax2; \
+        MY(notunderwater) = true; \
+        MY(sizeincrease) = -30; \
+        MY(size_min) = 45; \
+        MY(size_max) = 25; \
+        MY(tex_min) = 65; \
+        MY(tex_max) = 65; \
+        MY(trailspacing) = 64; \
+        MY(type) = "smoke"; \
+    } \
+    SUB(nade_##name##_burn) /* bubbles */ { \
+        MY(alpha_min) = 256; \
+        MY(alpha_max) = 256; \
+        MY(alpha_fade) = 256; \
+        MY(bounce) = 1.500000; \
+        MY(color_min) = colormin1; \
+        MY(color_max) = colormax1; \
+        MY(gravity) = -0.125000; \
+        MY(liquidfriction) = 4; \
+        MY(size_min) = 1; \
+        MY(size_max) = 1; \
+        MY(tex_min) = 62; \
+        MY(tex_max) = 62; \
+        MY(trailspacing) = 16; \
+        MY(type) = "bubble"; \
+        MY(underwater) = true; \
+        MY(velocityjitter) = '16.0 16.0 16.0'; \
+    } \
+    SUB(nade_##name##_burn) { \
+        MY(alpha_min) = 300; \
+        MY(alpha_max) = 900; \
+        MY(alpha_fade) = 1500; \
+        MY(color_min) = colormin1; \
+        MY(color_max) = colormax1; \
+        MY(originjitter) = '2.0 2.0 2.0'; \
+        MY(startangle_min) = -180; \
+        MY(startangle_max) = 180; \
+        MY(spin_min) = 20; \
+        MY(spin_max) = -20; \
+        MY(sizeincrease) = -40; \
+        MY(size_min) = 15; \
+        MY(size_max) = 25; \
+        MY(tex_min) = 71; \
+        MY(tex_max) = 73; \
+        MY(trailspacing) = 16; \
+        MY(type) = "smoke"; \
+        MY(velocityjitter) = '10.0 10.0 10.0'; \
+    } \
+    /**/
+
+nade_burn(red,      "0xff0000", "0xff3c00", "0xff0000", "0xffa2a2")
+nade_burn(blue,     "0x006cff", "0x0600ff", "0x0600ff", "0x9794ff")
+nade_burn(yellow,   "0xFFFF0F", "0xFFFF0F", "0xFFFF0F", "0xFFFF0F")
+nade_burn(pink,     "0xFF0FFF", "0xFF0FFF", "0xFF0FFF", "0xFF0FFF")
+nade_burn(neutral,  "0xFFFFFF", "0xFFFFFF", "0xFFFFFF", "0xFFFFFF")
+#undef nade_burn
+
+#define nade_explode(name, colorlight, colormin1, colormax1, colormin2, colormax2, colormin3, colormax3) \
+    DEF(nade_##name##_explode); \
+    SUB(nade_##name##_explode) { \
+        MY(alpha_min) = 256; \
+        MY(alpha_max) = 256; \
+        MY(countabsolute) = 1; \
+        MY(lightcolor) = colorlight; \
+        MY(lightradiusfade) = 1500; \
+        MY(lightradius) = 300; \
+        MY(originjitter) = '26.0 26.0 26.0'; \
+        MY(size_min) = 88; \
+        MY(size_max) = 88; \
+        MY(tex_min) = 8; \
+        MY(tex_max) = 16; \
+        MY(type) = "decal"; \
+    } \
+    SUB(nade_##name##_explode) /* shockwave */ { \
+        MY(alpha_min) = 80; \
+        MY(alpha_max) = 80; \
+        MY(alpha_fade) = 650; \
+        MY(color_min) = colormin1; \
+        MY(color_max) = colormax1; \
+        MY(countabsolute) = 1; \
+        MY(sizeincrease) = 1800; \
+        MY(size_min) = 32; \
+        MY(size_max) = 32; \
+        MY(tex_min) = 33; \
+        MY(tex_max) = 33; \
+        MY(type) = "smoke"; \
+        MY(velocitymultiplier) = 44; \
+    } \
+    SUB(nade_##name##_explode) /* fire */ { \
+        MY(airfriction) = 30; \
+        MY(alpha_min) = 400; \
+        MY(alpha_max) = 656; \
+        MY(alpha_fade) = 2000; \
+        MY(color_min) = colormin2; \
+        MY(color_max) = colormax2; \
+        MY(count) = 16; \
+        MY(notunderwater) = true; \
+        MY(originjitter) = '50.0 50.0 50.0'; \
+        MY(startangle_min) = -180; \
+        MY(startangle_max) = 180; \
+        MY(spin_min) = -9; \
+        MY(spin_max) = 9; \
+        MY(sizeincrease) = 555; \
+        MY(size_min) = 20; \
+        MY(size_max) = 24; \
+        MY(tex_min) = 48; \
+        MY(tex_max) = 55; \
+        MY(type) = "smoke"; \
+        MY(velocityjitter) = '320.0 320.0 320.0'; \
+    } \
+    SUB(nade_##name##_explode) /* fire stretched */ { \
+        MY(airfriction) = -9; \
+        MY(alpha_min) = 1500; \
+        MY(alpha_max) = 3000; \
+        MY(alpha_fade) = 13000; \
+        MY(color_min) = colormin2; \
+        MY(color_max) = colormax2; \
+        MY(count) = 8; \
+        MY(sizeincrease) = 40; \
+        MY(size_min) = 60; \
+        MY(size_max) = 90; \
+        MY(stretchfactor) = 80; \
+        MY(tex_min) = 48; \
+        MY(tex_max) = 55; \
+        MY(type) = "spark"; \
+        MY(velocityjitter) = '30.0 30.0 30.0'; \
+    } \
+    SUB(nade_##name##_explode) /* smoke */ { \
+        MY(airfriction) = 0.040000; \
+        MY(alpha_min) = 128; \
+        MY(alpha_max) = 328; \
+        MY(alpha_fade) = 390; \
+        MY(blend) = "alpha"; \
+        MY(color_min) = "0x222222"; \
+        MY(color_max) = "0x000000"; \
+        MY(count) = 32; \
+        MY(gravity) = 0.400000; \
+        MY(originjitter) = '50.0 50.0 10.0'; \
+        MY(startangle_min) = -180; \
+        MY(startangle_max) = 180; \
+        MY(spin_min) = 2; \
+        MY(spin_max) = -2; \
+        MY(sizeincrease) = 50; \
+        MY(size_min) = 60; \
+        MY(size_max) = 30; \
+        MY(tex_max) = 7; \
+        MY(type) = "smoke"; \
+        MY(velocityjitter) = '200.0 200.0 200.0'; \
+        MY(velocityoffset) = '0.0 0.0 180.0'; \
+    } \
+    SUB(nade_##name##_explode) /* underwater bubbles */ { \
+        MY(alpha_min) = 128; \
+        MY(alpha_max) = 256; \
+        MY(alpha_fade) = 64; \
+        MY(bounce) = 1.500000; \
+        MY(color_min) = "0x404040"; \
+        MY(color_max) = "0x808080"; \
+        MY(count) = 32; \
+        MY(gravity) = -0.125000; \
+        MY(liquidfriction) = 0.250000; \
+        MY(originjitter) = '16.0 16.0 16.0'; \
+        MY(size_min) = 3; \
+        MY(size_max) = 6; \
+        MY(tex_min) = 62; \
+        MY(tex_max) = 62; \
+        MY(type) = "bubble"; \
+        MY(underwater) = true; \
+        MY(velocityjitter) = '196.0 196.0 196.0'; \
+    } \
+    SUB(nade_##name##_explode) /* bouncing sparks */ { \
+        MY(airfriction) = 1; \
+        MY(alpha_min) = 644; \
+        MY(alpha_max) = 956; \
+        MY(alpha_fade) = 484; \
+        MY(bounce) = 1.600000; \
+        MY(color_min) = colormin3; \
+        MY(color_max) = colormax3; \
+        MY(count) = 8; \
+        MY(gravity) = 1; \
+        MY(liquidfriction) = 0.800000; \
+        MY(notunderwater) = true; \
+        MY(originjitter) = '16.0 16.0 16.0'; \
+        MY(size_min) = 1; \
+        MY(size_max) = 2; \
+        MY(tex_min) = 40; \
+        MY(tex_max) = 40; \
+        MY(type) = "spark"; \
+        MY(velocityjitter) = '424.0 424.0 624.0'; \
+        MY(velocityoffset) = '0.0 0.0 80.0'; \
+    } \
+    SUB(nade_##name##_explode) /* notbouncing sparks */ { \
+        MY(airfriction) = 0.700000; \
+        MY(alpha_min) = 644; \
+        MY(alpha_max) = 956; \
+        MY(alpha_fade) = 684; \
+        MY(color_min) = colormin3; \
+        MY(color_max) = colormax3; \
+        MY(count) = 16; \
+        MY(gravity) = 0.500000; \
+        MY(liquidfriction) = 0.800000; \
+        MY(originjitter) = '16.0 16.0 16.0'; \
+        MY(size_min) = 1; \
+        MY(size_max) = 2; \
+        MY(tex_min) = 40; \
+        MY(tex_max) = 40; \
+        MY(type) = "spark"; \
+        MY(velocityjitter) = '424.0 424.0 624.0'; \
+        MY(velocityoffset) = '0.0 0.0 80.0'; \
+    } \
+    SUB(nade_##name##_explode) /* debris */ { \
+        MY(alpha_min) = 644; \
+        MY(alpha_max) = 956; \
+        MY(alpha_fade) = 2500; \
+        MY(color_min) = colormin3; \
+        MY(color_max) = colormax3; \
+        MY(count) = 8; \
+        MY(notunderwater) = true; \
+        MY(originjitter) = '64.0 64.0 64.0'; \
+        MY(startangle_min) = -180; \
+        MY(startangle_max) = 180; \
+        MY(spin_min) = -100; \
+        MY(spin_max) = 100; \
+        MY(size_min) = 20; \
+        MY(size_max) = 40; \
+        MY(tex_min) = 71; \
+        MY(tex_max) = 73; \
+        MY(type) = "smoke"; \
+        MY(velocityjitter) = '324.0 324.0 324.0'; \
+    } \
+    /**/
+
+nade_explode(blue,      '20.0 20.0 100.0', "0x80C0FF", "0x80C0FF", "0x629dff", "0x0018ff", "0x006cff", "0x0600ff")
+nade_explode(red,       '100.0 20.0 20.0', "0xff0000", "0xffa2a2", "0xff0000", "0xff4200", "0xff0000", "0xffa2a2")
+nade_explode(yellow,    '100.0 20.0 20.0', "0xff0000", "0xffa2a2", "0xFFFF0F", "0xFFFF0F", "0xff0000", "0xffa2a2")
+nade_explode(pink,      '100.0 20.0 20.0', "0xff0000", "0xffa2a2", "0xFF0FFF", "0xFF0FFF", "0xff0000", "0xffa2a2")
+nade_explode(neutral,   '100.0 20.0 20.0', "0xff0000", "0xffa2a2", "0xFFFFFF", "0xFFFFFF", "0xff0000", "0xffa2a2")
+#undef nade_explode
diff --git a/qcsrc/common/effects/effectinfo_onslaught.inc b/qcsrc/common/effects/effectinfo_onslaught.inc
new file mode 100644 (file)
index 0000000..af330c7
--- /dev/null
@@ -0,0 +1,123 @@
+DEF(onslaught_generator_gib_explode);
+// fire effect which expands then slows
+SUB(onslaught_generator_gib_explode) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 356;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 17;
+    MY(liquidfriction) = 8;
+    MY(notunderwater) = true;
+    MY(originjitter) = '8.0 8.0 8.0';
+    MY(sizeincrease) = 45;
+    MY(size_min) = 20;
+    MY(size_max) = 26;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "static";
+    MY(velocityjitter) = '286.0 286.0 286.0';
+}
+// smoke
+SUB(onslaught_generator_gib_explode) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 500;
+    MY(alpha_fade) = 600;
+    MY(bounce) = 2;
+    MY(color_min) = "0x000000";
+    MY(color_max) = "0x111111";
+    MY(count) = 6;
+    MY(gravity) = -0.300000;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = 90;
+    MY(size_min) = 1;
+    MY(size_max) = 10;
+    MY(tex_max) = 8;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '244.0 244.0 244.0';
+}
+// underwater bubbles
+SUB(onslaught_generator_gib_explode) {
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 64;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0x404040";
+    MY(color_max) = "0x808080";
+    MY(count) = 16;
+    MY(gravity) = -0.125000;
+    MY(liquidfriction) = 0.250000;
+    MY(originjitter) = '16.0 16.0 16.0';
+    MY(size_min) = 3;
+    MY(size_max) = 3;
+    MY(tex_min) = 62;
+    MY(tex_max) = 62;
+    MY(type) = "bubble";
+    MY(underwater) = true;
+    MY(velocityjitter) = '96.0 96.0 96.0';
+}
+
+DEF(onslaught_generator_gib_flame);
+// fire effect which expands then slows
+SUB(onslaught_generator_gib_flame) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 356;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 15;
+    MY(gravity) = -0.500000;
+    MY(liquidfriction) = 8;
+    MY(notunderwater) = true;
+    MY(originjitter) = '3.0 3.0 3.0';
+    MY(sizeincrease) = 25;
+    MY(size_min) = 5;
+    MY(size_max) = 10;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "static";
+    MY(velocityjitter) = '86.0 86.0 86.0';
+}
+// smoke
+SUB(onslaught_generator_gib_flame) {
+    MY(airfriction) = 5;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 500;
+    MY(alpha_fade) = 600;
+    MY(bounce) = 2;
+    MY(color_min) = "0x000000";
+    MY(color_max) = "0x111111";
+    MY(count) = 1;
+    MY(gravity) = -0.800000;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = 30;
+    MY(size_min) = 10;
+    MY(size_max) = 20;
+    MY(tex_max) = 8;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '44.0 44.0 44.0';
+}
+// underwater bubbles
+SUB(onslaught_generator_gib_flame) {
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 64;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0x404040";
+    MY(color_max) = "0x808080";
+    MY(count) = 16;
+    MY(gravity) = -0.125000;
+    MY(liquidfriction) = 0.250000;
+    MY(originjitter) = '16.0 16.0 16.0';
+    MY(size_min) = 3;
+    MY(size_max) = 3;
+    MY(tex_min) = 62;
+    MY(tex_max) = 62;
+    MY(type) = "bubble";
+    MY(underwater) = true;
+    MY(velocityjitter) = '96.0 96.0 96.0';
+}
diff --git a/qcsrc/common/effects/effectinfo_vehicles.inc b/qcsrc/common/effects/effectinfo_vehicles.inc
new file mode 100644 (file)
index 0000000..31fed7f
--- /dev/null
@@ -0,0 +1,1166 @@
+DEF(spiderbot_minigun_trail);
+SUB(spiderbot_minigun_trail) {
+    MY(airfriction) = 1;
+    MY(alpha_min) = 20;
+    MY(alpha_max) = 50;
+    MY(alpha_fade) = 100;
+    MY(color_min) = "0xd0d0a0";
+    MY(color_max) = "0xffffff";
+    MY(gravity) = -0.030000;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = 2;
+    MY(size_min) = 1;
+    MY(size_max) = 2;
+    MY(tex_max) = 8;
+    MY(trailspacing) = 10;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '5.0 5.0 5.0';
+}
+
+DEF(spiderbot_minigun_muzzleflash);
+SUB(spiderbot_minigun_muzzleflash) {
+    MY(airfriction) = 10;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 512;
+    MY(alpha_fade) = 6280;
+    MY(color_min) = "0xff9c00";
+    MY(color_max) = "0xff8400";
+    MY(count) = 3;
+    MY(originjitter) = '2.0 2.0 2.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = 4000;
+    MY(spin_max) = -4000;
+    MY(sizeincrease) = -100;
+    MY(size_min) = 10;
+    MY(size_max) = 15;
+    MY(stretchfactor) = 1.300000;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '150.0 150.0 150.0';
+    MY(velocitymultiplier) = 0.350000;
+}
+// fire
+SUB(spiderbot_minigun_muzzleflash) {
+    MY(airfriction) = 12;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 512;
+    MY(alpha_fade) = 6280;
+    MY(color_min) = "0xff9c00";
+    MY(color_max) = "0xff8400";
+    MY(count) = 6;
+    MY(originjitter) = '2.0 2.0 2.0';
+    MY(sizeincrease) = -10;
+    MY(size_min) = 5;
+    MY(size_max) = 7;
+    MY(stretchfactor) = 0.800000;
+    MY(tex_min) = 8;
+    MY(tex_max) = 15;
+    MY(type) = "spark";
+    MY(velocityjitter) = '200.0 200.0 200.0';
+    MY(velocitymultiplier) = 0.200000;
+}
+SUB(spiderbot_minigun_muzzleflash) {
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 512;
+    MY(alpha_fade) = 6680;
+    MY(color_min) = "0xff9c00";
+    MY(color_max) = "0xff8400";
+    MY(countabsolute) = 2;
+    MY(lightcolor) = '3.0 3.0 0.0';
+    MY(lightradiusfade) = 8000;
+    MY(lightradius) = 120;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = 4000;
+    MY(spin_max) = -4000;
+    MY(sizeincrease) = -100;
+    MY(size_min) = 32;
+    MY(size_max) = 32;
+    MY(stretchfactor) = 0.100000;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "static";
+}
+
+DEF(spiderbot_minigun_impact);
+SUB(spiderbot_minigun_impact) {
+    MY(alpha_min) = 50;
+    MY(alpha_max) = 100;
+    MY(alpha_fade) = 1680;
+    MY(color_min) = "0xff9c00";
+    MY(color_max) = "0xf6ff00";
+    MY(countabsolute) = 1;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = 4000;
+    MY(spin_max) = -4000;
+    MY(sizeincrease) = -100;
+    MY(size_min) = 52;
+    MY(size_max) = 52;
+    MY(stretchfactor) = 0.100000;
+    MY(tex_min) = 65;
+    MY(tex_max) = 65;
+    MY(type) = "static";
+}
+// fire
+SUB(spiderbot_minigun_impact) {
+    MY(airfriction) = 6;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 512;
+    MY(alpha_fade) = 6280;
+    MY(color_min) = "0xff9c00";
+    MY(color_max) = "0xff8400";
+    MY(count) = 7;
+    MY(originjitter) = '2.0 2.0 2.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = 4000;
+    MY(spin_max) = -4000;
+    MY(sizeincrease) = 100;
+    MY(size_min) = 9;
+    MY(size_max) = 15;
+    MY(stretchfactor) = 3;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '250.0 250.0 150.0';
+    MY(velocitymultiplier) = 0.200000;
+}
+// smoke
+SUB(spiderbot_minigun_impact) {
+    MY(airfriction) = 10;
+    MY(alpha_min) = 50;
+    MY(alpha_max) = 50;
+    MY(alpha_fade) = 190;
+    MY(color_min) = "0xd0d0a0";
+    MY(color_max) = "0xffffff";
+    MY(count) = 6;
+    MY(gravity) = 1.300000;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(sizeincrease) = 80;
+    MY(size_min) = 10;
+    MY(size_max) = 20;
+    MY(tex_max) = 8;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '100.0 100.0 250.0';
+    MY(velocitymultiplier) = 0.490000;
+}
+// smoke 2
+SUB(spiderbot_minigun_impact) {
+    MY(airfriction) = 6;
+    MY(alpha_min) = 25;
+    MY(alpha_max) = 51;
+    MY(alpha_fade) = 128;
+    MY(color_min) = "0xd0d0a0";
+    MY(color_max) = "0xffffff";
+    MY(count) = 7;
+    MY(originjitter) = '2.0 2.0 2.0';
+    MY(sizeincrease) = 100;
+    MY(size_min) = 15;
+    MY(size_max) = 19;
+    MY(stretchfactor) = 7.600000;
+    MY(tex_max) = 8;
+    MY(type) = "spark";
+    MY(velocityjitter) = '250.0 250.0 150.0';
+    MY(velocitymultiplier) = 0.200000;
+}
+// debris
+SUB(spiderbot_minigun_impact) {
+    MY(airfriction) = 0.400000;
+    MY(alpha_min) = 644;
+    MY(alpha_max) = 756;
+    MY(alpha_fade) = 1484;
+    MY(color_min) = "0x99977D";
+    MY(color_max) = "0xFFFFFF";
+    MY(count) = 3;
+    MY(gravity) = 1.100000;
+    MY(notunderwater) = true;
+    MY(originjitter) = '16.0 16.0 16.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -1000;
+    MY(spin_max) = 1000;
+    MY(sizeincrease) = -10;
+    MY(size_min) = 6;
+    MY(size_max) = 8;
+    MY(tex_min) = 66;
+    MY(tex_max) = 68;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '124.0 124.0 224.0';
+    MY(velocitymultiplier) = 0.150000;
+}
+// decal
+SUB(spiderbot_minigun_impact) {
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(countabsolute) = 1;
+    MY(originjitter) = '16.0 16.0 16.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(size_min) = 20;
+    MY(size_max) = 25;
+    MY(tex_min) = 56;
+    MY(tex_max) = 59;
+    MY(type) = "decal";
+}
+
+DEF(spiderbot_rocket_explode);
+SUB(spiderbot_rocket_explode) {
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(countabsolute) = 1;
+    MY(lightcolor) = '8.0 4.0 0.0';
+    MY(lightradiusfade) = 1750;
+    MY(lightradius) = 300;
+    MY(originjitter) = '23.0 23.0 23.0';
+    MY(size_min) = 72;
+    MY(size_max) = 72;
+    MY(tex_min) = 8;
+    MY(tex_max) = 16;
+    MY(type) = "decal";
+}
+// shockwave
+SUB(spiderbot_rocket_explode) {
+    MY(alpha_min) = 56;
+    MY(alpha_max) = 56;
+    MY(alpha_fade) = 230;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(countabsolute) = 1;
+    MY(sizeincrease) = 2400;
+    MY(size_min) = 22;
+    MY(size_max) = 22;
+    MY(tex_min) = 33;
+    MY(tex_max) = 33;
+    MY(type) = "static";
+}
+// glow
+SUB(spiderbot_rocket_explode) {
+    MY(alpha_min) = 156;
+    MY(alpha_max) = 156;
+    MY(alpha_fade) = 830;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(countabsolute) = 1;
+    MY(sizeincrease) = 240;
+    MY(size_min) = 120;
+    MY(size_max) = 120;
+    MY(tex_min) = 64;
+    MY(tex_max) = 64;
+    MY(type) = "static";
+}
+// fire effect
+SUB(spiderbot_rocket_explode) {
+    MY(airfriction) = 8;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 812;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 32;
+    MY(liquidfriction) = 8;
+    MY(notunderwater) = true;
+    MY(originjitter) = '100.0 100.0 100.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -50;
+    MY(spin_max) = 50;
+    MY(sizeincrease) = 495;
+    MY(size_min) = 12;
+    MY(size_max) = 21;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "static";
+    MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// fire effect 2
+SUB(spiderbot_rocket_explode) {
+    MY(airfriction) = -2;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 912;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 16;
+    MY(liquidfriction) = 8;
+    MY(notunderwater) = true;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -150;
+    MY(spin_max) = 150;
+    MY(sizeincrease) = 120;
+    MY(size_min) = 3;
+    MY(size_max) = 3;
+    MY(stretchfactor) = 10;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '412.0 412.0 412.0';
+}
+// fire rays
+SUB(spiderbot_rocket_explode) {
+    MY(airfriction) = -3;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 1600;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 10;
+    MY(liquidfriction) = 8;
+    MY(notunderwater) = true;
+    MY(originjitter) = '40.0 40.0 40.0';
+    MY(sizeincrease) = 120;
+    MY(size_min) = 13;
+    MY(size_max) = 54;
+    MY(stretchfactor) = 10;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '712.0 712.0 712.0';
+}
+// smoke
+SUB(spiderbot_rocket_explode) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 300;
+    MY(alpha_max) = 650;
+    MY(alpha_fade) = 756;
+    MY(color_min) = "0x4F4B46";
+    MY(color_max) = "0x000000";
+    MY(count) = 10;
+    MY(notunderwater) = true;
+    MY(originjitter) = '100.0 100.0 100.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -20;
+    MY(spin_max) = 20;
+    MY(sizeincrease) = 280;
+    MY(size_min) = 10;
+    MY(size_max) = 15;
+    MY(tex_max) = 8;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '200.0 200.0 200.0';
+}
+// smoke2
+SUB(spiderbot_rocket_explode) {
+    MY(airfriction) = 2;
+    MY(alpha_min) = 300;
+    MY(alpha_max) = 650;
+    MY(alpha_fade) = 556;
+    MY(color_min) = "0x4F4B46";
+    MY(color_max) = "0x000000";
+    MY(count) = 3;
+    MY(gravity) = -0.500000;
+    MY(notunderwater) = true;
+    MY(originjitter) = '10.0 10.0 10.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -20;
+    MY(spin_max) = 20;
+    MY(sizeincrease) = 30;
+    MY(size_min) = 100;
+    MY(size_max) = 150;
+    MY(tex_max) = 8;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '200.0 200.0 200.0';
+}
+// underwater bubbles
+SUB(spiderbot_rocket_explode) {
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 64;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0x404040";
+    MY(color_max) = "0x808080";
+    MY(count) = 32;
+    MY(gravity) = -0.125000;
+    MY(liquidfriction) = 0.250000;
+    MY(originjitter) = '160.0 160.0 160.0';
+    MY(size_min) = 1;
+    MY(size_max) = 3;
+    MY(tex_min) = 62;
+    MY(tex_max) = 62;
+    MY(type) = "bubble";
+    MY(underwater) = true;
+    MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// underwatershockwave
+SUB(spiderbot_rocket_explode) {
+    MY(alpha_min) = 40;
+    MY(alpha_max) = 40;
+    MY(alpha_fade) = 300;
+    MY(countabsolute) = 1;
+    MY(sizeincrease) = 1200;
+    MY(size_min) = 30;
+    MY(size_max) = 30;
+    MY(tex_min) = 33;
+    MY(tex_max) = 33;
+    MY(type) = "smoke";
+    MY(underwater) = true;
+}
+
+DEF(spiderbot_rocket_thrust);
+SUB(spiderbot_rocket_thrust) {
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 1600;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 3;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = -40;
+    MY(size_min) = 5;
+    MY(size_max) = 10;
+    MY(stretchfactor) = 0.900000;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '20.0 20.0 20.0';
+    MY(velocitymultiplier) = -1.400000;
+}
+SUB(spiderbot_rocket_thrust) {
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 200;
+    MY(alpha_fade) = 9000;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 4;
+    MY(notunderwater) = true;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -500;
+    MY(spin_max) = 500;
+    MY(sizeincrease) = -3000;
+    MY(size_min) = 25;
+    MY(size_max) = 25;
+    MY(stretchfactor) = 1;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "static";
+    MY(velocityjitter) = '60.0 60.0 60.0';
+    MY(velocitymultiplier) = -1.400000;
+}
+
+DEF(spiderbot_rocket_launch);
+// long lasting smoke
+SUB(spiderbot_rocket_launch) {
+    MY(airfriction) = 0.300000;
+    MY(alpha_min) = 100;
+    MY(alpha_max) = 156;
+    MY(alpha_fade) = 60;
+    MY(color_min) = "0xFFFFFF";
+    MY(color_max) = "0xD9C4B0";
+    MY(count) = 8;
+    MY(gravity) = -0.010000;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = 20;
+    MY(size_min) = 30;
+    MY(size_max) = 30;
+    MY(tex_max) = 8;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '60.0 60.0 60.0';
+    MY(velocitymultiplier) = -0.100000;
+}
+// fast smoke
+SUB(spiderbot_rocket_launch) {
+    MY(airfriction) = 0.300000;
+    MY(alpha_min) = 100;
+    MY(alpha_max) = 156;
+    MY(alpha_fade) = 260;
+    MY(color_min) = "0xFFFFFF";
+    MY(color_max) = "0xD9C4B0";
+    MY(count) = 14;
+    MY(gravity) = -0.300000;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = 20;
+    MY(size_min) = 30;
+    MY(size_max) = 30;
+    MY(tex_max) = 8;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '160.0 160.0 60.0';
+}
+// fire
+SUB(spiderbot_rocket_launch) {
+    MY(airfriction) = 0.300000;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 1960;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 14;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = 40;
+    MY(size_min) = 30;
+    MY(size_max) = 30;
+    MY(stretchfactor) = 3;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '60.0 60.0 60.0';
+    MY(velocitymultiplier) = 0.500000;
+}
+// sparks
+SUB(spiderbot_rocket_launch) {
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 1000;
+    MY(color_min) = "0xFFFFFF";
+    MY(color_max) = "0xD9C4B0";
+    MY(count) = 10;
+    MY(notunderwater) = true;
+    MY(size_min) = 1;
+    MY(size_max) = 4;
+    MY(tex_min) = 40;
+    MY(tex_max) = 40;
+    MY(type) = "spark";
+    MY(velocityjitter) = '160.0 160.0 160.0';
+    MY(velocitymultiplier) = -0.500000;
+}
+
+DEF(wakizashi_gun_impact);
+SUB(wakizashi_gun_impact) {
+    MY(airfriction) = 4;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 512;
+    MY(alpha_fade) = 1180;
+    MY(color_min) = "0xff0000";
+    MY(color_max) = "0xc03535";
+    MY(count) = 15;
+    MY(gravity) = 3;
+    MY(originjitter) = '40.0 40.0 10.0';
+    MY(size_min) = 4;
+    MY(size_max) = 7;
+    MY(stretchfactor) = 0.900000;
+    MY(tex_min) = 41;
+    MY(tex_max) = 41;
+    MY(type) = "spark";
+    MY(velocityjitter) = '350.0 350.0 550.0';
+    MY(velocityoffset) = '0.0 0.0 700.0';
+}
+SUB(wakizashi_gun_impact) {
+    MY(airfriction) = 4;
+    MY(alpha_min) = 50;
+    MY(alpha_max) = 90;
+    MY(alpha_fade) = 150;
+    MY(color_min) = "0xd0d0a0";
+    MY(color_max) = "0xc03535";
+    MY(count) = 24;
+    MY(originjitter) = '40.0 40.0 10.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(sizeincrease) = 80;
+    MY(size_min) = 10;
+    MY(size_max) = 20;
+    MY(tex_max) = 8;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '250.0 250.0 450.0';
+    MY(velocityoffset) = '0.0 0.0 600.0';
+}
+SUB(wakizashi_gun_impact) {
+    MY(alpha_min) = 250;
+    MY(alpha_max) = 300;
+    MY(alpha_fade) = 680;
+    MY(color_min) = "0xff0000";
+    MY(color_max) = "0xc03535";
+    MY(countabsolute) = 1;
+    MY(sizeincrease) = -180;
+    MY(size_min) = 82;
+    MY(size_max) = 82;
+    MY(tex_min) = 65;
+    MY(tex_max) = 65;
+    MY(type) = "smoke";
+}
+SUB(wakizashi_gun_impact) {
+    MY(alpha_min) = 50;
+    MY(alpha_max) = 100;
+    MY(alpha_fade) = 620;
+    MY(color_min) = "0xff0000";
+    MY(color_max) = "0xc03535";
+    MY(countabsolute) = 1;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = 400;
+    MY(spin_max) = -400;
+    MY(sizeincrease) = 900;
+    MY(size_min) = 40;
+    MY(size_max) = 40;
+    MY(tex_min) = 33;
+    MY(tex_max) = 33;
+    MY(type) = "smoke";
+}
+SUB(wakizashi_gun_impact) {
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(countabsolute) = 1;
+    MY(originjitter) = '16.0 16.0 16.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(size_min) = 14;
+    MY(size_max) = 14;
+    MY(tex_min) = 59;
+    MY(tex_max) = 59;
+    MY(type) = "decal";
+}
+
+DEF(wakizashi_gun_muzzleflash);
+SUB(wakizashi_gun_muzzleflash) {
+    MY(airfriction) = 12;
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 512;
+    MY(alpha_fade) = 6280;
+    MY(color_min) = "0xff0000";
+    MY(color_max) = "0xc03535";
+    MY(count) = 16;
+    MY(originjitter) = '2.0 2.0 2.0';
+    MY(sizeincrease) = -10;
+    MY(size_min) = 5;
+    MY(size_max) = 7;
+    MY(stretchfactor) = 0.700000;
+    MY(tex_min) = 8;
+    MY(tex_max) = 15;
+    MY(type) = "spark";
+    MY(velocityjitter) = '200.0 200.0 200.0';
+    MY(velocitymultiplier) = 0.200000;
+}
+
+DEF(wakizashi_rocket_explode);
+SUB(wakizashi_rocket_explode) {
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(countabsolute) = 1;
+    MY(lightcolor) = '8.0 4.0 0.0';
+    MY(lightradiusfade) = 1750;
+    MY(lightradius) = 300;
+    MY(originjitter) = '23.0 23.0 23.0';
+    MY(size_min) = 72;
+    MY(size_max) = 72;
+    MY(tex_min) = 8;
+    MY(tex_max) = 16;
+    MY(type) = "decal";
+}
+// shockwave
+SUB(wakizashi_rocket_explode) {
+    MY(alpha_min) = 56;
+    MY(alpha_max) = 56;
+    MY(alpha_fade) = 230;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(countabsolute) = 1;
+    MY(sizeincrease) = 2400;
+    MY(size_min) = 22;
+    MY(size_max) = 22;
+    MY(tex_min) = 33;
+    MY(tex_max) = 33;
+    MY(type) = "static";
+}
+// glow
+SUB(wakizashi_rocket_explode) {
+    MY(alpha_min) = 156;
+    MY(alpha_max) = 156;
+    MY(alpha_fade) = 830;
+    MY(color_min) = "0x8f0d00";
+    MY(color_max) = "0xff5a00";
+    MY(countabsolute) = 1;
+    MY(sizeincrease) = 240;
+    MY(size_min) = 120;
+    MY(size_max) = 120;
+    MY(tex_min) = 64;
+    MY(tex_max) = 64;
+    MY(type) = "static";
+}
+// fire effect
+SUB(wakizashi_rocket_explode) {
+    MY(airfriction) = 2;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 512;
+    MY(color_min) = "0xFFAE00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 64;
+    MY(liquidfriction) = 8;
+    MY(notunderwater) = true;
+    MY(originjitter) = '10.0 10.0 10.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -50;
+    MY(spin_max) = 50;
+    MY(sizeincrease) = 195;
+    MY(size_min) = 12;
+    MY(size_max) = 21;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "static";
+    MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// fire rays
+SUB(wakizashi_rocket_explode) {
+    MY(airfriction) = -3;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 1600;
+    MY(color_min) = "0xFFEA00";
+    MY(color_max) = "0xff5a00";
+    MY(count) = 10;
+    MY(liquidfriction) = 8;
+    MY(notunderwater) = true;
+    MY(originjitter) = '40.0 40.0 40.0';
+    MY(sizeincrease) = 120;
+    MY(size_min) = 43;
+    MY(size_max) = 54;
+    MY(stretchfactor) = 10;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '512.0 512.0 512.0';
+}
+// smoke
+SUB(wakizashi_rocket_explode) {
+    MY(airfriction) = 3;
+    MY(alpha_min) = 300;
+    MY(alpha_max) = 450;
+    MY(alpha_fade) = 556;
+    MY(color_min) = "0x4F4B46";
+    MY(color_max) = "0x000000";
+    MY(count) = 32;
+    MY(notunderwater) = true;
+    MY(originjitter) = '100.0 100.0 100.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -20;
+    MY(spin_max) = 20;
+    MY(sizeincrease) = 230;
+    MY(size_min) = 10;
+    MY(size_max) = 15;
+    MY(tex_max) = 8;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '200.0 200.0 200.0';
+}
+// bouncing sparks
+SUB(wakizashi_rocket_explode) {
+    MY(airfriction) = 1;
+    MY(alpha_min) = 644;
+    MY(alpha_max) = 956;
+    MY(alpha_fade) = 884;
+    MY(color_min) = "0xffa35b";
+    MY(color_max) = "0xfff2be";
+    MY(count) = 14;
+    MY(gravity) = 1;
+    MY(liquidfriction) = 0.800000;
+    MY(notunderwater) = true;
+    MY(originjitter) = '60.0 60.0 60.0';
+    MY(size_min) = 1;
+    MY(size_max) = 2;
+    MY(tex_min) = 40;
+    MY(tex_max) = 40;
+    MY(type) = "spark";
+    MY(velocityjitter) = '524.0 524.0 524.0';
+    MY(velocityoffset) = '0.0 0.0 170.0';
+}
+// underwater bubbles
+SUB(wakizashi_rocket_explode) {
+    MY(alpha_min) = 128;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 64;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0x404040";
+    MY(color_max) = "0x808080";
+    MY(count) = 32;
+    MY(gravity) = -0.125000;
+    MY(liquidfriction) = 0.250000;
+    MY(originjitter) = '160.0 160.0 160.0';
+    MY(size_min) = 1;
+    MY(size_max) = 3;
+    MY(tex_min) = 62;
+    MY(tex_max) = 62;
+    MY(type) = "bubble";
+    MY(underwater) = true;
+    MY(velocityjitter) = '144.0 144.0 144.0';
+}
+// underwatershockwave
+SUB(wakizashi_rocket_explode) {
+    MY(alpha_min) = 40;
+    MY(alpha_max) = 40;
+    MY(alpha_fade) = 300;
+    MY(countabsolute) = 1;
+    MY(sizeincrease) = 1200;
+    MY(size_min) = 30;
+    MY(size_max) = 30;
+    MY(tex_min) = 33;
+    MY(tex_max) = 33;
+    MY(type) = "smoke";
+    MY(underwater) = true;
+}
+
+DEF(wakizashi_rocket_thrust);
+SUB(wakizashi_rocket_thrust) {
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 1600;
+    MY(color_min) = "0x00FFDD";
+    MY(color_max) = "0x6200FF";
+    MY(countabsolute) = 3;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = -2;
+    MY(size_min) = 14;
+    MY(size_max) = 19;
+    MY(stretchfactor) = 1;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '60.0 60.0 60.0';
+    MY(velocitymultiplier) = -1.100000;
+}
+SUB(wakizashi_rocket_thrust) {
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 1900;
+    MY(color_min) = "0xFFFF33";
+    MY(color_max) = "0xFFEE00";
+    MY(countabsolute) = 2;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = -2;
+    MY(size_min) = 5;
+    MY(size_max) = 10;
+    MY(stretchfactor) = 3;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '60.0 60.0 60.0';
+    MY(velocitymultiplier) = -0.300000;
+}
+
+DEF(wakizashi_rocket_launch);
+// long lasting smoke
+SUB(wakizashi_rocket_launch) {
+    MY(airfriction) = 0.300000;
+    MY(alpha_min) = 100;
+    MY(alpha_max) = 156;
+    MY(alpha_fade) = 60;
+    MY(color_min) = "0xFFFFFF";
+    MY(color_max) = "0xD9C4B0";
+    MY(count) = 8;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = 20;
+    MY(size_min) = 3;
+    MY(size_max) = 30;
+    MY(tex_max) = 8;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '160.0 160.0 60.0';
+    MY(velocitymultiplier) = -0.100000;
+}
+// fast smoke
+SUB(wakizashi_rocket_launch) {
+    MY(airfriction) = 0.300000;
+    MY(alpha_min) = 100;
+    MY(alpha_max) = 156;
+    MY(alpha_fade) = 260;
+    MY(color_min) = "0xFFFFFF";
+    MY(color_max) = "0xD9C4B0";
+    MY(count) = 14;
+    MY(notunderwater) = true;
+    MY(sizeincrease) = 20;
+    MY(size_min) = 30;
+    MY(size_max) = 30;
+    MY(tex_max) = 8;
+    MY(type) = "smoke";
+    MY(velocityjitter) = '160.0 160.0 60.0';
+    MY(velocitymultiplier) = 0.400000;
+}
+//sparks
+SUB(wakizashi_rocket_launch) {
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 1000;
+    MY(color_min) = "0xFFFFFF";
+    MY(color_max) = "0xD9C4B0";
+    MY(count) = 10;
+    MY(notunderwater) = true;
+    MY(size_min) = 1;
+    MY(size_max) = 4;
+    MY(tex_min) = 40;
+    MY(tex_max) = 40;
+    MY(type) = "spark";
+    MY(velocityjitter) = '60.0 60.0 60.0';
+    MY(velocitymultiplier) = -1.500000;
+}
+
+DEF(wakizashi_booster_smoke);
+SUB(wakizashi_booster_smoke) {
+    MY(airfriction) = 2;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 750;
+    MY(alpha_fade) = 200;
+    MY(color_min) = "0xA69A80";
+    MY(color_max) = "0xB3B39F";
+    MY(count) = 3;
+    MY(gravity) = -0.100000;
+    MY(notunderwater) = true;
+    MY(originjitter) = '60.0 60.0 60.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = -20;
+    MY(spin_max) = 20;
+    MY(sizeincrease) = 10;
+    MY(size_min) = 60;
+    MY(size_max) = 100;
+    MY(tex_max) = 8;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '40.0 40.0 40.0';
+}
+
+DEF(raptor_cannon_impact);
+// decal
+SUB(raptor_cannon_impact) {
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(countabsolute) = 1;
+    MY(originjitter) = '16.0 16.0 16.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(size_min) = 24;
+    MY(size_max) = 24;
+    MY(tex_min) = 47;
+    MY(tex_max) = 47;
+    MY(type) = "decal";
+}
+// spark
+SUB(raptor_cannon_impact) {
+    MY(airfriction) = 0.200000;
+    MY(alpha_min) = 644;
+    MY(alpha_max) = 956;
+    MY(alpha_fade) = 784;
+    MY(color_min) = "0xD400FF";
+    MY(color_max) = "0x571863";
+    MY(count) = 6;
+    MY(gravity) = 1;
+    MY(notunderwater) = true;
+    MY(originjitter) = '16.0 16.0 16.0';
+    MY(size_min) = 1;
+    MY(size_max) = 1;
+    MY(tex_min) = 40;
+    MY(tex_max) = 40;
+    MY(type) = "spark";
+    MY(velocityjitter) = '124.0 124.0 524.0';
+    MY(velocityoffset) = '0.0 0.0 150.0';
+}
+// smoke
+SUB(raptor_cannon_impact) {
+    MY(airfriction) = 2;
+    MY(alpha_min) = 428;
+    MY(alpha_max) = 428;
+    MY(alpha_fade) = 600;
+    MY(color_min) = "0x646364";
+    MY(color_max) = "0x151515";
+    MY(count) = 4;
+    MY(gravity) = 0.700000;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(size_min) = 50;
+    MY(size_max) = 50;
+    MY(tex_max) = 7;
+    MY(type) = "alphastatic";
+    MY(velocityjitter) = '200.0 200.0 300.0';
+    MY(velocityoffset) = '0.0 0.0 340.0';
+}
+// fire
+SUB(raptor_cannon_impact) {
+    MY(airfriction) = 8;
+    MY(alpha_min) = 200;
+    MY(alpha_max) = 256;
+    MY(alpha_fade) = 812;
+    MY(bounce) = 1.500000;
+    MY(color_min) = "0xD400FF";
+    MY(color_max) = "0x571863";
+    MY(count) = 10;
+    MY(liquidfriction) = 8;
+    MY(notunderwater) = true;
+    MY(originjitter) = '8.0 8.0 8.0';
+    MY(sizeincrease) = 25;
+    MY(size_min) = 33;
+    MY(size_max) = 44;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "static";
+    MY(velocityjitter) = '312.0 312.0 312.0';
+}
+
+DEF(raptor_cannon_muzzleflash);
+SUB(raptor_cannon_muzzleflash) {
+    MY(airfriction) = 12;
+    MY(alpha_min) = 1256;
+    MY(alpha_max) = 1512;
+    MY(alpha_fade) = 56280;
+    MY(color_min) = "0xD400FF";
+    MY(color_max) = "0x571863";
+    MY(count) = 16;
+    MY(originjitter) = '2.0 2.0 2.0';
+    MY(sizeincrease) = -10;
+    MY(size_min) = 10;
+    MY(size_max) = 17;
+    MY(stretchfactor) = 0.600000;
+    MY(tex_min) = 8;
+    MY(tex_max) = 15;
+    MY(type) = "spark";
+    MY(velocityjitter) = '200.0 200.0 200.0';
+    MY(velocitymultiplier) = 0.200000;
+}
+SUB(raptor_cannon_muzzleflash) {
+    MY(alpha_min) = 6056;
+    MY(alpha_max) = 20112;
+    MY(alpha_fade) = 406280;
+    MY(color_min) = "0xD400FF";
+    MY(color_max) = "0x571863";
+    MY(countabsolute) = 1;
+    MY(lightcolor) = '3.0 0.0 6.0';
+    MY(lightradiusfade) = 6000;
+    MY(lightradius) = 150;
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(spin_min) = 4000;
+    MY(spin_max) = -4000;
+    MY(sizeincrease) = -100;
+    MY(size_min) = 32;
+    MY(size_max) = 32;
+    MY(stretchfactor) = 0.100000;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "static";
+}
+
+DEF(raptor_bomb_impact);
+// decal
+SUB(raptor_bomb_impact) {
+    MY(alpha_min) = 256;
+    MY(alpha_max) = 256;
+    MY(countabsolute) = 1;
+    MY(originjitter) = '16.0 16.0 16.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(size_min) = 84;
+    MY(size_max) = 84;
+    MY(tex_min) = 8;
+    MY(tex_max) = 16;
+    MY(type) = "decal";
+}
+// spark vertical
+SUB(raptor_bomb_impact) {
+    MY(alpha_min) = 300;
+    MY(alpha_max) = 300;
+    MY(alpha_fade) = 600;
+    MY(color_min) = "0xff9c00";
+    MY(color_max) = "0xff3c00";
+    MY(count) = 3;
+    MY(originjitter) = '10.0 10.0 10.0';
+    MY(sizeincrease) = 50;
+    MY(size_min) = 20;
+    MY(size_max) = 40;
+    MY(stretchfactor) = 210;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "spark";
+    MY(velocityjitter) = '40.0 40.0 120.0';
+}
+// fire
+SUB(raptor_bomb_impact) {
+    MY(airfriction) = 2;
+    MY(alpha_min) = 300;
+    MY(alpha_max) = 300;
+    MY(alpha_fade) = 500;
+    MY(color_min) = "0xff9c00";
+    MY(color_max) = "0xff3c00";
+    MY(count) = 4;
+    MY(originjitter) = '10.0 10.0 10.0';
+    MY(sizeincrease) = 230;
+    MY(size_min) = 30;
+    MY(size_max) = 120;
+    MY(tex_min) = 48;
+    MY(tex_max) = 55;
+    MY(type) = "static";
+    MY(velocityjitter) = '950.0 950.0 0.0';
+}
+// smoke
+SUB(raptor_bomb_impact) {
+    MY(alpha_min) = 428;
+    MY(alpha_max) = 428;
+    MY(alpha_fade) = 600;
+    MY(blend) = "alpha";
+    MY(color_min) = "0x646364";
+    MY(color_max) = "0x151515";
+    MY(count) = 4;
+    MY(originjitter) = '30.0 30.0 10.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(size_min) = 120;
+    MY(size_max) = 180;
+    MY(stretchfactor) = 10;
+    MY(tex_max) = 7;
+    MY(type) = "spark";
+    MY(velocityjitter) = '200.0 200.0 280.0';
+    MY(velocityoffset) = '0.0 0.0 280.0';
+}
+// smoke 2
+SUB(raptor_bomb_impact) {
+    MY(airfriction) = 0.600000;
+    MY(alpha_min) = 328;
+    MY(alpha_max) = 328;
+    MY(alpha_fade) = 350;
+    MY(blend) = "alpha";
+    MY(color_min) = "0x646364";
+    MY(color_max) = "0x151515";
+    MY(count) = 4;
+    MY(gravity) = 2;
+    MY(originjitter) = '30.0 30.0 10.0';
+    MY(startangle_min) = -180;
+    MY(startangle_max) = 180;
+    MY(sizeincrease) = 60;
+    MY(size_min) = 40;
+    MY(size_max) = 100;
+    MY(tex_max) = 7;
+    MY(type) = "spark";
+    MY(velocityjitter) = '200.0 200.0 300.0';
+    MY(velocityoffset) = '0.0 0.0 580.0';
+}
+// sparks
+SUB(raptor_bomb_impact) {
+    MY(airfriction) = 0.300000;
+    MY(alpha_min) = 644;
+    MY(alpha_max) = 956;
+    MY(alpha_fade) = 984;
+    MY(color_min) = "0xffa35b";
+    MY(color_max) = "0xfff2be";
+    MY(count) = 5;
+    MY(gravity) = 1;
+    MY(notunderwater) = true;
+    MY(originjitter) = '16.0 16.0 16.0';
+    MY(size_min) = 3;
+    MY(size_max) = 5;
+    MY(stretchfactor) = 2;
+    MY(tex_min) = 40;
+    MY(tex_max) = 40;
+    MY(type) = "spark";
+    MY(velocityjitter) = '174.0 174.0 924.0';
+    MY(velocityoffset) = '0.0 0.0 350.0';
+}
+
+DEF(raptor_bomb_spread);
+SUB(raptor_bomb_spread) {
+    MY(airfriction) = 1;
+    MY(alpha_min) = 644;
+    MY(alpha_max) = 956;
+    MY(alpha_fade) = 1284;
+    MY(color_min) = "0xffa35b";
+    MY(color_max) = "0xfff2be";
+    MY(count) = 34;
+    MY(gravity) = 1;
+    MY(liquidfriction) = 0.800000;
+    MY(notunderwater) = true;
+    MY(originjitter) = '110.0 110.0 110.0';
+    MY(size_min) = 1;
+    MY(size_max) = 2;
+    MY(tex_min) = 40;
+    MY(tex_max) = 40;
+    MY(type) = "spark";
+    MY(velocityjitter) = '324.0 324.0 324.0';
+}
diff --git a/qcsrc/common/effects/effects.inc b/qcsrc/common/effects/effects.inc
new file mode 100644 (file)
index 0000000..4d82087
--- /dev/null
@@ -0,0 +1,293 @@
+// Global list of effects, networked to CSQC by ID to save bandwidth and to use client particle numbers (allows mismatching effectinfos to some degree)
+// Not too concerned about the order of this list, just keep the weapon effects together!
+
+// EFFECT(istrail, EFFECT_NAME,     "effectinfo_string")
+EFFECT(0, EXPLOSION_SMALL,          "explosion_small")
+EFFECT(0, EXPLOSION_MEDIUM,         "explosion_medium")
+EFFECT(0, EXPLOSION_BIG,            "explosion_big")
+
+EFFECT(0, SMOKE_SMALL,              "smoke_small")
+EFFECT(0, SMOKE_LARGE,              "smoke_large")
+
+
+
+EFFECT(0, BLASTER_IMPACT,           "laser_impact")
+EFFECT(0, BLASTER_MUZZLEFLASH,      "laser_muzzleflash")
+
+EFFECT(0, SHOTGUN_IMPACT,           "shotgun_impact")
+EFFECT(0, SHOTGUN_MUZZLEFLASH,      "shotgun_muzzleflash")
+
+EFFECT(0, ARC_BEAM,                 "arc_beam")
+EFFECT(0, ARC_BEAM_HEAL,            "arc_beam_heal")
+EFFECT(0, ARC_BEAM_HEAL_IMPACT,     "arc_beam_healimpact")
+EFFECT(0, ARC_BEAM_HEAL_IMPACT2,    "healray_impact")
+EFFECT(0, ARC_LIGHTNING,            "arc_lightning")
+EFFECT(0, ARC_LIGHTNING2,           "electro_lightning")
+
+EFFECT(0, MACHINEGUN_IMPACT,        "machinegun_impact")
+EFFECT(0, MACHINEGUN_MUZZLEFLASH,   "uzi_muzzleflash")
+
+EFFECT(0, GRENADE_EXPLODE,          "grenade_explode")
+EFFECT(0, GRENADE_MUZZLEFLASH,      "grenadelauncher_muzzleflash")
+
+EFFECT(0, ELECTRO_BALLEXPLODE,      "electro_ballexplode")
+EFFECT(0, ELECTRO_COMBO,            "electro_combo")
+EFFECT(0, ELECTRO_IMPACT,           "electro_impact")
+EFFECT(0, ELECTRO_MUZZLEFLASH,      "electro_muzzleflash")
+
+EFFECT(0, CRYLINK_IMPACT,           "crylink_impactbig")
+EFFECT(0, CRYLINK_IMPACT2,          "crylink_impact")
+EFFECT(0, CRYLINK_JOINEXPLODE,      "crylink_joinexplode")
+EFFECT(0, CRYLINK_MUZZLEFLASH,      "crylink_muzzleflash")
+
+EFFECT(0, VORTEX_BEAM,              "nex_beam")
+EFFECT(0, VORTEX_BEAM_OLD,          "TE_TEI_G3")
+EFFECT(0, VORTEX_IMPACT,            "nex_impact")
+EFFECT(0, VORTEX_MUZZLEFLASH,       "nex_muzzleflash")
+
+EFFECT(1, VAPORIZER_RED,            "TE_TEI_G3RED")
+EFFECT(1, VAPORIZER_HIT_RED,        "TE_TEI_G3RED_HIT")
+EFFECT(1, VAPORIZER_BLUE,           "TE_TEI_G3BLUE")
+EFFECT(1, VAPORIZER_HIT_BLUE,       "TE_TEI_G3BLUE_HIT")
+EFFECT(1, VAPORIZER_YELLOW,         "TE_TEI_G3YELLOW")
+EFFECT(1, VAPORIZER_HIT_YELLOW,     "TE_TEI_G3YELLOW_HIT")
+EFFECT(1, VAPORIZER_PINK,           "TE_TEI_G3PINK")
+EFFECT(1, VAPORIZER_HIT_PINK,       "TE_TEI_G3PINK_HIT")
+EFFECT(1, VAPORIZER_NEUTRAL,        "TE_TEI_G3")
+EFFECT(1, VAPORIZER_HIT_NEUTRAL,    "TE_TEI_G3_HIT")
+entity EFFECT_VAPORIZER(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_VAPORIZER_RED;
+        case NUM_TEAM_2:    return EFFECT_VAPORIZER_BLUE;
+        case NUM_TEAM_3:    return EFFECT_VAPORIZER_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_VAPORIZER_PINK;
+        default:            return EFFECT_VAPORIZER_NEUTRAL;
+    }
+}
+entity EFFECT_VAPORIZER_HIT(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_VAPORIZER_HIT_RED;
+        case NUM_TEAM_2:    return EFFECT_VAPORIZER_HIT_BLUE;
+        case NUM_TEAM_3:    return EFFECT_VAPORIZER_HIT_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_VAPORIZER_HIT_PINK;
+        default:            return EFFECT_VAPORIZER_HIT_NEUTRAL;
+    }
+}
+
+EFFECT(0, RIFLE_IMPACT,             "machinegun_impact")
+EFFECT(0, RIFLE_MUZZLEFLASH,        "rifle_muzzleflash")
+EFFECT(1, RIFLE,                    "tr_rifle")
+EFFECT(1, RIFLE_WEAK,               "tr_rifle_weak")
+
+EFFECT(0, HAGAR_BOUNCE,             "hagar_bounce")
+EFFECT(0, HAGAR_EXPLODE,            "hagar_explode")
+EFFECT(0, HAGAR_MUZZLEFLASH,        "hagar_muzzleflash")
+EFFECT(1, HAGAR_ROCKET,             "tr_hagar")
+
+EFFECT(0, ROCKET_EXPLODE,           "rocket_explode")
+EFFECT(0, ROCKET_GUIDE,             "rocket_guide")
+EFFECT(0, ROCKET_MUZZLEFLASH,       "rocketlauncher_muzzleflash")
+
+EFFECT(0, HOOK_EXPLODE,             "hookbomb_explode")
+EFFECT(0, HOOK_IMPACT,              "grapple_impact")
+EFFECT(0, HOOK_MUZZLEFLASH,         "grapple_muzzleflash")
+
+EFFECT(0, SEEKER_MUZZLEFLASH,       "seeker_muzzleflash")
+
+EFFECT(0, FLAK_BOUNCE,              "flak_bounce")
+
+EFFECT(1, FIREBALL,                 "fireball")
+EFFECT(0, FIREBALL_BFGDAMAGE,       "fireball_bfgdamage")
+EFFECT(0, FIREBALL_EXPLODE,         "fireball_explode")
+EFFECT(0, FIREBALL_LASER,           "fireball_laser")
+EFFECT(0, FIREBALL_MUZZLEFLASH,     "fireball_muzzleflash")
+EFFECT(0, FIREBALL_PRE_MUZZLEFLASH, "fireball_preattack_muzzleflash")
+
+
+
+EFFECT(0, RAPTOR_CANNON_IMPACT,     "raptor_cannon_impact")
+EFFECT(0, RAPTOR_BOMB_IMPACT,       "raptor_bomb_impact")
+EFFECT(0, RAPTOR_BOMB_SPREAD,       "raptor_bomb_spread")
+EFFECT(0, RAPTOR_MUZZLEFLASH,       "raptor_cannon_muzzleflash")
+
+EFFECT(0, RACER_BOOSTER,            "wakizashi_booster_smoke")
+EFFECT(0, RACER_IMPACT,             "wakizashi_gun_impact")
+EFFECT(0, RACER_MUZZLEFLASH,        "wakizashi_gun_muzzleflash")
+EFFECT(0, RACER_ROCKETLAUNCH,       "wakizashi_rocket_launch")
+EFFECT(0, RACER_ROCKET_EXPLODE,     "wakizashi_rocket_launch")
+EFFECT(1, RACER_ROCKET_TRAIL,       "wakizashi_rocket_thrust")
+
+EFFECT(0, SPIDERBOT_ROCKETLAUNCH,           "spiderbot_rocket_launch")
+EFFECT(1, SPIDERBOT_ROCKET_TRAIL,           "spiderbot_rocket_thrust")
+EFFECT(0, SPIDERBOT_ROCKET_EXPLODE,         "spiderbot_rocket_explode")
+EFFECT(0, SPIDERBOT_MINIGUN_IMPACT,         "spiderbot_minigun_impact")
+EFFECT(0, SPIDERBOT_MINIGUN_MUZZLEFLASH,    "spiderbot_minigun_muzzleflash")
+
+EFFECT(0, BUMBLEBEE_HEAL_MUZZLEFLASH,   "healray_muzzleflash")
+EFFECT(0, BUMBLEBEE_HEAL_IMPACT,        "healray_impact")
+
+EFFECT(0, BIGPLASMA_IMPACT,         "bigplasma_impact")
+EFFECT(0, BIGPLASMA_MUZZLEFLASH,    "bigplasma_muzzleflash")
+
+EFFECT(0, TELEPORT,                 "teleport")
+
+EFFECT(0, SPAWNPOINT_RED,           "spawn_point_red")
+EFFECT(0, SPAWN_RED,                "spawn_event_red")
+EFFECT(0, SPAWNPOINT_BLUE,          "spawn_point_blue")
+EFFECT(0, SPAWN_BLUE,               "spawn_event_blue")
+EFFECT(0, SPAWNPOINT_YELLOW,        "spawn_point_yellow")
+EFFECT(0, SPAWN_YELLOW,             "spawn_event_yellow")
+EFFECT(0, SPAWNPOINT_PINK,          "spawn_point_pink")
+EFFECT(0, SPAWN_PINK,               "spawn_event_pink")
+EFFECT(0, SPAWNPOINT_NEUTRAL,       "spawn_point_neutral")
+EFFECT(0, SPAWN_NEUTRAL,            "spawn_event_neutral")
+
+EFFECT(0, NADE_EXPLODE_RED,         "nade_red_explode")
+EFFECT(0, NADE_EXPLODE_BLUE,        "nade_blue_explode")
+EFFECT(0, NADE_EXPLODE_YELLOW,      "nade_yellow_explode")
+EFFECT(0, NADE_EXPLODE_PINK,        "nade_pink_explode")
+EFFECT(0, NADE_EXPLODE_NEUTRAL,     "nade_neutral_explode")
+entity EFFECT_NADE_EXPLODE(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_NADE_EXPLODE_RED;
+        case NUM_TEAM_2:    return EFFECT_NADE_EXPLODE_BLUE;
+        case NUM_TEAM_3:    return EFFECT_NADE_EXPLODE_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_NADE_EXPLODE_PINK;
+        default:                   return EFFECT_NADE_EXPLODE_NEUTRAL;
+    }
+}
+
+EFFECT(1, NADE_TRAIL_RED,           "nade_red")
+EFFECT(1, NADE_TRAIL_BLUE,          "nade_blue")
+EFFECT(1, NADE_TRAIL_YELLOW,        "nade_yellow")
+EFFECT(1, NADE_TRAIL_PINK,          "nade_pink")
+EFFECT(1, NADE_TRAIL_NEUTRAL,       "nade_neutral")
+entity EFFECT_NADE_TRAIL(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_NADE_TRAIL_RED;
+        case NUM_TEAM_2:    return EFFECT_NADE_TRAIL_BLUE;
+        case NUM_TEAM_3:    return EFFECT_NADE_TRAIL_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_NADE_TRAIL_PINK;
+        default:            return EFFECT_NADE_TRAIL_NEUTRAL;
+    }
+}
+
+EFFECT(1, NADE_TRAIL_BURN_RED,      "nade_red_burn")
+EFFECT(1, NADE_TRAIL_BURN_BLUE,     "nade_blue_burn")
+EFFECT(1, NADE_TRAIL_BURN_YELLOW,   "nade_yellow_burn")
+EFFECT(1, NADE_TRAIL_BURN_PINK,     "nade_pink_burn")
+EFFECT(1, NADE_TRAIL_BURN_NEUTRAL,  "nade_neutral_burn")
+entity EFFECT_NADE_TRAIL_BURN(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_NADE_TRAIL_BURN_RED;
+        case NUM_TEAM_2:    return EFFECT_NADE_TRAIL_BURN_BLUE;
+        case NUM_TEAM_3:    return EFFECT_NADE_TRAIL_BURN_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_NADE_TRAIL_BURN_PINK;
+        default:            return EFFECT_NADE_TRAIL_BURN_NEUTRAL;
+    }
+}
+
+EFFECT(0, ICEORGLASS,               "iceorglass")
+EFFECT(0, ICEFIELD,                 "icefield")
+EFFECT(0, FIREFIELD,                "firefield")
+EFFECT(0, HEALING,                  "healing_fx")
+EFFECT(1, LASER_BEAM_FAST,          "nex242_misc_laser_beam_fast")
+EFFECT(0, RESPAWN_GHOST,            "respawn_ghost")
+
+EFFECT(0, FLAG_TOUCH_RED,           "redflag_touch")
+EFFECT(0, FLAG_TOUCH_BLUE,          "blueflag_touch")
+EFFECT(0, FLAG_TOUCH_YELLOW,        "yellowflag_touch")
+EFFECT(0, FLAG_TOUCH_PINK,          "pinkflag_touch")
+EFFECT(0, FLAG_TOUCH_NEUTRAL,       "neutralflag_touch")
+entity EFFECT_FLAG_TOUCH(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_FLAG_TOUCH_RED;
+        case NUM_TEAM_2:    return EFFECT_FLAG_TOUCH_BLUE;
+        case NUM_TEAM_3:    return EFFECT_FLAG_TOUCH_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_FLAG_TOUCH_PINK;
+        default:            return EFFECT_FLAG_TOUCH_NEUTRAL;
+    }
+}
+
+EFFECT(1, PASS_RED,                 "red_pass")
+EFFECT(1, PASS_BLUE,                "blue_pass")
+EFFECT(1, PASS_YELLOW,              "yellow_pass")
+EFFECT(1, PASS_PINK,                "pink_pass")
+EFFECT(1, PASS_NEUTRAL,             "neutral_pass")
+
+EFFECT(0, CAP_RED,                  "red_cap")
+EFFECT(0, CAP_BLUE,                 "blue_cap")
+EFFECT(0, CAP_YELLOW,               "yellow_cap")
+EFFECT(0, CAP_PINK,                 "pink_cap")
+EFFECT(0, CAP_NEUTRAL,              "neutral_cap")
+entity EFFECT_CAP(int teamid)
+{
+    switch (teamid) {
+        case NUM_TEAM_1:    return EFFECT_CAP_RED;
+        case NUM_TEAM_2:    return EFFECT_CAP_BLUE;
+        case NUM_TEAM_3:    return EFFECT_CAP_YELLOW;
+        case NUM_TEAM_4:    return EFFECT_CAP_PINK;
+        default:            return EFFECT_CAP_NEUTRAL;
+    }
+}
+
+EFFECT(0, ITEM_PICKUP,              "item_pickup")
+EFFECT(0, ITEM_RESPAWN,             "item_respawn")
+
+EFFECT(0, ONS_GENERATOR_DAMAGED,    "torch_small")
+EFFECT(0, ONS_GENERATOR_GIB,        "onslaught_generator_gib_explode")
+EFFECT(0, ONS_GENERATOR_EXPLODE,    "onslaught_generator_smallexplosion")
+EFFECT(0, ONS_GENERATOR_EXPLODE2,   "onslaught_generator_finalexplosion")
+
+
+
+EFFECT(0, LASER_DEADLY,             "laser_deadly")
+EFFECT(1, FLAC_TRAIL,               "TR_SEEKER")
+EFFECT(1, SEEKER_TRAIL,             "TR_SEEKER")
+EFFECT(1, FIREMINE,                 "firemine")
+EFFECT(0, BALL_SPARKS,              "kaball_sparks")
+EFFECT(0, ELECTRIC_SPARKS,          "electricity_sparks")
+EFFECT(0, SPARKS,                   "sparks")
+EFFECT(0, RAGE,                     "rage")
+EFFECT(0, SMOKING,                  "smoking")
+EFFECT(0, SMOKE_RING,               "smoke_ring")
+EFFECT(0, JUMPPAD,                  "jumppad_activate")
+EFFECT(1, BULLET,                   "tr_bullet")
+EFFECT(0, EF_FLAME,                 "EF_FLAME")
+EFFECT(0, EF_STARDUST,              "EF_STARDUST")
+EFFECT(0, TE_EXPLOSION,             "TE_EXPLOSION")
+EFFECT(1, TR_NEXUIZPLASMA,          "TR_NEXUIZPLASMA")
+EFFECT(1, TR_CRYLINKPLASMA,         "TR_CRYLINKPLASMA")
+EFFECT(1, TR_ROCKET,                "TR_ROCKET")
+EFFECT(1, TR_GRENADE,               "TR_GRENADE")
+EFFECT(1, TR_BLOOD,                 "TR_BLOOD")
+EFFECT(1, TR_WIZSPIKE,              "TR_WIZSPIKE")
+EFFECT(1, TR_SLIGHTBLOOD,           "TR_SLIGHTBLOOD")
+EFFECT(1, TR_KNIGHTSPIKE,           "TR_KNIGHTSPIKE")
+EFFECT(1, TR_VORESPIKE,             "TR_VORESPIKE")
+EFFECT(0, TE_SPARK,                 "TE_SPARK")
+
+EFFECT(1, ROCKETMINSTA_LASER_RED,       "rocketminsta_laser_red")
+EFFECT(1, ROCKETMINSTA_LASER_BLUE,      "rocketminsta_laser_blue")
+EFFECT(1, ROCKETMINSTA_LASER_YELLOW,    "rocketminsta_laser_yellow")
+EFFECT(1, ROCKETMINSTA_LASER_PINK,      "rocketminsta_laser_pink")
+EFFECT(1, ROCKETMINSTA_LASER_NEUTRAL,   "rocketminsta_laser_neutral")
+entity EFFECT_ROCKETMINSTA_LASER(int teamid)
+{
+    entity e;
+    switch (teamid) {
+        case NUM_TEAM_1:    e = EFFECT_ROCKETMINSTA_LASER_RED; break;
+        case NUM_TEAM_2:    e = EFFECT_ROCKETMINSTA_LASER_BLUE; break;
+        case NUM_TEAM_3:    e = EFFECT_ROCKETMINSTA_LASER_YELLOW; break;
+        case NUM_TEAM_4:    e = EFFECT_ROCKETMINSTA_LASER_PINK; break;
+        default:            e = EFFECT_ROCKETMINSTA_LASER_NEUTRAL; break;
+    }
+    if (particleeffectnum(e) < 0 || Team_TeamToNumber(teamid) == -1) { e = EFFECT_TR_NEXUIZPLASMA; }
+    return e;
+}
diff --git a/qcsrc/common/effects/effects.qc b/qcsrc/common/effects/effects.qc
new file mode 100644 (file)
index 0000000..78bb675
--- /dev/null
@@ -0,0 +1,91 @@
+#ifdef CSQC
+void Read_Effect(bool is_new)
+{
+       int net_name = (Effects_COUNT >= 255) ? ReadShort() : ReadByte();
+
+       entity eff = Effects[net_name];
+
+       vector v, vel = '0 0 0';
+       int eff_cnt = 1;
+       bool eff_trail = eff.eent_eff_trail;
+       v_x = ReadCoord();
+       v_y = ReadCoord();
+       v_z = ReadCoord();
+
+       bool use_vel = ReadByte();
+       if(use_vel)
+       {
+               vel_x = ReadCoord();
+               vel_y = ReadCoord();
+               vel_z = ReadCoord();
+       }
+
+       if(!eff_trail)
+               eff_cnt = ReadByte();
+
+       if(is_new)
+       {
+               if(eff_trail)
+                       WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel);
+               else
+                       pointparticles(particleeffectnum(eff), v, vel, eff_cnt);
+       }
+}
+#endif
+
+#ifdef SVQC
+bool Net_Write_Effect(entity this, entity client, int sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_EFFECT);
+       (Effects_COUNT >= 255)
+       ? WriteShort(MSG_ENTITY, self.m_id)
+       : WriteByte(MSG_ENTITY, self.m_id);
+       WriteCoord(MSG_ENTITY, self.eent_net_location_x);
+       WriteCoord(MSG_ENTITY, self.eent_net_location_y);
+       WriteCoord(MSG_ENTITY, self.eent_net_location_z);
+
+       // attempt to save a tiny bit more bandwidth by not sending velocity if it isn't set
+       if(self.eent_net_velocity)
+       {
+               WriteByte(MSG_ENTITY, true);
+               WriteCoord(MSG_ENTITY, self.eent_net_velocity_x);
+               WriteCoord(MSG_ENTITY, self.eent_net_velocity_y);
+               WriteCoord(MSG_ENTITY, self.eent_net_velocity_z);
+       }
+       else { WriteByte(MSG_ENTITY, false); }
+
+       if(!self.eent_eff_trail) { WriteByte(MSG_ENTITY, self.eent_net_count); }
+       return true;
+}
+
+void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
+{
+       if(!eff) { return; }
+       if(!eff.eent_eff_trail && !eff_cnt) { return; } // effect has no count!
+       entity net_eff = spawn();
+       net_eff.owner = eff;
+       net_eff.classname = "net_effect";
+       //net_eff.eent_broadcast = broadcast;
+       net_eff.m_id = eff.m_id;
+       net_eff.eent_net_velocity = eff_vel;
+       net_eff.eent_net_location = eff_loc;
+       net_eff.eent_net_count = eff_cnt;
+       net_eff.eent_eff_trail = eff.eent_eff_trail;
+
+       net_eff.think = SUB_Remove;
+       net_eff.nextthink = time + 0.2; // don't need to keep this long
+
+       Net_LinkEntity(net_eff, false, 0, Net_Write_Effect);
+}
+
+void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
+{
+       // problem with this is, we might not have all the available effects for it
+       FOREACH(Effects, it.eent_eff_name == eff_name, LAMBDA(
+               Send_Effect(it, eff_loc, eff_vel, eff_cnt);
+               return;
+       ));
+       // revert to engine handling
+       pointparticles(_particleeffectnum(eff_name), eff_loc, eff_vel, eff_cnt);
+}
+#endif
diff --git a/qcsrc/common/effects/effects.qh b/qcsrc/common/effects/effects.qh
new file mode 100644 (file)
index 0000000..2182175
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef P_EFFECTS_H
+#define P_EFFECTS_H
+
+#ifdef CSQC
+void Read_Effect(bool is_new);
+#elif defined(SVQC)
+void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt);
+void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt);
+#endif
+
+#define particleeffectnum(e) _particleeffectnum(e.eent_eff_name)
+
+REGISTRY(Effects, BIT(8))
+REGISTER_REGISTRY(RegisterEffects)
+#define EFFECT(istrail, name, realname) \
+    REGISTER(RegisterEffects, EFFECT, Effects, name, m_id, Create_Effect_Entity(realname, istrail));
+
+.int m_id;
+.string eent_eff_name;
+.int eent_eff_trail;
+
+.vector eent_net_location;
+.vector eent_net_velocity;
+.int eent_net_count;
+
+entity Create_Effect_Entity(string eff_name, bool eff_trail)
+{
+       entity this = new(effect_entity);
+       this.eent_eff_name = eff_name;
+       this.eent_eff_trail = eff_trail;
+       return this;
+}
+
+void RegisterEffects_First()
+{
+    #ifdef SVQC
+    #define dedi (server_is_dedicated ? "a dedicated " : "")
+    #else
+    #define dedi ""
+    #endif
+
+    LOG_TRACEF("Beginning effect initialization on %s%s program...\n", dedi, PROGNAME);
+    #undef dedi
+}
+
+void RegisterEffects_Done()
+{
+    LOG_TRACE("Effects initialization successful!\n");
+}
+
+// NOW we actually activate the declarations
+ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_First)
+EFFECT(0, Null, string_null)
+#include "effects.inc"
+ACCUMULATE_FUNCTION(RegisterEffects, RegisterEffects_Done)
+
+#endif
index fc225cdb7d40ecf648da2b802ecd504fba8631cc..927b2ece26c1ed5282d9dda604c765a1aac0c281 100644 (file)
@@ -6,9 +6,19 @@
 
 void Dump_Items()
 {
-    FOREACH(ITEMS, true, LAMBDA(
+    FOREACH(Items, true, LAMBDA(
         ITEM_HANDLE(Show, it);
     ));
 }
 
+string Item_Model(string item_mdl)
+{
+    string output = strcat("models/items/", item_mdl);
+#ifdef SVQC
+    MUTATOR_CALLHOOK(ItemModel, item_mdl, output);
+    output = item_model_output;
+#endif
+    return output;
+}
+
 #endif
index 2e33119fb089920e71c69ccf07051223dc945496..672ed707cd0c3bf271d98fd713ba3f44177ae32a 100644 (file)
@@ -1,16 +1,19 @@
 #ifndef ITEMS_ALL_H
 #define ITEMS_ALL_H
 
-void RegisterItems();
-const int MAX_ITEMS = 24;
-entity ITEMS[MAX_ITEMS], ITEMS_first, ITEMS_last;
-int ITEM_COUNT;
-/** If you register a new item, make sure to add it to all.inc */
-#define REGISTER_ITEM(id, class) REGISTER(RegisterItems, ITEM, ITEMS, ITEM_COUNT, id, m_id, NEW(class))
+#include "item.qh"
+
+REGISTRY(Items, BIT(5))
 REGISTER_REGISTRY(RegisterItems)
+/** If you register a new item, make sure to add it to all.inc */
+#define REGISTER_ITEM(id, class) REGISTER(RegisterItems, ITEM, Items, id, m_id, NEW(class))
 
 void Dump_Items();
 
+#ifndef MENUQC
+string Item_Model(string item_mdl);
+#endif
+
 #endif
 
 #include "inventory.qh"
index 9b4013405d6740e7db8b23ac5a463a2bcc0e6e51..a6d266ae5fba57d3d50727b25cb41d1fe1c396e2 100644 (file)
@@ -6,7 +6,7 @@
 
 entityclass(Inventory);
 /** Stores counts of items, the id being the index */
-class(Inventory) .int inv_items[MAX_ITEMS];
+class(Inventory) .int inv_items[Items_MAX];
 
 /** Player inventory; Inventories also have one inventory for storing the previous state */
 .Inventory inventory;
@@ -15,11 +15,11 @@ class(Inventory) .int inv_items[MAX_ITEMS];
 void Inventory_Read(Inventory data)
 {
     const int bits = ReadInt24_t();
-    FOREACH(ITEMS, bits & BIT(i), LAMBDA(
-        .int fld = inv_items[i];
+    FOREACH(Items, bits & BIT(it.m_id), LAMBDA(
+        .int fld = inv_items[it.m_id];
         int prev = data.(fld);
         int next = data.(fld) = ReadByte();
-        LOG_TRACEF("%s: %.0f -> %.0f\n", ITEMS[i].m_name, prev, next);
+        LOG_TRACEF("%s: %.0f -> %.0f\n", it.m_name, prev, next);
     ));
 }
 #endif
@@ -28,19 +28,19 @@ void Inventory_Read(Inventory data)
 void Inventory_Write(Inventory data)
 {
     int bits = 0;
-    FOREACH(ITEMS, true, LAMBDA(
-        .int fld = inv_items[i];
-        bits = BITSET(bits, BIT(i), data.inventory.(fld) != (data.inventory.(fld) = data.(fld)));
+    FOREACH(Items, true, LAMBDA(
+        .int fld = inv_items[it.m_id];
+        bits = BITSET(bits, BIT(it.m_id), data.inventory.(fld) != (data.inventory.(fld) = data.(fld)));
     ));
     WriteInt24_t(MSG_ENTITY, bits);
-    FOREACH(ITEMS, bits & BIT(i), LAMBDA(
-        WriteByte(MSG_ENTITY, data.inv_items[i]);
+    FOREACH(Items, bits & BIT(it.m_id), LAMBDA(
+        WriteByte(MSG_ENTITY, data.inv_items[it.m_id]);
     ));
 }
 #endif
 
 #ifdef SVQC
-bool Inventory_Send(entity to, int sf)
+bool Inventory_Send(entity this, entity to, int sf)
 {
     WriteByte(MSG_ENTITY, ENT_CLIENT_INVENTORY);
     entity e = self.owner;
index 2d487a7b51be6723a030f44af5e14d5997da9883..16673711eea4b463b17c76d37702148dfa72176b 100644 (file)
@@ -3,8 +3,14 @@
     #include "../../../server/t_items.qh"
 #endif
 
+#ifndef MENUQC
+MODEL(Bullets_ITEM, Item_Model("a_bullets.mdl"));
+#endif
+
 REGISTER_ITEM(Bullets, Ammo) {
-    this.m_model    =   "a_bullets.mdl";
+#ifndef MENUQC
+    this.m_model    =   MDL_Bullets_ITEM;
+#endif
     this.m_name     =   "bullets";
     this.m_icon     =   "ammo_bullets";
 #ifdef SVQC
@@ -12,8 +18,15 @@ REGISTER_ITEM(Bullets, Ammo) {
     this.m_itemid   =   IT_NAILS;
 #endif
 }
+
+#ifndef MENUQC
+MODEL(Cells_ITEM, Item_Model("a_cells.md3"));
+#endif
+
 REGISTER_ITEM(Cells, Ammo) {
-    this.m_model    =   "a_cells.md3";
+#ifndef MENUQC
+    this.m_model    =   MDL_Cells_ITEM;
+#endif
     this.m_name     =   "cells";
     this.m_icon     =   "ammo_cells";
 #ifdef SVQC
@@ -21,8 +34,15 @@ REGISTER_ITEM(Cells, Ammo) {
     this.m_itemid   =   IT_CELLS;
 #endif
 }
+
+#ifndef MENUQC
+MODEL(Plasma_ITEM, Item_Model("a_cells.md3"));
+#endif
+
 REGISTER_ITEM(Plasma, Ammo) {
-    this.m_model    =   "a_cells.md3";
+#ifndef MENUQC
+    this.m_model    =   MDL_Plasma_ITEM;
+#endif
     this.m_name     =   "plasma";
     this.m_icon     =   "ammo_plasma";
 #ifdef SVQC
@@ -30,8 +50,15 @@ REGISTER_ITEM(Plasma, Ammo) {
     this.m_itemid   =   IT_PLASMA;
 #endif
 }
+
+#ifndef MENUQC
+MODEL(Rockets_ITEM, Item_Model("a_rockets.md3"));
+#endif
+
 REGISTER_ITEM(Rockets, Ammo) {
-    this.m_model    =   "a_rockets.md3";
+#ifndef MENUQC
+    this.m_model    =   MDL_Rockets_ITEM;
+#endif
     this.m_name     =   "rockets";
     this.m_icon     =   "ammo_rockets";
 #ifdef SVQC
@@ -39,8 +66,15 @@ REGISTER_ITEM(Rockets, Ammo) {
     this.m_itemid   =   IT_ROCKETS;
 #endif
 }
+
+#ifndef MENUQC
+MODEL(Shells_ITEM, Item_Model("a_shells.md3"));
+#endif
+
 REGISTER_ITEM(Shells, Ammo) {
-    this.m_model    =   "a_shells.md3";
+#ifndef MENUQC
+    this.m_model    =   MDL_Shells_ITEM;
+#endif
     this.m_name     =   "shells";
     this.m_icon     =   "ammo_shells";
 #ifdef SVQC
index e7965803e2115e1e2f7f631fae6680a878d2eeaa..13a774ebcec18f693120f19e7b89982d688fe788 100644 (file)
@@ -3,8 +3,14 @@
     #include "../../../server/t_items.qh"
 #endif
 
+#ifndef MENUQC
+MODEL(ArmorSmall_ITEM, Item_Model("item_armor_small.md3"));
+#endif
+
 REGISTER_ITEM(ArmorSmall, Armor) {
-    this.m_model                =   "item_armor_small.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_ArmorSmall_ITEM;
+#endif
     this.m_sound                =   "misc/armor1.wav";
     this.m_name                 =   "5 Armor";
     this.m_icon                 =   "armor";
@@ -16,8 +22,14 @@ REGISTER_ITEM(ArmorSmall, Armor) {
 #endif
 }
 
+#ifndef MENUQC
+MODEL(ArmorMedium_ITEM, Item_Model("item_armor_medium.md3"));
+#endif
+
 REGISTER_ITEM(ArmorMedium, Armor) {
-    this.m_model                =   "item_armor_medium.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_ArmorMedium_ITEM;
+#endif
     this.m_sound                =   "misc/armor10.wav";
     this.m_name                 =   "25 Armor";
     this.m_icon                 =   "armor";
@@ -29,8 +41,14 @@ REGISTER_ITEM(ArmorMedium, Armor) {
 #endif
 }
 
+#ifndef MENUQC
+MODEL(ArmorLarge_ITEM, Item_Model("item_armor_big.md3"));
+#endif
+
 REGISTER_ITEM(ArmorLarge, Armor) {
-    this.m_model                =   "item_armor_big.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_ArmorLarge_ITEM;
+#endif
     this.m_sound                =   "misc/armor17_5.wav";
     this.m_name                 =   "50 Armor";
     this.m_icon                 =   "armor";
@@ -44,8 +62,14 @@ REGISTER_ITEM(ArmorLarge, Armor) {
 #endif
 }
 
+#ifndef MENUQC
+MODEL(ArmorMega_ITEM, Item_Model("item_armor_large.md3"));
+#endif
+
 REGISTER_ITEM(ArmorMega, Armor) {
-    this.m_model                =   "item_armor_large.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_ArmorMega_ITEM;
+#endif
     this.m_sound                =   "misc/armor25.wav";
     this.m_name                 =   "100 Armor";
     this.m_icon                 =   "item_large_armor";
index bb9d90eb44cdb9c2af8fc1d62cb54ec8665318a8..b81bde7afc22d1b0bd2152f990d5746725e215b3 100644 (file)
@@ -3,8 +3,14 @@
     #include "../../../server/t_items.qh"
 #endif
 
+#ifndef MENUQC
+MODEL(HealthSmall_ITEM, Item_Model("g_h1.md3"));
+#endif
+
 REGISTER_ITEM(HealthSmall, Health) {
-    this.m_model                =   "g_h1.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_HealthSmall_ITEM;
+#endif
     this.m_sound                =   "misc/minihealth.wav";
     this.m_name                 =   "5 Health";
     this.m_icon                 =   "health";
@@ -16,8 +22,14 @@ REGISTER_ITEM(HealthSmall, Health) {
 #endif
 }
 
+#ifndef MENUQC
+MODEL(HealthMedium_ITEM, Item_Model("g_h25.md3"));
+#endif
+
 REGISTER_ITEM(HealthMedium, Health) {
-    this.m_model                =   "g_h25.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_HealthMedium_ITEM;
+#endif
     this.m_sound                =   "misc/mediumhealth.wav";
     this.m_name                 =   "25 Health";
     this.m_icon                 =   "health";
@@ -29,8 +41,14 @@ REGISTER_ITEM(HealthMedium, Health) {
 #endif
 }
 
+#ifndef MENUQC
+MODEL(HealthLarge_ITEM, Item_Model("g_h50.md3"));
+#endif
+
 REGISTER_ITEM(HealthLarge, Health) {
-    this.m_model                =   "g_h50.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_HealthLarge_ITEM;
+#endif
     this.m_sound                =   "misc/mediumhealth.wav";
     this.m_name                 =   "50 Health";
     this.m_icon                 =   "health";
@@ -44,8 +62,14 @@ REGISTER_ITEM(HealthLarge, Health) {
 #endif
 }
 
+#ifndef MENUQC
+MODEL(HealthMega_ITEM, Item_Model("g_h100.md3"));
+#endif
+
 REGISTER_ITEM(HealthMega, Health) {
-    this.m_model                =   "g_h100.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_HealthMega_ITEM;
+#endif
     this.m_sound                =   "misc/megahealth.wav";
     this.m_name                 =   "100 Health";
     this.m_icon                 =   "item_mega_health";
index 3b4cfbc141c9a6b1798612f7b8ef7238162f20eb..63019aebe8bbf50800da4967ce6421144bb1d906 100644 (file)
@@ -6,8 +6,14 @@
 #include "ammo.qh"
 #include "powerup.qh"
 
+#ifndef MENUQC
+MODEL(Jetpack_ITEM, Item_Model("g_jetpack.md3"));
+#endif
+
 REGISTER_ITEM(Jetpack, Powerup) {
-    this.m_model                =   "g_jetpack.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_Jetpack_ITEM;
+#endif
     this.m_name                 =   "Jet pack";
     this.m_icon                 =   "jetpack";
     this.m_color                =   '0.5 0.5 0.5';
@@ -20,8 +26,14 @@ REGISTER_ITEM(Jetpack, Powerup) {
 #endif
 }
 
+#ifndef MENUQC
+MODEL(JetpackFuel_ITEM, Item_Model("g_fuel.md3"));
+#endif
+
 REGISTER_ITEM(JetpackFuel, Ammo) {
-    this.m_model    =   "g_fuel.md3";
+#ifndef MENUQC
+    this.m_model    =   MDL_JetpackFuel_ITEM;
+#endif
     this.m_name     =   "Fuel";
     this.m_icon     =   "ammo_fuel";
 #ifdef SVQC
@@ -30,8 +42,14 @@ REGISTER_ITEM(JetpackFuel, Ammo) {
 #endif
 }
 
+#ifndef MENUQC
+MODEL(JetpackRegen_ITEM, Item_Model("g_fuelregen.md3"));
+#endif
+
 REGISTER_ITEM(JetpackRegen, Pickup) {
-    this.m_model                =   "g_fuelregen.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_JetpackRegen_ITEM;
+#endif
     this.m_name                 =   "Fuel regenerator";
     this.m_icon                 =   "fuelregen";
     this.m_color                =   '1 0.5 0';
index 793230e359f831222ad7c309a7a7b001cbe332a0..6f60337c195a7ab7d79c43a04f5ec937e771ab67 100644 (file)
@@ -2,7 +2,9 @@
 #define PICKUP_H
 #include "../item.qh"
 CLASS(Pickup, GameItem)
-    ATTRIB(Pickup, m_model, string, string_null)
+#ifndef MENUQC
+    ATTRIB(Pickup, m_model, Model, NULL)
+#endif
     ATTRIB(Pickup, m_sound, string, "misc/itempickup.wav")
     ATTRIB(Pickup, m_name, string, string_null)
     METHOD(Pickup, show, void(entity this));
index fcfe2afb93a5a7c4b44183dfd6c654595f9c1c77..f411d748a8d5eaeb891ec8eace2d2dd76725695e 100644 (file)
@@ -4,8 +4,15 @@
 #ifndef SVQC
 .int m_itemid;
 #endif
+
+#ifndef MENUQC
+MODEL(Strength_ITEM, Item_Model("g_strength.md3"));
+#endif
+
 REGISTER_ITEM(Strength, Powerup) {
-    this.m_model            =   "g_strength.md3";
+#ifndef MENUQC
+    this.m_model            =   MDL_Strength_ITEM;
+#endif
     this.m_sound            =   "misc/powerup.wav";
     this.m_name             =   "Strength Powerup";
     this.m_icon             =   "strength";
@@ -14,8 +21,15 @@ REGISTER_ITEM(Strength, Powerup) {
     this.m_waypointblink    =   2;
     this.m_itemid           =   IT_STRENGTH;
 }
+
+#ifndef MENUQC
+MODEL(Shield_ITEM, Item_Model("g_invincible.md3"));
+#endif
+
 REGISTER_ITEM(Shield, Powerup) {
-    this.m_model            =   "g_invincible.md3";
+#ifndef MENUQC
+    this.m_model            =   MDL_Shield_ITEM;
+#endif
     this.m_sound            =   "misc/powerup_shield.wav";
     this.m_name             =   "Shield";
     this.m_icon             =   "shield";
index eff61dbdf713621fdb950acb44f4035408068c99..ba21ff43d9cac6da7b25050680d06f4baf5fe3df 100644 (file)
@@ -2,7 +2,7 @@
        #include "../dpdefs/csprogsdefs.qh"
     #include "../client/defs.qh"
     #include "util.qh"
-    #include "buffs.qh"
+    #include "buffs/all.qh"
     #include "weapons/all.qh"
     #include "mapinfo.qh"
 #elif defined(MENUQC)
@@ -10,7 +10,7 @@
        #include "../dpdefs/progsdefs.qh"
     #include "../dpdefs/dpextensions.qh"
     #include "util.qh"
-    #include "buffs.qh"
+    #include "buffs/all.qh"
     #include "monsters/all.qh"
     #include "mapinfo.qh"
 #endif
@@ -602,13 +602,13 @@ void _MapInfo_Map_ApplyGametype(string s, int pWantedType, int pThisType, int lo
 
 string _MapInfo_GetDefaultEx(float t)
 {
-       FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.model2));
+       FOREACH(Gametypes, it.items == t, LAMBDA(return it.model2));
        return "";
 }
 
 float _MapInfo_GetTeamPlayBool(float t)
 {
-       FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.team));
+       FOREACH(Gametypes, it.items == t, LAMBDA(return it.team));
        return false;
 }
 
@@ -707,53 +707,30 @@ void _MapInfo_Map_ApplyGametypeEx(string s, int pWantedType, int pThisType)
        }
 }
 
-float MapInfo_Type_FromString(string t)
+int MapInfo_Type_FromString(string t)
 {
-       if(t == "nexball")
-       {
-               LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
-               t = "nb";
-               LOG_INFO("'. Should use '", t, "'.\n");
-       }
-       if(t == "freezetag")
-       {
-               LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
-               t = "ft";
-               LOG_INFO("'. Should use '", t, "'.\n");
-       }
-       if(t == "keepaway")
-       {
-               LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
-               t = "ka";
-               LOG_INFO("'. Should use '", t, "'.\n");
-       }
-       if(t == "invasion")
-       {
-               LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
-               t = "inv";
-               LOG_INFO("'. Should use '", t, "'.\n");
-       }
-       if(t == "assault")
-       {
-               LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
-               t = "as";
-               LOG_INFO("'. Should use '", t, "'.\n");
-       }
-       if(t == "race")
-       {
-               LOG_INFO("MapInfo_Type_FromString (probably ", MapInfo_Map_bspname, "): using deprecated name '", t);
-               t = "rc";
-               LOG_INFO("'. Should use '", t, "'.\n");
-       }
-       if(t == "all")
-               return MAPINFO_TYPE_ALL;
-       FOREACH(MAPINFO_TYPES, it.mdl == t, LAMBDA(return it.items));
+#define deprecate(from, to) do { \
+       if (t == #from) { \
+               string replacement = #to; \
+               LOG_WARNINGF("MapInfo_Type_FromString (probably %s): using deprecated name '%s'. Should use '%s'.\n", MapInfo_Map_bspname, t, replacement); \
+               t = replacement; \
+       } \
+} while (0)
+       deprecate(nexball, nb);
+       deprecate(freezetag, ft);
+       deprecate(keepaway, ka);
+       deprecate(invasion, inv);
+       deprecate(assault, as);
+       deprecate(race, rc);
+       if (t == "all") return MAPINFO_TYPE_ALL;
+       FOREACH(Gametypes, it.mdl == t, LAMBDA(return it.items));
        return 0;
+#undef deprecate
 }
 
 string MapInfo_Type_Description(float t)
 {
-       FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.gametype_description));
+       FOREACH(Gametypes, it.items == t, LAMBDA(return it.gametype_description));
        return "";
 }
 
@@ -761,13 +738,13 @@ string MapInfo_Type_ToString(float t)
 {
        if(t == MAPINFO_TYPE_ALL)
                return "all";
-       FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.mdl));
+       FOREACH(Gametypes, it.items == t, LAMBDA(return it.mdl));
        return "";
 }
 
 string MapInfo_Type_ToText(float t)
 {
-       FOREACH(MAPINFO_TYPES, it.items == t, LAMBDA(return it.message));
+       FOREACH(Gametypes, it.items == t, LAMBDA(return it.message));
        /* xgettext:no-c-format */
        return _("@!#%'n Tuba Throwing");
 }
@@ -1062,7 +1039,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, int p
                {
                        t = car(s); s = cdr(s);
                        f = MapInfo_Type_FromString(t);
-                       LOG_TRACE("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");
+                       LOG_WARNING("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);
                        else
@@ -1272,7 +1249,7 @@ int MapInfo_CurrentFeatures()
 int MapInfo_CurrentGametype()
 {
        int prev = cvar("gamecfg");
-       FOREACH(MAPINFO_TYPES, cvar(it.netname) && it.items != prev, LAMBDA(return it.items));
+       FOREACH(Gametypes, cvar(it.netname) && it.items != prev, LAMBDA(return it.items));
        if (prev) return prev;
        return MAPINFO_TYPE_DEATHMATCH;
 }
@@ -1298,7 +1275,7 @@ float MapInfo_CheckMap(string s) // returns 0 if the map can't be played with th
 
 void MapInfo_SwitchGameType(int t)
 {
-       FOREACH(MAPINFO_TYPES, true, LAMBDA(
+       FOREACH(Gametypes, true, LAMBDA(
                cvar_set(it.netname, (it.items == t) ? "1" : "0")
        ));
 }
index e6c5ea47d5dd7c4566df236f0f50be116fab9547..9c96c6823c8c2d75ab9a2df17c92b663ddfee9db 100644 (file)
@@ -38,22 +38,18 @@ CLASS(Gametype, Object)
     }
 ENDCLASS(Gametype)
 
-void RegisterGametypes();
-const int MAX_MAPINFO_TYPES = 24;
-entity MAPINFO_TYPES[MAX_MAPINFO_TYPES], MAPINFO_TYPES_first, MAPINFO_TYPES_last;
-int MAPINFO_TYPE_COUNT;
+REGISTRY(Gametypes, BIT(4))
+REGISTER_REGISTRY(RegisterGametypes)
 int MAPINFO_TYPE_ALL;
-
 #define REGISTER_GAMETYPE(hname, sname, g_name, NAME, gteamplay, defaults, gdescription)                    \
     int MAPINFO_TYPE_##NAME;                                                                                \
-    REGISTER(RegisterGametypes, MAPINFO_TYPE, MAPINFO_TYPES, MAPINFO_TYPE_COUNT, g_name, m_id,              \
+    REGISTER(RegisterGametypes, MAPINFO_TYPE, Gametypes, g_name, m_id,                                      \
         NEW(Gametype, hname, #sname, #g_name, gteamplay, 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;                                                                   \
     }
-REGISTER_REGISTRY(RegisterGametypes)
 
 #define IS_GAMETYPE(NAME) \
     (MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME)
index 3a1cc86744c16f9ea93f40c0a3ce22801cd874d6..38614c7d4629481c9c8fafeb6b029b533e263491 100644 (file)
@@ -4,10 +4,10 @@
 void minigame_hud_simpleboard(vector pos, vector mySize, string board_texture)
 {
        if(panel.current_panel_bg != "0" && panel.current_panel_bg != "")
-               draw_BorderPicture(pos - '1 1 0' * panel_bg_border, 
-                                       panel.current_panel_bg, 
-                                       mySize + '1 1 0' * 2 * panel_bg_border, 
-                                       panel_bg_color, panel_bg_alpha, 
+               draw_BorderPicture(pos - '1 1 0' * panel_bg_border,
+                                       panel.current_panel_bg,
+                                       mySize + '1 1 0' * 2 * panel_bg_border,
+                                       panel_bg_color, panel_bg_alpha,
                                         '1 1 0' * (panel_bg_border/BORDER_MULTIPLIER));
        drawpic(pos, board_texture, mySize, '1 1 1', panel_bg_alpha, DRAWFLAG_NORMAL);
 }
@@ -42,27 +42,6 @@ bool minigame_hud_mouse_in(vector pos, vector sz)
               mousepos_y >= pos_y && mousepos_y < pos_y + sz_y ;
 }
 
-void initialize_minigames()
-{
-       entity last_minig = world;
-       entity minig;
-       #define MINIGAME(name,nicename) \
-               minig = spawn(); \
-               minig.classname = "minigame_descriptor"; \
-               minig.netname = strzone(strtolower(#name)); \
-               minig.message = nicename; \
-               minig.minigame_hud_board = name##_hud_board; \
-               minig.minigame_hud_status = name##_hud_status; \
-               minig.minigame_event = name##_client_event; \
-               if ( !last_minig ) minigame_descriptors = minig; \
-               else last_minig.list_next = minig; \
-               last_minig = minig;
-               
-       REGISTERED_MINIGAMES
-       
-       #undef MINIGAME
-}
-
 string minigame_texture_skin(string skinname, string name)
 {
        return sprintf("gfx/hud/%s/minigames/%s", skinname, name);
@@ -88,14 +67,14 @@ string minigame_texture(string name)
 #define MSLE_CLEAN_Vector2D(x)
 
 #define MSLE(Name,Fields) \
-       void msle_entremove_##Name() { strunzone(self.netname); Fields }
+       void msle_entremove_##Name() { SELFPARAM(); strunzone(self.netname); Fields }
 MINIGAME_SIMPLELINKED_ENTITIES
 #undef MSLE
 #undef FIELD
 
 void minigame_autoclean_entity(entity e)
 {
-       LOG_TRACE("CL Auto-cleaned: ",ftos(num_for_edict(e)), " (",e.classname,")\n");
+       LOG_DEBUG("CL Auto-cleaned: ",ftos(num_for_edict(e)), " (",e.classname,")\n");
        remove(e);
 }
 
@@ -127,7 +106,7 @@ void deactivate_minigame()
 }
 
 void minigame_entremove()
-{
+{SELFPARAM();
        if ( self == active_minigame )
                deactivate_minigame();
 }
@@ -139,26 +118,26 @@ void activate_minigame(entity minigame)
                deactivate_minigame();
                return;
        }
-       
+
        if ( !minigame.descriptor || minigame.classname != "minigame" )
        {
                LOG_TRACE("Trying to activate unregistered minigame ",minigame.netname," in client\n");
                return;
        }
-       
+
        if ( minigame == active_minigame )
                return;
-       
+
        if ( active_minigame )
        {
                deactivate_minigame();
        }
-       
+
        if ( minigame_self.owner != minigame )
                minigame_self = world;
        active_minigame = minigame;
        active_minigame.minigame_event(active_minigame,"activate");
-       
+
        if ( HUD_MinigameMenu_IsOpened() )
                HUD_MinigameMenu_CurrentButton();
        else
@@ -169,7 +148,7 @@ void activate_minigame(entity minigame)
 }
 
 void minigame_player_entremove()
-{
+{SELFPARAM();
        if ( self.owner == active_minigame && self.minigame_playerslot == player_localentnum )
                deactivate_minigame();
 }
@@ -190,7 +169,7 @@ string ReadString_Zoned() { return strzone(ReadString_Raw()); }
                Fields \
        }
 void minigame_read_owner()
-{
+{SELFPARAM();
        string owner_name = ReadString_Raw();
        self.owner = world;
        do
@@ -200,20 +179,20 @@ void minigame_read_owner()
                LOG_TRACE("Got a minigame entity without a minigame!\n");
 }
 void ent_read_minigame()
-{
+{SELFPARAM();
        float sf = ReadByte();
        if ( sf & MINIG_SF_CREATE )
        {
                self.classname = msle_classname(ReadShort());
                self.netname = ReadString_Zoned();
        }
-       
+
        entity minigame_ent = world;
-       
+
        if ( self.classname == "minigame" )
        {
                minigame_ent = self;
-               
+
                if ( sf & MINIG_SF_CREATE )
                {
                        self.entremove = minigame_entremove;
@@ -235,16 +214,16 @@ void ent_read_minigame()
                        minigame_read_owner();
                        float ent = ReadLong();
                        self.minigame_playerslot = ent;
-                       LOG_TRACE("Player: ",GetPlayerName(ent-1),"\n");
-                       
+                       LOG_DEBUG("Player: ",GetPlayerName(ent-1),"\n");
+
                        activate = (ent == player_localnum+1 && self.owner && self.owner != active_minigame);
-                       
+
                }
                minigame_ent = self.owner;
-                       
+
                if ( sf & MINIG_SF_UPDATE )
                        self.team = ReadByte();
-               
+
                if ( activate )
                {
                        minigame_self = self;
@@ -252,15 +231,15 @@ void ent_read_minigame()
                }
        }
        MINIGAME_SIMPLELINKED_ENTITIES
-       
+
        if ( minigame_ent )
                minigame_ent.minigame_event(minigame_ent,"network_receive",self,sf);
 
        if ( sf & MINIG_SF_CREATE )
        {
-               LOG_TRACE("CL Reading entity: ",ftos(num_for_edict(self)),
+               LOG_DEBUG("CL Reading entity: ",ftos(num_for_edict(self)),
                        " classname:",self.classname," enttype:",ftos(self.enttype) );
-               LOG_TRACE(" sf:",ftos(sf)," netname:",self.netname,"\n\n");
+               LOG_DEBUG(" sf:",ftos(sf)," netname:",self.netname,"\n\n");
        }
 }
 #undef ReadString
@@ -283,7 +262,7 @@ string minigame_getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_
        }
 
        take_until = textLengthUpToWidth(s, w, theFontSize, tw);
-       
+
        if ( take_until > strlen(s) )
                take_until = strlen(s);
 
@@ -294,7 +273,7 @@ string minigame_getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_
                        skip = 1;
                        break;
                }
-       
+
        if ( take_until > 0 || skip > 0 )
        {
                if ( skip == 0 && take_until < strlen(s) )
@@ -309,7 +288,7 @@ string minigame_getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_
                                skip = 1;
                        }
                }
-                       
+
                getWrappedLine_remaining = substring(s, take_until+skip, strlen(s) - (take_until+skip));
                if(getWrappedLine_remaining == "")
                        getWrappedLine_remaining = string_null;
@@ -324,9 +303,9 @@ string minigame_getWrappedLine(float w, vector theFontSize, textLengthUpToWidth_
        }
 }
 
-vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text, 
+vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text,
        vector fontsize, vector color, float theAlpha, int drawflags, float align )
-{      
+{
        getWrappedLine_remaining = text;
        vector mypos = pos;
        while ( getWrappedLine_remaining )
@@ -343,7 +322,7 @@ vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text,
        return mypos;
 }
 
-vector minigame_drawcolorcodedstring_wrapped( float maxwidth, vector pos, 
+vector minigame_drawcolorcodedstring_wrapped( float maxwidth, vector pos,
        string text, vector fontsize, float theAlpha, int drawflags, float align )
 {
        getWrappedLine_remaining = text;
@@ -362,21 +341,21 @@ vector minigame_drawcolorcodedstring_wrapped( float maxwidth, vector pos,
        return mypos;
 }
 
-void minigame_drawstring_trunc(float maxwidth, vector pos, string text, 
+void minigame_drawstring_trunc(float maxwidth, vector pos, string text,
        vector fontsize, vector color, float theAlpha, int drawflags )
 {
        string line = textShortenToWidth(text,maxwidth,fontsize,stringwidth_nocolors);
        drawstring(pos, line, fontsize, color, theAlpha, drawflags);
 }
 
-void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text, 
+void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text,
        vector fontsize, float theAlpha, int drawflags )
 {
        string line = textShortenToWidth(text,maxwidth,fontsize,stringwidth_colors);
        drawcolorcodedstring(pos, line, fontsize, theAlpha, drawflags);
 }
 
-void minigame_drawpic_centered( vector pos, string texture, vector sz, 
+void minigame_drawpic_centered( vector pos, string texture, vector sz,
        vector color, float thealpha, int drawflags )
 {
        drawpic( pos-sz/2, texture, sz, color, thealpha, drawflags );
@@ -394,7 +373,7 @@ void minigame_cmd_workaround(float dummy, string...cmdargc)
        localcmd(strcat(cmd,"\n"));
 }
 
-// Prompt the player to play in the current minigame 
+// Prompt the player to play in the current minigame
 // (ie: it's their turn and they should get back to the minigame)
 void minigame_prompt()
 {
index 0c1740127b3bb8156d8d39c3d707ce5066440381..a073af89757a3562c63a20e7b97196e3a07dd1cc 100644 (file)
@@ -48,25 +48,25 @@ bool minigame_hud_mouse_in(vector pos, vector sz);
 // Like drawstring, but wrapping words to fit maxwidth
 // returns the size of the drawn area
 // align selects the string alignment (0 = left, 0.5 = center, 1 = right)
-vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text, 
+vector minigame_drawstring_wrapped( float maxwidth, vector pos, string text,
        vector fontsize, vector color, float theAlpha, int drawflags, float align );
 
 // Like drawcolorcodedstring, but wrapping words to fit maxwidth
 // returns the size of the drawn area
 // align selects the string alignment (0 = left, 0.5 = center, 1 = right)
-vector minigame_drawcolorcodedstring_wrapped( float maxwidth, vector pos, 
+vector minigame_drawcolorcodedstring_wrapped( float maxwidth, vector pos,
        string text, vector fontsize, float theAlpha, int drawflags, float align );
 
 // Like drawstring but truncates the text to fit maxwidth
-void minigame_drawstring_trunc(float maxwidth, vector pos, string text, 
+void minigame_drawstring_trunc(float maxwidth, vector pos, string text,
        vector fontsize, vector color, float theAlpha, int drawflags );
 
 // Like drawcolorcodedstring but truncates the text to fit maxwidth
-void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text, 
+void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text,
        vector fontsize, float theAlpha, int drawflags );
 
 // like drawpic but pos represent the center rather than the topleft corner
-void minigame_drawpic_centered( vector pos, string texture, vector sz, 
+void minigame_drawpic_centered( vector pos, string texture, vector sz,
        vector color, float thealpha, int drawflags );
 
 // Get full path of a minigame texture
@@ -79,9 +79,6 @@ string minigame_texture(string name);
 // For minigame_player: player server slot, don't use for anything else
 .float minigame_playerslot;
 
-// register all minigames
-void initialize_minigames();
-
 // client-side minigame session cleanup
 void deactivate_minigame();
 
@@ -103,7 +100,7 @@ void minigame_cmd_workaround(float dummy, string...cmdargc);
 // Read a minigame entity from the server
 void ent_read_minigame();
 
-// Prompt the player to play in the current minigame 
+// Prompt the player to play in the current minigame
 // (ie: it's their turn and they should get back to the minigame)
 void minigame_prompt();
 
@@ -116,6 +113,24 @@ void HUD_MinigameMenu_CustomEntry(entity parent, string message, string event_ar
 
 #define FOREACH_MINIGAME_ENTITY(entityvar) \
        entityvar=world; \
-       while( (entityvar = findentity(entityvar,owner,active_minigame)) ) 
+       while( (entityvar = findentity(entityvar,owner,active_minigame)) )
+
+
+REGISTRY(Minigames, BIT(3))
+REGISTER_REGISTRY(RegisterMinigames)
+#define REGISTER_MINIGAME(name,nicename) \
+    REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, spawn()); \
+    void name##_hud_board(vector, vector); \
+    void name##_hud_status(vector, vector); \
+    int name##_client_event(entity, string, ...); \
+    REGISTER_INIT_POST(MINIGAME, name) { \
+        this.classname = "minigame_descriptor"; \
+        this.netname = strzone(strtolower(#name)); \
+        this.message = nicename; \
+        this.minigame_hud_board = name##_hud_board; \
+               this.minigame_hud_status = name##_hud_status; \
+               this.minigame_event = name##_client_event; \
+    } \
+    REGISTER_INIT(MINIGAME, name)
 
 #endif
index b7b7df128a501174a4faf43a220b3826d449e9b8..2a0b0362051f95426b7c2afd9d2dcc006278b9b1 100644 (file)
@@ -6,7 +6,7 @@ bool HUD_mouse_over(entity somepanel)
 {
        vector pos = stov(cvar_string(strcat("hud_panel_", somepanel.panel_name, "_pos")));
        vector sz = stov(cvar_string(strcat("hud_panel_", somepanel.panel_name, "_size")));
-       return mousepos_x >= pos_x*vid_conwidth  && mousepos_x <= (pos_x+sz_x)*vid_conwidth && 
+       return mousepos_x >= pos_x*vid_conwidth  && mousepos_x <= (pos_x+sz_x)*vid_conwidth &&
               mousepos_y >= pos_y*vid_conheight && mousepos_y <= (pos_y+sz_y)*vid_conheight ;
 }
 
@@ -18,22 +18,22 @@ bool HUD_mouse_over(entity somepanel)
 void HUD_MinigameBoard ()
 {
        entity hud_minigame = world;
-       
+
        if(!autocvar__hud_configure)
                hud_minigame = active_minigame.descriptor;
        else
                hud_minigame = minigame_get_descriptor("nmm");
-       
+
        if ( !hud_minigame )
                return;
-       
+
        HUD_Panel_UpdateCvars();
-       
-       
+
+
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
-       
+
        hud_minigame.minigame_hud_board(pos,mySize);
 }
 
@@ -44,28 +44,28 @@ void HUD_MinigameBoard ()
 void HUD_MinigameStatus ()
 {
        entity hud_minigame = world;
-       
+
        if(!autocvar__hud_configure)
                hud_minigame = active_minigame.descriptor;
        else
                hud_minigame = minigame_get_descriptor("nmm");
-       
+
        if ( !hud_minigame )
                return;
-       
+
        HUD_Panel_UpdateCvars();
-       
-       
+
+
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
-       
+
        if(panel_bg_padding)
        {
                pos += '1 1 0' * panel_bg_padding;
                mySize -= '2 2 0' * panel_bg_padding;
        }
-       
+
        hud_minigame.minigame_hud_status(pos,mySize);
 }
 
@@ -87,7 +87,7 @@ void HUD_MinigameMenu_InsertEntry(entity newentry, entity prev)
                HUD_MinigameMenu_last_entry = newentry;
                return;
        }
-       
+
        newentry.list_prev = prev;
        newentry.list_next = prev.list_next;
        if ( prev.list_next )
@@ -95,7 +95,7 @@ void HUD_MinigameMenu_InsertEntry(entity newentry, entity prev)
        else
                HUD_MinigameMenu_last_entry = newentry;
        prev.list_next = newentry;
-       
+
 }
 
 
@@ -104,13 +104,10 @@ entity HUD_MinigameMenu_activeitem;
 
 // Click the given item
 void HUD_MinigameMenu_Click(entity menuitem)
-{
+{SELFPARAM();
        if ( menuitem )
        {
-               entity e = self;
-               self = menuitem;
-               menuitem.use();
-               self = e;
+               WITH(entity, self, menuitem, menuitem.use());
        }
 }
 
@@ -123,20 +120,20 @@ void HUD_MinigameMenu_EraseEntry ( entity e )
        {
                HUD_MinigameMenu_Click(e);
        }
-       
+
        if ( e.list_prev )
                e.list_prev.list_next = e.list_next;
        else
                HUD_MinigameMenu_entries = e.list_next;
-                               
+
        if ( e.list_next )
                e.list_next.list_prev = e.list_prev;
        else
                HUD_MinigameMenu_last_entry = e.list_prev;
-       
+
        if ( HUD_MinigameMenu_activeitem == e )
                HUD_MinigameMenu_activeitem = world;
-       
+
        remove(e);
 }
 
@@ -167,18 +164,18 @@ entity HUD_MinigameMenu_SpawnSubEntry(string s, void() click, entity parent)
 
 // Click action for Create sub-entries
 void HUD_MinigameMenu_ClickCreate_Entry()
-{
+{SELFPARAM();
        minigame_cmd("create ",self.netname);
 }
 
 // Helper click action for collapsible entries
 // returns true when you have to create the sub-entries
 bool HUD_MinigameMenu_Click_ExpandCollapse()
-{
+{SELFPARAM();
        entity e;
        if ( self.flags & 2 )
        {
-               if ( HUD_MinigameMenu_activeitem && 
+               if ( HUD_MinigameMenu_activeitem &&
                                HUD_MinigameMenu_activeitem.owner == self )
                        HUD_MinigameMenu_activeitem = world;
                self.flags &= ~2;
@@ -201,9 +198,9 @@ bool HUD_MinigameMenu_Click_ExpandCollapse()
                        if ( e.flags & 2 && e.origin_x == self.origin_x)
                                HUD_MinigameMenu_Click(e);
                }
-               
+
                self.flags |= 2;
-               
+
                return true;
        }
        return false;
@@ -211,34 +208,33 @@ bool HUD_MinigameMenu_Click_ExpandCollapse()
 
 // Click action for the Create menu
 void HUD_MinigameMenu_ClickCreate()
-{
+{SELFPARAM();
        if ( HUD_MinigameMenu_Click_ExpandCollapse() )
        {
-               entity e;
                entity curr;
                entity prev = self;
-               for ( e = minigame_descriptors; e != world; e = e.list_next )
+               FOREACH(Minigames, true, LAMBDA(
                {
                        curr = HUD_MinigameMenu_SpawnSubEntry(
-                               e.message, HUD_MinigameMenu_ClickCreate_Entry,  self );
-                       curr.netname = e.netname;
-                       curr.model = strzone(minigame_texture(strcat(e.netname,"/icon")));
+                               it.message, HUD_MinigameMenu_ClickCreate_Entry,  self );
+                       curr.netname = it.netname;
+                       curr.model = strzone(minigame_texture(strcat(it.netname,"/icon")));
                        HUD_MinigameMenu_InsertEntry( curr, prev );
                        prev = curr;
-               }
+               }));
        }
 }
 
 // Click action for Join sub-entries
 void HUD_MinigameMenu_ClickJoin_Entry()
-{
+{SELFPARAM();
        minigame_cmd("join ",self.netname);
        HUD_MinigameMenu_EraseEntry(self);
 }
 
 // Click action for the Join menu
 void HUD_MinigameMenu_ClickJoin()
-{
+{SELFPARAM();
        if ( HUD_MinigameMenu_Click_ExpandCollapse() )
        {
                entity e = world;
@@ -274,13 +270,13 @@ void HUD_MinigameMenu_ClickQuit()
 
 // Click action for Invite sub-entries
 void HUD_MinigameMenu_ClickInvite_Entry()
-{
+{SELFPARAM();
        minigame_cmd("invite #",self.netname);
 }
 
 // Click action for the Invite menu
 void HUD_MinigameMenu_ClickInvite()
-{
+{SELFPARAM();
        if ( HUD_MinigameMenu_Click_ExpandCollapse() )
        {
                entity e;
@@ -304,7 +300,7 @@ void HUD_MinigameMenu_ClickInvite()
 }
 
 void HUD_MinigameMenu_ClickCustomEntry()
-{
+{SELFPARAM();
        if ( active_minigame )
                active_minigame.minigame_event(active_minigame,"menu_click",self.netname);
 }
@@ -321,14 +317,14 @@ void HUD_MinigameMenu_CustomEntry(entity parent, string menumessage, string even
 
 // Click action for the Current Game menu
 void HUD_MinigameMenu_ClickCurrentGame()
-{
+{SELFPARAM();
        if ( HUD_MinigameMenu_Click_ExpandCollapse() )
        {
                HUD_MinigameMenu_InsertEntry( HUD_MinigameMenu_SpawnSubEntry(
                        _("Quit"), HUD_MinigameMenu_ClickQuit, self ), self);
-               
+
                active_minigame.minigame_event(active_minigame,"menu_show",self);
-               
+
                HUD_MinigameMenu_InsertEntry( HUD_MinigameMenu_SpawnSubEntry(
                        _("Invite"), HUD_MinigameMenu_ClickInvite, self), self);
        }
@@ -378,7 +374,7 @@ void HUD_MinigameMenu_CurrentButton()
                HUD_MinigameMenu_InsertEntry(currb,HUD_MinigameMenu_last_entry);
                HUD_MinigameMenu_Click(currb);
        }
-       else 
+       else
        {
                entity p;
                for ( e = HUD_MinigameMenu_last_entry; e != world; e = p.list_prev )
@@ -433,11 +429,11 @@ void HUD_MinigameMenu_MouseInput()
                panel_pos += '1 1 0' * panel_bg_padding;
                panel_size -= '2 2 0' * panel_bg_padding;
        }
-       
+
        entity e;
-       
+
        panel_pos_y += hud_fontsize_y*2;
-       
+
        HUD_MinigameMenu_activeitem = world;
        vector sz;
        for ( e = HUD_MinigameMenu_entries; e != world; e = e.list_next )
@@ -468,14 +464,14 @@ void HUD_MinigameMenu_DrawColoredEntry(vector pos, string s, vector fontsize)
 
 // Minigame menu panel UI
 void HUD_MinigameMenu ()
-{      
+{
        if ( !HUD_MinigameMenu_IsOpened() )
                return;
-       
+
        HUD_Panel_UpdateCvars();
-       
+
        HUD_Panel_DrawBg(1);
-       
+
        if(panel_bg_padding)
        {
                panel_pos += '1 1 0' * panel_bg_padding;
@@ -492,16 +488,16 @@ void HUD_MinigameMenu ()
        for ( entity e = HUD_MinigameMenu_entries; e != world; e = e.list_next )
        {
                color = e.colormod;
-               
+
                offset = e.origin;
                itemh = e.size_y;
-               
+
                if ( e.model )
                        itemh = imgsz_y;
-               
+
                if ( e.flags & 2 )
                {
-                       drawfill(panel_pos, eX*panel_size_x + eY*itemh, e.colormod, 
+                       drawfill(panel_pos, eX*panel_size_x + eY*itemh, e.colormod,
                                        panel_fg_alpha, DRAWFLAG_NORMAL);
                        color = '0 0 0';
                }
@@ -512,15 +508,15 @@ void HUD_MinigameMenu ()
                        offset_x += imgsz_x;
                        offset_y = (imgsz_y-e.size_y) / 2;
                }
-               
+
                if ( e.flags & 1 )
                        HUD_MinigameMenu_DrawColoredEntry(panel_pos+offset,e.message,e.size);
                else
                        HUD_MinigameMenu_DrawEntry(panel_pos+offset,e.message,e.size,color);
-               
+
                if ( e == HUD_MinigameMenu_activeitem )
                        drawfill(panel_pos, eX*panel_size_x + eY*itemh,'1 1 1', 0.25, DRAWFLAG_ADDITIVE);
-               
+
                panel_pos_y += itemh;
        }
 }
@@ -532,29 +528,29 @@ void HUD_MinigameMenu ()
 void HUD_MinigameHelp()
 {
        string help_message;
-       
+
        if(!autocvar__hud_configure)
                help_message = active_minigame.message;
        else
                help_message = "Minigame message";
-       
+
        if ( !help_message )
                return;
-       
+
        HUD_Panel_UpdateCvars();
-       
-       
+
+
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
-       
+
        if(panel_bg_padding)
        {
                pos += '1 1 0' * panel_bg_padding;
                mySize -= '2 2 0' * panel_bg_padding;
        }
-       
-       minigame_drawcolorcodedstring_wrapped( mySize_x, pos, help_message, 
+
+       minigame_drawcolorcodedstring_wrapped( mySize_x, pos, help_message,
                hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5 );
 }
 
@@ -563,7 +559,7 @@ void HUD_MinigameHelp()
 // ====================================================================
 float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary)
 {
-               
+
        if( !HUD_MinigameMenu_IsOpened() || autocvar__hud_configure )
                return false;
 
@@ -574,7 +570,7 @@ float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary
                if ( minigame_isactive() && HUD_mouse_over(HUD_PANEL(MINIGAME_BOARD)) )
                        active_minigame.minigame_event(active_minigame,"mouse_moved",mousepos);
                return true;
-               
+
        }
        else
        {
@@ -592,7 +588,7 @@ float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary
                        if(nPrimary == K_MOUSE1) mouseClicked -= (mouseClicked & S_MOUSE1);
                        if(nPrimary == K_MOUSE2) mouseClicked -= (mouseClicked & S_MOUSE2);
                }
-               
+
                // allow some binds
                string con_keys;
                con_keys = findkeysforcommand("toggleconsole", 0);
@@ -602,7 +598,7 @@ float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary
                        if(nPrimary == stof(argv(i)))
                                return false;
                }
-               
+
                if ( minigame_isactive() && ( bInputType == 0 || bInputType == 1 ) )
                {
                        string device = "";
@@ -614,14 +610,14 @@ float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary
                        }
                        else
                                device = "key";
-                       
+
                        if ( device && active_minigame.minigame_event(
                                        active_minigame,strcat(device,"_",action),nPrimary) )
                                return true;
-                       
+
                        /// TODO: bInputType == 2?
                }
-               
+
                if ( bInputType == 0 )
                {
                        if ( nPrimary == K_MOUSE1 && HUD_MinigameMenu_activeitem &&
@@ -668,16 +664,16 @@ float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary
                        }
                }
        }
-       
+
        return false;
 
 }
 
 void HUD_Minigame_Mouse()
-{              
+{
        if( !HUD_MinigameMenu_IsOpened() || autocvar__hud_configure || mv_active )
                return;
-       
+
        if(!autocvar_hud_cursormode)
        {
                mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
@@ -685,12 +681,12 @@ void HUD_Minigame_Mouse()
                mousepos_x = bound(0, mousepos_x, vid_conwidth);
                mousepos_y = bound(0, mousepos_y, vid_conheight);
        }
-       
+
        if ( HUD_MinigameMenu_IsOpened() && HUD_mouse_over(HUD_PANEL(MINIGAME_MENU)) )
                HUD_MinigameMenu_MouseInput();
-       
+
        vector cursorsize = '32 32 0';
-       drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), 
+       drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"),
                        cursorsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 }
 
index d1899e7594328e0414b79ea37bdfbe1f093a410b..d3874e7aa77cb42b79bc8c42230982cb0a4781f6 100644 (file)
@@ -47,7 +47,7 @@ used as send flags for minigame entities:
 * MINIG_SF_UPDATE
        A miscellaneous update, can be safely used if the entity has just a few fields
 * MINIG_SF_CUSTOM
-       Starting value for custom flags, since there are bit-wise flags, 
+       Starting value for custom flags, since there are bit-wise flags,
        the following values shall be MINIG_SF_CUSTOM*2, MINIG_SF_CUSTOM*4 and MINIG_SF_CUSTOM*8.
 * MINIG_SF_MAX
        Maximum flag value that will be networked
@@ -65,31 +65,15 @@ that .owner is set to the minigame session entity and .minigame_autoclean is tru
 #include "ttt.qc"
 #include "c4.qc"
 #include "pong.qc"
-#include "qto.qc"
 #include "ps.qc"
 #include "pp.qc"
-
-/**
- * Registration:
- *     MINIGAME(id,"Name")
- *             id    (QuakeC symbol) Game identifier, used to find the functions explained above
- *             "Name"(String)        Human readable name for the game, shown in the UI
- */
-#define REGISTERED_MINIGAMES \
-       MINIGAME(nmm, "Nine Men's Morris") \
-       MINIGAME(ttt, "Tic Tac Toe") \
-       MINIGAME(pong,"Pong") \
-       MINIGAME(c4,  "Connect Four") \
-       MINIGAME(qto, "Quinto") \
-       MINIGAME(ps,  "Peg Solitaire") \
-       MINIGAME(pp,  "Push-Pull") \
-       /*empty line*/
+#include "snake.qc"
 
 /**
  * Set up automatic entity read/write functionality
  * To ensure that everything is handled automatically, spawn on the server using msle_spawn
  * Syntax:
- *     MSLE(classname,Field...) \ 
+ *     MSLE(classname,Field...) \
  *             classname: Identifier used to recognize the type of the entity
  *                        (must be set as .classname on the sent entities)
  *             Field... : List of FIELD calls
@@ -116,4 +100,4 @@ that .owner is set to the minigame session entity and .minigame_autoclean is tru
        MSLE(pong_paddle,FIELD(MINIG_SF_CREATE,Byte,team) FIELD(MINIG_SF_CREATE,Float,pong_length) FIELD(MINIG_SF_UPDATE,Vector2D,origin)) \
        MSLE(pong_ball,FIELD(MINIG_SF_CREATE,Float,pong_length) FIELD(PONG_SF_BALLTEAM,Byte,team) FIELD(MINIG_SF_UPDATE, Vector2D, velocity) FIELD(MINIG_SF_UPDATE, Vector2D, origin)) \
        MSLE(pong_ai, FIELD(MINIG_SF_CREATE,Byte,team) FIELD(PONG_SF_PLAYERSCORE, Long, pong_score)) \
-       /*empty line*/ 
+       /*empty line*/
index a153b39939ea47b061c85d9a0c124221b345b5ff..a7ba05068ac85e929d607a43e7d0028c4385edac 100644 (file)
@@ -1,7 +1,8 @@
+REGISTER_MINIGAME(c4, "Connect Four");
+
 const float C4_TURN_PLACE = 0x0100; // player has to place a piece on the board
 const float C4_TURN_WIN   = 0x0200; // player has won
 const float C4_TURN_DRAW  = 0x0400; // no moves are possible
-const float C4_TURN_TYPE  = 0x0f00; // turn type mask
 
 const float C4_TURN_TEAM1 = 0x0001;
 const float C4_TURN_TEAM2 = 0x0002;
@@ -120,7 +121,7 @@ bool c4_winning_piece(entity piece)
 
        if(found >= C4_WIN_CNT)
                return true;
-       
+
        return false;
 }
 
@@ -222,15 +223,15 @@ int c4_server_event(entity minigame, string event, ...)
                {
                        switch(argv(0))
                        {
-                               case "move": 
-                                       c4_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null ); 
+                               case "move":
+                                       c4_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
                                        return true;
                        }
 
                        return false;
                }
        }
-       
+
        return false;
 }
 
@@ -248,7 +249,7 @@ void c4_hud_board(vector pos, vector mySize)
        minigame_hud_fitsqare(pos, mySize);
        c4_boardpos = pos;
        c4_boardsize = mySize;
-       
+
        minigame_hud_simpleboard(pos,mySize,minigame_texture("c4/board_under"));
 
        drawpic(pos, minigame_texture("c4/board_over"), mySize, '1 1 1', 1, 0);
@@ -261,11 +262,11 @@ void c4_hud_board(vector pos, vector mySize)
        {
                tile_pos = minigame_tile_pos(c4_curr_pos,C4_NUM_CNT,C4_LET_CNT);
                tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-               minigame_drawpic_centered( tile_pos,  
+               minigame_drawpic_centered( tile_pos,
                                minigame_texture(strcat("c4/piece",ftos(minigame_self.team))),
                                tile_size, '1 1 1', panel_fg_alpha/2, DRAWFLAG_NORMAL );
        }
-       
+
        entity e;
        FOREACH_MINIGAME_ENTITY(e)
        {
@@ -273,11 +274,11 @@ void c4_hud_board(vector pos, vector mySize)
                {
                        tile_pos = minigame_tile_pos(e.netname,C4_NUM_CNT,C4_LET_CNT);
                        tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-                       
+
                        if ( active_minigame.minigame_flags & C4_TURN_WIN )
                        if ( !e.c4_checkwin )
                                e.c4_checkwin = c4_winning_piece(e) ? 1 : -1;
-                       
+
                        float icon_color = 1;
                        if ( e.c4_checkwin == -1 )
                                icon_color = 0.4;
@@ -287,8 +288,8 @@ void c4_hud_board(vector pos, vector mySize)
                                minigame_drawpic_centered( tile_pos, minigame_texture("c4/winglow"),
                                                tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_ADDITIVE );
                        }
-                               
-                       minigame_drawpic_centered( tile_pos,  
+
+                       minigame_drawpic_centered( tile_pos,
                                        minigame_texture(strcat("c4/piece",ftos(e.team))),
                                        tile_size, '1 1 1'*icon_color, panel_fg_alpha, DRAWFLAG_NORMAL );
                }
@@ -299,20 +300,20 @@ void c4_hud_board(vector pos, vector mySize)
                vector winfs = hud_fontsize*2;
                string playername = "";
                FOREACH_MINIGAME_ENTITY(e)
-                       if ( e.classname == "minigame_player" && 
+                       if ( e.classname == "minigame_player" &&
                                        e.team == (active_minigame.minigame_flags & C4_TURN_TEAM) )
                                playername = GetPlayerName(e.minigame_playerslot-1);
-               
+
                vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
                vector win_sz;
                win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("%s^7 won the game!",playername), 
+                       sprintf("%s^7 won the game!",playername),
                        winfs, 0, DRAWFLAG_NORMAL, 0.5);
-               
+
                drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
-               
+
                minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("%s^7 won the game!",playername), 
+                       sprintf("%s^7 won the game!",playername),
                        winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
        }
 }
@@ -325,10 +326,10 @@ void c4_hud_status(vector pos, vector mySize)
        vector ts;
        ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
                hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-       
+
        pos_y += ts_y;
        mySize_y -= ts_y;
-       
+
        vector player_fontsize = hud_fontsize * 1.75;
        ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
        ts_x = mySize_x;
@@ -353,12 +354,12 @@ void c4_hud_status(vector pos, vector mySize)
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
                                GetPlayerName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-                       
+
                        mypos_y += player_fontsize_y;
-                       drawpic( mypos,  
+                       drawpic( mypos,
                                        minigame_texture(strcat("c4/piece",ftos(e.team))),
                                        tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
-                       
+
                        mypos_x += tile_size_x;
                }
        }
@@ -369,20 +370,20 @@ string c4_turn_to_string(int turnflags)
 {
        if ( turnflags & C4_TURN_DRAW )
                return _("Draw");
-       
+
        if ( turnflags & C4_TURN_WIN )
        {
                if ( (turnflags&C4_TURN_TEAM) != minigame_self.team )
                        return _("You lost the game!");
                return _("You win!");
        }
-       
+
        if ( (turnflags & C4_TURN_TEAM) != minigame_self.team )
                return _("Wait for your opponent to make their move");
-       
+
        if ( turnflags & C4_TURN_PLACE )
                return _("Click on the game board to place your piece");
-       
+
        return "";
 }
 
@@ -502,4 +503,4 @@ int c4_client_event(entity minigame, string event, ...)
        return false;
 }
 
-#endif
\ No newline at end of file
+#endif
index b7ad467b8c2728ec128d8835c23157007540121f..1e4da05075ad20c76b11587a69f4a2e5b3105782 100644 (file)
@@ -1,3 +1,5 @@
+REGISTER_MINIGAME(nmm, "Nine Men's Morris");
+
 const int NMM_TURN_PLACE = 0x0100; // player has to place a piece on the board
 const int NMM_TURN_MOVE  = 0x0200; // player has to move a piece by one tile
 const int NMM_TURN_FLY   = 0x0400; // player has to move a piece anywhere
@@ -72,7 +74,7 @@ string nmm_tile_build_vmill(entity tile)
 
 // Create an new tile
 // \param id       Tile index (eg: a1)
-// \param minig    Owner minigame instance 
+// \param minig    Owner minigame instance
 // \param distance Distance from adjacent tiles
 void nmm_spawn_tile(string id, entity minig, int distance)
 {
@@ -89,7 +91,7 @@ void nmm_spawn_tile(string id, entity minig, int distance)
 }
 
 // Create a tile square and recursively create inner squares
-// \param minig    Owner minigame instance 
+// \param minig    Owner minigame instance
 // \param offset   Index offset (eg: 1 to start the square at b2, 0 at a1 etc.)
 // \param skip     Number of indices to skip between tiles (eg 1: a1, a3)
 void nmm_spawn_tile_square( entity minig, int offset, int skip )
@@ -107,7 +109,7 @@ void nmm_spawn_tile_square( entity minig, int offset, int skip )
                }
                letter += skip+1;
        }
-       
+
        if ( skip > 0 )
                nmm_spawn_tile_square(minig,offset+1,skip-1);
 }
@@ -145,10 +147,10 @@ entity nmm_find_tile(entity minig, string id)
 // Check whether two tiles are adjacent
 bool nmm_tile_adjacent(entity tile1, entity tile2)
 {
-               
+
        int dnumber = fabs ( minigame_tile_number(tile1.netname) - minigame_tile_number(tile2.netname) );
        int dletter = fabs ( minigame_tile_letter(tile1.netname) - minigame_tile_letter(tile2.netname) );
-       
+
        return ( dnumber == 0 && ( dletter == 1 || dletter == tile1.nmm_tile_distance ) ) ||
                ( dletter == 0 && ( dnumber == 1 || dnumber == tile1.nmm_tile_distance ) );
 }
@@ -158,7 +160,7 @@ bool nmm_tile_canmove(entity tile)
 {
        entity e = world;
        while ( ( e = findentity(e,owner,tile.owner) ) )
-               if ( e.classname == "minigame_nmm_tile" && !e.nmm_tile_piece 
+               if ( e.classname == "minigame_nmm_tile" && !e.nmm_tile_piece
                                && nmm_tile_adjacent(e,tile) )
                {
                        return true;
@@ -182,7 +184,7 @@ bool nmm_in_mill_string(entity tile, string s)
 // Check if a tile is in a mill
 bool nmm_in_mill(entity tile)
 {
-       return tile.nmm_tile_piece &&  ( 
+       return tile.nmm_tile_piece &&  (
                nmm_in_mill_string(tile,tile.nmm_tile_hmill) ||
                nmm_in_mill_string(tile,tile.nmm_tile_vmill) );
 }
@@ -194,7 +196,7 @@ entity nmm_find_piece(entity start, entity minigame, int teamn, int pieceflags)
 {
        entity e = start;
        while ( ( e = findentity(e,owner,minigame) ) )
-               if ( e.classname == "minigame_board_piece" && 
+               if ( e.classname == "minigame_board_piece" &&
                                (e.minigame_flags & pieceflags) && e.team == teamn )
                        return e;
        return world;
@@ -227,7 +229,7 @@ int nmm_server_event(entity minigame, string event, ...)
                        e.team = 2;
                        e.minigame_flags = NMM_PIECE_HOME;
                }
-                       
+
                return 1;
        }
        else if ( event == "end" )
@@ -253,8 +255,8 @@ int nmm_server_event(entity minigame, string event, ...)
                entity tile = world;
                entity piece = world;
                bool move_ok = false;
-               
-               if ( e && argc >= 2 && argv(0) == "move" && 
+
+               if ( e && argc >= 2 && argv(0) == "move" &&
                        ( minigame.minigame_flags & NMM_TURN_TEAM ) == e.team )
                {
                        tile = nmm_find_tile(minigame,argv(1));
@@ -290,7 +292,7 @@ int nmm_server_event(entity minigame, string event, ...)
                                                move_ok = true;
                                        }
                                }
-                               
+
                        }
                        else if ( minigame.minigame_flags & NMM_TURN_FLY )
                        {
@@ -308,7 +310,7 @@ int nmm_server_event(entity minigame, string event, ...)
                                                move_ok = true;
                                        }
                                }
-                               
+
                        }
                        else if ( minigame.minigame_flags & NMM_TURN_TAKE )
                        {
@@ -321,10 +323,10 @@ int nmm_server_event(entity minigame, string event, ...)
                                        move_ok = true;
                                }
                        }
-                       
+
                        int nextteam = e.team % 2 + 1;
                        int npieces = nmm_count_pieces(minigame,nextteam,NMM_PIECE_HOME|NMM_PIECE_BOARD);
-                       
+
                        if ( npieces < 3 )
                        {
                                minigame.minigame_flags = NMM_TURN_WIN | e.team;
@@ -431,7 +433,7 @@ void nmm_hud_board(vector pos, vector mySize)
        nmm_boardpos = pos;
        nmm_boardsize = mySize;
        minigame_hud_simpleboard(pos,mySize,minigame_texture("nmm/board"));
-       
+
        vector tile_size = minigame_hud_denormalize_size('1 1 0'/7,pos,mySize);
        vector tile_pos;
        entity e;
@@ -440,7 +442,7 @@ void nmm_hud_board(vector pos, vector mySize)
                if ( e.classname == "minigame_nmm_tile" )
                {
                        tile_pos = minigame_hud_denormalize(e.origin,pos,mySize);
-                       
+
                        if ( e == nmm_fromtile )
                        {
                                minigame_drawpic_centered( tile_pos, minigame_texture("nmm/tile_active"),
@@ -451,43 +453,43 @@ void nmm_hud_board(vector pos, vector mySize)
                                minigame_drawpic_centered( tile_pos, minigame_texture("nmm/tile_available"),
                                        tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
                        }
-                       
+
                        if ( e == nmm_currtile )
                        {
                                minigame_drawpic_centered( tile_pos, minigame_texture("nmm/tile_selected"),
                                        tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_ADDITIVE );
                        }
-                       
+
                        if ( e.nmm_tile_piece )
                        {
-                               minigame_drawpic_centered( tile_pos,  
+                               minigame_drawpic_centered( tile_pos,
                                        minigame_texture(strcat("nmm/piece",ftos(e.nmm_tile_piece.team))),
                                        tile_size*0.8, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
                        }
-                       
+
                        //drawstring(tile_pos, e.netname, hud_fontsize, '1 0 0', 1, DRAWFLAG_NORMAL);
                }
        }
-       
+
        if ( active_minigame.minigame_flags & NMM_TURN_WIN )
        {
                vector winfs = hud_fontsize*2;
                string playername = "";
                FOREACH_MINIGAME_ENTITY(e)
-                       if ( e.classname == "minigame_player" && 
+                       if ( e.classname == "minigame_player" &&
                                        e.team == (active_minigame.minigame_flags & NMM_TURN_TEAM) )
                                playername = GetPlayerName(e.minigame_playerslot-1);
-               
+
                vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
                vector win_sz;
                win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("%s^7 won the game!",playername), 
+                       sprintf("%s^7 won the game!",playername),
                        winfs, 0, DRAWFLAG_NORMAL, 0.5);
-               
+
                drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
-               
+
                minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("%s^7 won the game!",playername), 
+                       sprintf("%s^7 won the game!",playername),
                        winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
        }
 }
@@ -497,16 +499,16 @@ void nmm_hud_status(vector pos, vector mySize)
 {
        HUD_Panel_DrawBg(1);
        vector ts;
-       
+
        ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
                hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
        pos_y += ts_y;
        mySize_y -= ts_y;
-       
+
        vector player_fontsize = hud_fontsize * 1.75;
        ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
        ts_x = mySize_x;
-       
+
        float player1x = 0;
        float player2x = 0;
        vector piece_sz = '48 48 0';
@@ -514,14 +516,14 @@ void nmm_hud_status(vector pos, vector mySize)
        vector mypos;
        float piece_light = 1;
        entity e = world;
-       
+
        mypos = pos;
        if ( (active_minigame.minigame_flags&NMM_TURN_TEAM) == 2 )
                mypos_y  += player_fontsize_y + ts_y;
        drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
        mypos_y += player_fontsize_y;
        drawfill(mypos,eX*mySize_x+eY*piece_sz_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
-       
+
        FOREACH_MINIGAME_ENTITY(e)
        {
                if ( e.classname == "minigame_player" )
@@ -554,7 +556,7 @@ void nmm_hud_status(vector pos, vector mySize)
                                piece_light = 1;
                        else
                                piece_light = 0.15;
-                       
+
                        drawpic(mypos, minigame_texture(strcat("nmm/piece",ftos(e.team))), piece_sz,
                                '1 1 1'*piece_light, panel_fg_alpha, DRAWFLAG_NORMAL );
                }
@@ -600,7 +602,7 @@ string nmm_turn_to_string(int turnflags)
                        return _("You lost the game!");
                return _("You win!");
        }
-       
+
        if ( (turnflags&NMM_TURN_TEAM) != minigame_self.team )
                return _("Wait for your opponent to make their move");
        if ( turnflags & NMM_TURN_PLACE )
@@ -611,13 +613,13 @@ string nmm_turn_to_string(int turnflags)
                return _("You can select one of your pieces to move it anywhere on the board");
        if ( turnflags & NMM_TURN_TAKE )
                return _("You can take one of the opponent's pieces");
-       
+
        return "";
 }
 
 // Required function, handle client events
 int nmm_client_event(entity minigame, string event, ...)
-{
+{SELFPARAM();
        if ( event == "activate" )
        {
                nmm_fromtile = world;
@@ -640,7 +642,7 @@ int nmm_client_event(entity minigame, string event, ...)
                                else
                                {
                                        string tileid = nmm_currtile.netname;
-                                       nmm_currtile = world; 
+                                       nmm_currtile = world;
                                        while ( !nmm_currtile )
                                        {
                                                tileid = minigame_relative_tile(tileid,1,0,7,7);
@@ -655,7 +657,7 @@ int nmm_client_event(entity minigame, string event, ...)
                                else
                                {
                                        string tileid = nmm_currtile.netname;
-                                       nmm_currtile = world; 
+                                       nmm_currtile = world;
                                        while ( !nmm_currtile )
                                        {
                                                tileid = minigame_relative_tile(tileid,-1,0,7,7);
@@ -670,7 +672,7 @@ int nmm_client_event(entity minigame, string event, ...)
                                else
                                {
                                        string tileid = nmm_currtile.netname;
-                                       nmm_currtile = world; 
+                                       nmm_currtile = world;
                                        while ( !nmm_currtile )
                                        {
                                                tileid = minigame_relative_tile(tileid,0,1,7,7);
@@ -685,7 +687,7 @@ int nmm_client_event(entity minigame, string event, ...)
                                else
                                {
                                        string tileid = nmm_currtile.netname;
-                                       nmm_currtile = world; 
+                                       nmm_currtile = world;
                                        while ( !nmm_currtile )
                                        {
                                                tileid = minigame_relative_tile(tileid,0,-1,7,7);
@@ -745,15 +747,15 @@ int nmm_client_event(entity minigame, string event, ...)
                                }
                        }
                }
-               else if ( self.classname == "minigame" && ( ...(1,int) & MINIG_SF_UPDATE ) ) 
+               else if ( self.classname == "minigame" && ( ...(1,int) & MINIG_SF_UPDATE ) )
                {
                        self.message = nmm_turn_to_string(self.minigame_flags);
                        if ( self.minigame_flags & minigame_self.team )
                                minigame_prompt();
                }
        }
-       
+
        return 0;
 }
 
-#endif 
+#endif
index 6aca04cf95f4675f90e318b02af6c479080d0e9f..540f7ecf2f1d506b30a28e98f045c3783f9c4e0e 100644 (file)
@@ -1,3 +1,5 @@
+REGISTER_MINIGAME(pong, "Pong");
+
 // minigame flags
 const int PONG_STATUS_WAIT = 0x0010; // waiting for players to join
 const int PONG_STATUS_PLAY = 0x0020; // playing
@@ -53,7 +55,7 @@ void pong_ball_throw(entity ball)
 
 // Think equivalent of pong_ball_throw, used to delay throws
 void pong_ball_throwthink()
-{
+{SELFPARAM();
        pong_ball_throw(self);
 }
 
@@ -74,13 +76,13 @@ void pong_add_score(entity minigame, int team_thrower, int team_receiver, int de
 {
        if ( !minigame )
                return;
-       
+
        if ( team_thrower == 0 )
                team_thrower = team_receiver;
-       
+
        if ( team_thrower == team_receiver )
                delta *= -1;
-       
+
        entity paddle_thrower = minigame.pong_paddles[team_thrower-1];
        if ( paddle_thrower.realowner.minigame_players )
        {
@@ -105,11 +107,11 @@ void pong_paddle_bounce(entity ball, int pteam)
                case 3: ball.velocity_y = fabs(ball.velocity_y); break;
                case 4: ball.velocity_y = -fabs(ball.velocity_y); break;
        }
-       
+
        float angle = atan2(ball.velocity_y, ball.velocity_x);
        angle += ( random() - 0.5 ) * 2 * M_PI/6;
        float speed = vlen(ball.velocity);
-       
+
        ball.velocity_y = speed * sin(angle);
        ball.velocity_x = speed * cos(angle);
 }
@@ -120,7 +122,7 @@ bool pong_paddle_hit(entity ball, int pteam)
        entity paddle = ball.owner.pong_paddles[pteam-1];
        if (!paddle)
                return false;
-       vector near_point = box_nearest(paddle.mins+paddle.origin, 
+       vector near_point = box_nearest(paddle.mins+paddle.origin,
                                                                        paddle.maxs+paddle.origin, ball.origin);
        return vlen(near_point-ball.origin) <= ball.pong_length ;
 }
@@ -131,27 +133,27 @@ bool pong_goal(entity ball, int pteam)
        entity paddle = ball.owner.pong_paddles[pteam-1];
        if (!paddle)
                return false;
-       
+
        if ( !pong_paddle_hit(ball, pteam) )
        {
                pong_add_score(ball.owner ,ball.team, pteam, 1);
                pong_ball_reset(ball);
                return true;
        }
-       
+
        return false;
 }
 
 // Moves the ball around
 void pong_ball_think()
-{
+{SELFPARAM();
        float think_speed = autocvar_sys_ticrate;
        self.nextthink = time + think_speed;
-       
+
        self.origin_x += self.velocity_x * think_speed;
        self.origin_y += self.velocity_y * think_speed;
        self.SendFlags |= MINIG_SF_UPDATE;
-       
+
        int i;
        for ( i = 1; i <= PONG_MAX_PLAYERS; i++ )
                if ( pong_paddle_hit(self, i) )
@@ -161,7 +163,7 @@ void pong_ball_think()
                        self.SendFlags |= PONG_SF_BALLTEAM;
                        return;
                }
-       
+
        if ( self.origin_y <= self.pong_length )
        {
                if ( !pong_goal(self,3) )
@@ -178,7 +180,7 @@ void pong_ball_think()
                        self.velocity_y *= -1;
                }
        }
-       
+
        if ( self.origin_x <= self.pong_length )
        {
                if ( !pong_goal(self,2) )
@@ -195,15 +197,15 @@ void pong_ball_think()
                         self.velocity_x *= -1;
                }
        }
-       
+
 }
 
 // AI action
 void pong_ai_think()
-{
+{SELFPARAM();
        float think_speed = autocvar_sv_minigames_pong_ai_thinkspeed;
        self.nextthink = time + think_speed;
-       
+
        float distance;
        float next_distance;
        float min_distance = 1;
@@ -220,11 +222,11 @@ void pong_ai_think()
                                ball = mayball;
                        }
                }
-       
+
        float target = 0.5;
        float self_pos;
-       
-       
+
+
        if ( self.team <= 2 )
        {
                if ( ball )
@@ -237,7 +239,7 @@ void pong_ai_think()
                        target = ball.origin_x + ball.velocity_x*think_speed;
                self_pos = self.pong_ai_paddle.origin_x;
        }
-       
+
        distance = self.pong_length/2 * autocvar_sv_minigames_pong_ai_tolerance
                + autocvar_sv_minigames_pong_paddle_speed * think_speed;
 
@@ -257,32 +259,32 @@ entity pong_ai_spawn(entity paddle)
        ai.think = pong_ai_think;
        ai.nextthink = time;
        ai.pong_ai_paddle = paddle;
-       
+
        paddle.realowner = ai;
-       
+
        return ai;
 }
 
 // Moves the paddle
 void pong_paddle_think()
-{
+{SELFPARAM();
        float think_speed = autocvar_sys_ticrate;
        self.nextthink = time + think_speed;
 
-       if ( self.realowner.minigame_players.pong_keys == PONG_KEY_INCREASE || 
+       if ( self.realowner.minigame_players.pong_keys == PONG_KEY_INCREASE ||
                 self.realowner.minigame_players.pong_keys == PONG_KEY_DECREASE )
        {
                float movement = autocvar_sv_minigames_pong_paddle_speed * think_speed;
                float halflen = self.pong_length/2;
-       
+
                if ( self.realowner.minigame_players.pong_keys == PONG_KEY_DECREASE )
                        movement *= -1;
-               
+
                if ( self.team > 2 )
                        self.origin_x = bound(halflen, self.origin_x+movement, 1-halflen);
                else
                        self.origin_y = bound(halflen, self.origin_y+movement, 1-halflen);
-               
+
                self.SendFlags |= MINIG_SF_UPDATE;
        }
 }
@@ -318,14 +320,14 @@ entity pong_paddle_spawn(entity minigame, int pl_team, entity real_player)
        paddle.team = pl_team;
        paddle.mins = pong_team_to_box_halfsize(pl_team,-paddle.pong_length,-1/16);
        paddle.maxs = pong_team_to_box_halfsize(pl_team,paddle.pong_length,1/16);
-       
+
        if ( real_player == world )
                pong_ai_spawn(paddle);
        else
                paddle.realowner = real_player;
-       
+
        minigame.pong_paddles[pl_team-1] = paddle;
-       
+
        return paddle;
 
 }
@@ -345,7 +347,7 @@ int pong_server_event(entity minigame, string event, ...)
                        // Don't allow joining a match that is already running
                        if ( minigame.minigame_flags & PONG_STATUS_PLAY )
                                return false;
-                       
+
                        entity player = ...(0,entity);
                        int i;
                        for ( i = 0; i < PONG_MAX_PLAYERS; i++ )
@@ -356,7 +358,7 @@ int pong_server_event(entity minigame, string event, ...)
                                        return i+1;
                                }
                        }
-                       
+
                        return false;
                }
                case "part":
@@ -374,7 +376,7 @@ int pong_server_event(entity minigame, string event, ...)
                                        ai.pong_score = player.minigame_players.pong_score;
                                        break;
                                }
-                                       
+
                        }
                        return false;
                }
@@ -389,7 +391,7 @@ int pong_server_event(entity minigame, string event, ...)
                                                minigame.minigame_flags = PONG_STATUS_PLAY |
                                                        (minigame.minigame_flags & ~PONG_STATUS_WAIT);
                                                minigame.SendFlags |= MINIG_SF_UPDATE;
-                                               
+
                                                int i;
                                                entity ball;
                                                for ( i = 0; i < autocvar_sv_minigames_pong_ball_number; i++ )
@@ -436,7 +438,7 @@ int pong_server_event(entity minigame, string event, ...)
                                                for ( i = PONG_MAX_PLAYERS-1; i >= 0; i-- )
                                                {
                                                        paddle = minigame.pong_paddles[i];
-                                                       if ( paddle != world && 
+                                                       if ( paddle != world &&
                                                                paddle.realowner.classname == "pong_ai" )
                                                        {
                                                                minigame.pong_paddles[i] = world;
@@ -449,7 +451,7 @@ int pong_server_event(entity minigame, string event, ...)
                                        sprint(player.minigame_players,"Cannot remove AI\n");
                                        return true;
                                }
-                                               
+
                        }
                        return false;
                }
@@ -501,7 +503,7 @@ void pong_hud_board(vector pos, vector mySize)
 {
        minigame_hud_fitsqare(pos, mySize);
        minigame_hud_simpleboard(pos,mySize,minigame_texture("pong/board"));
-       
+
        entity e;
        vector obj_pos;
        vector obj_size;
@@ -512,27 +514,27 @@ void pong_hud_board(vector pos, vector mySize)
                        // Note: 4*radius = 2*diameter because the image is large enough to fit the glow around the ball
                        obj_size =  minigame_hud_denormalize_size('4 4 0'*e.pong_length,pos,mySize);
                        obj_pos = minigame_hud_denormalize(e.origin,pos,mySize);
-                       
+
                        minigame_drawpic_centered( obj_pos, minigame_texture("pong/ball"),
                                        obj_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
-                       
+
                        minigame_drawpic_centered( obj_pos, minigame_texture("pong/ball-glow"),
-                                       obj_size, pong_team_to_color(e.team), 
+                                       obj_size, pong_team_to_color(e.team),
                                        panel_fg_alpha, DRAWFLAG_ADDITIVE );
                }
                else if ( e.classname == "pong_paddle" )
                {
                        obj_pos = minigame_hud_denormalize(e.origin,pos,mySize);
                        obj_size = minigame_hud_denormalize_size(eX / 16 + eY*e.pong_length,pos,mySize);
-                       
-                       drawrotpic(obj_pos, pong_team_to_angle(e.team), minigame_texture("pong/paddle-glow"), 
-                               obj_size, obj_size/2, pong_team_to_color(e.team), 
+
+                       drawrotpic(obj_pos, pong_team_to_angle(e.team), minigame_texture("pong/paddle-glow"),
+                               obj_size, obj_size/2, pong_team_to_color(e.team),
                                panel_fg_alpha, DRAWFLAG_ADDITIVE );
-                       
-                       drawrotpic(obj_pos, pong_team_to_angle(e.team), minigame_texture("pong/paddle"), 
-                               obj_size, obj_size/2, '1 1 1', 
+
+                       drawrotpic(obj_pos, pong_team_to_angle(e.team), minigame_texture("pong/paddle"),
+                               obj_size, obj_size/2, '1 1 1',
                                panel_fg_alpha, DRAWFLAG_NORMAL );
-                       
+
                }
        }
 }
@@ -547,7 +549,7 @@ void pong_hud_status(vector pos, vector mySize)
        ts_y += hud_fontsize_y;
        pos_y += ts_y;
        mySize_y -= ts_y;
-       
+
        vector player_fontsize = hud_fontsize * 1.75;
        ts_y = ( mySize_y - PONG_MAX_PLAYERS*player_fontsize_y ) / PONG_MAX_PLAYERS;
        ts_x = mySize_x;
@@ -560,16 +562,16 @@ void pong_hud_status(vector pos, vector mySize)
                {
                        mypos = pos;
                        mypos_y  += (e.team-1) * (player_fontsize_y + ts_y);
-                       
+
                        drawfill(mypos, ts, pong_team_to_color(e.team), 0.25, DRAWFLAG_ADDITIVE);
-                       
+
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
                                (e.minigame_playerslot ? GetPlayerName(e.minigame_playerslot-1) : _("AI")),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-                       
+
                        drawstring(mypos+eY*player_fontsize_y,ftos(e.pong_score),'48 48 0',
                                           '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-                       
+
                        if ( e == minigame_self )
                                drawborderlines(1, mypos, ts, pong_team_to_color(e.team), 1, DRAWFLAG_NORMAL);
                }
index eacb985beba26a91e069ed1dd33147d9127e1aa7..efce0e66b6be5030a96beb0446cdd2c3378a4b66 100644 (file)
@@ -1,3 +1,5 @@
+REGISTER_MINIGAME(pp, "Push-Pull");
+
 const int PP_TURN_PLACE = 0x0100; // player has to place a piece on the board
 const int PP_TURN_WIN   = 0x0200; // player has won
 const int PP_TURN_DRAW  = 0x0400; // players have equal scores
@@ -58,7 +60,7 @@ bool pp_winning_piece(entity piece)
        if(!pp_valid_tile(minigame_tile_buildname(letter+1,number-1)) || pp_find_piece(piece.owner,minigame_tile_buildname(letter+1,number-1)).team == 5)
        if(!pp_valid_tile(minigame_tile_buildname(letter-1,number+1)) || pp_find_piece(piece.owner,minigame_tile_buildname(letter-1,number+1)).team == 5)
                return true;
-       
+
        return false;
 }
 
@@ -233,8 +235,8 @@ int pp_server_event(entity minigame, string event, ...)
                {
                        switch(argv(0))
                        {
-                               case "move": 
-                                       pp_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null ); 
+                               case "move":
+                                       pp_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
                                        return true;
                                case "next":
                                        pp_next_match(minigame,...(0,entity));
@@ -257,7 +259,7 @@ int pp_server_event(entity minigame, string event, ...)
                        return false;
                }
        }
-       
+
        return false;
 }
 
@@ -275,7 +277,7 @@ void pp_hud_board(vector pos, vector mySize)
        minigame_hud_fitsqare(pos, mySize);
        pp_boardpos = pos;
        pp_boardsize = mySize;
-       
+
        minigame_hud_simpleboard(pos,mySize,minigame_texture("pp/board"));
 
        vector tile_size = minigame_hud_denormalize_size('1 1 0'/PP_TILE_SIZE,pos,mySize);
@@ -305,7 +307,7 @@ void pp_hud_board(vector pos, vector mySize)
                                case 2: tile_color = '0.3 0.3 1'; break;
                                // 3, 4 coming later?
                        }
-                       
+
                        string tile_name = strcat("pp/piece",ftos(e.team));
                        if(e.team == 5) { tile_name = "pp/piece_taken"; }
 
@@ -314,12 +316,12 @@ void pp_hud_board(vector pos, vector mySize)
                                tile_name = "pp/piece_current";
 
                                // draw the splat too
-                               minigame_drawpic_centered( tile_pos,  
+                               minigame_drawpic_centered( tile_pos,
                                                minigame_texture("pp/piece_taken"),
                                                tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
                        }
 
-                       minigame_drawpic_centered( tile_pos,  
+                       minigame_drawpic_centered( tile_pos,
                                        minigame_texture(tile_name),
                                        tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
                }
@@ -330,7 +332,7 @@ void pp_hud_board(vector pos, vector mySize)
        {
                tile_pos = minigame_tile_pos(pp_curr_pos,PP_LET_CNT,PP_NUM_CNT);
                tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-               minigame_drawpic_centered( tile_pos,  
+               minigame_drawpic_centered( tile_pos,
                                minigame_texture("pp/piece_current"),
                                tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
        }
@@ -338,7 +340,7 @@ void pp_hud_board(vector pos, vector mySize)
        {
                tile_pos = minigame_tile_pos(pp_curr_pos,PP_LET_CNT,PP_NUM_CNT);
                tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-               minigame_drawpic_centered( tile_pos,  
+               minigame_drawpic_centered( tile_pos,
                                minigame_texture("pp/piece_selected"),
                                tile_size, '1 1 1', panel_fg_alpha / 2, DRAWFLAG_NORMAL );
        }
@@ -348,20 +350,20 @@ void pp_hud_board(vector pos, vector mySize)
                vector winfs = hud_fontsize*2;
                string playername = "";
                FOREACH_MINIGAME_ENTITY(e)
-                       if ( e.classname == "minigame_player" && 
+                       if ( e.classname == "minigame_player" &&
                                        e.team == (active_minigame.minigame_flags & PP_TURN_TEAM) )
                                playername = GetPlayerName(e.minigame_playerslot-1);
-               
+
                vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
                vector win_sz;
                win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("%s^7 won the game!",playername), 
+                       sprintf("%s^7 won the game!",playername),
                        winfs, 0, DRAWFLAG_NORMAL, 0.5);
-               
+
                drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
-               
+
                minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("%s^7 won the game!",playername), 
+                       sprintf("%s^7 won the game!",playername),
                        winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
        }
 }
@@ -374,10 +376,10 @@ void pp_hud_status(vector pos, vector mySize)
        vector ts;
        ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
                hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-       
+
        pos_y += ts_y;
        mySize_y -= ts_y;
-       
+
        vector player_fontsize = hud_fontsize * 1.75;
        ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
        ts_x = mySize_x;
@@ -410,17 +412,17 @@ void pp_hud_status(vector pos, vector mySize)
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
                                GetPlayerName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-                       
+
                        mypos_y += player_fontsize_y;
-                       drawpic( mypos,  
+                       drawpic( mypos,
                                        minigame_texture(strcat("pp/piece",ftos(e.team))),
                                        tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
-                       
+
                        mypos_x += tile_size_x;
                        int myscore = 0;
                        if(e.team == 1) { myscore = active_minigame.pp_team1_score; }
                        if(e.team == 2) { myscore = active_minigame.pp_team2_score; }
-                       
+
                        drawstring(mypos,ftos(myscore),tile_size,
                                           '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                }
@@ -432,27 +434,27 @@ string pp_turn_to_string(int turnflags)
 {
        if ( turnflags & PP_TURN_DRAW )
                return _("Draw");
-       
+
        if ( turnflags & PP_TURN_WIN )
        {
                if ( (turnflags&PP_TURN_TEAM) != minigame_self.team )
                        return _("You lost the game!\nSelect \"^1Next Match^7\" on the menu for a rematch!");
                return _("You win!\nSelect \"^1Next Match^7\" on the menu to start a new match!");
        }
-       
+
        if ( turnflags & PP_TURN_NEXT )
        {
                if ( (turnflags&PP_TURN_TEAM) != minigame_self.team )
                        return _("Select \"^1Next Match^7\" on the menu to start a new match!");
                return _("Wait for your opponent to confirm the rematch");
        }
-       
+
        if ( (turnflags & PP_TURN_TEAM) != minigame_self.team )
                return _("Wait for your opponent to make their move");
-       
+
        if ( turnflags & PP_TURN_PLACE )
                return _("Click on the game board to place your piece");
-       
+
        return "";
 }
 
@@ -589,4 +591,4 @@ int pp_client_event(entity minigame, string event, ...)
        return false;
 }
 
-#endif
\ No newline at end of file
+#endif
index 3acef2fd5f7d79571e95d5582d3a1e6650d8c9e0..54be75cd46f51ba2c62756d99ec8716cb6764fd0 100644 (file)
@@ -1,3 +1,5 @@
+REGISTER_MINIGAME(ps, "Peg Solitaire");
+
 const float PS_TURN_MOVE  = 0x0100; // player has to click on a piece on the board
 const float PS_TURN_WIN   = 0x0200; // player has won
 const float PS_TURN_DRAW  = 0x0400; // player can make no more moves
@@ -102,7 +104,7 @@ bool ps_winning_piece(entity minigame)
                                        return false; // a move is valid, abort!
                        }
                }
-       
+
        return true;
 }
 
@@ -248,7 +250,7 @@ int ps_server_event(entity minigame, string event, ...)
                {
                        switch(argv(0))
                        {
-                               case "move": 
+                               case "move":
 
                                        ps_move(minigame, ...(0,entity), (...(1,int) == 3 ? argv(1) : string_null), (...(1,int) == 3 ? argv(2) : string_null));
                                        return true;
@@ -257,7 +259,7 @@ int ps_server_event(entity minigame, string event, ...)
                        return false;
                }
        }
-       
+
        return false;
 }
 
@@ -275,7 +277,7 @@ void ps_hud_board(vector pos, vector mySize)
        minigame_hud_fitsqare(pos, mySize);
        ps_boardpos = pos;
        ps_boardsize = mySize;
-       
+
        minigame_hud_simpleboard(pos,mySize,minigame_texture("ps/board"));
 
        vector tile_size = minigame_hud_denormalize_size('1 1 0' / PS_TILE_SIZE,pos,mySize);
@@ -353,7 +355,7 @@ void ps_hud_board(vector pos, vector mySize)
                                draw_pos = true;
                }
        }
-       
+
        entity e;
        FOREACH_MINIGAME_ENTITY(e)
        {
@@ -368,18 +370,18 @@ void ps_hud_board(vector pos, vector mySize)
                        if(e.netname == ps_curr_pos)
                        if(ps_curr_piece.netname != ps_curr_pos)
                        {
-                               minigame_drawpic_centered( tile_pos,  
+                               minigame_drawpic_centered( tile_pos,
                                                minigame_texture("ps/tile_available"),
                                                tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
                        }
                        if(e == ps_curr_piece)
                        {
-                               minigame_drawpic_centered( tile_pos,  
+                               minigame_drawpic_centered( tile_pos,
                                                minigame_texture("ps/tile_selected"),
                                                tile_size, tile_color, panel_fg_alpha, DRAWFLAG_ADDITIVE );
                        }
 
-                       minigame_drawpic_centered( tile_pos,  
+                       minigame_drawpic_centered( tile_pos,
                                        minigame_texture("ps/piece"),
                                        tile_size * 0.8, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
                }
@@ -408,17 +410,17 @@ void ps_hud_board(vector pos, vector mySize)
                        remaining_text = "All pieces cleared!";
                else
                        remaining_text = strcat("Remaining pieces: ", ftos(remaining));
-               
+
                vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
                vector win_sz;
                win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("Game over! %s", remaining_text), 
+                       sprintf("Game over! %s", remaining_text),
                        winfs, 0, DRAWFLAG_NORMAL, 0.5);
-               
+
                drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
-               
+
                minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
-                       sprintf("Game over! %s", remaining_text), 
+                       sprintf("Game over! %s", remaining_text),
                        winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
        }
 }
@@ -431,10 +433,10 @@ void ps_hud_status(vector pos, vector mySize)
        vector ts;
        ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
                hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-       
+
        pos_y += ts_y;
        mySize_y -= ts_y;
-       
+
        vector player_fontsize = hud_fontsize * 1.75;
        ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
        ts_x = mySize_x;
@@ -464,12 +466,12 @@ void ps_hud_status(vector pos, vector mySize)
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
                                GetPlayerName(e.minigame_playerslot-1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-                       
+
                        mypos_y += player_fontsize_y;
-                       //drawpic( mypos,  
+                       //drawpic( mypos,
                        //              minigame_texture("ps/piece"),
                        //              tile_size, '1 0 0', panel_fg_alpha, DRAWFLAG_NORMAL );
-                       
+
                        //mypos_x += tile_size_x;
 
                        drawstring(mypos,sprintf(_("Pieces left: %s"), ftos(remaining)),'28 28 0',
@@ -486,10 +488,10 @@ string ps_turn_to_string(int turnflags)
 
        if ( turnflags & PS_TURN_WIN )
                return _("Well done, you win!");
-       
+
        if ( turnflags & PS_TURN_MOVE )
                return _("Jump a piece over another to capture it");
-       
+
        return "";
 }
 
@@ -617,4 +619,4 @@ int ps_client_event(entity minigame, string event, ...)
        return false;
 }
 
-#endif
\ No newline at end of file
+#endif
diff --git a/qcsrc/common/minigames/minigame/qto.qc b/qcsrc/common/minigames/minigame/qto.qc
deleted file mode 100644 (file)
index cef71df..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-const float QTO_TURN_MOVE  = 0x0100; // player has to click on a piece on the board
-const float QTO_TURN_WIN   = 0x0200; // player has won
-const float QTO_TURN_TYPE  = 0x0f00; // turn type mask
-
-const int QTO_SF_PLAYERSCORE = MINIG_SF_CUSTOM;
-
-const int QTO_LET_CNT = 5;
-const int QTO_NUM_CNT = 5;
-
-const int QTO_TILE_SIZE = 8;
-
-.int qto_moves;
-
-// find same game piece given its tile name
-entity qto_find_piece(entity minig, string tile)
-{
-       entity e = world;
-       while ( ( e = findentity(e,owner,minig) ) )
-               if ( e.classname == "minigame_board_piece" && e.netname == tile )
-                       return e;
-       return world;
-}
-
-// Checks if the given piece completes a row
-bool qto_winning_piece(entity minigame)
-{
-       //int number = minigame_tile_number(piece.netname);
-       //int letter = minigame_tile_letter(piece.netname);
-
-       entity e = world;
-       while ( ( e = findentity(e,owner,minigame) ) )
-               if ( e.classname == "minigame_board_piece" )
-               {
-                       if(!e.cnt)
-                               return false;
-               }
-       
-       return true;
-}
-
-// check if the tile name is valid (5x5 grid)
-bool qto_valid_tile(string tile)
-{
-       if ( !tile )
-               return false;
-       float number = minigame_tile_number(tile);
-       float letter = minigame_tile_letter(tile);
-       return 0 <= number && number < QTO_NUM_CNT && 0 <= letter && letter < QTO_LET_CNT;
-}
-
-void qto_setup_pieces(entity minigame)
-{
-       int i, t;
-       for(i = 0; i < QTO_NUM_CNT; ++i)
-       for(t = 0; t < QTO_LET_CNT; ++t)
-       {
-               entity piece = msle_spawn(minigame,"minigame_board_piece");
-               piece.team = 1; // init default team?
-               piece.cnt = 0; // initialize cnt
-               piece.netname = strzone(minigame_tile_buildname(t,i));
-               minigame_server_sendflags(piece,MINIG_SF_ALL);
-       }
-
-       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-}
-
-void qto_add_score(entity minigame, int thescore)
-{
-#ifdef SVQC
-       if(!minigame)
-               return;
-       if(minigame.minigame_players)
-       {
-               minigame.minigame_players.qto_moves += thescore;
-               minigame.minigame_players.SendFlags |= QTO_SF_PLAYERSCORE;
-       }
-#endif
-}
-
-// make a move
-void qto_move(entity minigame, entity player, string pos )
-{
-       if ( minigame.minigame_flags & QTO_TURN_MOVE )
-       if ( pos )
-       {
-               if ( qto_valid_tile(pos) )
-               if ( qto_find_piece(minigame, pos) )
-               {
-                       entity piece;
-               #define DO_JUNK \
-                       if(piece) \
-                       { \
-                               piece.cnt = (piece.cnt) ? 0 : 1; \
-                               minigame_server_sendflags(piece,MINIG_SF_UPDATE); \
-                       }
-
-                       int number = minigame_tile_number(pos);
-                       int letter = minigame_tile_letter(pos);
-                       piece = qto_find_piece(minigame, pos);
-                       DO_JUNK
-                       piece = qto_find_piece(minigame, minigame_tile_buildname(letter-1,number));
-                       DO_JUNK
-                       piece = qto_find_piece(minigame, minigame_tile_buildname(letter+1,number));
-                       DO_JUNK
-                       piece = qto_find_piece(minigame, minigame_tile_buildname(letter,number-1));
-                       DO_JUNK
-                       piece = qto_find_piece(minigame, minigame_tile_buildname(letter,number+1));
-                       DO_JUNK
-
-                       qto_add_score(minigame,1); // add 1 move score
-
-                       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-
-                       if ( qto_winning_piece(minigame) )
-                       {
-                               minigame.minigame_flags = QTO_TURN_WIN;
-                       }
-                       else
-                               minigame.minigame_flags = QTO_TURN_MOVE;
-               }
-       }
-}
-
-// restart match
-void qto_restart_match(entity minigame, entity player)
-{
-       minigame.minigame_flags = QTO_TURN_MOVE;
-       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
-       entity e = world;
-       while ( ( e = findentity(e,owner,minigame) ) )
-               if ( e.classname == "minigame_board_piece" )
-                       remove(e);
-
-       qto_setup_pieces(minigame);
-#ifdef SVQC
-       if(minigame.minigame_players)
-       {
-               minigame.minigame_players.qto_moves = 0;
-               minigame.minigame_players.SendFlags |= QTO_SF_PLAYERSCORE;
-       }
-#endif
-}
-
-#ifdef SVQC
-
-
-// required function, handle server side events
-int qto_server_event(entity minigame, string event, ...)
-{
-       switch(event)
-       {
-               case "start":
-               {
-                       qto_setup_pieces(minigame);
-                       minigame.minigame_flags = QTO_TURN_MOVE;
-                       return true;
-               }
-               case "end":
-               {
-                       entity e = world;
-                       while( (e = findentity(e, owner, minigame)) )
-                       if(e.classname == "minigame_board_piece")
-                       {
-                               if(e.netname) { strunzone(e.netname); }
-                               remove(e);
-                       }
-                       return false;
-               }
-               case "join":
-               {
-                       int pl_num = minigame_count_players(minigame);
-
-                       // Don't allow more than 1 player
-                       if(pl_num >= 1) { return false; }
-
-                       // Team 1 by default
-                       return 1;
-               }
-               case "cmd":
-               {
-                       switch(argv(0))
-                       {
-                               case "move": 
-                                       qto_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null ); 
-                                       return true;
-                               case "restart":
-                                       qto_restart_match(minigame,...(0,entity));
-                                       return true;
-                       }
-
-                       return false;
-               }
-               case "network_send":
-               {
-                       entity sent = ...(0,entity);
-                       int sf = ...(1,int);
-                       if ( sent.classname == "minigame_board_piece" && (sf & MINIG_SF_UPDATE) )
-                       {
-                               WriteByte(MSG_ENTITY,sent.cnt);
-                       }
-                       else if ( sent.classname == "minigame_player" && (sf & QTO_SF_PLAYERSCORE ) )
-                       {
-                               WriteLong(MSG_ENTITY,sent.qto_moves);
-                       }
-                       return false;
-               }
-       }
-       
-       return false;
-}
-
-
-#elif defined(CSQC)
-
-string qto_curr_pos; // identifier of the tile under the mouse
-vector qto_boardpos; // HUD board position
-vector qto_boardsize;// HUD board size
-
-// Required function, draw the game board
-void qto_hud_board(vector pos, vector mySize)
-{
-       minigame_hud_fitsqare(pos, mySize);
-       qto_boardpos = pos;
-       qto_boardsize = mySize;
-       
-       minigame_hud_simpleboard(pos,mySize,minigame_texture("qto/board"));
-
-       vector tile_size = minigame_hud_denormalize_size('1 1 0' / QTO_TILE_SIZE,pos,mySize);
-       vector tile_pos;
-
-       bool valid = qto_valid_tile(qto_curr_pos);
-       int number = minigame_tile_number(qto_curr_pos);
-       int letter = minigame_tile_letter(qto_curr_pos);
-       string pos1 = minigame_tile_buildname(letter-1,number);
-       string pos2 = minigame_tile_buildname(letter+1,number);
-       string pos3 = minigame_tile_buildname(letter,number-1);
-       string pos4 = minigame_tile_buildname(letter,number+1);
-       
-       entity e;
-       FOREACH_MINIGAME_ENTITY(e)
-       {
-               if ( e.classname == "minigame_board_piece" )
-               {
-                       tile_pos = minigame_tile_pos(e.netname,QTO_NUM_CNT,QTO_LET_CNT);
-                       tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-
-                       vector tile_color = '0.4 0.4 0.4';
-
-                       if(valid)
-                       switch(e.netname)
-                       {
-                               case qto_curr_pos:
-                               case pos1: case pos2: case pos3: case pos4:
-                                       tile_color = '0.8 0.8 0.8';
-                                       break;
-                       }
-                               
-                       minigame_drawpic_centered( tile_pos,  
-                                       minigame_texture(strcat("qto/piece", ftos(e.cnt))),
-                                       tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
-               }
-       }
-}
-
-
-// Required function, draw the game status panel
-void qto_hud_status(vector pos, vector mySize)
-{
-       HUD_Panel_DrawBg(1);
-       vector ts;
-       ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
-               hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-       
-       pos_y += ts_y;
-       mySize_y -= ts_y;
-       
-       vector player_fontsize = hud_fontsize * 1.75;
-       ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
-       ts_x = mySize_x;
-       vector mypos;
-       vector tile_size = '48 48 0';
-
-       mypos = pos;
-       drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
-       mypos_y += player_fontsize_y;
-       drawfill(mypos,eX*mySize_x+eY*tile_size_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
-
-       entity e;
-       FOREACH_MINIGAME_ENTITY(e)
-       {
-               if ( e.classname == "minigame_player" )
-               {
-                       mypos = pos;
-                       minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               GetPlayerName(e.minigame_playerslot-1),
-                               player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-                       
-                       mypos_y += player_fontsize_y;
-                       //drawpic( mypos,  
-                       //              minigame_texture("qto/piece"),
-                       //              tile_size, '1 0 0', panel_fg_alpha, DRAWFLAG_NORMAL );
-                       
-                       //mypos_x += tile_size_x;
-
-                       drawstring(mypos,sprintf(_("Moves: %s"), ftos(e.qto_moves)),'32 32 0',
-                                          '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-               }
-       }
-}
-
-// Turn a set of flags into a help message
-string qto_turn_to_string(int turnflags)
-{
-       if ( turnflags & QTO_TURN_WIN )
-               return _("Well done, you win!");
-       
-       if ( turnflags & QTO_TURN_MOVE )
-               return _("Turn all the angry faces into happy faces");
-       
-       return "";
-}
-
-// Make the correct move
-void qto_make_move(entity minigame)
-{
-       if ( minigame.minigame_flags == QTO_TURN_MOVE )
-       {
-               minigame_cmd("move ",qto_curr_pos);
-       }
-}
-
-void qto_set_curr_pos(string s)
-{
-       if ( qto_curr_pos )
-               strunzone(qto_curr_pos);
-       if ( s )
-               s = strzone(s);
-       qto_curr_pos = s;
-}
-
-// Required function, handle client events
-int qto_client_event(entity minigame, string event, ...)
-{
-       switch(event)
-       {
-               case "activate":
-               {
-                       qto_set_curr_pos("");
-                       minigame.message = qto_turn_to_string(minigame.minigame_flags);
-                       return false;
-               }
-               case "key_pressed":
-               {
-                       //if((minigame.minigame_flags & QTO_TURN_TEAM) == minigame_self.team)
-                       {
-                               switch ( ...(0,int) )
-                               {
-                                       case K_RIGHTARROW:
-                                       case K_KP_RIGHTARROW:
-                                               if ( ! qto_curr_pos )
-                                                       qto_set_curr_pos("a3");
-                                               else
-                                                       qto_set_curr_pos( minigame_relative_tile(qto_curr_pos,1,0,QTO_NUM_CNT,QTO_LET_CNT));
-                                               return true;
-                                       case K_LEFTARROW:
-                                       case K_KP_LEFTARROW:
-                                               if ( ! qto_curr_pos )
-                                                       qto_set_curr_pos("c3");
-                                               else
-                                                       qto_set_curr_pos(minigame_relative_tile(qto_curr_pos,-1,0,QTO_NUM_CNT,QTO_LET_CNT));
-                                               return true;
-                                       case K_UPARROW:
-                                       case K_KP_UPARROW:
-                                               if ( ! qto_curr_pos )
-                                                       qto_set_curr_pos("a1");
-                                               else
-                                                       qto_set_curr_pos(minigame_relative_tile(qto_curr_pos,0,1,QTO_NUM_CNT,QTO_LET_CNT));
-                                               return true;
-                                       case K_DOWNARROW:
-                                       case K_KP_DOWNARROW:
-                                               if ( ! qto_curr_pos )
-                                                       qto_set_curr_pos("a3");
-                                               else
-                                                       qto_set_curr_pos(minigame_relative_tile(qto_curr_pos,0,-1,QTO_NUM_CNT,QTO_LET_CNT));
-                                               return true;
-                                       case K_ENTER:
-                                       case K_KP_ENTER:
-                                       case K_SPACE:
-                                               qto_make_move(minigame);
-                                               return true;
-                               }
-                       }
-
-                       return false;
-               }
-               case "mouse_pressed":
-               {
-                       if(...(0,int) == K_MOUSE1)
-                       {
-                               qto_make_move(minigame);
-                               return true;
-                       }
-
-                       return false;
-               }
-               case "mouse_moved":
-               {
-                       vector mouse_pos = minigame_hud_normalize(mousepos,qto_boardpos,qto_boardsize);
-                       if ( minigame.minigame_flags == QTO_TURN_MOVE )
-                       {
-                               qto_set_curr_pos(minigame_tile_name(mouse_pos,QTO_NUM_CNT,QTO_LET_CNT));
-                       }
-                       if ( ! qto_valid_tile(qto_curr_pos) )
-                               qto_set_curr_pos("");
-
-                       return true;
-               }
-               case "network_receive":
-               {
-                       entity sent = ...(0,entity);
-                       int sf = ...(1,int);
-                       if ( sent.classname == "minigame" )
-                       {
-                               if ( sf & MINIG_SF_UPDATE )
-                               {
-                                       sent.message = qto_turn_to_string(sent.minigame_flags);
-                                       if ( sent.minigame_flags & minigame_self.team )
-                                               minigame_prompt();
-                               }
-                       }
-                       else if(sent.classname == "minigame_board_piece")
-                       {
-                               if(sf & MINIG_SF_UPDATE)
-                               {
-                                       sent.cnt = ReadByte();
-                               }
-                       }
-                       else if ( sent.classname == "minigame_player" && (sf & QTO_SF_PLAYERSCORE ) )
-                       {
-                               sent.qto_moves = ReadLong();
-                       }
-
-                       return false;
-               }
-               case "menu_show":
-               {
-                       HUD_MinigameMenu_CustomEntry(...(0,entity),_("Restart"),"restart");
-                       return false;
-               }
-               case "menu_click":
-               {
-                       if(...(0,string) == "restart")
-                               minigame_cmd("restart");
-                       return false;
-               }
-       }
-
-       return false;
-}
-
-#endif
\ No newline at end of file
diff --git a/qcsrc/common/minigames/minigame/snake.qc b/qcsrc/common/minigames/minigame/snake.qc
new file mode 100644 (file)
index 0000000..cbb1342
--- /dev/null
@@ -0,0 +1,853 @@
+REGISTER_MINIGAME(snake, "Snake"); // SNAAAAKE
+
+const float SNAKE_TURN_MOVE  = 0x0100; // the snake is moving, player must control it
+const float SNAKE_TURN_WIN   = 0x0200; // multiplayer victory
+const float SNAKE_TURN_LOSS  = 0x0400; // they did it?!
+const float SNAKE_TURN_TYPE  = 0x0f00; // turn type mask
+
+const int SNAKE_TURN_TEAM  = 0x000f; // turn team mask
+
+const int SNAKE_SF_PLAYERSCORE = MINIG_SF_CUSTOM;
+
+const int SNAKE_LET_CNT = 15;
+const int SNAKE_NUM_CNT = 15;
+
+const int SNAKE_TILE_SIZE = 15;
+
+const int SNAKE_TEAMS = 6;
+
+bool autocvar_sv_minigames_snake_wrap = false;
+float autocvar_sv_minigames_snake_delay_initial = 0.7;
+float autocvar_sv_minigames_snake_delay_multiplier = 50;
+float autocvar_sv_minigames_snake_delay_min = 0.1;
+int autocvar_sv_minigames_snake_lives = 3;
+
+.int snake_score;
+
+.float snake_delay;
+.vector snake_dir;
+
+.entity snake_next, snake_last, snake_prev;
+
+.bool snake_tail;
+
+.int snake_lives[SNAKE_TEAMS + 1];
+
+.int snake_lost_teams;
+
+bool snake_alone(entity minig)
+{
+       int headcount = 0;
+       entity e = world;
+       while ( ( e = findentity(e,owner,minig) ) )
+               if ( e.classname == "minigame_board_piece" && e.cnt == 1 )
+                       ++headcount;
+
+       return headcount <= 1;
+}
+
+// find same game piece given its tile name
+entity snake_find_piece(entity minig, string tile)
+{
+       entity e = world;
+       while ( ( e = findentity(e,owner,minig) ) )
+               if ( e.classname == "minigame_board_piece" && e.netname == tile )
+                       return e;
+       return world;
+}
+
+// find same game piece given its cnt
+entity snake_find_cnt(entity minig, int steam, int tile)
+{
+       entity e = world;
+       while ( ( e = findentity(e,owner,minig) ) )
+               if ( e.classname == "minigame_board_piece" && e.cnt == tile && e.team == steam )
+                       return e;
+       return world;
+}
+
+// check if the tile name is valid (15x15 grid)
+bool snake_valid_tile(string tile)
+{
+       if ( !tile )
+               return false;
+       int number = minigame_tile_number(tile);
+       int letter = minigame_tile_letter(tile);
+       return 0 <= number && number < SNAKE_NUM_CNT && 0 <= letter && letter < SNAKE_LET_CNT;
+}
+
+entity snake_find_head(entity minig, int steam)
+{
+       entity e = world;
+       while ( ( e = findentity(e,owner,minig) ) )
+               if ( e.classname == "minigame_board_piece" && e.cnt == 1 && e.team == steam )
+                       return e;
+       return world;
+}
+
+void snake_new_mouse(entity minigame)
+{
+       RandomSelection_Init();
+       int i, j;
+       for(i = 0; i < SNAKE_LET_CNT; ++i)
+       for(j = 0; j < SNAKE_NUM_CNT; ++j)
+       {
+               string pos = minigame_tile_buildname(i, j);
+               if(!snake_find_piece(minigame, pos))
+                       RandomSelection_Add(world, 0, pos, 1, 1);
+       }
+
+       entity piece = msle_spawn(minigame,"minigame_board_piece");
+       piece.team = 0;
+       piece.netname = strzone(RandomSelection_chosen_string);
+       minigame_server_sendflags(piece,MINIG_SF_ALL);
+
+       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+}
+
+entity snake_get_player(entity minigame, int pteam);
+int snake_winning_team(entity minigame)
+{
+       int winning_team = 0;
+       for(int i = 1; i <= SNAKE_TEAMS; ++i)
+       {
+               entity pl = snake_get_player(minigame, i);
+               if(pl && minigame.snake_lives[i] > 0)
+               {
+                       if(winning_team)
+                               return 0;
+                       winning_team = i;
+               }
+       }
+
+       return winning_team;
+}
+
+void snake_check_winner(entity minigame)
+{
+       if(snake_alone(minigame) && !minigame.snake_lost_teams)
+               return;
+
+       int winner = snake_winning_team(minigame);
+
+       int alivecnt = 0;
+       for(int i = 1; i <= SNAKE_TEAMS; ++i)
+       {
+               entity pl = snake_get_player(minigame, i);
+               if(pl && minigame.snake_lives[i] > 0)
+                       ++alivecnt;
+       }
+
+       if(!alivecnt)
+       {
+               minigame.minigame_flags = SNAKE_TURN_LOSS;
+               minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+               return;
+       }
+
+       if(winner)
+       {
+               minigame.minigame_flags = SNAKE_TURN_WIN | winner;
+               minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+       }
+}
+
+void snake_move_head(entity minigame, entity head);
+void snake_head_think()
+{
+       entity minigame = self.owner;
+
+       if(minigame.minigame_flags & SNAKE_TURN_MOVE)
+               snake_move_head(minigame, self);
+
+       snake_check_winner(minigame);
+
+       self.nextthink = time + self.snake_delay;
+}
+
+void minigame_setup_snake(entity minigame, int pteam)
+{
+       RandomSelection_Init();
+       int i, j;
+       for(i = 1; i < SNAKE_LET_CNT - 1; ++i)
+       for(j = 1; j < SNAKE_NUM_CNT - 1; ++j)
+       {
+               string pos = minigame_tile_buildname(i, j);
+               if(!snake_find_piece(minigame, pos))
+                       RandomSelection_Add(world, 0, pos, 1, 1);
+       }
+
+       entity piece = msle_spawn(minigame,"minigame_board_piece");
+       piece.team = pteam;
+       piece.netname = strzone(RandomSelection_chosen_string);
+       piece.cnt = 1;
+       piece.snake_next = world;
+       piece.snake_prev = world;
+       piece.snake_last = piece;
+       piece.think = snake_head_think;
+       piece.snake_delay = autocvar_sv_minigames_snake_delay_initial;
+       piece.nextthink = time + 0.1;
+       minigame_server_sendflags(piece,MINIG_SF_ALL);
+}
+
+void snake_setup_pieces(entity minigame)
+{
+       snake_new_mouse(minigame);
+
+       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+}
+
+entity snake_get_player(entity minigame, int pteam)
+{
+       entity e;
+#ifdef SVQC
+       for(e = minigame.minigame_players; e; e = e.list_next)
+#elif defined(CSQC)
+       e = world;
+       while( (e = findentity(e,owner,minigame)) )
+               if ( e.classname == "minigame_player" )
+#endif
+       if(e.team == pteam)
+               return e;
+       return world;
+}
+
+void snake_add_score(entity minigame, int pteam, int thescore)
+{
+#ifdef SVQC
+       if(!minigame)
+               return;
+       entity pl = snake_get_player(minigame, pteam);
+       if(pl)
+       {
+               pl.snake_score += thescore;
+               pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
+       }
+#endif
+}
+
+void snake_move_body(entity minigame, entity head, bool ate_mouse)
+{
+       for(entity e = head.snake_last; e; e = e.snake_prev)
+       {
+               if(!e || e == head) { break; }
+
+               entity nextpiece = e.snake_prev; // can be head
+
+               if(e.netname) { strunzone(e.netname); }
+               e.netname = strzone(nextpiece.netname);
+               e.snake_dir = nextpiece.snake_dir;
+               minigame_server_sendflags(e, MINIG_SF_UPDATE);
+       }
+
+       if(ate_mouse)
+       {
+               entity tail = head.snake_last;
+
+               tail.snake_tail = false;
+
+               int newcnt = tail.cnt + 1;
+               head.snake_delay = max(autocvar_sv_minigames_snake_delay_min, autocvar_sv_minigames_snake_delay_initial - (newcnt / autocvar_sv_minigames_snake_delay_multiplier));
+               snake_add_score(minigame, head.team, 1);
+
+               entity piece = msle_spawn(minigame,"minigame_board_piece");
+               piece.cnt = newcnt;
+               piece.team = head.team;
+               piece.snake_prev = tail;
+               piece.snake_dir = tail.snake_dir;
+               piece.snake_next = world;
+               piece.snake_tail = true;
+               piece.netname = strzone(tail.netname);
+
+               tail.snake_next = piece;
+               head.snake_last = piece;
+
+               minigame_server_sendflags(piece,MINIG_SF_UPDATE);
+
+               //minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+       }
+}
+
+void snake_eat_team(entity minigame, int pteam)
+{
+       entity head = snake_find_head(minigame, pteam);
+       if(!head) { return; }
+
+       minigame.snake_lives[pteam] -= 1;
+
+       entity pl = snake_get_player(minigame, pteam);
+#ifdef SVQC
+       pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
+#endif
+
+       head.nextthink = time + 1; // make sure they don't to eat us somehow
+
+       entity e = world;
+       while ( ( e = findentity(e,owner,minigame) ) )
+               if ( e.classname == "minigame_board_piece" && e.cnt && e.team == pteam )
+               {
+                       if(e.netname) { strunzone(e.netname); }
+                       remove(e);
+               }
+
+       if(minigame.snake_lives[pteam] <= 0)
+               minigame.snake_lost_teams |= BIT(pteam);
+
+       if(pl && minigame.snake_lives[pteam] > 0)
+               minigame_setup_snake(minigame, pteam);  
+}
+
+void snake_move_head(entity minigame, entity head)
+{
+       if(!head.snake_dir_x && !head.snake_dir_y)
+               return; // nope!
+
+       string newpos;
+
+       if(autocvar_sv_minigames_snake_wrap)
+               newpos = minigame_relative_tile(head.netname, head.snake_dir_x, head.snake_dir_y, SNAKE_NUM_CNT, SNAKE_LET_CNT);
+       else
+       {
+               int myx = minigame_tile_letter(head.netname);
+               int myy = minigame_tile_number(head.netname);
+
+               myx += head.snake_dir_x;
+               myy += head.snake_dir_y;
+
+               newpos = minigame_tile_buildname(myx, myy);
+       }
+
+       entity hit = snake_find_piece(minigame, newpos);
+
+       if(!snake_valid_tile(newpos) || (hit && hit.cnt && hit.team == head.team))
+       {
+               if(snake_alone(minigame))
+               {
+                       minigame.minigame_flags = SNAKE_TURN_LOSS;
+                       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+               }
+               else
+               {
+                       snake_add_score(minigame, head.team, -1);
+                       snake_eat_team(minigame, head.team);
+               }
+
+               return;
+       }
+
+       bool ate_mouse = (hit && !hit.cnt);
+
+       // move the body first, then set the new head position?
+       snake_move_body(minigame, head, ate_mouse);
+
+       if(head.netname) { strunzone(head.netname); }
+       head.netname = strzone(newpos);
+       minigame_server_sendflags(head,MINIG_SF_UPDATE);
+
+       // above check makes sure it's not our team
+       if(hit.cnt)
+       {
+               snake_eat_team(minigame, hit.team);
+               snake_add_score(minigame, head.team, 1);
+       }
+
+       if(ate_mouse)
+       {
+               if(hit.netname) { strunzone(hit.netname); }
+               remove(hit);
+
+               snake_new_mouse(minigame);
+       }
+}
+
+// make a move
+void snake_move(entity minigame, entity player, string dxs, string dys )
+{
+       if ( minigame.minigame_flags & SNAKE_TURN_MOVE )
+       if ( dxs || dys )
+       {
+               //if ( snake_valid_tile(pos) )
+               //if ( snake_find_piece(minigame, pos) )
+               {
+                       entity head = snake_find_head(minigame, player.team);
+                       if(!head)
+                               return; // their head is already dead
+
+                       int dx = ((dxs) ? bound(-1, stof(dxs), 1) : 0);
+                       int dy = ((dys) ? bound(-1, stof(dys), 1) : 0);
+
+                       int myl = minigame_tile_letter(head.netname);
+                       int myn = minigame_tile_number(head.netname);
+
+                       entity check_piece = snake_find_piece(minigame, minigame_tile_buildname(myl + dx, myn + dy));
+                       if(check_piece && check_piece.cnt == 2)
+                               return; // nope!
+
+                       if(head.snake_dir == '0 0 0')
+                               head.nextthink = time; // TODO: make sure this can't be exploited!
+                       head.snake_dir_x = dx;
+                       head.snake_dir_y = dy;
+                       head.snake_dir_z = 0;
+                       minigame_server_sendflags(head,MINIG_SF_UPDATE);
+                       minigame_server_sendflags(minigame,MINIG_SF_UPDATE);
+               }
+       }
+}
+
+#ifdef SVQC
+
+
+// required function, handle server side events
+int snake_server_event(entity minigame, string event, ...)
+{
+       switch(event)
+       {
+               case "start":
+               {
+                       snake_setup_pieces(minigame);
+                       minigame.minigame_flags = SNAKE_TURN_MOVE;
+                       minigame.snake_lost_teams = 0;
+
+                       if(SNAKE_TEAMS > 1)
+                       {
+                               for(int i = 1; i <= SNAKE_TEAMS; ++i)
+                                       minigame.snake_lives[i] = autocvar_sv_minigames_snake_lives;
+                       }
+                       else
+                               minigame.snake_lives[1] = 1;
+                       
+                       return true;
+               }
+               case "end":
+               {
+                       entity e = world;
+                       while( (e = findentity(e, owner, minigame)) )
+                       if(e.classname == "minigame_board_piece")
+                       {
+                               if(e.netname) { strunzone(e.netname); }
+                               remove(e);
+                       }
+                       return false;
+               }
+               case "join":
+               {
+                       int pl_num = minigame_count_players(minigame);
+
+                       if(pl_num >= SNAKE_TEAMS) { return false; }
+
+                       int t = 1; // Team 1 by default
+
+                       for(int i = 1; i <= SNAKE_TEAMS; ++i)
+                       {
+                               entity e = snake_get_player(minigame, i);
+                               if(!e)
+                               {
+                                       t = i;
+                                       break;
+                               }
+                       }
+
+                       if(!snake_find_head(minigame, t) && !(minigame.snake_lost_teams & BIT(t)))
+                       {
+                               entity pl = ...(1,entity);
+                               if(pl)
+                               {
+                                       //pl.snake_lives = ((SNAKE_TEAMS > 1) ? autocvar_sv_minigames_snake_lives : 1);
+                                       // send score anyway, lives are set
+                                       pl.SendFlags |= SNAKE_SF_PLAYERSCORE;
+                               }
+                               minigame_setup_snake(minigame, t);
+                       }
+
+                       return t;
+               }
+               case "cmd":
+               {
+                       switch(argv(0))
+                       {
+                               case "move": 
+                                       snake_move(minigame, ...(0,entity), ((...(1,int)) >= 2 ? argv(1) : string_null), ((...(1,int)) == 3 ? argv(2) : string_null)); 
+                                       return true;
+                       }
+
+                       return false;
+               }
+               case "network_send":
+               {
+                       entity sent = ...(0,entity);
+                       int sf = ...(1,int);
+                       if ( sent.classname == "minigame_board_piece" && (sf & MINIG_SF_UPDATE) )
+                       {
+                               int letter = minigame_tile_letter(sent.netname);
+                               int number = minigame_tile_number(sent.netname);
+
+                               WriteByte(MSG_ENTITY,letter);
+                               WriteByte(MSG_ENTITY,number);
+
+                               WriteByte(MSG_ENTITY,sent.cnt);
+                               WriteByte(MSG_ENTITY,sent.snake_tail);
+
+                               int dx = sent.snake_dir_x;
+                               int dy = sent.snake_dir_y;
+                               if(dx == -1) dx = 2;
+                               if(dy == -1) dy = 2;
+                               WriteByte(MSG_ENTITY,dx);
+                               WriteByte(MSG_ENTITY,dy);
+                       }
+                       else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
+                       {
+                               WriteLong(MSG_ENTITY,sent.snake_score);
+                               WriteByte(MSG_ENTITY,max(0, minigame.snake_lives[sent.team]));
+                       }
+                       else if ( sent.classname == "minigame" && (sf & MINIG_SF_UPDATE ) )
+                       {
+                               WriteByte(MSG_ENTITY,autocvar_sv_minigames_snake_wrap);
+                       }
+                       return false;
+               }
+       }
+       
+       return false;
+}
+
+
+#elif defined(CSQC)
+
+vector snake_boardpos; // HUD board position
+vector snake_boardsize;// HUD board size
+
+bool snake_wrap;
+
+vector snake_teamcolor(int steam)
+{
+       switch(steam)
+       {
+               case 1: return '1 0 0';
+               case 2: return '0 0 1';
+               case 3: return '1 1 0';
+               case 4: return '1 0 1';
+               case 5: return '0 1 0';
+               case 6: return '0 1 1';
+       }
+
+       return '1 1 1';
+}
+
+// Required function, draw the game board
+void snake_hud_board(vector pos, vector mySize)
+{
+       minigame_hud_fitsqare(pos, mySize);
+       snake_boardpos = pos;
+       snake_boardsize = mySize;
+       
+       minigame_hud_simpleboard(pos,mySize,minigame_texture("snake/board"));
+
+       vector tile_size = minigame_hud_denormalize_size('1 1 0' / SNAKE_TILE_SIZE,pos,mySize);
+       vector tile_pos;
+
+       entity e;
+       FOREACH_MINIGAME_ENTITY(e)
+       {
+               if ( e.classname == "minigame_board_piece" )
+               {
+                       tile_pos = minigame_tile_pos(e.netname,SNAKE_NUM_CNT,SNAKE_LET_CNT);
+                       tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
+
+                       vector tile_color = snake_teamcolor(e.team);
+
+                       string thepiece = "snake/mouse";
+                       if(e.cnt)
+                               thepiece = "snake/body";
+                       if(e.snake_tail)
+                               thepiece = "snake/tail";
+                       if(e.cnt == 1)
+                       {
+                               int dx = minigame_tile_letter(e.netname) + e.snake_dir_x * 2;
+                               int dy = minigame_tile_number(e.netname) + e.snake_dir_y * 2;
+                               entity mouse = snake_find_piece(active_minigame, minigame_tile_buildname(dx, dy));
+                               thepiece = "snake/head";
+                               if(mouse && mouse.team != e.team)
+                               {
+                                       float myang = 0;
+                                       int myx = minigame_tile_letter(e.netname);
+                                       int myy = minigame_tile_number(e.netname);
+                                       if(myx - 2 == dx)
+                                               myang = M_PI*3/2;
+                                       if(myx + 2 == dx)
+                                               myang = M_PI/2;
+                                       if(myy - 2 == dy)
+                                               myang = M_PI;
+
+                                       int newx = minigame_tile_letter(e.netname) + e.snake_dir_x;
+                                       int newy = minigame_tile_number(e.netname) + e.snake_dir_y;
+                                       string newpos = minigame_tile_buildname(newx, newy);
+
+                                       vector my_pos = minigame_tile_pos(newpos,SNAKE_NUM_CNT,SNAKE_LET_CNT);
+                                       my_pos = minigame_hud_denormalize(my_pos,pos,mySize);
+
+                                       drawrotpic(my_pos, myang, minigame_texture("snake/tongue"),
+                                                       tile_size, tile_size/2, tile_color,
+                                                       panel_fg_alpha, DRAWFLAG_NORMAL );
+                               }
+                       }
+
+                       if(e.cnt == 1 || e.snake_tail)
+                       {
+                               vector thedir = e.snake_dir;
+                               float theang = 0;
+                               if(e.snake_tail)
+                               {
+                                       int thex = minigame_tile_letter(e.netname);
+                                       int they = minigame_tile_number(e.netname);
+                                       entity t = snake_find_cnt(active_minigame, e.team, e.cnt - 1);
+                                       int tx = minigame_tile_letter(t.netname);
+                                       int ty = minigame_tile_number(t.netname);
+
+                                       if(thex - 1 == tx)
+                                       {
+                                               thedir_y = 0;
+                                               thedir_x = -1;
+                                       }
+                                       if(they + 1 == ty)
+                                       {
+                                               thedir_x = 0;
+                                               thedir_y = 1;
+                                       }
+                                       if(they - 1 == ty)
+                                       {
+                                               thedir_x = 0;
+                                               thedir_y = -1;
+                                       }
+                               }
+
+                               if(thedir_y == -1)
+                                       theang = M_PI;
+                               if(thedir_x == 1)
+                                       theang = M_PI/2;
+                               if(thedir_x == -1)
+                                       theang = M_PI*3/2;
+
+                               drawrotpic(tile_pos, theang, minigame_texture(thepiece),
+                                                       tile_size, tile_size/2, tile_color,
+                                                       panel_fg_alpha, DRAWFLAG_NORMAL );
+                       }
+                       else
+                       {
+                               minigame_drawpic_centered( tile_pos,  
+                                               minigame_texture(thepiece),
+                                               tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
+                       }
+               }
+       }
+
+       if ( (active_minigame.minigame_flags & SNAKE_TURN_LOSS) || (active_minigame.minigame_flags & SNAKE_TURN_WIN) || (active_minigame.snake_lives[minigame_self.team] <= 0) )
+       {
+               int scores = minigame_self.snake_score;
+
+               vector winfs = hud_fontsize*2;
+               string scores_text, victory_text;
+               victory_text = "Game over!";
+               scores_text = strcat("Score: ", ftos(scores));
+
+               if(active_minigame.minigame_flags & SNAKE_TURN_WIN)
+               if((active_minigame.minigame_flags & SNAKE_TURN_TEAM) == minigame_self.team)
+                       victory_text = "You win!";
+               if(active_minigame.snake_lives[minigame_self.team] <= 0)
+                       victory_text = "You ran out of lives!";
+               
+               vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
+               vector win_sz;
+               win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
+                       sprintf("%s %s", victory_text, scores_text), 
+                       winfs, 0, DRAWFLAG_NORMAL, 0.5);
+               
+               drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'0.3 0.3 1',0.8,DRAWFLAG_ADDITIVE);
+               
+               minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
+                       sprintf("%s %s", victory_text, scores_text), 
+                       winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
+       }
+}
+
+
+// Required function, draw the game status panel
+void snake_hud_status(vector pos, vector mySize)
+{
+       HUD_Panel_DrawBg(1);
+       vector ts;
+       ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
+               hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
+
+       pos_y += ts_y;
+       mySize_y -= ts_y;
+
+       vector player_fontsize = hud_fontsize * 1.75;
+       ts_y = ( mySize_y - 2*player_fontsize_y ) / SNAKE_TEAMS;
+       ts_x = mySize_x;
+       vector mypos;
+       vector tile_size = '48 48 0';
+
+       mypos = pos;
+       if ( minigame_self.team > 1 )
+               mypos_y  += player_fontsize_y + (ts_y * (minigame_self.team - 1));
+       drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE);
+       mypos_y += player_fontsize_y;
+       drawfill(mypos,eX*mySize_x+eY*tile_size_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE);
+
+       entity e;
+       FOREACH_MINIGAME_ENTITY(e)
+       {
+               if ( e.classname == "minigame_player" )
+               {
+                       mypos = pos;
+                       if ( e.team > 1 )
+                               mypos_y  += player_fontsize_y + (ts_y * (e.team - 1));
+                       minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
+                               GetPlayerName(e.minigame_playerslot-1),
+                               player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+                       vector tile_color = snake_teamcolor(e.team);
+
+                       mypos_y += player_fontsize_y;
+                       drawpic( mypos,
+                                       minigame_texture("snake/head"),
+                                       tile_size * 0.7, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL );
+
+                       mypos_x += tile_size_x;
+
+                       drawstring(mypos,ftos(e.snake_score),tile_size,
+                                          '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+                       mypos_x += tile_size_x;
+
+                       drawstring(mypos,strcat("1UP: ", ftos(active_minigame.snake_lives[e.team])),tile_size * 0.6,
+                                                        '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               }
+       }
+}
+
+// Turn a set of flags into a help message
+string snake_turn_to_string(int turnflags)
+{
+       if ( turnflags & SNAKE_TURN_LOSS )
+               return _("Game over!");
+
+       if ( turnflags & SNAKE_TURN_WIN )
+       {
+               if ( (turnflags&SNAKE_TURN_TEAM) != minigame_self.team )
+                       return _("You ran out of lives!");
+               return _("You win!");
+       }
+
+       if(active_minigame.snake_lives[minigame_self.team] <= 0)
+               return _("You ran out of lives!");
+       
+       if ( (snake_find_head(active_minigame, minigame_self.team)).snake_dir == '0 0 0' )
+               return _("Press an arrow key to begin the game");
+
+       if ( turnflags & SNAKE_TURN_MOVE )
+               if(snake_wrap)
+                       return _("Avoid the snake's body, collect the mice!");
+               else
+                       return _("Avoid the screen edges and the snake's body, collect the mice!");
+       
+       return "";
+}
+
+// Make the correct move
+void snake_set_direction(entity minigame, int dx, int dy)
+{
+       //if ( minigame.minigame_flags == SNAKE_TURN_MOVE )
+       //{
+               minigame_cmd("move ",ftos(dx), " ", ftos(dy));
+       //}
+}
+
+// Required function, handle client events
+int snake_client_event(entity minigame, string event, ...)
+{
+       switch(event)
+       {
+               case "activate":
+               {
+                       minigame.message = snake_turn_to_string(minigame.minigame_flags);
+                       return false;
+               }
+               case "key_pressed":
+               {
+                       //if((minigame.minigame_flags & SNAKE_TURN_TEAM) == minigame_self.team)
+                       {
+                               switch ( ...(0,int) )
+                               {
+                                       case K_RIGHTARROW:
+                                       case K_KP_RIGHTARROW:
+                                               snake_set_direction(minigame, 1, 0);
+                                               return true;
+                                       case K_LEFTARROW:
+                                       case K_KP_LEFTARROW:
+                                               snake_set_direction(minigame, -1, 0);
+                                               return true;
+                                       case K_UPARROW:
+                                       case K_KP_UPARROW:
+                                               snake_set_direction(minigame, 0, 1);
+                                               return true;
+                                       case K_DOWNARROW:
+                                       case K_KP_DOWNARROW:
+                                               snake_set_direction(minigame, 0, -1);
+                                               return true;
+                               }
+                       }
+
+                       return false;
+               }
+               case "network_receive":
+               {
+                       entity sent = ...(0,entity);
+                       int sf = ...(1,int);
+                       if ( sent.classname == "minigame" )
+                       {
+                               if ( sf & MINIG_SF_UPDATE )
+                               {
+                                       snake_wrap = ReadByte();
+                                       sent.message = snake_turn_to_string(sent.minigame_flags);
+                                       //if ( sent.minigame_flags & minigame_self.team )
+                                               minigame_prompt();
+                               }
+                       }
+                       else if(sent.classname == "minigame_board_piece")
+                       {
+                               if(sf & MINIG_SF_UPDATE)
+                               {
+                                       int letter = ReadByte();
+                                       int number = ReadByte();
+                                       if(sent.netname) { strunzone(sent.netname); }
+                                       sent.netname = strzone(minigame_tile_buildname(letter, number));
+
+                                       sent.cnt = ReadByte();
+                                       sent.snake_tail = ReadByte();
+
+                                       int dx = ReadByte();
+                                       int dy = ReadByte();
+
+                                       if(dx == 2) dx = -1;
+                                       if(dy == 2) dy = -1;
+
+                                       sent.snake_dir_x = dx;
+                                       sent.snake_dir_y = dy;
+                                       sent.snake_dir_z = 0;
+                               }
+                       }
+                       else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) )
+                       {
+                               sent.snake_score = ReadLong();
+                               minigame.snake_lives[sent.team] = ReadByte();
+                       }
+
+                       return false;
+               }
+       }
+
+       return false;
+}
+
+#endif
\ No newline at end of file
index 18a64e4264b39fd4317a8a64f3482f0e7d0aa160..8c5005ed259f301e924a19c781ec2080db2e064a 100644 (file)
@@ -1,3 +1,5 @@
+REGISTER_MINIGAME(ttt, "Tic Tac Toe");
+
 const int TTT_TURN_PLACE = 0x0100; // player has to place a piece on the board
 const int TTT_TURN_WIN   = 0x0200; // player has won
 const int TTT_TURN_DRAW  = 0x0400; // no moves are possible
@@ -35,29 +37,29 @@ bool ttt_winning_piece(entity piece)
 {
        int number = minigame_tile_number(piece.netname);
        int letter = minigame_tile_letter(piece.netname);
-       
+
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(0,number)).team == piece.team )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(1,number)).team == piece.team )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(2,number)).team == piece.team )
                return true;
-       
+
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(letter,0)).team == piece.team )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(letter,1)).team == piece.team )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(letter,2)).team == piece.team )
                return true;
-       
+
        if ( number == letter )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(0,0)).team == piece.team )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(1,1)).team == piece.team )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(2,2)).team == piece.team )
                return true;
-       
+
        if ( number == 2-letter )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(0,2)).team == piece.team )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(1,1)).team == piece.team )
        if ( ttt_find_piece(piece.owner,minigame_tile_buildname(2,0)).team == piece.team )
                return true;
-       
+
        return false;
 }
 
@@ -152,7 +154,7 @@ int ttt_server_event(entity minigame, string event, ...)
                case "join":
                {
                        int pl_num = minigame_count_players(minigame);
-                       
+
                        // Don't allow joining a single player match
                        if ( (minigame.ttt_ai) && pl_num > 0 )
                                return false;
@@ -171,8 +173,8 @@ int ttt_server_event(entity minigame, string event, ...)
                {
                        switch(argv(0))
                        {
-                               case "move": 
-                                       ttt_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null ); 
+                               case "move":
+                                       ttt_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
                                        return true;
                                case "next":
                                        ttt_next_match(minigame,...(0,entity));
@@ -203,7 +205,7 @@ int ttt_server_event(entity minigame, string event, ...)
                        return false;
                }
        }
-       
+
        return false;
 }
 
@@ -221,7 +223,7 @@ void ttt_hud_board(vector pos, vector mySize)
        minigame_hud_fitsqare(pos, mySize);
        ttt_boardpos = pos;
        ttt_boardsize = mySize;
-       
+
        minigame_hud_simpleboard(pos,mySize,minigame_texture("ttt/board"));
 
        vector tile_size = minigame_hud_denormalize_size('1 1 0'/TTT_TILE_SIZE,pos,mySize);
@@ -232,11 +234,11 @@ void ttt_hud_board(vector pos, vector mySize)
        {
                tile_pos = minigame_tile_pos(ttt_curr_pos,TTT_LET_CNT,TTT_NUM_CNT);
                tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-               minigame_drawpic_centered( tile_pos,  
+               minigame_drawpic_centered( tile_pos,
                                minigame_texture(strcat("ttt/piece",ftos(minigame_self.team))),
                                tile_size, '1 1 1', panel_fg_alpha/2, DRAWFLAG_NORMAL );
        }
-       
+
        entity e;
        FOREACH_MINIGAME_ENTITY(e)
        {
@@ -244,11 +246,11 @@ void ttt_hud_board(vector pos, vector mySize)
                {
                        tile_pos = minigame_tile_pos(e.netname,TTT_LET_CNT,TTT_NUM_CNT);
                        tile_pos = minigame_hud_denormalize(tile_pos,pos,mySize);
-                       
+
                        if ( active_minigame.minigame_flags & TTT_TURN_WIN )
                        if ( !e.ttt_checkwin )
                                e.ttt_checkwin = ttt_winning_piece(e) ? 1 : -1;
-                       
+
                        float icon_color = 1;
                        if ( e.ttt_checkwin == -1 )
                                icon_color = 0.4;
@@ -258,8 +260,8 @@ void ttt_hud_board(vector pos, vector mySize)
                                minigame_drawpic_centered( tile_pos, minigame_texture("ttt/winglow"),
                                                tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_ADDITIVE );
                        }
-                               
-                       minigame_drawpic_centered( tile_pos,  
+
+                       minigame_drawpic_centered( tile_pos,
                                        minigame_texture(strcat("ttt/piece",ftos(e.team))),
                                        tile_size, '1 1 1'*icon_color, panel_fg_alpha, DRAWFLAG_NORMAL );
                }
@@ -274,10 +276,10 @@ void ttt_hud_status(vector pos, vector mySize)
        vector ts;
        ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
                hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-       
+
        pos_y += ts_y;
        mySize_y -= ts_y;
-       
+
        vector player_fontsize = hud_fontsize * 1.75;
        ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
        ts_x = mySize_x;
@@ -295,14 +297,14 @@ void ttt_hud_status(vector pos, vector mySize)
                        minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
                                (e.minigame_playerslot ? GetPlayerName(e.minigame_playerslot-1) : _("AI")),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
-                       
+
                        mypos_y += player_fontsize_y;
-                       drawpic( mypos,  
+                       drawpic( mypos,
                                        minigame_texture(strcat("ttt/piece",ftos(e.team))),
                                        tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
-                       
+
                        mypos_x += tile_size_x;
-                       
+
                        drawstring(mypos,ftos(e.minigame_flags),tile_size,
                                           '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                }
@@ -314,27 +316,27 @@ string ttt_turn_to_string(int turnflags)
 {
        if ( turnflags & TTT_TURN_DRAW )
                return _("Draw");
-       
+
        if ( turnflags & TTT_TURN_WIN )
        {
                if ( (turnflags&TTT_TURN_TEAM) != minigame_self.team )
                        return _("You lost the game!\nSelect \"^1Next Match^7\" on the menu for a rematch!");
                return _("You win!\nSelect \"^1Next Match^7\" on the menu to start a new match!");
        }
-       
+
        if ( turnflags & TTT_TURN_NEXT )
        {
                if ( (turnflags&TTT_TURN_TEAM) != minigame_self.team )
                        return _("Select \"^1Next Match^7\" on the menu to start a new match!");
                return _("Wait for your opponent to confirm the rematch");
        }
-       
+
        if ( (turnflags & TTT_TURN_TEAM) != minigame_self.team )
                return _("Wait for your opponent to make their move");
-       
+
        if ( turnflags & TTT_TURN_PLACE )
                return _("Click on the game board to place your piece");
-       
+
        return "";
 }
 
@@ -359,21 +361,21 @@ string ttt_ai_piece_flag2pos(int pieceflag)
                        return "a2";
                case TTT_AI_POSFLAG_A3:
                        return "a3";
-                       
+
                case TTT_AI_POSFLAG_B1:
                        return "b1";
                case TTT_AI_POSFLAG_B2:
                        return "b2";
                case TTT_AI_POSFLAG_B3:
                        return "b3";
-                       
+
                case TTT_AI_POSFLAG_C1:
                        return "c1";
                case TTT_AI_POSFLAG_C2:
                        return "c2";
                case TTT_AI_POSFLAG_C3:
                        return "c3";
-                       
+
                default:
                        return string_null;
        }
@@ -389,13 +391,13 @@ int ttt_ai_1of3(int piecemask, int flag1, int flag2, int flag3)
 {
        if ( ttt_ai_checkmask(piecemask,flag1|flag2|flag3) )
                return 0;
-       
+
        if ( ttt_ai_checkmask(piecemask,flag1|flag2) )
                return flag3;
-       
+
        if ( ttt_ai_checkmask(piecemask,flag3|flag2) )
                return flag1;
-       
+
        if ( ttt_ai_checkmask(piecemask,flag3|flag1) )
                return flag2;
 
@@ -407,18 +409,18 @@ int ttt_ai_random(int piecemask)
 {
        if ( !piecemask )
                return 0;
-       
+
        int f = 1;
-       
+
        RandomSelection_Init();
-       
+
        for ( int i = 0; i < 9; i++ )
        {
                if ( piecemask & f )
                        RandomSelection_Add(world, f, string_null, 1, 1);
                f <<= 1;
        }
-       
+
        LOG_TRACE(sprintf("TTT AI: selected %x from %x\n",
                        RandomSelection_chosen_float, piecemask) );
        return RandomSelection_chosen_float;
@@ -428,7 +430,7 @@ int ttt_ai_random(int piecemask)
 int ttt_ai_block3 ( int piecemask, int piecemask_free )
 {
        int r = 0;
-       
+
        r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_A1,TTT_AI_POSFLAG_A2,TTT_AI_POSFLAG_A3);
        r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_B1,TTT_AI_POSFLAG_B2,TTT_AI_POSFLAG_B3);
        r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_C1,TTT_AI_POSFLAG_C2,TTT_AI_POSFLAG_C3);
@@ -449,15 +451,15 @@ int ttt_ai_block3 ( int piecemask, int piecemask_free )
 string ttt_ai_choose_simple(int piecemask_self, int piecemask_opponent, int piecemask_free )
 {
        int move = 0;
-       
+
        LOG_TRACE("TTT AI: checking winning move\n");
        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");
        if (( move = ttt_ai_block3(piecemask_opponent,piecemask_free) ))
                return ttt_ai_piece_flag2pos(move); // block opponent
-               
+
        LOG_TRACE("TTT AI: random move\n");
        return ttt_ai_piece_flag2pos(ttt_ai_random(piecemask_free));
 }
@@ -471,14 +473,14 @@ void ttt_aimove(entity minigame)
                while ( ( aiplayer = findentity(aiplayer,owner,minigame) ) )
                        if ( aiplayer.classname == "minigame_player" && !aiplayer.minigame_playerslot )
                                break;
-               
+
                /*
                 * Build bit masks for the board pieces
                 * .---.---.---.
                 * | 4 | 32|256| 3
-                * |---+---+---| 
+                * |---+---+---|
                 * | 2 | 16|128| 2
-                * |---+---+---| 
+                * |---+---+---|
                 * | 1 | 8 | 64| 1
                 * '---'---'---'
                 *   A   B   C
@@ -506,7 +508,7 @@ void ttt_aimove(entity minigame)
                                pieceflag <<= 1;
                        }
                }
-                       
+
                // TODO multiple AI difficulties
                LOG_TRACE(sprintf("TTT AI: self: %x opponent: %x free: %x\n",
                                piecemask_self, piecemask_opponent, piecemask_free));
@@ -631,13 +633,13 @@ int ttt_client_event(entity minigame, string event, ...)
                                        if ( sent.minigame_flags & minigame_self.team )
                                                minigame_prompt();
                                }
-                               
+
                                if ( (sf & TTT_SF_SINGLEPLAYER) )
                                {
                                        int ai = ReadByte();
                                        bool spawnai = ai && !sent.ttt_ai;
                                        sent.ttt_ai = ai;
-                                       
+
                                        if ( spawnai )
                                        {
                                                entity aiplayer = spawn();
@@ -648,7 +650,7 @@ int ttt_client_event(entity minigame, string event, ...)
                                                aiplayer.minigame_autoclean = 1;
                                                ttt_aimove(minigame);
                                        }
-                                       
+
                                }
                        }
                        else if ( sent.classname == "minigame_player" && (sf & TTT_SF_PLAYERSCORE ) )
index 61ab9a6ba40a361cf72c974c7ba043be8217714a..bc854952e7f9562dea72efdd50d91b15d81bc7b1 100644 (file)
@@ -2,10 +2,11 @@
 
 entity minigame_get_descriptor(string id)
 {
-       entity e;
-       for ( e = minigame_descriptors; e != world; e = e.list_next )
-               if ( e.netname == id )
-                       return e;
+       FOREACH(Minigames, true, LAMBDA(
+       {
+               if(it.netname == id)
+                       return it;
+       }));
        return world;
 }
 
@@ -17,7 +18,7 @@ int minigame_tile_letter(string id)
 
 // Get number index of a tile name
 // Note: this is 0 based, useful for mathematical operations
-// Note: Since the tile notation starts from the bottom left, 
+// Note: Since the tile notation starts from the bottom left,
 //     you may want to do number_of_rows - what_this_function_returns or something
 int minigame_tile_number(string id)
 {
@@ -27,7 +28,7 @@ int minigame_tile_number(string id)
 // Get relative position of the center of a given tile
 vector minigame_tile_pos(string id, int rows, int columns)
 {
-       return eX*(minigame_tile_letter(id)+0.5)/columns + 
+       return eX*(minigame_tile_letter(id)+0.5)/columns +
               eY - eY*(minigame_tile_number(id)+0.5)/rows;
 }
 
@@ -56,7 +57,7 @@ string minigame_tile_name(vector pos, int rows, int columns)
 {
        if ( pos_x < 0 || pos_x > 1 || pos_y < 0 || pos_y > 1 )
                return ""; // no tile
-               
+
        int letter = floor(pos_x * columns);
        int number = floor((1-pos_y) * rows);
        return minigame_tile_buildname(letter, number);
index 86fb778dcbc6f116da25b2610a66de9d82aa625d..7425149f389d9b484c38d089ebef97c2b750f6df 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef MINIGAMES_H
 #define MINIGAMES_H
 
-entity minigame_descriptors;
-
 // previous node in a doubly linked list
 .entity list_prev;
 // next node in a linked list
@@ -15,7 +13,7 @@ int minigame_tile_letter(string id);
 
 // Get number index of a tile name
 // Note: this is 0 based, useful for mathematical operations
-// Note: Since the tile notation starts from the bottom left, 
+// Note: Since the tile notation starts from the bottom left,
 //     you may want to do number_of_rows - what_this_function_returns or something
 int minigame_tile_number(string id);
 
@@ -88,7 +86,7 @@ int minigame_count_players(entity minigame);
 ///            IMPORTANT: always read in client everything you send from the server!
 ///    cmd(entity minigame_player, int argc, string command)
 ///            self = client entity triggering this
-///            argv(n) = console token 
+///            argv(n) = console token
 ///            argc: number of console tokens
 ///            command: full command string
 ///            triggered when a player does "cmd minigame ..." with some unrecognized command
index feb4b02944874bc692c0672b90881d6dee8094b9..56d0ece1a2a3c944812642e0c0f9dc889b276ab0 100644 (file)
@@ -15,7 +15,7 @@ void minigame_rmplayer(entity minigame_session, entity player)
 {
        entity e;
        entity p = minigame_session.minigame_players;
-       
+
        if ( p.minigame_players == player )
        {
                if ( p.list_next == world )
@@ -60,26 +60,26 @@ void minigame_rmplayer(entity minigame_session, entity player)
 
 // Send an entity to a client
 // only use on minigame entities or entities with a minigame owner
-bool minigame_SendEntity(entity to, int sf)
+bool minigame_SendEntity(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_MINIGAME);
        WriteByte(MSG_ENTITY, sf);
-       
+
        if ( sf & MINIG_SF_CREATE )
        {
                WriteShort(MSG_ENTITY,msle_id(self.classname));
                WriteString(MSG_ENTITY,self.netname);
        }
-       
+
        entity minigame_ent = self.owner;
-       
+
        if ( self.classname == "minigame" )
        {
                minigame_ent = self;
-               
+
                if ( sf & MINIG_SF_CREATE )
                        WriteString(MSG_ENTITY,self.descriptor.netname);
-               
+
                if ( sf & MINIG_SF_UPDATE )
                        WriteLong(MSG_ENTITY,self.minigame_flags);
        }
@@ -94,11 +94,11 @@ bool minigame_SendEntity(entity to, int sf)
                        WriteByte(MSG_ENTITY,self.team);
        }
        MINIGAME_SIMPLELINKED_ENTITIES
-       
+
        minigame_ent.minigame_event(minigame_ent,"network_send",self,sf);
-       
+
        return true;
-       
+
 }
 #undef FIELD
 #undef MSLE
@@ -115,7 +115,7 @@ void minigame_resend(entity minigame)
 }
 
 bool minigame_CheckSend()
-{
+{SELFPARAM();
        entity e;
        for ( e = self.owner.minigame_players; e != world; e = e.list_next )
                if ( e.minigame_players == other )
@@ -124,19 +124,18 @@ bool minigame_CheckSend()
 }
 
 int minigame_addplayer(entity minigame_session, entity player)
-{
+{SELFPARAM();
        if ( player.active_minigame )
        {
                if ( player.active_minigame == minigame_session )
                        return 0;
                minigame_rmplayer(player.active_minigame,player);
        }
-       
-       int mgteam = minigame_session.minigame_event(minigame_session,"join",player);
-       
+       entity player_pointer = spawn();
+       int mgteam = minigame_session.minigame_event(minigame_session,"join",player,player_pointer);
+
        if ( mgteam )
        {
-               entity player_pointer = spawn();
                player_pointer.classname = "minigame_player";
                player_pointer.owner = minigame_session;
                player_pointer.minigame_players = player;
@@ -150,19 +149,17 @@ int minigame_addplayer(entity minigame_session, entity player)
 
                if ( !IS_OBSERVER(player) && autocvar_sv_minigames_observer )
                {
-                       entity e = self;
-                       self = player;
-                       PutObserverInServer();
-                       self = e;
+                       WITH(entity, self, player, PutObserverInServer());
                }
                if ( autocvar_sv_minigames_observer == 2 )
                        player.team_forced = -1;
-               
+
                minigame_resend(minigame_session);
        }
+       else { remove(player_pointer); }
        GameLogEcho(strcat(":minigame:join",(mgteam?"":"fail"),":",minigame_session.netname,":",
                ftos(num_for_edict(player)),":",player.netname));
-       
+
        return mgteam;
 }
 
@@ -170,9 +167,9 @@ entity start_minigame(entity player, string minigame )
 {
        if ( !autocvar_sv_minigames || !IS_REAL_CLIENT(player) )
                return world;
-       
+
        entity e = minigame_get_descriptor(minigame);
-       if ( e ) 
+       if ( e )
        {
                entity minig = spawn();
                minig.classname = "minigame";
@@ -188,7 +185,7 @@ entity start_minigame(entity player, string minigame )
                        return world;
                }
                Net_LinkEntity(minig, false, 0, minigame_SendEntity);
-               
+
                if ( !minigame_sessions )
                        minigame_sessions = minig;
                else
@@ -199,7 +196,7 @@ entity start_minigame(entity player, string minigame )
                }
                return minig;
        }
-               
+
        return world;
 }
 
@@ -207,7 +204,7 @@ entity join_minigame(entity player, string game_id )
 {
        if ( !autocvar_sv_minigames || !IS_REAL_CLIENT(player) )
                return world;
-       
+
        entity minig;
        for ( minig = minigame_sessions; minig != world; minig = minig.list_next )
        {
@@ -215,14 +212,14 @@ entity join_minigame(entity player, string game_id )
                if ( minigame_addplayer(minig,player) )
                        return minig;
        }
-       
+
        return world;
 }
 
 void part_minigame(entity player )
 {
        entity minig = player.active_minigame;
-       
+
        if ( minig && minig.classname == "minigame" )
                minigame_rmplayer(minig,player);
 }
@@ -233,11 +230,11 @@ void end_minigame(entity minigame_session)
                minigame_session.owner.list_next = minigame_session.list_next;
        else
                minigame_sessions = minigame_session.list_next;
-       
+
        minigame_session.minigame_event(minigame_session,"end");
        GameLogEcho(strcat(":minigame:end:",minigame_session.netname));
-       
-       
+
+
        entity e = world;
        while( (e = findentity(e, owner, minigame_session)) )
                if ( e.minigame_autoclean )
@@ -245,7 +242,7 @@ void end_minigame(entity minigame_session)
                        LOG_TRACE("SV Auto-cleaned: ",ftos(num_for_edict(e)), " (",e.classname,")\n");
                        remove(e);
                }
-       
+
        entity p;
        for ( e = minigame_session.minigame_players; e != world; e = p )
        {
@@ -253,7 +250,7 @@ void end_minigame(entity minigame_session)
                player_clear_minigame(e.minigame_players);
                remove(e);
        }
-       
+
        strunzone(minigame_session.netname);
        remove(minigame_session);
 }
@@ -266,25 +263,6 @@ void end_minigames()
        }
 }
 
-void initialize_minigames()
-{
-       entity last_minig = world;
-       entity minig;
-       #define MINIGAME(name,nicename) \
-               minig = spawn(); \
-               minig.classname = "minigame_descriptor"; \
-               minig.netname = #name; \
-               minig.message = nicename; \
-               minig.minigame_event = name##_server_event; \
-               if ( !last_minig ) minigame_descriptors = minig; \
-               else last_minig.list_next = minig; \
-               last_minig = minig;
-               
-       REGISTERED_MINIGAMES
-       
-       #undef MINIGAME
-}
-
 string invite_minigame(entity inviter, entity player)
 {
        if ( !inviter || !inviter.active_minigame )
@@ -295,13 +273,13 @@ string invite_minigame(entity inviter, entity player)
                return "You can't invite yourself";
        if ( player.active_minigame == inviter.active_minigame )
                return strcat(player.netname," is already playing");
-       
-       Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_MINIGAME_INVITE, 
+
+       Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_MINIGAME_INVITE,
                inviter.active_minigame.netname, inviter.netname );
-       
+
        GameLogEcho(strcat(":minigame:invite:",inviter.active_minigame.netname,":",
                ftos(num_for_edict(player)),":",player.netname));
-       
+
        return "";
 }
 
@@ -317,7 +295,7 @@ entity minigame_find_player(entity client)
 }
 
 bool MinigameImpulse(int imp)
-{
+{SELFPARAM();
        entity e = minigame_find_player(self);
        if ( imp && self.active_minigame && e )
        {
@@ -329,13 +307,13 @@ bool MinigameImpulse(int imp)
 
 
 void ClientCommand_minigame(int request, int argc, string command)
-{
+{SELFPARAM();
        if ( !autocvar_sv_minigames )
        {
                sprint(self,"Minigames are not enabled!\n");
                return;
        }
-       
+
        if (request == CMD_REQUEST_COMMAND )
        {
                string minig_cmd = argv(1);
@@ -362,9 +340,10 @@ void ClientCommand_minigame(int request, int argc, string command)
                }
                else if ( minig_cmd == "list" )
                {
-                       entity e;
-                       for ( e = minigame_descriptors; e != world; e = e.list_next )
-                               sprint(self,e.netname," (",e.message,") ","\n");
+                       FOREACH(Minigames, true, LAMBDA(
+                       {
+                               sprint(self,it.netname," (",it.message,") ","\n");
+                       }));
                        return;
                }
                else if ( minig_cmd == "list-sessions" )
@@ -410,11 +389,11 @@ void ClientCommand_minigame(int request, int argc, string command)
                        int arg_c = tokenize_console(subcommand);
                        if ( self.active_minigame.minigame_event(self.active_minigame,"cmd",e,arg_c,subcommand) )
                                return;
-                               
+
                }
                else sprint(self,strcat("Wrong command:^1 ",command,"\n"));
        }
-       
+
        sprint(self, "\nUsage:^3 cmd minigame create <minigame>\n");
        sprint(self, "  Start a new minigame session\n");
        sprint(self, "Usage:^3 cmd minigame join <session>\n");
index 246440d39e5d0f84f03f06c0353033f03f5f4967..e36d690d9bc743247aabbc104a3f7971e6e24b5a 100644 (file)
@@ -1,9 +1,6 @@
 #ifndef SV_MINIGAMES_H
 #define SV_MINIGAMES_H
 
-/// Initialize the minigame system
-void initialize_minigames();
-
 /// Create a new minigame session
 /// \return minigame session entity
 entity start_minigame(entity player, string minigame );
@@ -47,6 +44,19 @@ entity minigame_find_player(entity client);
 
 entity minigame_sessions;
 
-bool minigame_SendEntity(entity to, int sf);
+bool minigame_SendEntity(entity this, entity to, int sf);
+
+REGISTRY(Minigames, BIT(3))
+REGISTER_REGISTRY(RegisterMinigames)
+#define REGISTER_MINIGAME(name,nicename) \
+    REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, spawn()); \
+    int name##_server_event(entity, string, ...); \
+    REGISTER_INIT_POST(MINIGAME, name) { \
+        this.classname = "minigame_descriptor"; \
+        this.netname = strzone(strtolower(#name)); \
+        this.message = nicename; \
+               this.minigame_event = name##_server_event; \
+    } \
+    REGISTER_INIT(MINIGAME, name)
 
 #endif
diff --git a/qcsrc/common/models/all.inc b/qcsrc/common/models/all.inc
new file mode 100644 (file)
index 0000000..f675d8a
--- /dev/null
@@ -0,0 +1,354 @@
+// Global list of models
+// TODO: remove uses of _setmodel
+
+string W_Model(string w_mdl);
+
+MODEL(CTF_SHIELD,                       "models/ctf/shield.md3");
+MODEL(CTF_CAPTURE,                      "models/ctf/shockwavetransring.md3");
+
+MODEL(DOM_NEUTRAL,                      "models/domination/dom_unclaimed.md3");
+MODEL(DOM_RED,                          "models/domination/dom_red.md3");
+MODEL(DOM_BLUE,                         "models/domination/dom_blue.md3");
+MODEL(DOM_YELLOW,                       "models/domination/dom_yellow.md3");
+MODEL(DOM_PINK,                         "models/domination/dom_pink.md3");
+
+MODEL(ICE,                              "models/ice/ice.md3");
+
+MODEL(KH_KEY,                           "models/keyhunt/key.md3");
+#ifdef KH_PLAYER_USE_CARRIEDMODEL
+MODEL(KH_KEY_CARRIED,                   "models/keyhunt/key-carried.md3");
+#endif
+
+MODEL(OK_HMG,                           W_Model("g_ok_hmg.md3"));
+
+MODEL(OK_RPC,                           W_Model("g_ok_rl.md3"));
+
+MODEL(OK_MG_VIEW,                       W_Model("h_ok_mg.iqm"));
+MODEL(OK_MG_WORLD,                      W_Model("v_ok_mg.md3"));
+MODEL(OK_MG_ITEM,                       W_Model("g_ok_mg.md3"));
+
+MODEL(OK_SHOTGUN_VIEW,                  W_Model("h_ok_shotgun.iqm"));
+MODEL(OK_SHOTGUN_WORLD,                 W_Model("v_ok_shotgun.md3"));
+MODEL(OK_SHOTGUN_ITEM,                  W_Model("g_ok_shotgun.md3"));
+
+MODEL(OK_SNIPER_VIEW,                   W_Model("h_ok_sniper.iqm"));
+MODEL(OK_SNIPER_WORLD,                  W_Model("v_ok_sniper.md3"));
+MODEL(OK_SNIPER_ITEM,                   W_Model("g_ok_sniper.md3"));
+
+MODEL(ONS_CP,                           "models/onslaught/controlpoint_icon.md3");
+MODEL(ONS_CP_SHIELD,                    "models/onslaught/controlpoint_shield.md3");
+MODEL(ONS_CP_PAD1,                      "models/onslaught/controlpoint_pad.md3");
+MODEL(ONS_CP_PAD2,                      "models/onslaught/controlpoint_pad2.md3");
+MODEL(ONS_CP1,                          "models/onslaught/controlpoint_icon_dmg1.md3");
+MODEL(ONS_CP1_GIB,                      "models/onslaught/controlpoint_icon_gib1.md3");
+MODEL(ONS_CP2,                          "models/onslaught/controlpoint_icon_dmg2.md3");
+MODEL(ONS_CP2_GIB,                      "models/onslaught/controlpoint_icon_gib2.md3");
+MODEL(ONS_CP3,                          "models/onslaught/controlpoint_icon_dmg3.md3");
+MODEL(ONS_CP3_GIB,                      "models/onslaught/controlpoint_icon_gib4.md3");
+MODEL(ONS_RAY,                          "models/onslaught/ons_ray.md3");
+MODEL(ONS_GEN,                          "models/onslaught/generator.md3");
+MODEL(ONS_GEN_SHIELD,                   "models/onslaught/generator_shield.md3");
+MODEL(ONS_GEN_GIB1,                     "models/onslaught/gen_gib1.md3");
+MODEL(ONS_GEN_GIB2,                     "models/onslaught/gen_gib2.md3");
+MODEL(ONS_GEN_GIB3,                     "models/onslaught/gen_gib3.md3");
+MODEL(ONS_GEN1,                         "models/onslaught/generator_dmg1.md3");
+MODEL(ONS_GEN2,                         "models/onslaught/generator_dmg2.md3");
+MODEL(ONS_GEN3,                         "models/onslaught/generator_dmg3.md3");
+MODEL(ONS_GEN4,                         "models/onslaught/generator_dmg4.md3");
+MODEL(ONS_GEN5,                         "models/onslaught/generator_dmg5.md3");
+MODEL(ONS_GEN6,                         "models/onslaught/generator_dmg6.md3");
+MODEL(ONS_GEN7,                         "models/onslaught/generator_dmg7.md3");
+MODEL(ONS_GEN8,                         "models/onslaught/generator_dmg8.md3");
+MODEL(ONS_GEN9,                         "models/onslaught/generator_dmg9.md3");
+MODEL(ONS_GEN_DEAD,                     "models/onslaught/generator_dead.md3");
+
+MODEL(PROJECTILE_ELECTRO,               "models/ebomb.mdl");
+MODEL(PROJECTILE_ELECTRO_BEAM,          "models/elaser.mdl");
+
+MODEL(PROJECTILE_ROCKET,                "models/rocket.md3");
+
+MODEL(PROJECTILE_CRYLINK,               "models/plasmatrail.mdl");
+MODEL(PROJECTILE_CRYLINK_BOUNCING,      "models/plasmatrail.mdl");
+
+MODEL(PROJECTILE_GRENADE,               "models/grenademodel.md3");
+MODEL(PROJECTILE_GRENADE_BOUNCING,      "models/grenademodel.md3");
+
+MODEL(PROJECTILE_MINE,                  "models/mine.md3");
+
+MODEL(PROJECTILE_BLASTER,               "models/laser.mdl");
+
+MODEL(PROJECTILE_HLAC,                  "models/hlac_bullet.md3");
+
+MODEL(PROJECTILE_PORTO_RED,             "models/grenademodel.md3");
+MODEL(PROJECTILE_PORTO_BLUE,            "models/grenademodel.md3");
+
+MODEL(PROJECTILE_HOOKBOMB,              "models/grenademodel.md3");
+
+MODEL(PROJECTILE_HAGAR,                 "models/hagarmissile.mdl");
+MODEL(PROJECTILE_HAGAR_BOUNCING,        "models/hagarmissile.mdl");
+
+// napalm grenade
+MODEL(PROJECTILE_NAPALM_FOUNTAIN,       "null");
+// fireball primary
+MODEL(PROJECTILE_FIREBALL,              "null");
+// fireball secondary
+MODEL(PROJECTILE_FIREMINE,              "null");
+
+MODEL(PROJECTILE_TAG,                   "models/laser.mdl");
+
+MODEL(PROJECTILE_FLAC,                  "models/hagarmissile.mdl");
+
+MODEL(PROJECTILE_SEEKER,                "models/tagrocket.md3");
+
+MODEL(PROJECTILE_MAGE_SPIKE,            "models/ebomb.mdl");
+MODEL(PROJECTILE_SHAMBLER_LIGHTNING,    "models/ebomb.mdl");
+
+MODEL(PROJECTILE_RAPTORBOMB,            "models/vehicles/clusterbomb.md3");
+MODEL(PROJECTILE_RAPTORBOMBLET,         "models/vehicles/bomblet.md3");
+MODEL(PROJECTILE_RAPTORCANNON,          "models/plasmatrail.mdl");
+
+MODEL(PROJECTILE_SPIDERROCKET,          "models/vehicles/rocket02.md3");
+
+MODEL(PROJECTILE_WAKIROCKET,            "models/vehicles/rocket01.md3");
+MODEL(PROJECTILE_WAKICANNON,            "models/laser.mdl");
+
+MODEL(PROJECTILE_BUMBLE_GUN,            "models/elaser.mdl");
+MODEL(PROJECTILE_BUMBLE_BEAM,           "models/elaser.mdl");
+
+MODEL(PROJECTILE_RPC,                   W_Model("ok_rocket.md3"));
+
+MODEL(PROJECTILE_ROCKETMINSTA_LASER,    "models/elaser.mdl");
+
+MODEL(PROJECTILE_NADE,                  W_Model("v_ok_grenade.md3"));
+MODEL(NADE_VIEW,                        W_Model("h_ok_grenade.iqm"));
+MODEL(NADE_TIMER,                       "models/ok_nade_counter/ok_nade_counter.md3");
+MODEL(NADE_HEAL,                        "models/ctf/shield.md3");
+
+MODEL(GIB_CHUNK,                        "models/gibs/chunk.mdl");
+MODEL(GIB_LEG1,                         "models/gibs/leg1.md3");
+MODEL(GIB_LEG2,                         "models/gibs/leg2.md3");
+MODEL(GIB_CHEST,                        "models/gibs/chest.md3");
+MODEL(GIB_SMALLCHEST,                   "models/gibs/smallchest.md3");
+MODEL(GIB_ARM,                          "models/gibs/arm.md3");
+MODEL(GIB_BLOODYSKULL,                  "models/gibs/bloodyskull.md3");
+MODEL(GIB_EYE,                          "models/gibs/eye.md3");
+
+MODEL(GIB_ROBO,                         "models/gibs/robo.md3");
+MODEL(GIB_ROBO_1,                       "models/gibs/robo1.md3");
+MODEL(GIB_ROBO_2,                       "models/gibs/robo2.md3");
+MODEL(GIB_ROBO_3,                       "models/gibs/robo3.md3");
+MODEL(GIB_ROBO_4,                       "models/gibs/robo4.md3");
+MODEL(GIB_ROBO_5,                       "models/gibs/robo5.md3");
+MODEL(GIB_ROBO_6,                       "models/gibs/robo6.md3");
+MODEL(GIB_ROBO_7,                       "models/gibs/robo7.md3");
+MODEL(GIB_ROBO_8,                       "models/gibs/robo8.md3");
+Model MDL_GIB_ROBO_RANDOM() {
+    int i = floor(random() * 8);
+    return Models[MDL_GIB_ROBO_1.m_id + i];
+}
+
+MODEL(CASING_SHELL,                     "models/casing_shell.mdl");
+MODEL(CASING_BULLET,                    "models/casing_bronze.iqm");
+
+MODEL(BUFF,                             "models/relics/relic.md3");
+
+MODEL(BLASTER_VIEW,                     W_Model("h_laser.iqm"));
+MODEL(BLASTER_WORLD,                    W_Model("v_laser.md3"));
+MODEL(BLASTER_ITEM,                     W_Model("g_laser.md3"));
+
+MODEL(SHOTGUN_MUZZLEFLASH,              "models/uziflash.md3");
+MODEL(SHOTGUN_VIEW,                     W_Model("h_shotgun.iqm"));
+MODEL(SHOTGUN_WORLD,                    W_Model("v_shotgun.md3"));
+MODEL(SHOTGUN_ITEM,                     W_Model("g_shotgun.md3"));
+
+MODEL(MACHINEGUN_MUZZLEFLASH,           "models/uziflash.md3");
+MODEL(MACHINEGUN_VIEW,                  W_Model("h_uzi.iqm"));
+MODEL(MACHINEGUN_WORLD,                 W_Model("v_uzi.md3"));
+MODEL(MACHINEGUN_ITEM,                  W_Model("g_uzi.md3"));
+
+MODEL(MORTAR_VIEW,                      W_Model("h_gl.iqm"));
+MODEL(MORTAR_WORLD,                     W_Model("v_gl.md3"));
+MODEL(MORTAR_ITEM,                      W_Model("g_gl.md3"));
+
+MODEL(MINELAYER_MUZZLEFLASH,            "models/flash.md3");
+MODEL(MINELAYER_MINE,                   "models/mine.md3");
+MODEL(MINELAYER_VIEW,                   W_Model("h_minelayer.iqm"));
+MODEL(MINELAYER_WORLD,                  W_Model("v_minelayer.md3"));
+MODEL(MINELAYER_ITEM,                   W_Model("g_minelayer.md3"));
+
+MODEL(ELECTRO_VIEW,                     W_Model("h_electro.iqm"));
+MODEL(ELECTRO_WORLD,                    W_Model("v_electro.md3"));
+MODEL(ELECTRO_ITEM,                     W_Model("g_electro.md3"));
+
+MODEL(CRYLINK_VIEW,                     W_Model("h_crylink.iqm"));
+MODEL(CRYLINK_WORLD,                    W_Model("v_crylink.md3"));
+MODEL(CRYLINK_ITEM,                     W_Model("g_crylink.md3"));
+
+MODEL(VORTEX_MUZZLEFLASH,               "models/nexflash.md3");
+MODEL(VORTEX_VIEW,                      W_Model("h_nex.iqm"));
+MODEL(VORTEX_WORLD,                     W_Model("v_nex.md3"));
+MODEL(VORTEX_ITEM,                      W_Model("g_nex.md3"));
+
+MODEL(HAGAR_VIEW,                       W_Model("h_hagar.iqm"));
+MODEL(HAGAR_WORLD,                      W_Model("v_hagar.md3"));
+MODEL(HAGAR_ITEM,                       W_Model("g_hagar.md3"));
+
+MODEL(DEVASTATOR_MUZZLEFLASH,           "models/flash.md3");
+MODEL(DEVASTATOR_VIEW,                  W_Model("h_rl.iqm"));
+MODEL(DEVASTATOR_WORLD,                 W_Model("v_rl.md3"));
+MODEL(DEVASTATOR_ITEM,                  W_Model("g_rl.md3"));
+
+MODEL(PORTAL,                           "models/portal.md3");
+MODEL(PORTO_VIEW,                       W_Model("h_porto.iqm"));
+MODEL(PORTO_WORLD,                      W_Model("v_porto.md3"));
+MODEL(PORTO_ITEM,                       W_Model("g_porto.md3"));
+
+MODEL(VAPORIZER_MUZZLEFLASH,            "models/nexflash.md3");
+MODEL(VAPORIZER_VIEW,                   W_Model("h_minstanex.iqm"));
+MODEL(VAPORIZER_WORLD,                  W_Model("v_minstanex.md3"));
+MODEL(VAPORIZER_ITEM,                   W_Model("g_minstanex.md3"));
+
+MODEL(HOOK,                             "models/hook.md3");
+MODEL(HOOK_VIEW,                        W_Model("h_hookgun.iqm"));
+MODEL(HOOK_WORLD,                       W_Model("v_hookgun.md3"));
+MODEL(HOOK_ITEM,                        W_Model("g_hookgun.md3"));
+
+MODEL(HLAC_VIEW,                        W_Model("h_hlac.iqm"));
+MODEL(HLAC_WORLD,                       W_Model("v_hlac.md3"));
+MODEL(HLAC_ITEM,                        W_Model("g_hlac.md3"));
+
+MODEL(TUBA_VIEW,                        W_Model("h_tuba.iqm"));
+MODEL(TUBA_WORLD,                       W_Model("v_tuba.md3"));
+MODEL(TUBA_ITEM,                        W_Model("g_tuba.md3"));
+MODEL(ACCORDION_VIEW,                   W_Model("h_akordeon.iqm"));
+MODEL(ACCORDION_WORLD,                  W_Model("v_akordeon.md3"));
+MODEL(KLEINBOTTLE_VIEW,                 W_Model("h_kleinbottle.iqm"));
+MODEL(KLEINBOTTLE_WORLD,                W_Model("v_kleinbottle.md3"));
+
+MODEL(RIFLE_VIEW,                       W_Model("h_campingrifle.iqm"));
+MODEL(RIFLE_WORLD,                      W_Model("v_campingrifle.md3"));
+MODEL(RIFLE_ITEM,                       W_Model("g_campingrifle.md3"));
+
+MODEL(FIREBALL_SPHERE,                  "models/sphere/sphere.md3");
+MODEL(FIREBALL_VIEW,                    W_Model("h_fireball.iqm"));
+MODEL(FIREBALL_WORLD,                   W_Model("v_fireball.md3"));
+MODEL(FIREBALL_ITEM,                    W_Model("g_fireball.md3"));
+
+MODEL(SEEKER_VIEW,                      W_Model("h_seeker.iqm"));
+MODEL(SEEKER_WORLD,                     W_Model("v_seeker.md3"));
+MODEL(SEEKER_ITEM,                      W_Model("g_seeker.md3"));
+
+MODEL(SHOCKWAVE_MUZZLEFLASH,            "models/uziflash.md3");
+MODEL(SHOCKWAVE_VIEW,                   W_Model("h_shotgun.iqm"));
+MODEL(SHOCKWAVE_WORLD,                  W_Model("v_shotgun.md3"));
+MODEL(SHOCKWAVE_ITEM,                   W_Model("g_shotgun.md3"));
+
+MODEL(ARC_MUZZLEFLASH,                  "models/flash.md3");
+MODEL(ARC_VIEW,                         W_Model("h_arc.iqm"));
+MODEL(ARC_WORLD,                        W_Model("v_arc.md3"));
+MODEL(ARC_ITEM,                         W_Model("g_arc.md3"));
+
+MODEL(HMG_MUZZLEFLASH,                  "models/uziflash.md3");
+MODEL(HMG_VIEW,                         W_Model("h_ok_hmg.iqm"));
+MODEL(HMG_WORLD,                        W_Model("v_ok_hmg.md3"));
+MODEL(HMG_ITEM,                         W_Model("g_ok_hmg.md3"));
+
+MODEL(RPC_MUZZLEFLASH,                  "models/flash.md3");
+MODEL(RPC_VIEW,                         W_Model("h_ok_rl.iqm"));
+MODEL(RPC_WORLD,                        W_Model("v_ok_rl.md3"));
+MODEL(RPC_ITEM,                         W_Model("g_ok_rl.md3"));
+
+MODEL(TUR_GIB_BASE1,                    "models/turrets/base-gib1.md3");
+MODEL(TUR_GIB_BASE2,                    "models/turrets/base-gib2.md3");
+MODEL(TUR_GIB_BASE3,                    "models/turrets/base-gib3.md3");
+MODEL(TUR_GIB_BASE4,                    "models/turrets/base-gib4.md3");
+MODEL(TUR_GIB_HEAD1,                    "models/turrets/head-gib1.md3");
+MODEL(TUR_GIB_HEAD2,                    "models/turrets/head-gib2.md3");
+MODEL(TUR_GIB_HEAD3,                    "models/turrets/head-gib3.md3");
+MODEL(TUR_GIB_HEAD4,                    "models/turrets/head-gib4.md3");
+MODEL(TUR_BASE,                         "models/turrets/base.md3");
+
+MODEL(TUR_EWHEEL_BASE,                  "models/turrets/ewheel-base2.md3");
+MODEL(TUR_EWHEEL_HEAD,                  "models/turrets/ewheel-gun1.md3");
+
+MODEL(TUR_FLAC_BASE,                    "models/turrets/base.md3");
+MODEL(TUR_FLAC_HEAD,                    "models/turrets/flac.md3");
+
+MODEL(TUR_FUSIONREACTOR_BASE,           "models/turrets/base.md3");
+MODEL(TUR_FUSIONREACTOR_HEAD,           "models/turrets/reactor.md3");
+
+MODEL(TUR_HELLION_BASE,                 "models/turrets/base.md3");
+MODEL(TUR_HELLION_HEAD,                 "models/turrets/hellion.md3");
+
+MODEL(TUR_HK_BASE,                      "models/turrets/base.md3");
+MODEL(TUR_HK_HEAD,                      "models/turrets/hk.md3");
+
+MODEL(TUR_MACHINEGUN_BASE,              "models/turrets/base.md3");
+MODEL(TUR_MACHINEGUN_HEAD,              "models/turrets/machinegun.md3");
+
+MODEL(TUR_MIRS_BASE,                    "models/turrets/base.md3");
+MODEL(TUR_MIRS_HEAD,                    "models/turrets/mlrs.md3");
+
+MODEL(TUR_PHASER_BASE,                  "models/turrets/base.md3");
+MODEL(TUR_PHASER_BEAM,                  "models/turrets/phaser_beam.md3");
+MODEL(TUR_PHASER_HEAD,                  "models/turrets/phaser.md3");
+
+MODEL(TUR_PLASMA_BASE,                  "models/turrets/base.md3");
+MODEL(TUR_PLASMA_HEAD,                  "models/turrets/plasma.md3");
+
+MODEL(TUR_PLASMA_DUAL_BASE,             "models/turrets/base.md3");
+MODEL(TUR_PLASMA_DUAL_HEAD,             "models/turrets/plasmad.md3");
+
+MODEL(TUR_TESLA_BASE,                   "models/turrets/tesla_base.md3");
+MODEL(TUR_TESLA_HEAD,                   "models/turrets/tesla_head.md3");
+
+MODEL(TUR_WALKER_BASE,                  "models/turrets/walker_body.md3");
+MODEL(TUR_WALKER_HEAD,                  "models/turrets/walker_head_minigun.md3");
+
+MODEL(VEH_SHIELD,                       "models/vhshield.md3");
+
+MODEL(VEH_BUMBLEBEE_BODY,               "models/vehicles/bumblebee_body.dpm");
+MODEL(VEH_BUMBLEBEE_CANNON_CENTER,      "models/vehicles/bumblebee_ray.dpm");
+MODEL(VEH_BUMBLEBEE_CANNON_LEFT,        "models/vehicles/bumblebee_plasma_left.dpm");
+MODEL(VEH_BUMBLEBEE_CANNON_RIGHT,       "models/vehicles/bumblebee_plasma_right.dpm");
+MODEL(VEH_BUMBLEBEE_SHIELD,             "models/vhshield.md3");
+
+MODEL(VEH_RACER_BODY,                   "models/vehicles/wakizashi.dpm");
+MODEL(VEH_RACER_VIEW,                   "models/vehicles/wakizashi_cockpit.dpm");
+
+MODEL(VEH_RAPTOR_BODY,                  "models/vehicles/raptor.dpm");
+MODEL(VEH_RAPTOR_CB_FOLDED,             "models/vehicles/clusterbomb_folded.md3");
+MODEL(VEH_RAPTOR_CB_FRAGMENT,           "models/vehicles/clusterbomb_fragment.md3");
+MODEL(VEH_RAPTOR_FLARE,                 "models/runematch/rune.mdl");
+MODEL(VEH_RAPTOR_GUN,                   "models/vehicles/raptor_gun.dpm");
+MODEL(VEH_RAPTOR_PROP,                  "models/vehicles/spinner.dpm");
+MODEL(VEH_RAPTOR_TAIL,                  "models/vehicles/raptor_body.dpm");
+MODEL(VEH_RAPTOR_VIEW,                  "models/vehicles/raptor_cockpit.dpm");
+
+MODEL(VEH_SPIDERBOT_BODY,               "models/vehicles/spiderbot.dpm");
+MODEL(VEH_SPIDERBOT_GUN,                "models/vehicles/spiderbot_barrels.dpm");
+MODEL(VEH_SPIDERBOT_MUZZLEFLASH,        "models/uziflash.md3");
+MODEL(VEH_SPIDERBOT_TOP,                "models/vehicles/spiderbot_top.dpm");
+MODEL(VEH_SPIDERBOT_VIEW,               "models/vehicles/spiderbot_cockpit.dpm");
+
+MODEL(CHAT,                             "models/misc/chatbubble.spr");
+
+MODEL(0,                                "models/sprites/0.spr32");
+MODEL(1,                                "models/sprites/1.spr32");
+MODEL(2,                                "models/sprites/2.spr32");
+MODEL(3,                                "models/sprites/3.spr32");
+MODEL(4,                                "models/sprites/4.spr32");
+MODEL(5,                                "models/sprites/5.spr32");
+MODEL(6,                                "models/sprites/6.spr32");
+MODEL(7,                                "models/sprites/7.spr32");
+MODEL(8,                                "models/sprites/8.spr32");
+MODEL(9,                                "models/sprites/9.spr32");
+MODEL(10,                               "models/sprites/10.spr32");
+Model MDL_NUM(int i) {
+    if ((i >= 0 && i <= 10))
+        return Models[MDL_0.m_id + i];
+    return MDL_Null;
+}
+
+MODEL(WAYPOINT,                         "models/runematch/rune.mdl");
+MODEL(MARKER,                           "models/marker.md3");
diff --git a/qcsrc/common/models/all.qh b/qcsrc/common/models/all.qh
new file mode 100644 (file)
index 0000000..38c5334
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef MODELS_ALL_H
+#define MODELS_ALL_H
+
+#define setmodel(e, m) _setmodel((e), (m).model_str())
+
+REGISTRY(Models, BIT(9))
+REGISTER_REGISTRY(RegisterModels)
+
+CLASS(Model, Object)
+    ATTRIB(Model, m_id, int, 0)
+    ATTRIB(Model, model_str, string(), func_null)
+    CONSTRUCTOR(Model, string() path)
+    {
+        CONSTRUCT(Model);
+        this.model_str = path;
+    }
+    METHOD(Model, model_precache, void(entity this)) {
+        string s = this.model_str();
+        if (s != "" && s != "null" && !fexists(s)) {
+            LOG_WARNINGF("Missing model: \"%s\"\n", s);
+            return;
+        }
+        LOG_TRACEF("precache_model(\"%s\")\n", s);
+        precache_model(s);
+    }
+ENDCLASS(Model)
+
+#define MODEL(name, path) \
+    string MDL_##name##_get() { return path; } \
+    REGISTER(RegisterModels, MDL, Models, name, m_id, NEW(Model, MDL_##name##_get))
+
+STATIC_INIT(RegisterModels_precache) {
+    FOREACH(Models, true, LAMBDA({
+        it.model_precache(it);
+    }));
+}
+
+MODEL(Null, "null");
+#include "all.inc"
+
+#endif
index e17a90a7cb1469818166a4f4ef5dac1ce69b3f92..f4b2a4bf0bbb5ac7892ccc1f3ec60497bbbf8503 100644 (file)
@@ -1,27 +1,10 @@
 #ifndef MONSTERS_ALL_C
 #define MONSTERS_ALL_C
-#include "all.qh"
 
-REGISTER_MONSTER(Null, Monster) {
-       this.netname = "";
-       this.monster_name = "Monster";
-       this.monster_func = m_null;
-       this.mdl = "";
-       this.mins = '-0 -0 -0';
-       this.maxs = '0 0 0';
-       this.model = "";
-}
+#include "all.qh"
 
+#define IMPLEMENTATION
 #include "all.inc"
-
-entity get_monsterinfo(int id)
-{
-       if (id >= MON_FIRST && id <= MON_LAST)
-       {
-               entity m = monster_info[id];
-               if (m) return m;
-       }
-       return MON_Null;
-}
+#undef IMPLEMENTATION
 
 #endif
index 20a2103785f0bffb5b6a14cfe347eac076cc1b6a..39a928a85749b98f4299e728d583f9d6e4aaa47c 100644 (file)
@@ -1,71 +1,26 @@
 #ifndef MONSTERS_ALL_H
 #define MONSTERS_ALL_H
 
-void RegisterMonsters();
-const int MON_MAXCOUNT = 24;
-entity monster_info[MON_MAXCOUNT], monster_info_first, monster_info_last;
-entity get_monsterinfo(float id);
-int MON_COUNT;
-const int MON_FIRST = 1;
-#define MON_LAST (MON_FIRST + MON_COUNT - 1)
-/** If you register a new monster, make sure to add it to all.inc */
-#define REGISTER_MONSTER(id, class) REGISTER(RegisterMonsters, MON, monster_info, MON_COUNT, id, monsterid, NEW(class))
 #include "monster.qh"
-#define REGISTER_MONSTER_SIMPLE(id, monsterflags, min_s, max_s, modelname, shortname, mname) \
-    REGISTER_MONSTER(id, Monster) {                                     \
-        this.netname = shortname;                                       \
-        this.monster_name = mname;                                      \
-        this.mdl = modelname;                                           \
-        this.spawnflags = monsterflags;                                 \
-        this.mins = min_s;                                              \
-        this.maxs = max_s;                                              \
-        this.model = strzone(strcat("models/monsters/", modelname));    \
-    }                                                                   \
-    REGISTER_INIT(MON, id)
-REGISTER_REGISTRY(RegisterMonsters)
-
-#include "../util.qh"
 
-// monster requests
-const int MR_SETUP = 1; // (SERVER) setup monster data
-const int MR_THINK = 2; // (SERVER) logic to run every frame
-const int MR_DEATH = 3; // (SERVER) called when monster dies
-const int MR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this monster
-const int MR_PAIN = 5; // (SERVER) called when monster is damaged
-const int MR_ANIM = 6; // (BOTH?) sets animations for monster
-
-// special spawn flags
-const int MONSTER_RESPAWN_DEATHPOINT = 16; // re-spawn where we died
-const int MONSTER_TYPE_FLY = 32;
-const int MONSTER_TYPE_SWIM = 64;
-const int MONSTER_SIZE_BROKEN = 128; // TODO: remove when bad models are replaced
-const int MON_FLAG_SUPERMONSTER = 256; // incredibly powerful monster
-const int MON_FLAG_RANGED = 512; // monster shoots projectiles
-const int MON_FLAG_MELEE = 1024;
-const int MON_FLAG_CRUSH = 2048; // monster can be stomped in special modes
-const int MON_FLAG_RIDE = 4096; // monster can be ridden in special modes
+REGISTRY(Monsters, BIT(3))
+REGISTER_REGISTRY(RegisterMonsters)
+const int MON_FIRST = 1;
+#define MON_LAST (Monsters_COUNT - 1)
+/** If you register a new monster, make sure to add it to all.inc */
+#define REGISTER_MONSTER(id, inst) REGISTER(RegisterMonsters, MON, Monsters, id, monsterid, inst)
 
-// entity properties of monsterinfo:
-.string netname; // short name
-.string mdl; // currently a copy of the model
-.string model; // full name of model
-.int spawnflags;
-.vector mins, maxs; // monster hitbox size
-.bool(int) monster_attackfunc;
+REGISTER_MONSTER(Null, NEW(Monster));
 
-// animations
-.vector anim_blockend;
-.vector anim_blockstart;
-.vector anim_melee1;
-.vector anim_melee2;
-.vector anim_melee3;
-.vector anim_pain3;
-.vector anim_pain4;
-.vector anim_pain5;
-.vector anim_walk;
-.vector anim_spawn;
+Monster get_monsterinfo(int id)
+{
+       if (id >= MON_FIRST && id <= MON_LAST) {
+               Monster m = Monsters[id];
+               if (m) return m;
+       }
+       return MON_Null;
+}
 
-// other useful macros
-#define MON_ACTION(monstertype,mrequest) (get_monsterinfo(monstertype)).monster_func(mrequest)
+#include "all.inc"
 
 #endif
index 79077acc3c111a3988b608ba53c460e920cc40b0..0a78b7772292bbb884b9fce938b6a5b384375c0c 100644 (file)
@@ -1,15 +1,61 @@
 #ifndef MONSTER_H
 #define MONSTER_H
 
-bool m_null(int) { return false; }
+// special spawn flags
+const int MONSTER_RESPAWN_DEATHPOINT = 16; // re-spawn where we died
+const int MONSTER_TYPE_FLY = 32;
+const int MONSTER_TYPE_SWIM = 64;
+const int MONSTER_SIZE_BROKEN = 128; // TODO: remove when bad models are replaced
+const int MON_FLAG_SUPERMONSTER = 256; // incredibly powerful monster
+const int MON_FLAG_RANGED = 512; // monster shoots projectiles
+const int MON_FLAG_MELEE = 1024;
+const int MON_FLAG_CRUSH = 2048; // monster can be stomped in special modes
+const int MON_FLAG_RIDE = 4096; // monster can be ridden in special modes
+
+// entity properties of monsterinfo:
+.bool(int, entity targ) monster_attackfunc;
+
+// animations
+.vector anim_blockend;
+.vector anim_blockstart;
+.vector anim_melee1;
+.vector anim_melee2;
+.vector anim_melee3;
+.vector anim_pain3;
+.vector anim_pain4;
+.vector anim_pain5;
+.vector anim_walk;
+.vector anim_spawn;
 
 /** If you register a new monster, make sure to add it to all.inc */
 CLASS(Monster, Object)
     ATTRIB(Monster, monsterid, int, 0)
-    ATTRIB(Monster, classname, string, "monster_info")
+    /** attributes */
+    ATTRIB(Monster, spawnflags, int, 0)
     /** human readable name */
-    ATTRIB(Monster, monster_name, string, string_null)
-    ATTRIB(Monster, monster_func, bool(int), m_null)
+    ATTRIB(Monster, monster_name, string, "Monster")
+    /** short name */
+    ATTRIB(Monster, netname, string, "")
+    /** model */
+    ATTRIB(Monster, m_model, entity, NULL)
+    /** hitbox size */
+    ATTRIB(Monster, mins, vector, '-0 -0 -0')
+    /** hitbox size */
+    ATTRIB(Monster, maxs, vector, '0 0 0')
+    
+    /** (SERVER) setup monster data */
+    METHOD(Monster, mr_setup, bool(Monster this)) { return false; }
+    /** (SERVER) logic to run every frame */
+    METHOD(Monster, mr_think, bool(Monster this)) { return false; }
+    /** (SERVER) called when monster dies */
+    METHOD(Monster, mr_death, bool(Monster this)) { return false; }
+    /** (BOTH) precaches models/sounds used by this monster */
+    METHOD(Monster, mr_precache, bool(Monster this)) { return false; }
+    /** (SERVER) called when monster is damaged */
+    METHOD(Monster, mr_pain, bool(Monster this)) { return false; }
+    /** (BOTH?) sets animations for monster */
+    METHOD(Monster, mr_anim, bool(Monster this)) { return false; }
+
 ENDCLASS(Monster)
 
 #endif
index 8f92d693a6e614fbf2422f36722a8484b84d9b06..9952063f60133e5fe4845ffd5f76e66ae7065d30 100644 (file)
@@ -1,21 +1,75 @@
+#ifndef MAGE_H
+#define MAGE_H
+
 #ifndef MENUQC
-bool M_Mage(int);
+MODEL(MON_MAGE, "models/monsters/mage.dpm");
 #endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id   */ MAGE,
-/* spawnflags */ MON_FLAG_MELEE | MON_FLAG_RANGED,
-/* mins,maxs  */ '-36 -36 -24', '36 36 50',
-/* model      */ "mage.dpm",
-/* netname    */ "mage",
-/* fullname   */ _("Mage")
-) {
+
+CLASS(Mage, Monster)
+    ATTRIB(Mage, spawnflags, int, MON_FLAG_MELEE | MON_FLAG_RANGED);
+    ATTRIB(Mage, mins, vector, '-36 -36 -24');
+    ATTRIB(Mage, maxs, vector, '36 36 50');
+#ifndef MENUQC
+    ATTRIB(Mage, m_model, Model, MDL_MON_MAGE);
+#endif
+    ATTRIB(Mage, netname, string, "mage");
+    ATTRIB(Mage, monster_name, string, _("Mage"));
+ENDCLASS(Mage)
+
+REGISTER_MONSTER(MAGE, NEW(Mage)) {
 #ifndef MENUQC
-    this.monster_func = M_Mage;
-    this.monster_func(MR_PRECACHE);
+    this.mr_precache(this);
 #endif
 }
 
+#include "../../weapons/all.qh"
+
+CLASS(MageSpike, PortoLaunch)
+/* flags     */ ATTRIB(MageSpike, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(MageSpike, impulse, int, 9);
+/* refname   */ ATTRIB(MageSpike, netname, string, "magespike");
+/* wepname   */ ATTRIB(MageSpike, message, string, _("Mage spike"));
+ENDCLASS(MageSpike)
+REGISTER_WEAPON(MAGE_SPIKE, NEW(MageSpike));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
 #ifdef SVQC
+
+void M_Mage_Attack_Spike(vector dir);
+void M_Mage_Attack_Push();
+METHOD(MageSpike, wr_think, void(MageSpike thiswep, entity actor, bool fire1, bool fire2)) {
+    if (fire1)
+    if (!IS_PLAYER(actor) || weapon_prepareattack(thiswep, actor, 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, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+       if (!IS_PLAYER(actor)) w_shotdir = normalize((actor.enemy.origin + '0 0 10') - actor.origin);
+        M_Mage_Attack_Spike(w_shotdir);
+        weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+    }
+    if (fire2)
+    if (!IS_PLAYER(actor) || weapon_prepareattack(thiswep, actor, true, 0.5)) {
+        M_Mage_Attack_Push();
+        weapon_thinkf(actor, WFRAME_FIRE2, 0, w_ready);
+    }
+}
+
+void M_Mage_Attack_Teleport();
+
+CLASS(OffhandMageTeleport, OffhandWeapon)
+    .bool OffhandMageTeleport_key_pressed;
+    METHOD(OffhandMageTeleport, offhand_think, void(OffhandMageTeleport this, entity player, bool key_pressed))
+    {
+        if (key_pressed && !player.OffhandMageTeleport_key_pressed)
+            WITH(entity, self, player, M_Mage_Attack_Teleport());
+        player.OffhandMageTeleport_key_pressed = key_pressed;
+    }
+ENDCLASS(OffhandMageTeleport)
+OffhandMageTeleport OFFHAND_MAGE_TELEPORT; STATIC_INIT(OFFHAND_MAGE_TELEPORT) { OFFHAND_MAGE_TELEPORT = NEW(OffhandMageTeleport); }
+
 float autocvar_g_monster_mage_health;
 float autocvar_g_monster_mage_damageforcescale = 0.5;
 float autocvar_g_monster_mage_attack_spike_damage;
@@ -62,7 +116,7 @@ void() M_Mage_Defend_Shield;
 .float mage_shield_time;
 
 float M_Mage_Defend_Heal_Check(entity e)
-{
+{SELFPARAM();
        if(e == world)
                return false;
        if(e.health <= 0)
@@ -88,10 +142,10 @@ float M_Mage_Defend_Heal_Check(entity e)
 }
 
 void M_Mage_Attack_Spike_Explode()
-{
+{SELFPARAM();
        self.event_damage = func_null;
 
-       sound(self, CH_SHOTS, W_Sound("grenade_impact"), VOL_BASE, ATTEN_NORM);
+       sound(self, CH_SHOTS, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
 
        self.realowner.mage_spike = world;
 
@@ -110,20 +164,13 @@ void M_Mage_Attack_Spike_Touch()
 
 // copied from W_Seeker_Think
 void M_Mage_Attack_Spike_Think()
-{
-       entity e;
-       vector desireddir, olddir, newdir, eorg;
-       float turnrate;
-       float dist;
-       float spd;
-
-       if (time > self.ltime || self.enemy.health <= 0 || self.owner.health <= 0)
-       {
+{SELFPARAM();
+       if (time > self.ltime || (self.enemy && self.enemy.health <= 0) || self.owner.health <= 0) {
                self.projectiledeathtype |= HITTYPE_SPLASH;
                M_Mage_Attack_Spike_Explode();
        }
 
-       spd = vlen(self.velocity);
+       float spd = vlen(self.velocity);
        spd = bound(
                spd - (autocvar_g_monster_mage_attack_spike_decel) * frametime,
                (autocvar_g_monster_mage_attack_spike_speed_max),
@@ -136,12 +183,12 @@ void M_Mage_Attack_Spike_Think()
 
        if (self.enemy != world)
        {
-               e                               = self.enemy;
-               eorg                    = 0.5 * (e.absmin + e.absmax);
-               turnrate                = (autocvar_g_monster_mage_attack_spike_turnrate); // how fast to turn
-               desireddir              = normalize(eorg - self.origin);
-               olddir                  = normalize(self.velocity); // get my current direction
-               dist                    = vlen(eorg - self.origin);
+               entity e = self.enemy;
+               vector eorg = 0.5 * (e.absmin + e.absmax);
+               float turnrate = (autocvar_g_monster_mage_attack_spike_turnrate); // how fast to turn
+               vector desireddir = normalize(eorg - self.origin);
+               vector olddir = normalize(self.velocity); // get my current direction
+               float dist = vlen(eorg - self.origin);
 
                // Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
                if ((autocvar_g_monster_mage_attack_spike_smart) && (dist > (autocvar_g_monster_mage_attack_spike_smart_mindist)))
@@ -159,11 +206,9 @@ void M_Mage_Attack_Spike_Think()
                        desireddir = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
                }
 
-               newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy
+               vector newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy
                self.velocity = newdir * spd; // make me fly in the new direction at my flight speed
        }
-       else
-               dist = 0;
 
        ///////////////
 
@@ -172,14 +217,12 @@ void M_Mage_Attack_Spike_Think()
        UpdateCSQCProjectile(self);
 }
 
-void M_Mage_Attack_Spike()
+void M_Mage_Attack_Spike(vector dir)
 {
-       entity missile;
-       vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
-
+       SELFPARAM();
        makevectors(self.angles);
 
-       missile = spawn ();
+       entity missile = spawn();
        missile.owner = missile.realowner = self;
        missile.think = M_Mage_Attack_Spike_Think;
        missile.ltime = time + 7;
@@ -188,7 +231,7 @@ void M_Mage_Attack_Spike()
        missile.movetype = MOVETYPE_FLYMISSILE;
        missile.flags = FL_PROJECTILE;
        setorigin(missile, self.origin + v_forward * 14 + '0 0 30' + v_right * -14);
-       setsize (missile, '0 0 0', '0 0 0');
+       setsize(missile, '0 0 0', '0 0 0');
        missile.velocity = dir * 400;
        missile.avelocity = '300 300 300';
        missile.enemy = self.enemy;
@@ -200,7 +243,7 @@ void M_Mage_Attack_Spike()
 }
 
 void M_Mage_Defend_Heal()
-{
+{SELFPARAM();
        entity head;
        float washealed = false;
 
@@ -257,8 +300,8 @@ void M_Mage_Defend_Heal()
 }
 
 void M_Mage_Attack_Push()
-{
-       sound(self, CH_SHOTS, W_Sound("tagexp1"), 1, ATTEN_NORM);
+{SELFPARAM();
+       sound(self, CH_SHOTS, SND_TAGEXP1, 1, ATTEN_NORM);
        RadiusDamage (self, self, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius), world, world, (autocvar_g_monster_mage_attack_push_force), DEATH_MONSTER_MAGE, self.enemy);
        Send_Effect(EFFECT_TE_EXPLOSION, self.origin, '0 0 0', 1);
 
@@ -267,30 +310,38 @@ void M_Mage_Attack_Push()
 }
 
 void M_Mage_Attack_Teleport()
-{
-       if(vlen(self.enemy.origin - self.origin) >= 500)
-               return;
+{SELFPARAM();
+       entity targ = self.enemy;
+       if (!targ) return;
+       if (vlen(targ.origin - self.origin) > 1500) return;
 
-       makevectors(self.enemy.angles);
-       tracebox(self.enemy.origin + ((v_forward * -1) * 200), self.mins, self.maxs, self.origin, MOVE_NOMONSTERS, self);
+       makevectors(targ.angles);
+       tracebox(targ.origin + ((v_forward * -1) * 200), self.mins, self.maxs, self.origin, MOVE_NOMONSTERS, self);
 
        if(trace_fraction < 1)
                return;
 
        Send_Effect(EFFECT_SPAWN_NEUTRAL, self.origin, '0 0 0', 1);
-       setorigin(self, self.enemy.origin + ((v_forward * -1) * 200));
+       setorigin(self, targ.origin + ((v_forward * -1) * 200));
+
+       vector a = vectoangles(targ.origin - self.origin);
+       a.x = -a.x;
+       self.angles_x = a.x;
+       self.angles_y = a.y;
+       self.fixangle = true;
+       self.velocity *= 0.5;
 
        self.attack_finished_single = time + 0.2;
 }
 
 void M_Mage_Defend_Shield_Remove()
-{
+{SELFPARAM();
        self.effects &= ~(EF_ADDITIVE | EF_BLUE);
        self.armorvalue = autocvar_g_monsters_armor_blockpercent;
 }
 
 void M_Mage_Defend_Shield()
-{
+{SELFPARAM();
        self.effects |= (EF_ADDITIVE | EF_BLUE);
        self.mage_shield_delay = time + (autocvar_g_monster_mage_shield_delay);
        self.armorvalue = (autocvar_g_monster_mage_shield_blockpercent);
@@ -300,15 +351,16 @@ void M_Mage_Defend_Shield()
        self.anim_finished = time + 1;
 }
 
-float M_Mage_Attack(float attack_type)
-{
+float M_Mage_Attack(float attack_type, entity targ)
+{SELFPARAM();
        switch(attack_type)
        {
                case MONSTER_ATTACK_MELEE:
                {
                        if(random() <= 0.7)
                        {
-                               M_Mage_Attack_Push();
+                               Weapon wep = WEP_MAGE_SPIKE;
+                               wep.wr_think(wep, self, false, true);
                                return true;
                        }
 
@@ -320,7 +372,8 @@ float M_Mage_Attack(float attack_type)
                        {
                                if(random() <= 0.4)
                                {
-                                       M_Mage_Attack_Teleport();
+                                       OffhandWeapon off = OFFHAND_MAGE_TELEPORT;
+                                       off.offhand_think(off, self, true);
                                        return true;
                                }
                                else
@@ -328,7 +381,8 @@ float M_Mage_Attack(float attack_type)
                                        setanim(self, self.anim_shoot, true, true, true);
                                        self.attack_finished_single = time + (autocvar_g_monster_mage_attack_spike_delay);
                                        self.anim_finished = time + 1;
-                                       Monster_Delay(1, 0, 0.2, M_Mage_Attack_Spike);
+                                       Weapon wep = WEP_MAGE_SPIKE;
+                                       wep.wr_think(wep, self, true, false);
                                        return true;
                                }
                        }
@@ -343,17 +397,14 @@ float M_Mage_Attack(float attack_type)
        return false;
 }
 
-void spawnfunc_monster_mage() { Monster_Spawn(MON_MAGE.monsterid); }
+spawnfunc(monster_mage) { Monster_Spawn(MON_MAGE.monsterid); }
 
 #endif // SVQC
 
-bool M_Mage(int req)
-{
-       switch(req)
-       {
                #ifdef SVQC
-               case MR_THINK:
+               METHOD(Mage, mr_think, bool(Monster thismon))
                {
+                       SELFPARAM();
                        entity head;
                        bool need_help = false;
 
@@ -382,19 +433,21 @@ bool M_Mage(int req)
 
                        return true;
                }
-               case MR_PAIN:
+               METHOD(Mage, mr_pain, bool(Monster thismon))
                {
                        return true;
                }
-               case MR_DEATH:
+               METHOD(Mage, mr_death, bool(Monster thismon))
                {
+                       SELFPARAM();
                        setanim(self, self.anim_die1, false, true, true);
                        return true;
                }
                #endif
                #ifndef MENUQC
-               case MR_ANIM:
+               METHOD(Mage, mr_anim, bool(Monster thismon))
                {
+                       SELFPARAM();
                        vector none = '0 0 0';
                        self.anim_die1 = animfixfps(self, '4 1 0.5', none); // 2 seconds
                        self.anim_walk = animfixfps(self, '1 1 1', none);
@@ -407,8 +460,9 @@ bool M_Mage(int req)
                }
                #endif
                #ifdef SVQC
-               case MR_SETUP:
+               METHOD(Mage, mr_setup, bool(Monster thismon))
                {
+                       SELFPARAM();
                        if(!self.health) self.health = (autocvar_g_monster_mage_health);
                        if(!self.speed) { self.speed = (autocvar_g_monster_mage_speed_walk); }
                        if(!self.speed2) { self.speed2 = (autocvar_g_monster_mage_speed_run); }
@@ -420,15 +474,10 @@ bool M_Mage(int req)
 
                        return true;
                }
-               case MR_PRECACHE:
+               METHOD(Mage, mr_precache, bool(Monster thismon))
                {
-                       precache_model("models/monsters/mage.dpm");
-                       precache_sound (W_Sound("grenade_impact"));
-                       precache_sound (W_Sound("tagexp1"));
                        return true;
                }
                #endif
-       }
 
-       return true;
-}
+#endif
index 4640fe945bcf33f6e9ea8744bdf0d79303334d2f..937c83c9edbe868b7f2f3c25f5d3d4caaab628cf 100644 (file)
@@ -1,20 +1,31 @@
+#ifndef SHAMBLER_H
+#define SHAMBLER_H
+
+#ifndef MENUQC
+MODEL(MON_SHAMBLER, "models/monsters/shambler.mdl");
+#endif
+
+CLASS(Shambler, Monster)
+    ATTRIB(Shambler, spawnflags, int, MONSTER_SIZE_BROKEN | MON_FLAG_SUPERMONSTER | MON_FLAG_MELEE | MON_FLAG_RANGED);
+    ATTRIB(Shambler, mins, vector, '-41 -41 -31');
+    ATTRIB(Shambler, maxs, vector, '41 41 65');
 #ifndef MENUQC
-bool M_Shambler(int);
+    ATTRIB(Shambler, m_model, Model, MDL_MON_SHAMBLER);
 #endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id   */ SHAMBLER,
-/* spawnflags */ MONSTER_SIZE_BROKEN | MON_FLAG_SUPERMONSTER | MON_FLAG_MELEE | MON_FLAG_RANGED,
-/* mins,maxs  */ '-41 -41 -31', '41 41 65',
-/* model      */ "shambler.mdl",
-/* netname    */ "shambler",
-/* fullname   */ _("Shambler")
-) {
+    ATTRIB(Shambler, netname, string, "shambler");
+    ATTRIB(Shambler, monster_name, string, _("Shambler"));
+ENDCLASS(Shambler)
+
+REGISTER_MONSTER(SHAMBLER, NEW(Shambler)) {
 #ifndef MENUQC
-       this.monster_func = M_Shambler;
-       this.monster_func(MR_PRECACHE);
+    this.mr_precache(this);
 #endif
 }
 
+#endif
+
+#ifdef IMPLEMENTATION
+
 #ifdef SVQC
 float autocvar_g_monster_shambler_health;
 float autocvar_g_monster_shambler_damageforcescale = 0.1;
@@ -47,10 +58,10 @@ const float shambler_anim_death             = 8;
 .float shambler_lastattack; // delay attacks separately
 
 void M_Shambler_Attack_Smash()
-{
+{SELFPARAM();
        makevectors(self.angles);
        Send_Effect(EFFECT_EXPLOSION_MEDIUM, (self.origin + (v_forward * 150)) - ('0 0 1' * self.maxs.z), '0 0 0', 1);
-       sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+       sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 
        // RadiusDamage does NOT support custom starting location, which means we must use this hack...
 
@@ -61,7 +72,7 @@ void M_Shambler_Attack_Smash()
 }
 
 void M_Shambler_Attack_Swing()
-{
+{SELFPARAM();
        float r = (random() < 0.5);
        if(r && Monster_Attack_Melee(self.enemy, (autocvar_g_monster_shambler_attack_claw_damage), ((r) ? self.anim_melee2 : self.anim_melee3), self.attack_range, 0.8, DEATH_MONSTER_SHAMBLER_CLAW, true))
        {
@@ -72,10 +83,10 @@ void M_Shambler_Attack_Swing()
 }
 
 void M_Shambler_Attack_Lightning_Explode()
-{
+{SELFPARAM();
        entity head;
 
-       sound(self, CH_SHOTS, W_Sound("electro_impact"), VOL_BASE, ATTEN_NORM);
+       sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_NORM);
        Send_Effect(EFFECT_ELECTRO_IMPACT, '0 0 0', '0 0 0', 1);
 
        self.event_damage = func_null;
@@ -99,7 +110,7 @@ void M_Shambler_Attack_Lightning_Explode()
 }
 
 void M_Shambler_Attack_Lightning_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if (self.health <= 0)
                return;
 
@@ -113,14 +124,14 @@ void M_Shambler_Attack_Lightning_Damage(entity inflictor, entity attacker, float
 }
 
 void M_Shambler_Attack_Lightning_Touch()
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
 
        self.use ();
 }
 
 void M_Shambler_Attack_Lightning_Think()
-{
+{SELFPARAM();
        self.nextthink = time;
        if (time > self.cnt)
        {
@@ -131,7 +142,7 @@ void M_Shambler_Attack_Lightning_Think()
 }
 
 void M_Shambler_Attack_Lightning()
-{
+{SELFPARAM();
        entity gren;
 
        monster_makevectors(self.enemy);
@@ -168,8 +179,8 @@ void M_Shambler_Attack_Lightning()
        CSQCProjectile(gren, true, PROJECTILE_SHAMBLER_LIGHTNING, true);
 }
 
-float M_Shambler_Attack(float attack_type)
-{
+float M_Shambler_Attack(float attack_type, entity targ)
+{SELFPARAM();
        switch(attack_type)
        {
                case MONSTER_ATTACK_MELEE:
@@ -211,33 +222,32 @@ float M_Shambler_Attack(float attack_type)
        return false;
 }
 
-void spawnfunc_monster_shambler() { Monster_Spawn(MON_SHAMBLER.monsterid); }
+spawnfunc(monster_shambler) { Monster_Spawn(MON_SHAMBLER.monsterid); }
 #endif // SVQC
 
-bool M_Shambler(int req)
-{
-       switch(req)
-       {
                #ifdef SVQC
-               case MR_THINK:
+               METHOD(Shambler, mr_think, bool(Shambler thismon))
                {
                        return true;
                }
-               case MR_PAIN:
+               METHOD(Shambler, mr_pain, bool(Shambler thismon))
                {
+                       SELFPARAM();
                        self.pain_finished = time + 0.5;
                        setanim(self, self.anim_pain1, true, true, false);
                        return true;
                }
-               case MR_DEATH:
+               METHOD(Shambler, mr_death, bool(Shambler thismon))
                {
+                       SELFPARAM();
                        setanim(self, self.anim_die1, false, true, true);
                        return true;
                }
                #endif
                #ifndef MENUQC
-               case MR_ANIM:
+               METHOD(Shambler, mr_anim, bool(Shambler thismon))
                {
+                       SELFPARAM();
                        vector none = '0 0 0';
                        self.anim_die1 = animfixfps(self, '8 1 0.5', none); // 2 seconds
                        self.anim_walk = animfixfps(self, '1 1 1', none);
@@ -253,8 +263,9 @@ bool M_Shambler(int req)
                }
                #endif
                #ifdef SVQC
-               case MR_SETUP:
+               METHOD(Shambler, mr_setup, bool(Shambler thismon))
                {
+                       SELFPARAM();
                        if(!self.health) self.health = (autocvar_g_monster_shambler_health);
                        if(!self.attack_range) self.attack_range = 150;
                        if(!self.speed) { self.speed = (autocvar_g_monster_shambler_speed_walk); }
@@ -272,13 +283,10 @@ bool M_Shambler(int req)
 
                        return true;
                }
-               case MR_PRECACHE:
+               METHOD(Shambler, mr_precache, bool(Shambler thismon))
                {
-                       precache_model("models/monsters/shambler.mdl");
                        return true;
                }
                #endif
-       }
 
-       return true;
-}
+#endif
index 0179c66b9add72b73c2a165e64fbd0f4e9fd996d..35a320b9d50908b6209927e604db3f6004f57397 100644 (file)
@@ -1,29 +1,85 @@
+#ifndef SPIDER_H
+#define SPIDER_H
+
 #ifndef MENUQC
-bool M_Spider(int);
+MODEL(MON_SPIDER, "models/monsters/spider.dpm");
 #endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id   */ SPIDER,
-/* spawnflags */ MON_FLAG_MELEE | MON_FLAG_RANGED | MON_FLAG_RIDE,
-/* mins,maxs  */ '-18 -18 -25', '18 18 30',
-/* model      */ "spider.dpm",
-/* netname    */ "spider",
-/* fullname   */ _("Spider")
-) {
+
+CLASS(Spider, Monster)
+    ATTRIB(Spider, spawnflags, int, MON_FLAG_MELEE | MON_FLAG_RANGED | MON_FLAG_RIDE);
+    ATTRIB(Spider, mins, vector, '-18 -18 -25');
+    ATTRIB(Spider, maxs, vector, '18 18 30');
+#ifndef MENUQC
+    ATTRIB(Spider, m_model, Model, MDL_MON_SPIDER);
+#endif
+    ATTRIB(Spider, netname, string, "spider");
+    ATTRIB(Spider, monster_name, string, _("Spider"));
+ENDCLASS(Spider)
+
+REGISTER_MONSTER(SPIDER, NEW(Spider)) {
 #ifndef MENUQC
-       this.monster_func = M_Spider;
-       this.monster_func(MR_PRECACHE);
+    this.mr_precache(this);
 #endif
 }
 
+#include "../../weapons/all.qh"
+
+CLASS(SpiderAttack, PortoLaunch)
+/* flags     */ ATTRIB(SpiderAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(SpiderAttack, impulse, int, 9);
+/* refname   */ ATTRIB(SpiderAttack, netname, string, "spider");
+/* wepname   */ ATTRIB(SpiderAttack, message, string, _("Spider attack"));
+ENDCLASS(SpiderAttack)
+REGISTER_WEAPON(SPIDER_ATTACK, NEW(SpiderAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
 #ifdef SVQC
-float autocvar_g_monster_spider_health;
-float autocvar_g_monster_spider_damageforcescale = 0.6;
-float autocvar_g_monster_spider_attack_bite_damage;
-float autocvar_g_monster_spider_attack_bite_delay;
+
+.float spider_web_delay;
+
 float autocvar_g_monster_spider_attack_web_damagetime;
 float autocvar_g_monster_spider_attack_web_speed;
 float autocvar_g_monster_spider_attack_web_speed_up;
 float autocvar_g_monster_spider_attack_web_delay;
+
+float autocvar_g_monster_spider_attack_bite_damage;
+float autocvar_g_monster_spider_attack_bite_delay;
+
+void M_Spider_Attack_Web();
+
+METHOD(SpiderAttack, wr_think, void(SpiderAttack thiswep, entity actor, bool fire1, bool fire2)) {
+    bool isPlayer = IS_PLAYER(actor);
+    if (fire1)
+    if ((!isPlayer && time >= actor.spider_web_delay) || weapon_prepareattack(thiswep, actor, false, autocvar_g_monster_spider_attack_web_delay)) {
+               if (!isPlayer) {
+                       actor.spider_web_delay = time + 3;
+                       setanim(actor, actor.anim_shoot, true, true, true);
+                       actor.attack_finished_single = time + (autocvar_g_monster_spider_attack_web_delay);
+                       actor.anim_finished = time + 1;
+               }
+        if (isPlayer) actor.enemy = Monster_FindTarget(actor);
+        W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+       if (!isPlayer) w_shotdir = normalize((actor.enemy.origin + '0 0 10') - actor.origin);
+               M_Spider_Attack_Web();
+        weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+        return;
+    }
+    if (fire2)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, true, 0.5)) {
+       if (isPlayer) {
+               actor.enemy = Monster_FindTarget(actor);
+               actor.attack_range = 60;
+       }
+       Monster_Attack_Melee(actor.enemy, (autocvar_g_monster_spider_attack_bite_damage), ((random() > 0.5) ? self.anim_melee : self.anim_shoot), self.attack_range, (autocvar_g_monster_spider_attack_bite_delay), DEATH_MONSTER_SPIDER, true);
+        weapon_thinkf(actor, WFRAME_FIRE2, 0, w_ready);
+    }
+}
+
+float autocvar_g_monster_spider_health;
+float autocvar_g_monster_spider_damageforcescale = 0.6;
 float autocvar_g_monster_spider_speed_stop;
 float autocvar_g_monster_spider_speed_run;
 float autocvar_g_monster_spider_speed_walk;
@@ -35,10 +91,8 @@ const float spider_anim_attack               = 2;
 const float spider_anim_attack2                = 3;
 */
 
-.float spider_web_delay;
-
 void M_Spider_Attack_Web_Explode()
-{
+{SELFPARAM();
        entity e;
        if(self)
        {
@@ -60,10 +114,10 @@ void M_Spider_Attack_Web_Touch()
 }
 
 void M_Spider_Attack_Web()
-{
+{SELFPARAM();
        monster_makevectors(self.enemy);
 
-       sound(self, CH_SHOTS, W_Sound("electro_fire2"), VOL_BASE, ATTEN_NORM);
+       sound(self, CH_SHOTS, SND_ELECTRO_FIRE2, VOL_BASE, ATTEN_NORM);
 
        entity proj = spawn ();
        proj.classname = "plasma";
@@ -97,59 +151,50 @@ void M_Spider_Attack_Web()
        CSQCProjectile(proj, true, PROJECTILE_ELECTRO, true);
 }
 
-bool M_Spider_Attack(int attack_type)
-{
+bool M_Spider_Attack(int attack_type, entity targ)
+{SELFPARAM();
        switch(attack_type)
        {
+               Weapon wep = WEP_SPIDER_ATTACK;
                case MONSTER_ATTACK_MELEE:
                {
-                       return Monster_Attack_Melee(self.enemy, (autocvar_g_monster_spider_attack_bite_damage), ((random() > 0.5) ? self.anim_melee : self.anim_shoot), self.attack_range, (autocvar_g_monster_spider_attack_bite_delay), DEATH_MONSTER_SPIDER, true);
+                       wep.wr_think(wep, self, false, true);
+                       return true;
                }
                case MONSTER_ATTACK_RANGED:
                {
-                       if(time >= self.spider_web_delay)
-                       {
-                               setanim(self, self.anim_shoot, true, true, true);
-                               self.attack_finished_single = time + (autocvar_g_monster_spider_attack_web_delay);
-                               self.anim_finished = time + 1;
-                               M_Spider_Attack_Web();
-                               self.spider_web_delay = time + 3;
-                               return true;
-                       }
-
-                       return false;
+                       wep.wr_think(wep, self, true, false);
+                       return true;
                }
        }
 
        return false;
 }
 
-void spawnfunc_monster_spider() { Monster_Spawn(MON_SPIDER.monsterid); }
+spawnfunc(monster_spider) { Monster_Spawn(MON_SPIDER.monsterid); }
 #endif // SVQC
 
-bool M_Spider(int req)
-{
-       switch(req)
-       {
                #ifdef SVQC
-               case MR_THINK:
+               METHOD(Spider, mr_think, bool(Spider thismon))
                {
                        return true;
                }
-               case MR_PAIN:
+               METHOD(Spider, mr_pain, bool(Spider thismon))
                {
                        return true;
                }
-               case MR_DEATH:
+               METHOD(Spider, mr_death, bool(Spider thismon))
                {
+                       SELFPARAM();
                        setanim(self, self.anim_melee, false, true, true);
                        self.angles_x = 180;
                        return true;
                }
                #endif
                #ifndef MENUQC
-               case MR_ANIM:
+               METHOD(Spider, mr_anim, bool(Spider thismon))
                {
+                       SELFPARAM();
                        vector none = '0 0 0';
                        self.anim_walk = animfixfps(self, '1 1 1', none);
                        self.anim_idle = animfixfps(self, '0 1 1', none);
@@ -161,8 +206,9 @@ bool M_Spider(int req)
                }
                #endif
                #ifdef SVQC
-               case MR_SETUP:
+               METHOD(Spider, mr_setup, bool(Spider thismon))
                {
+                       SELFPARAM();
                        if(!self.health) self.health = (autocvar_g_monster_spider_health);
                        if(!self.speed) { self.speed = (autocvar_g_monster_spider_speed_walk); }
                        if(!self.speed2) { self.speed2 = (autocvar_g_monster_spider_speed_run); }
@@ -174,14 +220,10 @@ bool M_Spider(int req)
 
                        return true;
                }
-               case MR_PRECACHE:
+               METHOD(Spider, mr_precache, bool(Spider thismon))
                {
-                       precache_model("models/monsters/spider.dpm");
-                       precache_sound (W_Sound("electro_fire2"));
                        return true;
                }
                #endif
-       }
 
-       return true;
-}
+#endif
index 9bdc4c63afa57ed7bd000df7894ace290844d187..102fd6a5c1fdfb1aa4a58bcc320c195f645ce03f 100644 (file)
@@ -1,29 +1,88 @@
+#ifndef WYVERN_H
+#define WYVERN_H
+
 #ifndef MENUQC
-bool M_Wyvern(int);
+MODEL(MON_WYVERN, "models/monsters/wizard.mdl");
 #endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id   */ WYVERN,
-/* spawnflags */ MONSTER_TYPE_FLY | MONSTER_SIZE_BROKEN | MON_FLAG_RANGED | MON_FLAG_RIDE,
-/* mins,maxs  */ '-20 -20 -58', '20 20 20',
-/* model      */ "wizard.mdl",
-/* netname    */ "wyvern",
-/* fullname   */ _("Wyvern")
-) {
+
+CLASS(Wyvern, Monster)
+    ATTRIB(Wyvern, spawnflags, int, MONSTER_TYPE_FLY | MONSTER_SIZE_BROKEN | MON_FLAG_RANGED | MON_FLAG_RIDE);
+    ATTRIB(Wyvern, mins, vector, '-20 -20 -58');
+    ATTRIB(Wyvern, maxs, vector, '20 20 20');
+#ifndef MENUQC
+    ATTRIB(Wyvern, m_model, Model, MDL_MON_WYVERN);
+#endif
+    ATTRIB(Wyvern, netname, string, "wyvern");
+    ATTRIB(Wyvern, monster_name, string, _("Wyvern"));
+ENDCLASS(Wyvern)
+
+REGISTER_MONSTER(WYVERN, NEW(Wyvern)) {
 #ifndef MENUQC
-       this.monster_func = M_Wyvern;
-       this.monster_func(MR_PRECACHE);
+    this.mr_precache(this);
 #endif
 }
 
+#include "../../weapons/all.qh"
+
+CLASS(WyvernAttack, PortoLaunch)
+/* flags     */ ATTRIB(WyvernAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(WyvernAttack, impulse, int, 9);
+/* refname   */ ATTRIB(WyvernAttack, netname, string, "wyvern");
+/* wepname   */ ATTRIB(WyvernAttack, message, string, _("Wyvern attack"));
+ENDCLASS(WyvernAttack)
+REGISTER_WEAPON(WYVERN_ATTACK, NEW(WyvernAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
 #ifdef SVQC
-float autocvar_g_monster_wyvern_health;
-float autocvar_g_monster_wyvern_damageforcescale = 0.6;
+
 float autocvar_g_monster_wyvern_attack_fireball_damage;
 float autocvar_g_monster_wyvern_attack_fireball_edgedamage;
 float autocvar_g_monster_wyvern_attack_fireball_damagetime;
 float autocvar_g_monster_wyvern_attack_fireball_force;
 float autocvar_g_monster_wyvern_attack_fireball_radius;
 float autocvar_g_monster_wyvern_attack_fireball_speed;
+
+void M_Wyvern_Attack_Fireball_Explode();
+void M_Wyvern_Attack_Fireball_Touch();
+
+METHOD(WyvernAttack, wr_think, void(WyvernAttack thiswep, entity actor, bool fire1, bool fire2)) {
+    if (fire1)
+    if (time > actor.attack_finished_single || weapon_prepareattack(thiswep, actor, false, 1.2)) {
+        if (IS_PLAYER(actor)) W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+               if (IS_MONSTER(actor)) {
+                       actor.attack_finished_single = time + 1.2;
+                       actor.anim_finished = time + 1.2;
+                       monster_makevectors(actor.enemy);
+               }
+
+               entity missile = spawn();
+               missile.owner = missile.realowner = actor;
+               missile.solid = SOLID_TRIGGER;
+               missile.movetype = MOVETYPE_FLYMISSILE;
+               missile.projectiledeathtype = DEATH_MONSTER_WYVERN;
+               setsize(missile, '-6 -6 -6', '6 6 6');
+               setorigin(missile, actor.origin + actor.view_ofs + v_forward * 14);
+               missile.flags = FL_PROJECTILE;
+               missile.velocity = w_shotdir * (autocvar_g_monster_wyvern_attack_fireball_speed);
+               missile.avelocity = '300 300 300';
+               missile.nextthink = time + 5;
+               missile.think = M_Wyvern_Attack_Fireball_Explode;
+               missile.touch = M_Wyvern_Attack_Fireball_Touch;
+               CSQCProjectile(missile, true, PROJECTILE_FIREMINE, true);
+
+        weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+    }
+}
+
+METHOD(WyvernAttack, wr_checkammo1, bool(WyvernAttack thiswep)) {
+       return true;
+}
+
+float autocvar_g_monster_wyvern_health;
+float autocvar_g_monster_wyvern_damageforcescale = 0.6;
 float autocvar_g_monster_wyvern_speed_stop;
 float autocvar_g_monster_wyvern_speed_run;
 float autocvar_g_monster_wyvern_speed_walk;
@@ -38,18 +97,18 @@ const float wyvern_anim_death       = 4;
 
 void M_Wyvern_Attack_Fireball_Explode()
 {
-       entity e;
-       if(self)
-       {
-               Send_Effect(EFFECT_FIREBALL_EXPLODE, self.origin, '0 0 0', 1);
+       SELFPARAM();
+       Send_Effect(EFFECT_FIREBALL_EXPLODE, self.origin, '0 0 0', 1);
 
-               RadiusDamage(self, self.realowner, (autocvar_g_monster_wyvern_attack_fireball_damage), (autocvar_g_monster_wyvern_attack_fireball_edgedamage), (autocvar_g_monster_wyvern_attack_fireball_force), world, world, (autocvar_g_monster_wyvern_attack_fireball_radius), self.projectiledeathtype, world);
+       entity owner = self.realowner;
 
-               for(e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); ) if(vlen(e.origin - self.origin) <= (autocvar_g_monster_wyvern_attack_fireball_radius))
-                       Fire_AddDamage(e, self, 5 * MONSTER_SKILLMOD(self), (autocvar_g_monster_wyvern_attack_fireball_damagetime), self.projectiledeathtype);
+       RadiusDamage(self, owner, autocvar_g_monster_wyvern_attack_fireball_damage, autocvar_g_monster_wyvern_attack_fireball_edgedamage, autocvar_g_monster_wyvern_attack_fireball_force, world, world, autocvar_g_monster_wyvern_attack_fireball_radius, self.projectiledeathtype, world);
 
-               remove(self);
-       }
+       for (entity e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); )
+       if (vlen(e.origin - self.origin) <= (autocvar_g_monster_wyvern_attack_fireball_radius))
+               Fire_AddDamage(e, owner, 5 * MONSTER_SKILLMOD(owner), (autocvar_g_monster_wyvern_attack_fireball_damagetime), self.projectiledeathtype);
+
+       remove(self);
 }
 
 void M_Wyvern_Attack_Fireball_Touch()
@@ -59,41 +118,17 @@ void M_Wyvern_Attack_Fireball_Touch()
        M_Wyvern_Attack_Fireball_Explode();
 }
 
-void M_Wyvern_Attack_Fireball()
-{
-       entity missile = spawn();
-       vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
-
-       monster_makevectors(self.enemy);
-
-       missile.owner = missile.realowner = self;
-       missile.solid = SOLID_TRIGGER;
-       missile.movetype = MOVETYPE_FLYMISSILE;
-       missile.projectiledeathtype = DEATH_MONSTER_WYVERN;
-       setsize(missile, '-6 -6 -6', '6 6 6');
-       setorigin(missile, self.origin + self.view_ofs + v_forward * 14);
-       missile.flags = FL_PROJECTILE;
-       missile.velocity = dir * (autocvar_g_monster_wyvern_attack_fireball_speed);
-       missile.avelocity = '300 300 300';
-       missile.nextthink = time + 5;
-       missile.think = M_Wyvern_Attack_Fireball_Explode;
-       missile.enemy = self.enemy;
-       missile.touch = M_Wyvern_Attack_Fireball_Touch;
-       CSQCProjectile(missile, true, PROJECTILE_FIREMINE, true);
-}
-
-float M_Wyvern_Attack(float attack_type)
+float M_Wyvern_Attack(float attack_type, entity targ)
 {
+       SELFPARAM();
        switch(attack_type)
        {
                case MONSTER_ATTACK_MELEE:
                case MONSTER_ATTACK_RANGED:
                {
-                       self.attack_finished_single = time + 1.2;
-                       self.anim_finished = time + 1.2;
-
-                       M_Wyvern_Attack_Fireball();
-
+                       w_shotdir = normalize((self.enemy.origin + '0 0 10') - self.origin);
+                       Weapon wep = WEP_WYVERN_ATTACK;
+                       wep.wr_think(wep, self, true, false);
                        return true;
                }
        }
@@ -101,26 +136,24 @@ float M_Wyvern_Attack(float attack_type)
        return false;
 }
 
-void spawnfunc_monster_wyvern() { Monster_Spawn(MON_WYVERN.monsterid); }
+spawnfunc(monster_wyvern) { Monster_Spawn(MON_WYVERN.monsterid); }
 #endif // SVQC
 
-bool M_Wyvern(int req)
-{
-       switch(req)
-       {
                #ifdef SVQC
-               case MR_THINK:
+               METHOD(Wyvern, mr_think, bool(Wyvern thismon))
                {
                        return true;
                }
-               case MR_PAIN:
+               METHOD(Wyvern, mr_pain, bool(Wyvern thismon))
                {
+                       SELFPARAM();
                        self.pain_finished = time + 0.5;
                        setanim(self, self.anim_pain1, true, true, false);
                        return true;
                }
-               case MR_DEATH:
+               METHOD(Wyvern, mr_death, bool(Wyvern thismon))
                {
+                       SELFPARAM();
                        setanim(self, self.anim_die1, false, true, true);
                        self.velocity_x = -200 + 400 * random();
                        self.velocity_y = -200 + 400 * random();
@@ -129,8 +162,9 @@ bool M_Wyvern(int req)
                }
                #endif
                #ifndef MENUQC
-               case MR_ANIM:
+               METHOD(Wyvern, mr_anim, bool(Wyvern thismon))
                {
+                       SELFPARAM();
                        vector none = '0 0 0';
                        self.anim_die1 = animfixfps(self, '4 1 0.5', none); // 2 seconds
                        self.anim_walk = animfixfps(self, '1 1 1', none);
@@ -143,8 +177,9 @@ bool M_Wyvern(int req)
                }
                #endif
                #ifdef SVQC
-               case MR_SETUP:
+               METHOD(Wyvern, mr_setup, bool(Wyvern thismon))
                {
+                       SELFPARAM();
                        if(!self.health) self.health = (autocvar_g_monster_wyvern_health);
                        if(!self.speed) { self.speed = (autocvar_g_monster_wyvern_speed_walk); }
                        if(!self.speed2) { self.speed2 = (autocvar_g_monster_wyvern_speed_run); }
@@ -156,13 +191,10 @@ bool M_Wyvern(int req)
 
                        return true;
                }
-               case MR_PRECACHE:
+               METHOD(Wyvern, mr_precache, bool(Wyvern thismon))
                {
-                       precache_model("models/monsters/wizard.mdl");
                        return true;
                }
                #endif
-       }
 
-       return true;
-}
+#endif
index 780cf74b381dadb7fc5db70ee4f45bef5fa63e11..8425a123add60d29469b219c2d0f3b191a34b7de 100644 (file)
@@ -1,20 +1,31 @@
+#ifndef ZOMBIE_H
+#define ZOMBIE_H
+
 #ifndef MENUQC
-bool M_Zombie(int);
+MODEL(MON_ZOMBIE, "models/monsters/zombie.dpm");
 #endif
-REGISTER_MONSTER_SIMPLE(
-/* MON_##id   */ ZOMBIE,
-/* spawnflags */ MON_FLAG_MELEE | MON_FLAG_RIDE,
-/* mins,maxs  */ '-18 -18 -25', '18 18 47',
-/* model      */ "zombie.dpm",
-/* netname    */ "zombie",
-/* fullname   */ _("Zombie")
-) {
+
+CLASS(Zombie, Monster)
+    ATTRIB(Zombie, spawnflags, int, MON_FLAG_MELEE | MON_FLAG_RIDE);
+    ATTRIB(Zombie, mins, vector, '-18 -18 -25');
+    ATTRIB(Zombie, maxs, vector, '18 18 47');
 #ifndef MENUQC
-       this.monster_func = M_Zombie;
-       this.monster_func(MR_PRECACHE);
+    ATTRIB(Zombie, m_model, Model, MDL_MON_ZOMBIE);
+#endif
+    ATTRIB(Zombie, netname, string, "zombie");
+    ATTRIB(Zombie, monster_name, string, _("Zombie"));
+ENDCLASS(Zombie)
+
+REGISTER_MONSTER(ZOMBIE, NEW(Zombie)) {
+#ifndef MENUQC
+    this.mr_precache(this);
 #endif
 }
 
+#endif
+
+#ifdef IMPLEMENTATION
+
 #ifdef SVQC
 float autocvar_g_monster_zombie_health;
 float autocvar_g_monster_zombie_damageforcescale = 0.55;
@@ -63,7 +74,7 @@ const float zombie_anim_spawn                         = 30;
 */
 
 void M_Zombie_Attack_Leap_Touch()
-{
+{SELFPARAM();
        if (self.health <= 0)
                return;
 
@@ -86,7 +97,7 @@ void M_Zombie_Attack_Leap_Touch()
 }
 
 void M_Zombie_Defend_Block_End()
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -95,7 +106,7 @@ void M_Zombie_Defend_Block_End()
 }
 
 float M_Zombie_Defend_Block()
-{
+{SELFPARAM();
        self.armorvalue = 0.9;
        self.state = MONSTER_ATTACK_MELEE; // freeze monster
        self.attack_finished_single = time + 2.1;
@@ -107,8 +118,8 @@ float M_Zombie_Defend_Block()
        return true;
 }
 
-float M_Zombie_Attack(float attack_type)
-{
+float M_Zombie_Attack(float attack_type, entity targ)
+{SELFPARAM();
        switch(attack_type)
        {
                case MONSTER_ATTACK_MELEE:
@@ -138,28 +149,27 @@ float M_Zombie_Attack(float attack_type)
        return false;
 }
 
-void spawnfunc_monster_zombie() { Monster_Spawn(MON_ZOMBIE.monsterid); }
+spawnfunc(monster_zombie) { Monster_Spawn(MON_ZOMBIE.monsterid); }
 #endif // SVQC
 
-bool M_Zombie(int req)
-{
-       switch(req)
-       {
                #ifdef SVQC
-               case MR_THINK:
+               METHOD(Zombie, mr_think, bool(Zombie thismon))
                {
+                       SELFPARAM();
                        if(time >= self.spawn_time)
                                self.damageforcescale = autocvar_g_monster_zombie_damageforcescale;
                        return true;
                }
-               case MR_PAIN:
+               METHOD(Zombie, mr_pain, bool(Zombie thismon))
                {
+                       SELFPARAM();
                        self.pain_finished = time + 0.34;
                        setanim(self, ((random() > 0.5) ? self.anim_pain1 : self.anim_pain2), true, true, false);
                        return true;
                }
-               case MR_DEATH:
+               METHOD(Zombie, mr_death, bool(Zombie thismon))
                {
+                       SELFPARAM();
                        self.armorvalue = autocvar_g_monsters_armor_blockpercent;
 
                        setanim(self, ((random() > 0.5) ? self.anim_die1 : self.anim_die2), false, true, true);
@@ -167,8 +177,9 @@ bool M_Zombie(int req)
                }
                #endif
                #ifndef MENUQC
-               case MR_ANIM:
+               METHOD(Zombie, mr_anim, bool(Zombie thismon))
                {
+                       SELFPARAM();
                        vector none = '0 0 0';
                        self.anim_die1 = animfixfps(self, '9 1 0.5', none); // 2 seconds
                        self.anim_die2 = animfixfps(self, '12 1 0.5', none); // 2 seconds
@@ -189,7 +200,7 @@ bool M_Zombie(int req)
                }
                #endif
                #ifdef SVQC
-               case MR_SETUP:
+               METHOD(Zombie, mr_setup, bool(Zombie thismon))
                {
                        if(!self.health) self.health = (autocvar_g_monster_zombie_health);
                        if(!self.speed) { self.speed = (autocvar_g_monster_zombie_speed_walk); }
@@ -212,13 +223,10 @@ bool M_Zombie(int req)
 
                        return true;
                }
-               case MR_PRECACHE:
+               METHOD(Zombie, mr_precache, bool(Zombie thismon))
                {
-                       precache_model("models/monsters/zombie.dpm");
                        return true;
                }
                #endif
-       }
 
-       return true;
-}
+#endif
index 4a84f943584499708acab79e9a387ab8909f7dc5..cf23639e015b5276ee781229f98e0af1674c9d8a 100644 (file)
@@ -10,7 +10,7 @@
     #include "../../server/defs.qh"
 #endif
 entity spawnmonster (string monster, float monster_id, entity spawnedby, entity own, vector orig, float respwn, float invincible, float moveflag)
-{
+{SELFPARAM();
        float i;
        entity e = spawn();
 
@@ -62,12 +62,9 @@ entity spawnmonster (string monster, float monster_id, entity spawnedby, entity
 
                e.angles_y = spawnedby.angles_y;
        }
-       
+
        // Monster_Spawn checks if monster is valid
-       entity oldself = self;
-       self = e;
-       Monster_Spawn(monster_id);
-       self = oldself;
+       WITH(entity, self, e, Monster_Spawn(monster_id));
 
        return e;
 }
index d0b39828d1acbcf1da0b7ff5706ae558ab0d066b..8b05f781d2e395b44a3893474fdc6788501dd40e 100644 (file)
 #endif
 
 void monsters_setstatus()
-{
+{SELFPARAM();
        self.stat_monsters_total = monsters_total;
        self.stat_monsters_killed = monsters_killed;
 }
 
 void monster_dropitem()
-{
+{SELFPARAM();
        if(!self.candrop || !self.monster_loot)
                return;
 
        vector org = self.origin + ((self.mins + self.maxs) * 0.5);
-       entity e = spawn(), oldself = self;
+       entity e = spawn();
+       e.spawnfunc_checked = true;
 
        e.monster_loot = self.monster_loot;
 
@@ -47,9 +48,9 @@ void monster_dropitem()
 
        if(e && e.monster_loot)
        {
-               self = e;
+               setself(e);
                e.noalign = true;
-               e.monster_loot();
+               e.monster_loot(e);
                e.gravity = 1;
                e.movetype = MOVETYPE_TOSS;
                e.reset = SUB_Remove;
@@ -58,12 +59,12 @@ void monster_dropitem()
                e.item_spawnshieldtime = time + 0.7;
                e.classname = "droppedweapon"; // use weapon handling to remove it on touch
                SUB_SetFade(e, time + autocvar_g_monsters_drop_time, 1);
-               self = oldself;
+               setself(this);
        }
 }
 
 void monster_makevectors(entity e)
-{
+{SELFPARAM();
        if(IS_MONSTER(self))
        {
                vector v;
@@ -81,7 +82,7 @@ void monster_makevectors(entity e)
 // ===============
 
 bool Monster_ValidTarget(entity mon, entity player)
-{
+{SELFPARAM();
        // ensure we're not checking nonexistent monster/target
        if(!mon || !player) { return false; }
 
@@ -118,7 +119,7 @@ bool Monster_ValidTarget(entity mon, entity player)
                makevectors (mon.angles);
                dot = normalize (player.origin - mon.origin) * v_forward;
 
-               if(dot <= 0.3) { return false; }
+               if(dot <= autocvar_g_monsters_target_infront_range) { return false; }
        }
 
        return true; // this target is valid!
@@ -181,11 +182,11 @@ void monster_setupcolors(entity mon)
 void monster_changeteam(entity ent, float newteam)
 {
        if(!teamplay) { return; }
-       
+
        ent.team = newteam;
        ent.monster_attack = true; // new team, activate attacking
        monster_setupcolors(ent);
-       
+
        if(ent.sprite)
        {
                WaypointSprite_UpdateTeamRadar(ent.sprite, RADARICON_DANGER, ((newteam) ? Team_ColorRGB(newteam) : '1 0 0'));
@@ -196,9 +197,9 @@ void monster_changeteam(entity ent, float newteam)
 }
 
 void Monster_Delay_Action()
-{
+{SELFPARAM();
        entity oldself = self;
-       self = self.owner;
+       setself(self.owner);
        if(Monster_ValidTarget(self, self.enemy)) { oldself.use(); }
 
        if(oldself.cnt > 0)
@@ -215,7 +216,7 @@ void Monster_Delay_Action()
 }
 
 void Monster_Delay(float repeat_count, float repeat_defer, float defer_amnt, void() func)
-{
+{SELFPARAM();
        // deferred attacking, checks if monster is still alive and target is still valid before attacking
        entity e = spawn();
 
@@ -266,8 +267,8 @@ void Monster_Sound_Precache(string f)
 }
 
 void Monster_Sounds_Precache()
-{
-       string m = (get_monsterinfo(self.monsterid)).model;
+{SELFPARAM();
+       string m = (get_monsterinfo(self.monsterid)).m_model.model_str();
        float globhandle, n, i;
        string f;
 
@@ -285,7 +286,7 @@ void Monster_Sounds_Precache()
 }
 
 void Monster_Sounds_Clear()
-{
+{SELFPARAM();
 #define _MSOUND(m) if(self.monstersound_##m) { strunzone(self.monstersound_##m); self.monstersound_##m = string_null; }
        ALLMONSTERSOUNDS
 #undef _MSOUND
@@ -305,7 +306,7 @@ void Monster_Sounds_Clear()
 }
 
 bool Monster_Sounds_Load(string f, int first)
-{
+{SELFPARAM();
        float fh;
        string s;
        var .string field;
@@ -332,7 +333,7 @@ bool Monster_Sounds_Load(string f, int first)
 
 .int skin_for_monstersound;
 void Monster_Sounds_Update()
-{
+{SELFPARAM();
        if(self.skin == self.skin_for_monstersound) { return; }
 
        self.skin_for_monstersound = self.skin;
@@ -342,7 +343,7 @@ void Monster_Sounds_Update()
 }
 
 void Monster_Sound(.string samplefield, float sound_delay, float delaytoo, float chan)
-{
+{SELFPARAM();
        if(!autocvar_g_monsters_sounds) { return; }
 
        if(delaytoo)
@@ -359,7 +360,7 @@ void Monster_Sound(.string samplefield, float sound_delay, float delaytoo, float
 // =======================
 
 float Monster_Attack_Melee(entity targ, float damg, vector anim, float er, float animtime, int deathtype, float dostop)
-{
+{SELFPARAM();
        if(dostop && (self.flags & FL_MONSTER)) { self.state = MONSTER_ATTACK_MELEE; }
 
        setanim(self, anim, false, true, false);
@@ -380,7 +381,7 @@ float Monster_Attack_Melee(entity targ, float damg, vector anim, float er, float
 }
 
 float Monster_Attack_Leap_Check(vector vel)
-{
+{SELFPARAM();
        if(self.state && (self.flags & FL_MONSTER))
                return false; // already attacking
        if(!(self.flags & FL_ONGROUND))
@@ -402,7 +403,7 @@ float Monster_Attack_Leap_Check(vector vel)
 }
 
 bool Monster_Attack_Leap(vector anm, void() touchfunc, vector vel, float animtime)
-{
+{SELFPARAM();
        if(!Monster_Attack_Leap_Check(vel))
                return false;
 
@@ -434,7 +435,7 @@ void Monster_Attack_Check(entity e, entity targ)
 
        if(targ_vlen <= e.attack_range)
        {
-               float attack_success = e.monster_attackfunc(MONSTER_ATTACK_MELEE);
+               float attack_success = e.monster_attackfunc(MONSTER_ATTACK_MELEE, targ);
                if(attack_success == 1)
                        Monster_Sound(monstersound_melee, 0, false, CH_VOICE);
                else if(attack_success > 0)
@@ -443,7 +444,7 @@ void Monster_Attack_Check(entity e, entity targ)
 
        if(targ_vlen > e.attack_range)
        {
-               float attack_success = e.monster_attackfunc(MONSTER_ATTACK_RANGED);
+               float attack_success = e.monster_attackfunc(MONSTER_ATTACK_RANGED, targ);
                if(attack_success == 1)
                        Monster_Sound(monstersound_melee, 0, false, CH_VOICE);
                else if(attack_success > 0)
@@ -457,7 +458,7 @@ void Monster_Attack_Check(entity e, entity targ)
 // ======================
 
 void Monster_UpdateModel()
-{
+{SELFPARAM();
        // assume some defaults
        /*self.anim_idle   = animfixfps(self, '0 1 0.01', '0 0 0');
        self.anim_walk   = animfixfps(self, '1 1 0.01', '0 0 0');
@@ -471,11 +472,12 @@ void Monster_UpdateModel()
        self.anim_die2   = animfixfps(self, '9 1 0.01', '0 0 0');*/
 
        // then get the real values
-       MON_ACTION(self.monsterid, MR_ANIM);
+       Monster mon = get_monsterinfo(self.monsterid);
+       mon.mr_anim(mon);
 }
 
 void Monster_Touch()
-{
+{SELFPARAM();
        if(other == world) { return; }
 
        if(other.monster_attack)
@@ -486,7 +488,7 @@ void Monster_Touch()
 }
 
 void Monster_Miniboss_Check()
-{
+{SELFPARAM();
        if(MUTATOR_CALLHOOK(MonsterCheckBossFlag))
                return;
 
@@ -503,7 +505,7 @@ void Monster_Miniboss_Check()
 }
 
 bool Monster_Respawn_Check()
-{
+{SELFPARAM();
        if(self.deadflag == DEAD_DEAD) // don't call when monster isn't dead
        if(MUTATOR_CALLHOOK(MonsterRespawn, self))
                return true; // enabled by a mutator
@@ -517,10 +519,10 @@ bool Monster_Respawn_Check()
        return true;
 }
 
-void Monster_Respawn() { Monster_Spawn(self.monsterid); }
+void Monster_Respawn() { SELFPARAM(); Monster_Spawn(self.monsterid); }
 
 void Monster_Dead_Fade()
-{
+{SELFPARAM();
        if(Monster_Respawn_Check())
        {
                self.spawnflags |= MONSTERFLAG_RESPAWNED;
@@ -538,7 +540,7 @@ void Monster_Dead_Fade()
                setorigin(self, self.pos1);
                self.angles = self.pos2;
                self.health = self.max_health;
-               setmodel(self, "null");
+               setmodel(self, MDL_Null);
        }
        else
        {
@@ -550,12 +552,12 @@ void Monster_Dead_Fade()
 }
 
 void Monster_Use()
-{
+{SELFPARAM();
        if(Monster_ValidTarget(self, activator)) { self.enemy = activator; }
 }
 
 vector Monster_Move_Target(entity targ)
-{
+{SELFPARAM();
        // enemy is always preferred target
        if(self.enemy)
        {
@@ -664,7 +666,7 @@ vector Monster_Move_Target(entity targ)
 }
 
 void Monster_CalculateVelocity(entity mon, vector to, vector from, float turnrate, float movespeed)
-{
+{SELFPARAM();
        float current_distance = vlen((('1 0 0' * to.x) + ('0 1 0' * to.y)) - (('1 0 0' * from.x) + ('0 1 0' * from.y))); // for the sake of this check, exclude Z axis
        float initial_height = 0; //min(50, (targ_distance * tanh(20)));
        float current_height = (initial_height * min(1, (self.pass_distance) ? (current_distance / self.pass_distance) : current_distance));
@@ -698,7 +700,7 @@ void Monster_CalculateVelocity(entity mon, vector to, vector from, float turnrat
 }
 
 void Monster_Move(float runspeed, float walkspeed, float stpspeed)
-{
+{SELFPARAM();
        if(self.target2) { self.goalentity = find(world, targetname, self.target2); }
 
        entity targ;
@@ -831,7 +833,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
                                self.moveto = WarpZone_RefSys_TransformOrigin(self.enemy, self, (0.5 * (self.enemy.absmin + self.enemy.absmax)));
                                self.monster_moveto = '0 0 0';
                                self.monster_face = '0 0 0';
-                               
+
                                self.pass_distance = vlen((('1 0 0' * self.enemy.origin_x) + ('0 1 0' * self.enemy.origin_y)) - (('1 0 0' *  self.origin_x) + ('0 1 0' *  self.origin_y)));
                                Monster_Sound(monstersound_sight, 0, false, CH_VOICE);
                        }
@@ -924,7 +926,7 @@ void Monster_Remove(entity mon)
 }
 
 void Monster_Dead_Think()
-{
+{SELFPARAM();
        self.nextthink = time + self.ticrate;
 
        if(self.monster_lifetime != 0)
@@ -936,7 +938,7 @@ void Monster_Dead_Think()
 }
 
 void Monster_Appear()
-{
+{SELFPARAM();
        self.enemy = activator;
        self.spawnflags &= ~MONSTERFLAG_APPEAR; // otherwise, we get an endless loop
        Monster_Spawn(self.monsterid);
@@ -957,7 +959,7 @@ float Monster_Appear_Check(entity ent, float monster_id)
 }
 
 void Monster_Reset()
-{
+{SELFPARAM();
        setorigin(self, self.pos1);
        self.angles = self.pos2;
 
@@ -972,7 +974,7 @@ void Monster_Reset()
 }
 
 void Monster_Dead_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        self.health -= damage;
 
        Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
@@ -991,7 +993,7 @@ void Monster_Dead_Damage(entity inflictor, entity attacker, float damage, int de
 }
 
 void Monster_Dead(entity attacker, float gibbed)
-{
+{SELFPARAM();
        self.think = Monster_Dead_Think;
        self.nextthink = time;
        self.monster_lifetime = time + 5;
@@ -1035,17 +1037,18 @@ void Monster_Dead(entity attacker, float gibbed)
        if(!((self.flags & FL_FLY) || (self.flags & FL_SWIM)))
                self.velocity = '0 0 0';
 
-       CSQCModel_UnlinkEntity();
+       CSQCModel_UnlinkEntity(self);
 
-       MON_ACTION(self.monsterid, MR_DEATH);
+       Monster mon = get_monsterinfo(self.monsterid);
+       mon.mr_death(mon);
 
        if(self.candrop && self.weapon)
                W_ThrowNewWeapon(self, self.weapon, 0, self.origin, randomvec() * 150 + '0 0 325');
 }
 
 void Monster_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
-       if((self.spawnflags & MONSTERFLAG_INVINCIBLE) && deathtype != DEATH_KILL)
+{SELFPARAM();
+       if((self.spawnflags & MONSTERFLAG_INVINCIBLE) && deathtype != DEATH_KILL && !ITEM_DAMAGE_NEEDKILL(deathtype))
                return;
 
        if(self.frozen && deathtype != DEATH_KILL && deathtype != DEATH_NADE_ICE_FREEZE)
@@ -1070,7 +1073,8 @@ void Monster_Damage(entity inflictor, entity attacker, float damage, int deathty
        damage_take = take;
        frag_attacker = attacker;
        frag_deathtype = deathtype;
-       MON_ACTION(self.monsterid, MR_PAIN);
+       Monster mon = get_monsterinfo(self.monsterid);
+       mon.mr_pain(mon);
        take = damage_take;
 
        if(take)
@@ -1085,7 +1089,7 @@ void Monster_Damage(entity inflictor, entity attacker, float damage, int deathty
        self.dmg_time = time;
 
        if(sound_allowed(MSG_BROADCAST, attacker) && deathtype != DEATH_DROWN)
-               spamsound (self, CH_PAIN, "misc/bodyimpact1.wav", VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
+               spamsound (self, CH_PAIN, SND(BODYIMPACT1), VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
 
        self.velocity += force * self.damageforcescale;
 
@@ -1128,7 +1132,7 @@ void Monster_Damage(entity inflictor, entity attacker, float damage, int deathty
 
 // don't check for enemies, just keep walking in a straight line
 void Monster_Move_2D(float mspeed, float allow_jumpoff)
-{
+{SELFPARAM();
        if(gameover || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || self.draggedby != world || time < game_starttime || (autocvar_g_campaign && !campaign_bots_may_start) || time < self.spawn_time)
        {
                mspeed = 0;
@@ -1140,22 +1144,22 @@ void Monster_Move_2D(float mspeed, float allow_jumpoff)
 
        float reverse = FALSE;
        vector a, b;
-       
+
        makevectors(self.angles);
        a = self.origin + '0 0 16';
        b = self.origin + '0 0 16' + v_forward * 32;
-       
+
        traceline(a, b, MOVE_NORMAL, self);
-       
+
        if(trace_fraction != 1.0)
        {
                reverse = TRUE;
-               
+
                if(trace_ent)
                if(IS_PLAYER(trace_ent) && !(trace_ent.items & IT_STRENGTH))
                        reverse = FALSE;
        }
-       
+
        // TODO: fix this... tracing is broken if the floor is thin
        /*
        if(!allow_jumpoff)
@@ -1165,13 +1169,13 @@ void Monster_Move_2D(float mspeed, float allow_jumpoff)
                if(trace_fraction == 1.0)
                        reverse = TRUE;
        } */
-       
+
        if(reverse)
        {
                self.angles_y = anglemods(self.angles_y - 180);
                makevectors(self.angles);
        }
-       
+
        movelib_move_simple_gravity(v_forward, mspeed, 1);
 
        if(time > self.pain_finished)
@@ -1183,7 +1187,7 @@ void Monster_Move_2D(float mspeed, float allow_jumpoff)
 }
 
 void Monster_Anim()
-{
+{SELFPARAM();
        int deadbits = (self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
        if(self.deadflag)
        {
@@ -1220,7 +1224,7 @@ void Monster_Anim()
 }
 
 void Monster_Think()
-{
+{SELFPARAM();
        self.think = Monster_Think;
        self.nextthink = self.ticrate;
 
@@ -1231,17 +1235,19 @@ void Monster_Think()
                return;
        }
 
-       if(MON_ACTION(self.monsterid, MR_THINK))
+       Monster mon = get_monsterinfo(self.monsterid);
+       if(mon.mr_think(mon))
                Monster_Move(self.speed2, self.speed, self.stopspeed);
 
        Monster_Anim();
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 float Monster_Spawn_Setup()
-{
-       MON_ACTION(self.monsterid, MR_SETUP);
+{SELFPARAM();
+       Monster mon = get_monsterinfo(self.monsterid);
+       mon.mr_setup(mon);
 
        // ensure some basic needs are met
        if(!self.health) { self.health = 100; }
@@ -1300,14 +1306,13 @@ float Monster_Spawn_Setup()
 }
 
 bool Monster_Spawn(int mon_id)
-{
+{SELFPARAM();
        // setup the basic required properties for a monster
        entity mon = get_monsterinfo(mon_id);
        if(!mon.monsterid) { return false; } // invalid monster
 
        if(!autocvar_g_monsters) { Monster_Remove(self); return false; }
 
-       self.mdl = mon.model;
        if(Monster_Appear_Check(self, mon_id)) { return true; } // return true so the monster isn't removed
 
        if(!self.monster_skill)
@@ -1325,7 +1330,7 @@ bool Monster_Spawn(int mon_id)
        if(!(self.spawnflags & MONSTERFLAG_RESPAWNED)) // don't count re-spawning monsters either
                monsters_total += 1;
 
-       setmodel(self, self.mdl);
+       setmodel(self, mon.m_model);
        self.flags                              = FL_MONSTER;
        self.classname                  = "monster";
        self.takedamage                 = DAMAGE_AIM;
@@ -1361,7 +1366,7 @@ bool Monster_Spawn(int mon_id)
        self.monster_moveto             = '0 0 0';
        self.monster_face               = '0 0 0';
        self.dphitcontentsmask  = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_BOTCLIP | DPCONTENTS_MONSTERCLIP;
-       
+
        if(!self.scale) { self.scale = 1; }
        if(autocvar_g_monsters_edit) { self.grab = 1; }
        if(autocvar_g_fullbrightplayers) { self.effects |= EF_FULLBRIGHT; }
@@ -1400,7 +1405,7 @@ bool Monster_Spawn(int mon_id)
        if(!(self.spawnflags & MONSTERFLAG_RESPAWNED))
                monster_setupcolors(self);
 
-       CSQCMODEL_AUTOINIT();
+       CSQCMODEL_AUTOINIT(self);
 
        return true;
 }
index 6cf28d6f1724bf6d1342c487cb10b6fe2848c973..b636772687ebdc66113ffec3ad69fdabe7995082 100644 (file)
@@ -1,5 +1,5 @@
 void _Movetype_Physics_Follow() // SV_Physics_Follow
-{
+{SELFPARAM();
        entity e = self.move_aiment; // TODO: networking?
 
        // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects
index e92e81a0dad19b2757fbc534c61659427295788a..cfa6346dc44178904f2003208d28e4a63198bb1e 100644 (file)
@@ -33,20 +33,16 @@ void _Movetype_WallFriction(vector stepnormal)  // SV_WallFriction
 
 vector planes[MAX_CLIP_PLANES];
 int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
-{
+{SELFPARAM();
        int blocked = 0, bumpcount;
        int i, j, numplanes = 0;
        float time_left = dt, grav = 0;
        vector push;
-       vector primal_velocity, original_velocity, new_velocity = '0 0 0', restore_velocity;
+       vector primal_velocity, original_velocity, restore_velocity;
 
-       for(i = 0; i <= MAX_CLIP_PLANES; ++i)
+       for(i = 0; i < MAX_CLIP_PLANES; ++i)
                planes[i] = '0 0 0';
 
-       grav = 0;
-
-       restore_velocity = self.move_velocity;
-
        if(applygravity)
        {
                self.move_didgravity = 1;
@@ -61,15 +57,17 @@ int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float step
                }
        }
 
-       original_velocity = primal_velocity = self.move_velocity;
+       original_velocity = primal_velocity = restore_velocity = self.move_velocity;
 
        for(bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
        {
-               if(!self.move_velocity_x && !self.move_velocity_y && !self.move_velocity_z)
+               if(self.move_velocity == '0 0 0')
                        break;
 
                push = self.move_velocity * time_left;
-               if(!_Movetype_PushEntity(push, false))
+               vector prev_origin = self.move_origin;
+               _Movetype_PushEntity(push, true);
+               if(trace_startsolid && self.move_origin != prev_origin)
                {
                        // we got teleported by a touch function
                        // let's abort the move
@@ -87,6 +85,10 @@ int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float step
 
                if(trace_fraction == 1)
                        break;
+
+               float my_trace_fraction = trace_fraction;
+               vector my_trace_plane_normal = trace_plane_normal;
+
                if(trace_plane_normal_z)
                {
                        if(trace_plane_normal_z > 0.7)
@@ -107,45 +109,40 @@ int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float step
                else if(stepheight)
                {
                        // step - handle it immediately
-                       vector org;
-                       vector steppush;
-                       //Con_Printf("step %f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
-                       steppush = '0 0 1' * stepheight;
-                       org = self.move_origin;
-                       if(!_Movetype_PushEntity(steppush, false))
+                       vector org = self.move_origin;
+                       vector steppush = '0 0 1' * stepheight;
+
+                       _Movetype_PushEntity(steppush, true);
+                       if(trace_startsolid && self.move_origin != org)
                        {
                                blocked |= 8;
                                break;
                        }
-                       //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
-                       if(!_Movetype_PushEntity(push, false))
+                       _Movetype_PushEntity(push, true);
+                       if(trace_startsolid && self.move_origin != org)
                        {
                                blocked |= 8;
                                break;
                        }
                        float trace2_fraction = trace_fraction;
-                       //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
                        steppush = '0 0 1' * (org_z - self.move_origin_z);
-                       if(!_Movetype_PushEntity(steppush, false))
+                       _Movetype_PushEntity(steppush, true);
+                       if(trace_startsolid && self.move_origin != org)
                        {
                                blocked |= 8;
                                break;
                        }
-                       //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+
                        // accept the new position if it made some progress...
                        if(fabs(self.move_origin_x - org_x) >= 0.03125 || fabs(self.move_origin_y - org_y) >= 0.03125)
                        {
-                               //Con_Printf("accepted (delta %f %f %f)\n", self.move_origin_x - org_x, PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
                                trace_endpos = self.move_origin;
                                time_left *= 1 - trace2_fraction;
                                numplanes = 0;
                                continue;
                        }
                        else
-                       {
-                               //Con_Printf("REJECTED (delta %f %f %f)\n", self.move_origin_x - org_x, PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
                                self.move_origin = org;
-                       }
                }
                else
                {
@@ -155,14 +152,15 @@ int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float step
                        if(stepnormal)
                                stepnormal = trace_plane_normal;
                }
-               if(trace_fraction >= 0.001)
+
+               if(my_trace_fraction >= 0.001)
                {
                        // actually covered some distance
                        original_velocity = self.move_velocity;
                        numplanes = 0;
                }
 
-               time_left *= 1 - trace_fraction;
+               time_left *= 1 - my_trace_fraction;
 
                // clipped to another plane
                if(numplanes >= MAX_CLIP_PLANES)
@@ -173,10 +171,11 @@ int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float step
                        break;
                }
 
-               planes[numplanes] = trace_plane_normal;
+               planes[numplanes] = my_trace_plane_normal;
                numplanes++;
 
                // modify original_velocity so it parallels all of the clip planes
+               vector new_velocity = '0 0 0';
                for (i = 0;i < numplanes;i++)
                {
                        new_velocity = _Movetype_ClipVelocity(original_velocity, planes[i], 1);
@@ -207,10 +206,7 @@ int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float step
                                blocked = 7;
                                break;
                        }
-                       vector dir;
-                       dir.x = planes[0].y * planes[1].z - planes[0].z * planes[1].y;
-                       dir.y = planes[0].z * planes[1].x - planes[0].x * planes[1].z;
-                       dir.z = planes[0].x * planes[1].y - planes[0].y * planes[1].x;
+                       vector dir = cross(planes[0], planes[1]);
                        // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
                        float ilength = sqrt((dir * dir));
                        if(ilength)
@@ -321,8 +317,7 @@ void _Movetype_CheckWaterTransition(entity ent)  // SV_CheckWaterTransition
 }
 
 void _Movetype_Impact(entity oth)  // SV_Impact
-{
-       entity oldself = self;
+{SELFPARAM();
        entity oldother = other;
 
        if(self.move_touch)
@@ -337,26 +332,23 @@ void _Movetype_Impact(entity oth)  // SV_Impact
        if(oth.move_touch)
        {
                other = self;
-               self = oth;
 
-               self.move_touch();
+               WITH(entity, self, oth, oth.move_touch());
 
-               self = oldself;
                other = oldother;
        }
 }
 
 void _Movetype_LinkEdict_TouchAreaGrid()  // SV_LinkEdict_TouchAreaGrid
-{
-       entity oldself = self;
+{SELFPARAM();
        entity oldother = other;
 
        for (entity e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
        {
-               if(e.move_touch && boxesoverlap(e.absmin, e.absmax, oldself.absmin, oldself.absmax))
+               if(e.move_touch && boxesoverlap(e.absmin, e.absmax, this.absmin, this.absmax))
                {
-                       self = e;
-                       other = oldself;
+                       setself(e);
+                       other = this;
 
                        trace_allsolid = false;
                        trace_startsolid = false;
@@ -366,18 +358,18 @@ void _Movetype_LinkEdict_TouchAreaGrid()  // SV_LinkEdict_TouchAreaGrid
                        trace_endpos = e.origin;
                        trace_plane_normal = '0 0 1';
                        trace_plane_dist = 0;
-                       trace_ent = oldself;
+                       trace_ent = this;
 
                        e.move_touch();
                }
        }
 
        other = oldother;
-       self = oldself;
+       setself(this);
 }
 
 void _Movetype_LinkEdict(bool touch_triggers)  // SV_LinkEdict
-{
+{SELFPARAM();
        vector mi, ma;
        if(self.solid == SOLID_BSP)
        {
@@ -420,7 +412,7 @@ void _Movetype_LinkEdict(bool touch_triggers)  // SV_LinkEdict
 }
 
 bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
-{
+{SELFPARAM();
 //     vector org = self.move_origin + ofs;
 
        int cont = self.dphitcontentsmask;
@@ -437,7 +429,7 @@ bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
 }
 
 bool _Movetype_UnstickEntity()  // SV_UnstickEntity
-{
+{SELFPARAM();
        if(!_Movetype_TestEntityPosition('0 0 0')) return true;
        if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
        if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
@@ -474,7 +466,7 @@ vector _Movetype_ClipVelocity(vector vel, vector norm, float f)  // SV_ClipVeloc
 }
 
 void _Movetype_PushEntityTrace(vector push)
-{
+{SELFPARAM();
        vector end = self.move_origin + push;
        int type;
        if(self.move_nomonsters)
@@ -490,7 +482,7 @@ void _Movetype_PushEntityTrace(vector push)
 }
 
 float _Movetype_PushEntity(vector push, bool failonstartsolid)  // SV_PushEntity
-{
+{SELFPARAM();
        _Movetype_PushEntityTrace(push);
 
        if(trace_startsolid && failonstartsolid)
@@ -564,7 +556,7 @@ void makevectors_matrix(vector myangles)  // AngleVectorsFLU
 }
 
 void _Movetype_Physics_Frame(float movedt)
-{
+{SELFPARAM();
        self.move_didgravity = -1;
        switch (self.move_movetype)
        {
@@ -600,7 +592,7 @@ void _Movetype_Physics_Frame(float movedt)
 }
 
 void Movetype_Physics_NoMatchServer()  // optimized
-{
+{SELFPARAM();
        float movedt = time - self.move_time;
        self.move_time = time;
 
@@ -620,7 +612,7 @@ void Movetype_Physics_MatchServer(bool sloppy)
 }
 
 void Movetype_Physics_MatchTicrate(float tr, bool sloppy)  // SV_Physics_Entity
-{
+{SELFPARAM();
        if(tr <= 0)
        {
                Movetype_Physics_NoMatchServer();
index 954033edbe9f59256914958a0963b2fd29f6b90b..aeb75ded3053773acb45263e9fb46fe86636079b 100644 (file)
@@ -1,5 +1,5 @@
 void _Movetype_PushMove(float dt)  // SV_PushMove
-{
+{SELFPARAM();
        if (self.move_velocity == '0 0 0' && self.move_avelocity == '0 0 0')
        {
                self.move_ltime += dt;
@@ -93,26 +93,23 @@ void _Movetype_PushMove(float dt)  // SV_PushMove
                        if (check.move_movetype == 32)  // MOVETYPE_PHYSICS
                        {
                                check.move_origin = check.move_origin + move;
-                               entity oldself = self;
-                               self = check;
-                               _Movetype_LinkEdict(true);
-                               self = oldself;
+                               WITH(entity, self, check, _Movetype_LinkEdict(true));
                                continue;
                        }
 
                        // try moving the contacted entity
                        self.solid = SOLID_NOT;
-                       entity oldself = self;
-                       self = check;
-                       if (!_Movetype_PushEntity(move, true))
+                       bool flag;
+                       WITH(entity, self, check, {
+                               flag = _Movetype_PushEntity(move, true);
+                       });
+                       if (!flag)
                        {
-                               self = oldself;
                                // entity "check" got teleported
                                check.move_angles_y += trace_fraction * moveangle.y;
                                self.solid = savesolid;
                                continue;  // pushed enough
                        }
-                       self = oldself;
                        // FIXME: turn players specially
                        check.move_angles_y += trace_fraction * moveangle.y;
                        self.solid = savesolid;
@@ -131,7 +128,7 @@ void _Movetype_PushMove(float dt)  // SV_PushMove
 }
 
 void _Movetype_Physics_Pusher(float dt)  // SV_Physics_Pusher
-{
+{SELFPARAM();
        float oldltime = self.move_ltime;
        float thinktime = self.move_nextthink;
        float movetime;
index 822bf093511606dc3faacd664f9984c07ae746d2..f4884ba27a23a5137af32c369dade827dc06d282 100644 (file)
@@ -1,5 +1,5 @@
 void _Movetype_Physics_Step(float dt) // SV_Physics_Step
-{
+{SELFPARAM();
        if(self.move_flags & FL_ONGROUND)
        {
                if(self.velocity_z >= (1.0 / 32.0) && UPWARD_VELOCITY_CLEARS_ONGROUND)
index 6ed0407eb30f80c2776e34551191d636efe37da3..32ce9ca31223f4afd2b42c00259ec2fce1e3f214 100644 (file)
@@ -1,7 +1,7 @@
 #include "../physics.qh"
 
 void _Movetype_Physics_Toss(float dt)  // SV_Physics_Toss
-{
+{SELFPARAM();
        if (self.move_flags & FL_ONGROUND)
        {
                if (self.move_velocity.z >= 1 / 32)
index 180dfcc7fb5a2b793d95d9a643298cf9e26bd895..0f18a47bfc6ee4bcc487f464ddd6eeb625e615ef 100644 (file)
@@ -1,5 +1,5 @@
 void _Movetype_Physics_Walk(float dt)  // SV_WalkMove
-{
+{SELFPARAM();
        vector stepnormal = '0 0 0';
 
        // if frametime is 0 (due to client sending the same timestamp twice), don't move
@@ -89,7 +89,11 @@ void _Movetype_Physics_Walk(float dt)  // SV_WalkMove
 
                // move up
                vector upmove = '0 0 1' * PHYS_STEPHEIGHT;
-               if (!_Movetype_PushEntity(upmove, true))
+               vector prev_origin = self.move_origin;
+               _Movetype_PushEntity(upmove, true);
+               if(wasfreed(self))
+                       return;
+               if(trace_startsolid && self.move_origin != prev_origin)
                {
                        // we got teleported when upstepping... must abort the move
                        return;
@@ -130,7 +134,7 @@ void _Movetype_Physics_Walk(float dt)  // SV_WalkMove
                // Con_Printf("step - ");
 
                // extra friction based on view angle
-               if (clip & 2 && PHYS_WALLFRICTION)
+               if ((clip & 2) && PHYS_WALLFRICTION)
                        _Movetype_WallFriction(stepnormal);
        }
        // don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
@@ -141,7 +145,12 @@ void _Movetype_Physics_Walk(float dt)  // SV_WalkMove
 
        // move down
        vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT + start_velocity.z * dt);
-       if (!_Movetype_PushEntity(downmove, true))
+       vector prev_origin = self.move_origin;
+       _Movetype_PushEntity(downmove, true);
+       if(wasfreed(self))
+               return;
+
+       if(trace_startsolid && self.move_origin != prev_origin)
        {
                // we got teleported when downstepping... must abort the move
                return;
index d92bd5b57c90b43c60180a25c18a3af381a5c68b..6e1c7c051aab09b2b11a6a2a5efdc0a5462fd398 100644 (file)
@@ -155,7 +155,7 @@ CLASS(Mutator, Object)
     }
 ENDCLASS(Mutator)
 
-const int MAX_MUTATORS = 15;
+const int MAX_MUTATORS = 30;
 Mutator loaded_mutators[MAX_MUTATORS];
 
 bool Mutator_Add(Mutator mut)
@@ -220,7 +220,7 @@ noref int MUTATORS_COUNT;
         bool ret = MUTATORFUNCTION_##id##_hooks(mode); if (ret) return ret; \
     } \
     bool MUTATOR_##id##_check() { return dependence; } \
-    REGISTER(RegisterMutators, MUTATOR, MUTATORS, MUTATORS_COUNT, id, m_id, NEW(Mutator, #id, MUTATORFUNCTION_##id)) \
+    REGISTER(RegisterMutators, MUTATOR, MUTATORS, id, m_id, NEW(Mutator, #id, MUTATORFUNCTION_##id)) \
     { this.mutatorcheck = MUTATOR_##id##_check; } \
     [[accumulate]] bool MUTATORFUNCTION_##id(int mode)
 
@@ -247,14 +247,14 @@ STATIC_INIT_LATE(Mutators) {
     [[accumulate]] void RegisterCallbacks() { CALLBACK_##name = NEW(Callback, func); }
 
 #define MUTATOR_HOOKFUNCTION(...) \
-    OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__)
+    EVAL(OVERLOAD(MUTATOR_HOOKFUNCTION, __VA_ARGS__))
 
 #define MUTATOR_HOOKFUNCTION_1(name) \
     _MUTATOR_CALLBACK(name, HOOKFUNCTION_##name) \
     bool HOOKFUNCTION_##name()
 
 #define MUTATOR_HOOKFUNCTION_2(mut, cb) \
-    MUTATOR_HOOKFUNCTION(mut, cb, CBC_ORDER_ANY)
+    MUTATOR_HOOKFUNCTION_3(mut, cb, CBC_ORDER_ANY)
 
 #define MUTATOR_HOOKFUNCTION_3(mut, cb, order) \
     _MUTATOR_CALLBACK(mut##_##cb, mut##_##cb) \
index a9a86f81f1984e331a60ccc541b5f89c9af4de4d..9ed5fefa7ac5b85b6eaeea351324e44acc7648a2 100644 (file)
@@ -9,7 +9,7 @@ REGISTER_MUTATOR(casings, true);
 
 #ifdef SVQC
 void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float randomavel, int casingtype, entity casingowner)
-{
+{SELFPARAM();
     vector org = self.origin + self.view_ofs + self.weaponentity.spawnorigin.x * v_forward - self.weaponentity.spawnorigin.y * v_right + self.weaponentity.spawnorigin.z * v_up;
 
     if (!sound_allowed(MSG_BROADCAST, casingowner))
@@ -36,11 +36,11 @@ class(Casing) .int state;
 class(Casing) .float cnt;
 
 void Casing_Delete()
-{
+{SELFPARAM();
     remove(self);
 }
 
-void Casing_Draw()
+void Casing_Draw(entity this)
 {
     if (self.move_flags & FL_ONGROUND)
     {
@@ -63,8 +63,21 @@ void Casing_Draw()
     }
 }
 
+SOUND(BRASS1, W_Sound("brass1"));
+SOUND(BRASS2, W_Sound("brass2"));
+SOUND(BRASS3, W_Sound("brass3"));
+Sound SND_BRASS_RANDOM() {
+    return Sounds[SND_BRASS1.m_id + floor(prandom() * 3)];
+}
+SOUND(CASINGS1, W_Sound("casings1"));
+SOUND(CASINGS2, W_Sound("casings2"));
+SOUND(CASINGS3, W_Sound("casings3"));
+Sound SND_CASINGS_RANDOM() {
+    return Sounds[SND_CASINGS1.m_id + floor(prandom() * 3)];
+}
+
 void Casing_Touch()
-{
+{SELFPARAM();
     if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
     {
         Casing_Delete();
@@ -78,16 +91,14 @@ void Casing_Touch()
         {
             if (time >= self.nextthink)
             {
-                string s;
-                int f = floor(prandom() * 3) + 1;
-
+                Sound s;
                 switch (self.state)
                 {
                     case 1:
-                        s = W_Sound(strcat("casings", itos(f)));
+                        s = SND_CASINGS_RANDOM();
                         break;
                     default:
-                        s = W_Sound(strcat("brass", itos(f)));
+                        s = SND_BRASS_RANDOM();
                         break;
                 }
 
@@ -100,7 +111,7 @@ void Casing_Touch()
 }
 
 void Casing_Damage(float thisdmg, int hittype, vector org, vector thisforce)
-{
+{SELFPARAM();
     if (thisforce.z < 0)
         thisforce.z = 0;
     self.move_velocity = self.move_velocity + thisforce + '0 0 100';
@@ -149,11 +160,11 @@ MUTATOR_HOOKFUNCTION(casings, CSQC_Parse_TempEntity)
     switch (casing.state)
     {
         case 1:
-            setmodel(casing, "models/casing_shell.mdl");
+            setmodel(casing, MDL_CASING_SHELL);
             casing.cnt = time + autocvar_cl_casings_shell_time;
             break;
         default:
-            setmodel(casing, "models/casing_bronze.iqm");
+            setmodel(casing, MDL_CASING_BULLET);
             casing.cnt = time + autocvar_cl_casings_bronze_time;
             break;
     }
@@ -163,15 +174,4 @@ MUTATOR_HOOKFUNCTION(casings, CSQC_Parse_TempEntity)
     RubbleLimit("casing", autocvar_cl_casings_maxcount, Casing_Delete);
 }
 
-STATIC_INIT(Casings)
-{
-    precache_model("models/casing_shell.mdl");
-    precache_model("models/casing_bronze.iqm");
-    precache_sound(W_Sound("brass1"));
-    precache_sound(W_Sound("brass2"));
-    precache_sound(W_Sound("brass3"));
-    precache_sound(W_Sound("casings1"));
-    precache_sound(W_Sound("casings2"));
-    precache_sound(W_Sound("casings3"));
-}
 #endif
index eec2d356b01b72ca3f9ef6509b2e026a872a0227..e4e4be5e8792eaafacd152d1db9546c99c4b0115 100644 (file)
@@ -24,8 +24,7 @@ CLASS(DamageText, Object)
     ATTRIB(DamageText, m_armordamage, int, 0)
     ATTRIB(DamageText, time_prev, float, time)
 
-    void DamageText_draw() {
-        entity this = self;
+    void DamageText_draw2d(DamageText this) {
         float dt = time - this.time_prev;
         this.time_prev = time;
         setorigin(this, this.origin + dt * this.velocity);
@@ -38,7 +37,7 @@ CLASS(DamageText, Object)
             drawcolorcodedstring2(pos, s, this.m_size * '1 1 0', this.m_color, this.alpha, DRAWFLAG_NORMAL);
         }
     }
-    ATTRIB(DamageText, draw2d, void(), DamageText_draw)
+    ATTRIB(DamageText, draw2d, void(DamageText), DamageText_draw2d)
 
     void DamageText_update(DamageText this, vector _origin, int _health, int _armor) {
         this.m_damage = _health;
index c3a025080d39315274a0676db7812d682001fc47..1d615b7c0607623312b7f4ad95978cb27f53f6cb 100644 (file)
@@ -12,8 +12,8 @@ void IT_Write(entity e, int i, float f) {
 #endif
 
 #ifdef CSQC
-float ItemsTime_time[MAX_ITEMS];
-float ItemsTime_availableTime[MAX_ITEMS];
+float ItemsTime_time[Items_MAX];
+float ItemsTime_availableTime[Items_MAX];
 MUTATOR_HOOKFUNCTION(itemstime, CSQC_Parse_TempEntity) {
     if (MUTATOR_RETURNVALUE) return false;
     if (!ReadMutatorEquals(mutator_argv_int_0, itemstime)) return false;
@@ -60,11 +60,11 @@ bool Item_ItemsTime_Allow(GameItem it, WepSet _weapons)
 
 #ifdef SVQC
 
-float it_times[MAX_ITEMS];
+float it_times[Items_MAX];
 
 void Item_ItemsTime_Init()
 {
-    FOREACH(ITEMS, true, LAMBDA(
+    FOREACH(Items, true, LAMBDA(
         it_times[it.m_id] = -1;
     ));
 }
@@ -76,21 +76,21 @@ STATIC_INIT(ItemsTime_Init) {
 
 void Item_ItemsTime_ResetTimes()
 {
-    FOREACH(ITEMS, true, LAMBDA(
+    FOREACH(Items, true, LAMBDA(
         it_times[it.m_id] = (it_times[it.m_id] == -1) ? -1 : 0;
     ));
 }
 
 void Item_ItemsTime_ResetTimesForPlayer(entity e)
 {
-    FOREACH(ITEMS, true, LAMBDA(
+    FOREACH(Items, true, LAMBDA(
         IT_Write(e, it.m_id, (it_times[it.m_id] == -1) ? -1 : 0);
     ));
 }
 
 void Item_ItemsTime_SetTimesForPlayer(entity e)
 {
-    FOREACH(ITEMS, true, LAMBDA(
+    FOREACH(Items, true, LAMBDA(
         IT_Write(e, it.m_id, it_times[it.m_id]);
     ));
 }
@@ -118,7 +118,7 @@ float Item_ItemsTime_UpdateTime(entity e, float t)
     {
         for (entity head = world; (head = nextent(head)); )
         {
-            if (clienttype(head) != CLIENTTYPE_NOTACLIENT || !(head.weapons & WEPSET_SUPERWEAPONS) || head.classname == "weapon_info")
+            if (clienttype(head) != CLIENTTYPE_NOTACLIENT || !(head.weapons & WEPSET_SUPERWEAPONS) || head.instanceOfWeapon)
                 continue;
             if (e == head)
                 continue;
@@ -149,24 +149,28 @@ float Item_ItemsTime_UpdateTime(entity e, float t)
     return t;
 }
 
-MUTATOR_HOOKFUNCTION(itemstime, reset_map_global) {
+MUTATOR_HOOKFUNCTION(itemstime, reset_map_global)
+{SELFPARAM();
     Item_ItemsTime_ResetTimes();
     // ALL the times need to be reset before .reset()ing each item
     // since Item_Reset schedules respawn of superweapons and powerups
-    for (self = world; (self = nextent(self)); )
-    if (IS_NOT_A_CLIENT(self))
+    for (entity e = NULL; (e = nextent(e)); )
+    if (IS_NOT_A_CLIENT(e))
     {
+        setself(e);
         if (self.reset)
             Item_ItemsTime_SetTime(self, 0);
     }
     Item_ItemsTime_SetTimesForAllPlayers();
 }
 
-MUTATOR_HOOKFUNCTION(itemstime, MakePlayerObserver) {
+MUTATOR_HOOKFUNCTION(itemstime, MakePlayerObserver)
+{SELFPARAM();
     Item_ItemsTime_SetTimesForPlayer(self);
 }
 
-MUTATOR_HOOKFUNCTION(itemstime, PlayerSpawn) {
+MUTATOR_HOOKFUNCTION(itemstime, PlayerSpawn)
+{SELFPARAM();
     if (warmup_stage) return;
     Item_ItemsTime_ResetTimesForPlayer(self);
 }
@@ -228,10 +232,15 @@ void DrawItemsTimeItem(vector myPos, vector mySize, float ar, entity item, float
         HUD_Panel_DrawProgressBar(p_pos, p_size, autocvar_hud_panel_itemstime_progressbar_name, t/autocvar_hud_panel_itemstime_progressbar_maxtime, 0, autocvar_hud_panel_itemstime_iconalign, color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
     }
 
-    if (t > 0 && autocvar_hud_panel_itemstime_text)
-        drawstring_aspect(numpos, ftos(t), eX * ((ar - 1)/ar) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
-    else
-        picpos.x = myPos.x + mySize.x / 2 - mySize.y / 2;
+    if(autocvar_hud_panel_itemstime_text)
+    {
+        if(t > 0)
+            drawstring_aspect(numpos, ftos(t), eX * ((ar - 1)/ar) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
+        else if(precache_pic("gfx/hud/default/checkmark")) // COMPAT: check if this image exists, as 0.8.1 clients lack it
+            drawpic_aspect_skin(numpos, "checkmark", eX * (ar - 1) * mySize_y + eY * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL);
+        else // legacy code, if the image is missing just center the icon
+            picpos.x = myPos.x + mySize.x / 2 - mySize.y / 2;
+    }
     if (item_availableTime)
         drawpic_aspect_skin_expanding(picpos, item.m_icon, '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL, item_availableTime);
     drawpic_aspect_skin(picpos, item.m_icon, '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL);
@@ -256,16 +265,16 @@ void HUD_ItemsTime()
 
     int count = 0;
     if (autocvar_hud_panel_itemstime_hidespawned == 1)
-        FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
-            count += (ItemsTime_time[i] > time || -ItemsTime_time[i] > time);
+        FOREACH(Items, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
+            count += (ItemsTime_time[it.m_id] > time || -ItemsTime_time[it.m_id] > time);
         ));
     else if (autocvar_hud_panel_itemstime_hidespawned == 2)
-        FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
-            count += (ItemsTime_time[i] > time);
+        FOREACH(Items, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
+            count += (ItemsTime_time[it.m_id] > time);
         ));
     else
-        FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
-            count += (ItemsTime_time[i] != -1);
+        FOREACH(Items, Item_ItemsTime_Allow(it, '0 0 0'), LAMBDA(
+            count += (ItemsTime_time[it.m_id] != -1);
         ));
     if (count == 0)
         return;
@@ -337,8 +346,8 @@ void HUD_ItemsTime()
 
     float row = 0, column = 0;
     bool item_available;
-    FOREACH(ITEMS, Item_ItemsTime_Allow(it, '0 0 0') && ItemsTime_time[i] != -1, LAMBDA(
-        float item_time = ItemsTime_time[i];
+    FOREACH(Items, Item_ItemsTime_Allow(it, '0 0 0') && ItemsTime_time[it.m_id] != -1, LAMBDA(
+        float item_time = ItemsTime_time[it.m_id];
         if (item_time < -1)
         {
             item_available = true;
@@ -347,25 +356,25 @@ void HUD_ItemsTime()
         else
             item_available = (item_time <= time);
 
-        if (ItemsTime_time[i] >= 0)
+        if (ItemsTime_time[it.m_id] >= 0)
         {
-            if (time <= ItemsTime_time[i])
-                ItemsTime_availableTime[i] = 0;
-            else if (ItemsTime_availableTime[i] == 0)
-                ItemsTime_availableTime[i] = time;
+            if (time <= ItemsTime_time[it.m_id])
+                ItemsTime_availableTime[it.m_id] = 0;
+            else if (ItemsTime_availableTime[it.m_id] == 0)
+                ItemsTime_availableTime[it.m_id] = time;
         }
-        else if (ItemsTime_availableTime[i] == 0)
-            ItemsTime_availableTime[i] = time;
+        else if (ItemsTime_availableTime[it.m_id] == 0)
+            ItemsTime_availableTime[it.m_id] = time;
 
-        float f = (time - ItemsTime_availableTime[i]) * 2;
+        float f = (time - ItemsTime_availableTime[it.m_id]) * 2;
         f = (f > 1) ? 0 : bound(0, f, 1);
 
         if (autocvar_hud_panel_itemstime_hidespawned == 1)
-            if (!(ItemsTime_time[i] > time || -ItemsTime_time[i] > time))
+            if (!(ItemsTime_time[it.m_id] > time || -ItemsTime_time[it.m_id] > time))
                 continue;
 
         if (autocvar_hud_panel_itemstime_hidespawned == 2)
-            if (!(ItemsTime_time[i] > time))
+            if (!(ItemsTime_time[it.m_id] > time))
                 continue;
 
         DrawItemsTimeItem(pos + eX * column * (itemstime_size.x + offset.x) + eY * row * (itemstime_size.y + offset.y), itemstime_size, ar, it, item_time, item_available, f);
index e1153c2b82fdb0d41066b64605c65bb491b37051..47fafe7ed5490169352a47e918ec4ea7f781b0a6 100644 (file)
@@ -1,6 +1,4 @@
 /** If you register a new waypoint, make sure to add it to this list */
-REGISTER_WAYPOINT(, "", '0 0 0', 1);
-#define WP_Null WP_
 
 REGISTER_WAYPOINT(Waypoint, _("Waypoint"), '0 1 1', 1);
 REGISTER_WAYPOINT(Helpme, _("Help me!"), '1 0.5 0', 1);
index 790d08698858a2ff4c9b910f3bdf12a26f87d34d..f7fd03837d46449f3d28df90dbe615aeade36813 100644 (file)
@@ -3,13 +3,10 @@
 
 #include "waypointsprites.qh"
 
-void RegisterWaypoints();
-const int MAX_WAYPOINTS = 240;
-entity WAYPOINTS[MAX_WAYPOINTS], WAYPOINTS_first, WAYPOINTS_last;
-int WAYPOINT_COUNT;
-/** If you register a new waypoint, make sure to add it to all.inc */
-#define REGISTER_WAYPOINT_(id, init) REGISTER(RegisterWaypoints, WP, WAYPOINTS, WAYPOINT_COUNT, id, m_id, init)
+REGISTRY(Waypoints, BIT(6))
 REGISTER_REGISTRY(RegisterWaypoints)
+/** If you register a new waypoint, make sure to add it to all.inc */
+#define REGISTER_WAYPOINT_(id, init) REGISTER(RegisterWaypoints, WP, Waypoints, id, m_id, init)
 
 CLASS(Waypoint, Object)
     ATTRIB(Waypoint, m_id, int, 0)
@@ -28,6 +25,34 @@ ENDCLASS(Waypoint)
 
 #define REGISTER_WAYPOINT(id, text, color, blink) REGISTER_WAYPOINT_(id, NEW(Waypoint, #id, text, color, blink))
 
+REGISTRY(RadarIcons, BITS(7))
+REGISTER_REGISTRY(RegisterRadarIcons)
+.int m_radaricon;
+#define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { this.m_radaricon = num; this.netname = #id; }
+
+REGISTER_WAYPOINT(Null, "", '0 0 0', 1);
+
+REGISTER_RADARICON(NONE,            0);
+REGISTER_RADARICON(FLAG,            1);
+REGISTER_RADARICON(FLAGCARRIER,     1);
+
+// TODO make these 3 and 4, and make images for them
+REGISTER_RADARICON(HERE,            1);
+REGISTER_RADARICON(DANGER,          1);
+
+REGISTER_RADARICON(WAYPOINT,        1);
+REGISTER_RADARICON(HELPME,          1);
+REGISTER_RADARICON(CONTROLPOINT,    1);
+REGISTER_RADARICON(GENERATOR,       1);
+REGISTER_RADARICON(OBJECTIVE,       1);
+REGISTER_RADARICON(DOMPOINT,        1);
+REGISTER_RADARICON(TAGGED,          1);
+
+REGISTER_RADARICON(Buff,            1);
+REGISTER_RADARICON(Item,            1);
+REGISTER_RADARICON(Vehicle,         1);
+REGISTER_RADARICON(Weapon,          1);
+
 #include "all.inc"
 
 #endif
index 8673b96b35717946d6ce952dc62afe25a564035b..3be3266bc359be9870c31068e2f6a32b0df15882 100644 (file)
@@ -4,7 +4,7 @@ REGISTER_MUTATOR(waypointsprites, true);
 
 #ifdef SVQC
 /** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */
-float WaypointSprite_SendEntity(entity to, float sendflags)
+bool WaypointSprite_SendEntity(entity this, entity to, float sendflags)
 {
     WriteMutator(MSG_ENTITY, waypointsprites);
 
@@ -118,7 +118,7 @@ MUTATOR_HOOKFUNCTION(waypointsprites, CSQC_Ent_Update) {
 }
 
 void Ent_RemoveWaypointSprite()
-{
+{SELFPARAM();
     if (self.netname) strunzone(self.netname);
     if (self.netname2) strunzone(self.netname2);
     if (self.netname3) strunzone(self.netname3);
@@ -126,7 +126,7 @@ void Ent_RemoveWaypointSprite()
 
 /** flags origin [team displayrule] [spritename] [spritename2] [spritename3] [lifetime maxdistance hideable] */
 void Ent_WaypointSprite()
-{
+{SELFPARAM();
     int sendflags = ReadByte();
     self.wp_extra = ReadByte();
 
@@ -210,8 +210,8 @@ void Ent_WaypointSprite()
     if (sendflags & 32)
     {
         int f = ReadByte();
-        self.teamradar_icon = (f & 0x7F);
-        if (f & 0x80)
+        self.teamradar_icon = f & BITS(7);
+        if (f & BIT(7))
         {
             self.(teamradar_times[self.teamradar_time_index]) = time;
             self.teamradar_time_index = (self.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES;
@@ -232,50 +232,38 @@ void Ent_WaypointSprite()
 
 #ifdef CSQC
 float spritelookupblinkvalue(string s)
-{
+{SELFPARAM();
     if (s == WP_Weapon.netname) {
         if (get_weaponinfo(self.wp_extra).spawnflags & WEP_FLAG_SUPERWEAPON)
             return 2;
     }
-    if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_waypointblink;
+    if (s == WP_Item.netname) return Items[self.wp_extra].m_waypointblink;
 
-    switch (s)
-    {
-        case "item-invis":       return 2;
-        case "item-extralife":   return 2;
-        case "item-speed":       return 2;
-        default:                 return 1;
-    }
+    return 1;
 }
 
-vector spritelookupcolor(string s, vector def)
+vector spritelookupcolor(entity this, string s, vector def)
 {
-    if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).wpcolor;
-    if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_color;
-    if (s == WP_Buff.netname) return BUFFS[self.wp_extra].m_color;
+    if (s == WP_Weapon.netname  || s == RADARICON_Weapon.netname) return get_weaponinfo(this.wp_extra).wpcolor;
+    if (s == WP_Item.netname    || s == RADARICON_Item.netname) return Items[this.wp_extra].m_color;
+    if (s == WP_Buff.netname    || s == RADARICON_Buff.netname) return Buffs[this.wp_extra].m_color;
     return def;
 }
 
 string spritelookuptext(string s)
-{
+{SELFPARAM();
     if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
     if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).message;
-    if (s == WP_Item.netname) return ITEMS[self.wp_extra].m_waypoint;
-    if (s == WP_Buff.netname) return BUFFS[self.wp_extra].m_prettyName;
+    if (s == WP_Item.netname) return Items[self.wp_extra].m_waypoint;
+    if (s == WP_Buff.netname) return Buffs[self.wp_extra].m_prettyName;
     if (s == WP_Monster.netname) return get_monsterinfo(self.wp_extra).monster_name;
 
     // need to loop, as our netname could be one of three
-    FOREACH(WAYPOINTS, it.netname == s, LAMBDA(
+    FOREACH(Waypoints, it.netname == s, LAMBDA(
         return it.m_name;
     ));
 
-    switch (s)
-    {
-        case "item-invis": return _("Invisibility");
-        case "item-extralife": return _("Extra life");
-        case "item-speed": return _("Speed");
-        default: return s;
-    }
+    return s;
 }
 #endif
 
@@ -467,7 +455,7 @@ vector fixrgbexcess(vector rgb)
     return rgb;
 }
 
-void Draw_WaypointSprite()
+void Draw_WaypointSprite(entity this)
 {
     if (self.lifetime)
         self.alpha = pow(bound(0, (self.fadetime - time) / self.lifetime, 1), waypointsprite_timealphaexponent);
@@ -541,7 +529,7 @@ void Draw_WaypointSprite()
     else if (self.maxdistance > 0)
         a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
 
-    vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+    vector rgb = spritelookupcolor(self, spriteimage, self.teamradar_color);
     if (rgb == '0 0 0')
     {
         self.teamradar_color = '1 0 1';
@@ -839,10 +827,11 @@ void WaypointSprite_UpdateRule(entity e, float t, float r)
     e.SendFlags |= 1;
 }
 
-void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col)
+void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col)
 {
     // no check, as this is never called without doing an actual change (usually only once)
-    e.cnt = (icon & 0x7F) | (e.cnt & 0x80);
+    int i = icon.m_id;
+    e.cnt = (e.cnt & BIT(7)) | (i & BITS(7));
     e.colormod = col;
     e.SendFlags |= 32;
 }
@@ -853,7 +842,7 @@ void WaypointSprite_Ping(entity e)
     if (time < e.waypointsprite_pingtime) return;
     e.waypointsprite_pingtime = time + 0.3;
     // ALWAYS sends (this causes a radar circle), thus no check
-    e.cnt |= 0x80;
+    e.cnt |= BIT(7);
     e.SendFlags |= 32;
 }
 
@@ -924,7 +913,7 @@ void WaypointSprite_Disown(entity wp, float fadetime)
 }
 
 void WaypointSprite_Think()
-{
+{SELFPARAM();
     bool doremove = false;
 
     if (self.fade_time && time >= self.teleport_time)
@@ -942,7 +931,7 @@ void WaypointSprite_Think()
 }
 
 float WaypointSprite_visible_for_player(entity e)
-{
+{SELFPARAM();
     // personal waypoints
     if (self.enemy && self.enemy != e)
         return false;
@@ -984,7 +973,7 @@ float WaypointSprite_isteammate(entity e, entity e2)
 }
 
 float WaypointSprite_Customize()
-{
+{SELFPARAM();
     // this is not in SendEntity because it shall run every frame, not just every update
 
     // make spectators see what the player would see
@@ -996,10 +985,10 @@ float WaypointSprite_Customize()
     return self.waypointsprite_visible_for_player(e);
 }
 
-float WaypointSprite_SendEntity(entity to, float sendflags);
+bool WaypointSprite_SendEntity(entity this, entity to, float sendflags);
 
 void WaypointSprite_Reset()
-{
+{SELFPARAM();
     // if a WP wants to time out, let it time out immediately; other WPs ought to be reset/killed by their owners
 
     if (self.fade_time) // there was there before: || g_keyhunt, do we really need this?
@@ -1013,7 +1002,7 @@ entity WaypointSprite_Spawn(
     entity showto, float t, // show to whom? Use a flag to indicate a team
     entity own, .entity ownfield, // remove when own gets killed
     float hideable, // true when it should be controlled by cl_hidewaypoints
-    float icon // initial icon
+    entity icon // initial icon
 )
 {
     entity wp = new(sprite_waypoint);
@@ -1045,7 +1034,7 @@ entity WaypointSprite_Spawn(
     wp.customizeentityforclient = WaypointSprite_Customize;
     wp.waypointsprite_visible_for_player = WaypointSprite_visible_for_player;
     wp.reset2 = WaypointSprite_Reset;
-    wp.cnt = icon;
+    wp.cnt = icon.m_id;
     wp.colormod = spr.m_color;
     Net_LinkEntity(wp, false, 0, WaypointSprite_SendEntity);
     return wp;
@@ -1056,7 +1045,7 @@ entity WaypointSprite_SpawnFixed(
     vector ofs,
     entity own,
     .entity ownfield,
-    float icon // initial icon
+    entity icon // initial icon
 )
 {
     return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, own, ownfield, true, icon);
@@ -1066,9 +1055,9 @@ entity WaypointSprite_DeployFixed(
     entity spr,
     float limited_range,
     vector ofs,
-    float icon // initial icon
+    entity icon // initial icon
 )
-{
+{SELFPARAM();
     float t;
     if (teamplay)
         t = self.team;
@@ -1085,18 +1074,18 @@ entity WaypointSprite_DeployFixed(
 entity WaypointSprite_DeployPersonal(
     entity spr,
     vector ofs,
-    float icon // initial icon
+    entity icon // initial icon
 )
-{
+{SELFPARAM();
     return WaypointSprite_Spawn(spr, 0, 0, world, ofs, world, 0, self, waypointsprite_deployed_personal, false, icon);
 }
 
 entity WaypointSprite_Attach(
     entity spr,
     float limited_range,
-    float icon // initial icon
+    entity icon // initial icon
 )
-{
+{SELFPARAM();
     float t;
     if (self.waypointsprite_attachedforcarrier)
         return world; // can't attach to FC
@@ -1115,7 +1104,7 @@ entity WaypointSprite_Attach(
 entity WaypointSprite_AttachCarrier(
     entity spr,
     entity carrier,
-    float icon // initial icon and color
+    entity icon // initial icon and color
 )
 {
     WaypointSprite_Kill(carrier.waypointsprite_attached); // FC overrides attached
@@ -1134,25 +1123,25 @@ void WaypointSprite_DetachCarrier(entity carrier)
 }
 
 void WaypointSprite_ClearPersonal()
-{
+{SELFPARAM();
     WaypointSprite_Kill(self.waypointsprite_deployed_personal);
 }
 
 void WaypointSprite_ClearOwned()
-{
+{SELFPARAM();
     WaypointSprite_Kill(self.waypointsprite_deployed_fixed);
     WaypointSprite_Kill(self.waypointsprite_deployed_personal);
     WaypointSprite_Kill(self.waypointsprite_attached);
 }
 
 void WaypointSprite_PlayerDead()
-{
+{SELFPARAM();
     WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime);
     WaypointSprite_DetachCarrier(self);
 }
 
 void WaypointSprite_PlayerGone()
-{
+{SELFPARAM();
     WaypointSprite_Disown(self.waypointsprite_deployed_fixed, waypointsprite_deadlifetime);
     WaypointSprite_Kill(self.waypointsprite_deployed_personal);
     WaypointSprite_Disown(self.waypointsprite_attached, waypointsprite_deadlifetime);
index d6ea51867e4a97a3f0a26a9d837d5f28bb5c1c0f..c9a553431940139b4fd58e8155b7ef7e32f09a84 100644 (file)
@@ -98,7 +98,7 @@ vector drawspritearrow(vector o, float ang, vector rgb, float a, float t);
 vector drawspritetext(vector o, float ang, float minwidth, vector rgb, float a, vector fontsize, string s);
 
 float spritelookupblinkvalue(string s);
-vector spritelookupcolor(string s, vector def);
+vector spritelookupcolor(entity this, string s, vector def);
 string spritelookuptext(string s);
 
 vector fixrgbexcess_move(vector rgb, vector src, vector dst);
@@ -114,7 +114,7 @@ void WaypointSprite_Load_Frames(string ext);
 
 void WaypointSprite_Load();
 .float alpha;
-void Draw_WaypointSprite();
+void Draw_WaypointSprite(entity this);
 #endif
 
 #ifdef SVQC
@@ -142,7 +142,7 @@ void WaypointSprite_UpdateOrigin(entity e, vector o);
 
 void WaypointSprite_UpdateRule(entity e, float t, float r);
 
-void WaypointSprite_UpdateTeamRadar(entity e, float icon, vector col);
+void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col);
 
 .float waypointsprite_pingtime;
 .float waypointsprite_helpmetime;
@@ -171,7 +171,7 @@ float WaypointSprite_isteammate(entity e, entity e2);
 
 float WaypointSprite_Customize();
 
-float WaypointSprite_SendEntity(entity to, float sendflags);
+bool WaypointSprite_SendEntity(entity this, entity to, float sendflags);
 
 void WaypointSprite_Reset();
 
@@ -182,7 +182,7 @@ entity WaypointSprite_Spawn(
     entity showto, float t, // show to whom? Use a flag to indicate a team
     entity own, .entity ownfield, // remove when own gets killed
     float hideable, // true when it should be controlled by cl_hidewaypoints
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 entity WaypointSprite_SpawnFixed(
@@ -190,7 +190,7 @@ entity WaypointSprite_SpawnFixed(
     vector ofs,
     entity own,
     .entity ownfield,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 .entity waypointsprite_deployed_fixed;
@@ -198,14 +198,14 @@ entity WaypointSprite_DeployFixed(
     entity spr,
     float limited_range,
     vector ofs,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 .entity waypointsprite_deployed_personal;
 entity WaypointSprite_DeployPersonal(
     entity spr,
     vector ofs,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 .entity waypointsprite_attached;
@@ -213,13 +213,13 @@ entity WaypointSprite_DeployPersonal(
 entity WaypointSprite_Attach(
     entity spr,
     float limited_range,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 entity WaypointSprite_AttachCarrier(
     entity spr,
     entity carrier,
-    float icon // initial icon
+    entity icon // initial icon
 );
 
 void WaypointSprite_DetachCarrier(entity carrier);
diff --git a/qcsrc/common/nades.qc b/qcsrc/common/nades.qc
deleted file mode 100644 (file)
index f9ddb8e..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "../client/defs.qh"
-       #include "nades.qh"
-       #include "buffs.qh"
-       #include "../common/movetypes/movetypes.qh"
-       #include "../client/main.qh"
-       #include "../csqcmodellib/cl_model.qh"
-#elif defined(MENUQC)
-#elif defined(SVQC)
-       #include "../dpdefs/progsdefs.qh"
-    #include "constants.qh"
-    #include "../server/constants.qh"
-       #include "../common/turrets/sv_turrets.qh"
-#endif
-
-
-#ifdef SVQC
-float healer_send(entity to, int sf)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_HEALING_ORB);
-       WriteByte(MSG_ENTITY, sf);
-
-       if(sf & 1)
-       {
-               WriteCoord(MSG_ENTITY, self.origin.x);
-               WriteCoord(MSG_ENTITY, self.origin.y);
-               WriteCoord(MSG_ENTITY, self.origin.z);
-
-               WriteByte(MSG_ENTITY, self.healer_lifetime);
-               //WriteByte(MSG_ENTITY, self.ltime - time + 1);
-               WriteShort(MSG_ENTITY, self.healer_radius);
-               // round time delta to a 1/10th of a second
-               WriteByte(MSG_ENTITY, (self.ltime - time)*10.0+0.5);
-       }
-
-       return true;
-}
-#endif // SVQC
-
-#ifdef CSQC
-.float ltime;
-void healer_draw()
-{
-       float dt = time - self.move_time;
-       self.move_time = time;
-       if(dt <= 0)
-               return;
-
-       self.alpha = (self.ltime - time) / self.healer_lifetime;
-       self.scale = min((1 - self.alpha)*self.healer_lifetime*4,1)*self.healer_radius;
-
-}
-
-void healer_setup()
-{
-       setmodel(self, "models/ctf/shield.md3");
-
-       setorigin(self, self.origin);
-
-       float model_radius = self.maxs.x;
-       vector size = '1 1 1' * self.healer_radius / 2;
-       setsize(self,-size,size);
-       self.healer_radius = self.healer_radius/model_radius*0.6;
-
-       self.draw = healer_draw;
-       self.health = 255;
-       self.movetype = MOVETYPE_NONE;
-       self.solid = SOLID_NOT;
-       self.drawmask = MASK_NORMAL;
-       self.scale = 0.01;
-       self.avelocity = self.move_avelocity = '7 0 11';
-       self.colormod = '1 0 0';
-       self.renderflags |= RF_ADDITIVE;
-}
-
-void ent_healer()
-{
-       int sf = ReadByte();
-
-       if(sf & TNSF_SETUP)
-       {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-               setorigin(self, self.origin);
-
-               self.healer_lifetime = ReadByte();
-               self.healer_radius = ReadShort();
-               self.ltime = time + ReadByte()/10.0;
-               //self.ltime = time + self.healer_lifetime;
-
-               healer_setup();
-       }
-}
-#endif // CSQC
diff --git a/qcsrc/common/nades.qh b/qcsrc/common/nades.qh
deleted file mode 100644 (file)
index 5a9877c..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-#ifndef NADES_H
-#define NADES_H
-
-#include "teams.qh"
-
-.float healer_lifetime;
-.float healer_radius;
-
-// use slots 70-100
-const int PROJECTILE_NADE = 71;
-const int PROJECTILE_NADE_BURN = 72;
-const int PROJECTILE_NADE_NAPALM = 73;
-const int PROJECTILE_NADE_NAPALM_BURN = 74;
-const int PROJECTILE_NAPALM_FOUNTAIN = 75;
-const int PROJECTILE_NADE_ICE = 76;
-const int PROJECTILE_NADE_ICE_BURN = 77;
-const int PROJECTILE_NADE_TRANSLOCATE = 78;
-const int PROJECTILE_NADE_SPAWN = 79;
-const int PROJECTILE_NADE_HEAL = 80;
-const int PROJECTILE_NADE_HEAL_BURN = 81;
-const int PROJECTILE_NADE_MONSTER = 82;
-const int PROJECTILE_NADE_MONSTER_BURN = 83;
-
-void RegisterNades();
-const int NADES_MAX = 8;
-entity NADES[NADES_MAX], NADES_first, NADES_last;
-int NADES_COUNT;
-#define REGISTER_NADE(id) REGISTER(RegisterNades, NADE_TYPE, NADES, NADES_COUNT, id, m_id, NEW(Nade))
-REGISTER_REGISTRY(RegisterNades)
-
-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, string, 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));
-    }
-ENDCLASS(Nade)
-
-REGISTER_NADE(NULL);
-
-#define NADE_PROJECTILE(i, projectile, trail) do { \
-    this.m_projectile[i] = projectile; \
-    this.m_trail[i] = trail; \
-} while (0)
-
-REGISTER_NADE(NORMAL) {
-    this.m_color = '1 1 1';
-    NADE_PROJECTILE(0, PROJECTILE_NADE, string_null);
-    NADE_PROJECTILE(1, PROJECTILE_NADE_BURN, string_null);
-}
-
-REGISTER_NADE(NAPALM) {
-    this.m_color = '2 0.5 0';
-    this.m_name = _("Napalm grenade");
-    this.m_icon = "nade_napalm";
-    NADE_PROJECTILE(0, PROJECTILE_NADE_NAPALM, "TR_ROCKET");
-    NADE_PROJECTILE(1, PROJECTILE_NADE_NAPALM_BURN, "spiderbot_rocket_thrust");
-}
-
-REGISTER_NADE(ICE) {
-    this.m_color = '0 0.5 2';
-    this.m_name = _("Ice grenade");
-    this.m_icon = "nade_ice";
-    NADE_PROJECTILE(0, PROJECTILE_NADE_ICE, "TR_NEXUIZPLASMA");
-    NADE_PROJECTILE(1, PROJECTILE_NADE_ICE_BURN, "wakizashi_rocket_thrust");
-}
-
-REGISTER_NADE(TRANSLOCATE) {
-    this.m_color = '1 0 1';
-    this.m_name = _("Translocate grenade");
-    this.m_icon = "nade_translocate";
-    NADE_PROJECTILE(0, PROJECTILE_NADE_TRANSLOCATE, "TR_CRYLINKPLASMA");
-    NADE_PROJECTILE(1, PROJECTILE_NADE_TRANSLOCATE, "TR_CRYLINKPLASMA");
-}
-
-REGISTER_NADE(SPAWN) {
-    this.m_color = '1 0.9 0';
-    this.m_name = _("Spawn grenade");
-    this.m_icon = "nade_spawn";
-    NADE_PROJECTILE(0, PROJECTILE_NADE_SPAWN, "nade_yellow");
-    NADE_PROJECTILE(1, PROJECTILE_NADE_SPAWN, "nade_yellow");
-}
-
-REGISTER_NADE(HEAL) {
-    this.m_color = '1 0 0';
-    this.m_name = _("Heal grenade");
-    this.m_icon = "nade_heal";
-    NADE_PROJECTILE(0, PROJECTILE_NADE_HEAL, "nade_red");
-    NADE_PROJECTILE(1, PROJECTILE_NADE_HEAL_BURN, "nade_red_burn");
-}
-
-REGISTER_NADE(MONSTER) {
-    this.m_color = '0.25 0.75 0';
-    this.m_name = _("Monster grenade");
-    this.m_icon = "nade_monster";
-    NADE_PROJECTILE(0, PROJECTILE_NADE_MONSTER, "nade_red");
-    NADE_PROJECTILE(1, PROJECTILE_NADE_MONSTER_BURN, "nade_red_burn");
-}
-
-entity Nade_FromProjectile(float proj)
-{
-    FOREACH(NADES, true, LAMBDA(
-        for (int j = 0; j < 2; j++)
-        {
-            if (it.m_projectile[j] == proj) return it;
-        }
-    ));
-    return NADE_TYPE_NULL;
-}
-
-string Nade_TrailEffect(float proj, float nade_team)
-{
-    FOREACH(NADES, true, LAMBDA(
-        for (int j = 0; j < 2; j++)
-        {
-            if (it.m_projectile[j] == proj)
-            {
-                string trail = it.m_trail[j];
-                if (trail) return trail;
-                break;
-            }
-        }
-    ));
-    switch (proj)
-    {
-        case PROJECTILE_NADE: return strcat("nade_", Static_Team_ColorName_Lower(nade_team));
-        case PROJECTILE_NADE_BURN: return strcat("nade_", Static_Team_ColorName_Lower(nade_team), "_burn");
-    }
-    return "";
-}
-
-#ifdef SVQC
-float healer_send(entity to, int sf);
-#endif
-
-#ifdef CSQC
-// misc functions
-void ent_healer();
-#endif // CSQC
-#endif
diff --git a/qcsrc/common/nades/all.inc b/qcsrc/common/nades/all.inc
new file mode 100644 (file)
index 0000000..90326ed
--- /dev/null
@@ -0,0 +1,58 @@
+#define NADE_PROJECTILE(i, projectile, trail) do { \
+    this.m_projectile[i] = projectile; \
+    this.m_trail[i] = trail; \
+} while (0)
+
+REGISTER_NADE(NORMAL) {
+    this.m_color = '1 1 1';
+    NADE_PROJECTILE(0, PROJECTILE_NADE, EFFECT_Null);
+    NADE_PROJECTILE(1, PROJECTILE_NADE_BURN, EFFECT_Null);
+}
+
+REGISTER_NADE(NAPALM) {
+    this.m_color = '2 0.5 0';
+    this.m_name = _("Napalm grenade");
+    this.m_icon = "nade_napalm";
+    NADE_PROJECTILE(0, PROJECTILE_NADE_NAPALM, EFFECT_TR_ROCKET);
+    NADE_PROJECTILE(1, PROJECTILE_NADE_NAPALM_BURN, EFFECT_SPIDERBOT_ROCKET_TRAIL);
+}
+
+REGISTER_NADE(ICE) {
+    this.m_color = '0 0.5 2';
+    this.m_name = _("Ice grenade");
+    this.m_icon = "nade_ice";
+    NADE_PROJECTILE(0, PROJECTILE_NADE_ICE, EFFECT_TR_NEXUIZPLASMA);
+    NADE_PROJECTILE(1, PROJECTILE_NADE_ICE_BURN, EFFECT_RACER_ROCKET_TRAIL);
+}
+
+REGISTER_NADE(TRANSLOCATE) {
+    this.m_color = '1 0 1';
+    this.m_name = _("Translocate grenade");
+    this.m_icon = "nade_translocate";
+    NADE_PROJECTILE(0, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA);
+    NADE_PROJECTILE(1, PROJECTILE_NADE_TRANSLOCATE, EFFECT_TR_CRYLINKPLASMA);
+}
+
+REGISTER_NADE(SPAWN) {
+    this.m_color = '1 0.9 0';
+    this.m_name = _("Spawn grenade");
+    this.m_icon = "nade_spawn";
+    NADE_PROJECTILE(0, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW);
+    NADE_PROJECTILE(1, PROJECTILE_NADE_SPAWN, EFFECT_NADE_TRAIL_YELLOW);
+}
+
+REGISTER_NADE(HEAL) {
+    this.m_color = '1 0 0';
+    this.m_name = _("Heal grenade");
+    this.m_icon = "nade_heal";
+    NADE_PROJECTILE(0, PROJECTILE_NADE_HEAL, EFFECT_NADE_TRAIL_RED);
+    NADE_PROJECTILE(1, PROJECTILE_NADE_HEAL_BURN, EFFECT_NADE_TRAIL_BURN_RED);
+}
+
+REGISTER_NADE(MONSTER) {
+    this.m_color = '0.25 0.75 0';
+    this.m_name = _("Monster grenade");
+    this.m_icon = "nade_monster";
+    NADE_PROJECTILE(0, PROJECTILE_NADE_MONSTER, EFFECT_NADE_TRAIL_RED);
+    NADE_PROJECTILE(1, PROJECTILE_NADE_MONSTER_BURN, EFFECT_NADE_TRAIL_BURN_RED);
+}
diff --git a/qcsrc/common/nades/all.qc b/qcsrc/common/nades/all.qc
new file mode 100644 (file)
index 0000000..90d7ca3
--- /dev/null
@@ -0,0 +1,92 @@
+#if defined(CSQC)
+       #include "../../dpdefs/csprogsdefs.qh"
+       #include "../../client/defs.qh"
+       #include "all.qh"
+       #include "../buffs/all.qh"
+       #include "../movetypes/movetypes.qh"
+       #include "../../client/main.qh"
+       #include "../../csqcmodellib/cl_model.qh"
+#elif defined(MENUQC)
+#elif defined(SVQC)
+       #include "../../dpdefs/progsdefs.qh"
+    #include "../constants.qh"
+    #include "../../server/constants.qh"
+       #include "../turrets/sv_turrets.qh"
+#endif
+
+
+#ifdef CSQC
+.float ltime;
+void healer_draw(entity this)
+{
+       float dt = time - self.move_time;
+       self.move_time = time;
+       if(dt <= 0)
+               return;
+
+       self.alpha = (self.ltime - time) / self.healer_lifetime;
+       self.scale = min((1 - self.alpha)*self.healer_lifetime*4,1)*self.healer_radius;
+}
+
+void healer_setup(entity e)
+{
+       setmodel(e, MDL_NADE_HEAL);
+
+       setorigin(e, e.origin);
+
+       float model_radius = e.maxs.x;
+       vector size = '1 1 1' * e.healer_radius / 2;
+       setsize(e,-size,size);
+       e.healer_radius = e.healer_radius/model_radius*0.6;
+
+       e.draw = healer_draw;
+       e.health = 255;
+       e.movetype = MOVETYPE_NONE;
+       e.solid = SOLID_NOT;
+       e.drawmask = MASK_NORMAL;
+       e.scale = 0.01;
+       e.avelocity = e.move_avelocity = '7 0 11';
+       e.colormod = '1 0 0';
+       e.renderflags |= RF_ADDITIVE;
+}
+#endif // CSQC
+
+REGISTER_NET_LINKED(Nade_Heal, bool isNew)
+#ifdef CSQC
+{
+       Net_Accept();
+       int sf = ReadByte();
+       if (sf & 1) {
+               this.origin_x = ReadCoord();
+               this.origin_y = ReadCoord();
+               this.origin_z = ReadCoord();
+               setorigin(this, this.origin);
+               this.healer_lifetime = ReadByte();
+               this.healer_radius = ReadShort();
+               this.ltime = time + ReadByte()/10.0;
+               // this.ltime = time + this.healer_lifetime;
+               healer_setup(this);
+       }
+}
+#endif
+
+#ifdef SVQC
+bool healer_send(entity this, entity to, int sf)
+{
+       int channel = MSG_ENTITY;
+       WriteHeader(channel, Nade_Heal);
+       WriteByte(channel, sf);
+       if (sf & 1) {
+               WriteCoord(channel, this.origin.x);
+               WriteCoord(channel, this.origin.y);
+               WriteCoord(channel, this.origin.z);
+
+               WriteByte(channel, this.healer_lifetime);
+               //WriteByte(MSG_ENTITY, this.ltime - time + 1);
+               WriteShort(channel, this.healer_radius);
+               // round time delta to a 1/10th of a second
+               WriteByte(channel, (this.ltime - time)*10.0+0.5);
+       }
+       return true;
+}
+#endif // SVQC
diff --git a/qcsrc/common/nades/all.qh b/qcsrc/common/nades/all.qh
new file mode 100644 (file)
index 0000000..ad51a1e
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef NADES_ALL_H
+#define NADES_ALL_H
+
+#include "../teams.qh"
+
+.float healer_lifetime;
+.float healer_radius;
+
+// use slots 70-100
+const int PROJECTILE_NADE = 71;
+const int PROJECTILE_NADE_BURN = 72;
+const int PROJECTILE_NADE_NAPALM = 73;
+const int PROJECTILE_NADE_NAPALM_BURN = 74;
+const int PROJECTILE_NAPALM_FOUNTAIN = 75;
+const int PROJECTILE_NADE_ICE = 76;
+const int PROJECTILE_NADE_ICE_BURN = 77;
+const int PROJECTILE_NADE_TRANSLOCATE = 78;
+const int PROJECTILE_NADE_SPAWN = 79;
+const int PROJECTILE_NADE_HEAL = 80;
+const int PROJECTILE_NADE_HEAL_BURN = 81;
+const int PROJECTILE_NADE_MONSTER = 82;
+const int PROJECTILE_NADE_MONSTER_BURN = 83;
+
+REGISTRY(Nades, BIT(3))
+REGISTER_REGISTRY(RegisterNades)
+#define REGISTER_NADE(id) REGISTER(RegisterNades, NADE_TYPE, Nades, 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)
+    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));
+    }
+ENDCLASS(Nade)
+
+REGISTER_NADE(Null);
+
+#ifdef SVQC
+bool healer_send(entity this, entity to, int sf);
+#endif
+
+entity Nade_FromProjectile(float proj)
+{
+    FOREACH(Nades, true, LAMBDA(
+        for (int j = 0; j < 2; j++)
+        {
+            if (it.m_projectile[j] == proj) return it;
+        }
+    ));
+    return NADE_TYPE_Null;
+}
+
+entity Nade_TrailEffect(int proj, int nade_team)
+{
+    switch (proj)
+    {
+        case PROJECTILE_NADE:       return EFFECT_NADE_TRAIL(nade_team);
+        case PROJECTILE_NADE_BURN:  return EFFECT_NADE_TRAIL_BURN(nade_team);
+    }
+
+    FOREACH(Nades, true, LAMBDA(
+        for (int j = 0; j < 2; j++)
+        {
+            if (it.m_projectile[j] == proj)
+            {
+                string trail = it.m_trail[j].eent_eff_name;
+                if (trail) return it.m_trail[j];
+                break;
+            }
+        }
+    ));
+
+    return EFFECT_Null;
+}
+
+#include "all.inc"
+
+#endif
index fb9958b08fcbd186fd151b65afb89462d442a357..f748f9903825ad96ec0073a99af653e533717278 100644 (file)
@@ -2,7 +2,7 @@
 
 #ifdef SVQC
 void sv_notice_join_think()
-{
+{SELFPARAM();
     //NextLevel();
     float argc = tokenizebyseparator(autocvar_sv_join_notices, "|");
     if(argc > 0)
@@ -15,7 +15,7 @@ void sv_notice_join_think()
 }
 
 void sv_notice_join()
-{
+{SELFPARAM();
     // to-do: make sv_join_notices support per-entry times
     if(autocvar_sv_join_notices == "")
         return;
index 5145e5340cff8f3a78748bb88c1d107e90ac8e08..13097a425f01b65388324e75f4d73a796a6f3d0f 100644 (file)
@@ -69,7 +69,7 @@ string Notification_CheckArgs_TypeName(float net_type, float net_name)
 {
        // check supplied type and name for errors
        string checkargs = "";
-       #define CHECKARG_TYPENAME(type) case MSG_##type##: \
+       #define CHECKARG_TYPENAME(type) case MSG_##type: \
                { if(!net_name || (net_name > NOTIF_##type##_COUNT)) \
                { checkargs = sprintf("Improper name: %d!", net_name); } break; }
        switch(net_type)
@@ -1286,7 +1286,7 @@ void Local_Notification_sound(
                ));
                #endif
 
-               sound(
+               _sound(
                        world,
                        soundchannel,
                        sprintf(
@@ -1550,7 +1550,7 @@ void Local_Notification(int net_type, int net_name, ...count)
 
                case MSG_INFO:
                {
-                       LOG_INFO(
+                       print(
                                Local_Notification_sprintf(
                                        notif.nent_string,
                                        notif.nent_args,
@@ -1756,7 +1756,7 @@ void Read_Notification(float is_new)
 
 #ifdef SVQC
 void Net_Notification_Remove()
-{
+{SELFPARAM();
        if (!self) { backtrace(sprintf("Net_Notification_Remove() at %f: Missing self!?\n", time)); return; }
 
        #ifdef NOTIFICATIONS_DEBUG
@@ -1773,7 +1773,7 @@ void Net_Notification_Remove()
        remove(self);
 }
 
-float Net_Write_Notification(entity client, int sf)
+bool Net_Write_Notification(entity this, entity client, int sf)
 {
        if(Notification_ShouldSend(self.nent_broadcast, client, self.nent_client))
        {
index 2fbc9cdf0e67154affb28ff7f62bdb3be2600fe0..01d6cbe5538e2207c295c08906ca543aa8c40acf 100644 (file)
@@ -265,8 +265,8 @@ const float ARG_DC = 6; // unique result to durcnt/centerprint
     ARG_CASE(ARG_CS_SV,     "spree_end",     (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \
     ARG_CASE(ARG_CS_SV,     "spree_lost",    (autocvar_notification_show_sprees ? notif_arg_spree_inf(-2, "", "", f1) : "")) \
     ARG_CASE(ARG_CS_SV,     "item_wepname",  WEP_NAME(f1)) \
-    ARG_CASE(ARG_CS_SV,     "item_buffname", sprintf("%s%s", rgb_to_hexcolor(BUFFS[f1].m_color), BUFFS[f1].m_prettyName)) \
-    ARG_CASE(ARG_CS_SV,     "f3buffname",    sprintf("%s%s", rgb_to_hexcolor(BUFFS[f3].m_color), BUFFS[f3].m_prettyName)) \
+    ARG_CASE(ARG_CS_SV,     "item_buffname", sprintf("%s%s", rgb_to_hexcolor(Buffs[f1].m_color), Buffs[f1].m_prettyName)) \
+    ARG_CASE(ARG_CS_SV,     "f3buffname",    sprintf("%s%s", rgb_to_hexcolor(Buffs[f3].m_color), Buffs[f3].m_prettyName)) \
     ARG_CASE(ARG_CS_SV,     "item_wepammo",  (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \
     ARG_CASE(ARG_DC,        "item_centime",  ftos(autocvar_notification_item_centerprinttime)) \
     ARG_CASE(ARG_SV,        "death_team",    Team_ColoredFullName(f1)) \
@@ -623,7 +623,7 @@ float notif_global_error;
             NO_MSG,   /* optiona     */ \
             NO_MSG);  /* optionb     */ \
     } \
-    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
 #define MSG_INFO_NOTIF(default,name,strnum,flnum,args,hudargs,icon,normal,gentle) \
     NOTIF_ADD_AUTOCVAR(name, default) \
@@ -665,7 +665,7 @@ float notif_global_error;
             NO_MSG,   /* optiona     */ \
             NO_MSG);  /* optionb     */ \
     } \
-    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
 .string nent_iconargs;
 #define MULTIICON_INFO(default,name,strnum,flnum,args,hudargs,iconargs,icon,normal,gentle) \
@@ -709,7 +709,7 @@ float notif_global_error;
             NO_MSG);  /* optionb     */ \
         msg_info_notifs[name - 1].nent_iconargs = iconargs; \
     } \
-    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
 #define MSG_CENTER_NOTIF(default,name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
     NOTIF_ADD_AUTOCVAR(name, default) \
@@ -751,7 +751,7 @@ float notif_global_error;
             NO_MSG,   /* optiona     */ \
             NO_MSG);  /* optionb     */ \
     } \
-    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
 #define MSG_MULTI_NOTIF(default,name,anncename,infoname,centername) \
     NOTIF_ADD_AUTOCVAR(name, default) \
@@ -793,7 +793,7 @@ float notif_global_error;
             NO_MSG,   /* optiona     */ \
             NO_MSG);  /* optionb     */ \
     } \
-    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
 #define ACVNN(name) autocvar_notification_##name
 
@@ -838,7 +838,7 @@ float notif_global_error;
             optiona,                                 /* optiona     */ \
             optionb);                                /* optionb     */ \
     } \
-    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name);
+    ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
 
 void RegisterNotifications_First()
 {
@@ -882,8 +882,8 @@ void RegisterNotifications_Done()
 }
 
 // NOW we actually activate the declarations
-ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_First);
+ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_First)
 #include "notifications.inc"
-ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_Done);
+ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_Done)
 
 #endif
index b53696b987b18ad7604406bde27eac5763560db3..cb823b1074c8ee19ed2048831b5e2b7f5d82cb89 100644 (file)
@@ -25,15 +25,15 @@ float Physics_ClientOption(entity pl, string option)
 {
        if(Physics_Valid(pl.cvar_cl_physics))
        {
-               string var = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
-               if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
-                       return cvar(var);
+               string s = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
+               if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
+                       return cvar(s);
        }
        if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default)
        {
-               string var = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option);
-               if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
-                       return cvar(var);
+               string s = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option);
+               if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
+                       return cvar(s);
        }
        return cvar(strcat("sv_", option));
 }
@@ -78,7 +78,8 @@ void Physics_AddStats()
        addstat(STAT_JETPACK_MAXSPEED_SIDE, AS_FLOAT, stat_jetpack_maxspeed_side);
 
        // hack to fix track_canjump
-       addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
+       addstat(STAT_MOVEVARS_CL_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
+       addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, stat_sv_track_canjump);
 
        // double jump
        addstat(STAT_DOUBLEJUMP, AS_INT, stat_doublejump);
@@ -116,7 +117,7 @@ void Physics_AddStats()
 }
 
 void Physics_UpdateStats(float maxspd_mod)
-{
+{SELFPARAM();
        // blah
        self.stat_pl_view_ofs = PL_VIEW_OFS;
        self.stat_pl_crouch_view_ofs = PL_CROUCH_VIEW_OFS;
@@ -175,6 +176,8 @@ void Physics_UpdateStats(float maxspd_mod)
        self.stat_sv_airstopaccelerate = Physics_ClientOption(self, "airstopaccelerate");
        self.stat_sv_jumpvelocity = Physics_ClientOption(self, "jumpvelocity");
 
+       self.stat_sv_track_canjump = Physics_ClientOption(self, "track_canjump");
+
        self.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND;
 }
 #endif
@@ -222,7 +225,7 @@ vector unstick_offsets[unstick_count] =
 };
 
 void PM_ClientMovement_Unstick()
-{
+{SELFPARAM();
        float i;
        for (i = 0; i < unstick_count; i++)
        {
@@ -237,7 +240,7 @@ void PM_ClientMovement_Unstick()
 }
 
 void PM_ClientMovement_UpdateStatus(bool ground)
-{
+{SELFPARAM();
        // make sure player is not stuck
        PM_ClientMovement_Unstick();
 
@@ -308,7 +311,7 @@ void PM_ClientMovement_UpdateStatus(bool ground)
 }
 
 void PM_ClientMovement_Move()
-{
+{SELFPARAM();
 #ifdef CSQC
        int bump;
        float t;
@@ -397,7 +400,7 @@ void PM_ClientMovement_Move()
 }
 
 void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
-{
+{SELFPARAM();
        float k = 32 * (2 * IsMoveInDirection(self.movement, 0) - 1);
        if (k <= 0)
                return;
@@ -434,7 +437,7 @@ float AdjustAirAccelQW(float accelqw, float factor)
 //   prvm_globalset server speedclamp_mode 1
 //     (or 2)
 void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
-{
+{SELFPARAM();
        float speedclamp = stretchfactor > 0 ? stretchfactor
        : accelqw < 0 ? 1 // full clamping, no stretch
        : -1; // no clamping
@@ -498,7 +501,7 @@ void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float acce
 }
 
 void PM_AirAccelerate(vector wishdir, float wishspeed)
-{
+{SELFPARAM();
        if (wishspeed == 0)
                return;
 
@@ -541,7 +544,7 @@ returns true if handled
 =============
 */
 bool PlayerJump (void)
-{
+{SELFPARAM();
        if (PHYS_FROZEN(self))
                return true; // no jumping in freezetag when frozen
 
@@ -591,7 +594,11 @@ bool PlayerJump (void)
                if (!IS_ONGROUND(self))
                        return IS_JUMP_HELD(self);
 
-       if (PHYS_TRACK_CANJUMP(self))
+       bool track_jump = PHYS_CL_TRACK_CANJUMP(self);
+       if(PHYS_TRACK_CANJUMP(self))
+               track_jump = true;
+
+       if (track_jump)
                if (IS_JUMP_HELD(self))
                        return true;
 
@@ -657,7 +664,7 @@ bool PlayerJump (void)
 }
 
 void CheckWaterJump()
-{
+{SELFPARAM();
 // check for a jump-out-of-water
        makevectors(self.v_angle);
        vector start = self.origin;
@@ -697,7 +704,7 @@ void CheckWaterJump()
 // Hack: shouldn't need to know about this
 .float multijump_count;
 void CheckPlayerJump()
-{
+{SELFPARAM();
 #ifdef SVQC
        float was_flying = ITEMS_STAT(self) & IT_USING_JETPACK;
 #endif
@@ -757,7 +764,7 @@ float racecar_angle(float forward, float down)
 }
 
 void RaceCarPhysics()
-{
+{SELFPARAM();
 #ifdef SVQC
        // using this move type for "big rigs"
        // the engine does not push the entity!
@@ -977,7 +984,7 @@ void SpecialCommand()
 }
 
 void PM_check_race_movetime(void)
-{
+{SELFPARAM();
 #ifdef SVQC
        self.race_movetime_frac += PHYS_INPUT_TIMELENGTH;
        float f = floor(self.race_movetime_frac);
@@ -988,7 +995,7 @@ void PM_check_race_movetime(void)
 }
 
 float PM_check_specialcommand(float buttons)
-{
+{SELFPARAM();
 #ifdef SVQC
        string c;
        if (!buttons)
@@ -1025,7 +1032,7 @@ float PM_check_specialcommand(float buttons)
 }
 
 void PM_check_nickspam(void)
-{
+{SELFPARAM();
 #ifdef SVQC
        if (time >= self.nickspamtime)
                return;
@@ -1047,7 +1054,7 @@ void PM_check_nickspam(void)
 }
 
 void PM_check_punch()
-{
+{SELFPARAM();
 #ifdef SVQC
        if (self.punchangle != '0 0 0')
        {
@@ -1070,7 +1077,7 @@ void PM_check_punch()
 }
 
 void PM_check_spider(void)
-{
+{SELFPARAM();
 #ifdef SVQC
        if (time >= self.spider_slowness)
                return;
@@ -1083,7 +1090,7 @@ void PM_check_spider(void)
 
 // predict frozen movement, as frozen players CAN move in some cases
 void PM_check_frozen(void)
-{
+{SELFPARAM();
        if (!PHYS_FROZEN(self))
                return;
        if (PHYS_DODGING_FROZEN
@@ -1110,7 +1117,7 @@ void PM_check_frozen(void)
 }
 
 void PM_check_hitground()
-{
+{SELFPARAM();
 #ifdef SVQC
        if (IS_ONGROUND(self))
        if (IS_PLAYER(self)) // no fall sounds for observers thank you very much
@@ -1137,7 +1144,7 @@ void PM_check_hitground()
 }
 
 void PM_check_blocked(void)
-{
+{SELFPARAM();
 #ifdef SVQC
        if (!self.player_blocked)
                return;
@@ -1151,7 +1158,7 @@ float speedaward_lastsent;
 float speedaward_lastupdate;
 #endif
 void PM_check_race(void)
-{
+{SELFPARAM();
 #ifdef SVQC
        if(!(g_cts || g_race))
                return;
@@ -1181,7 +1188,7 @@ void PM_check_race(void)
 }
 
 void PM_check_vortex(void)
-{
+{SELFPARAM();
 #ifdef SVQC
        // WEAPONTODO
        float xyspeed = vlen(vec2(self.velocity));
@@ -1197,7 +1204,7 @@ void PM_check_vortex(void)
 }
 
 void PM_fly(float maxspd_mod)
-{
+{SELFPARAM();
        // noclipping or flying
        UNSET_ONGROUND(self);
 
@@ -1218,7 +1225,7 @@ void PM_fly(float maxspd_mod)
 }
 
 void PM_swim(float maxspd_mod)
-{
+{SELFPARAM();
        // swimming
        UNSET_ONGROUND(self);
 
@@ -1301,7 +1308,7 @@ void PM_swim(float maxspd_mod)
 }
 
 void PM_ladder(float maxspd_mod)
-{
+{SELFPARAM();
        // on a spawnfunc_func_ladder or swimming in spawnfunc_func_water
        UNSET_ONGROUND(self);
 
@@ -1354,7 +1361,7 @@ void PM_ladder(float maxspd_mod)
 }
 
 void PM_jetpack(float maxspd_mod)
-{
+{SELFPARAM();
        //makevectors(self.v_angle.y * '0 1 0');
        makevectors(self.v_angle);
        vector wishvel = v_forward * self.movement_x
@@ -1470,7 +1477,7 @@ void PM_jetpack(float maxspd_mod)
 }
 
 void PM_walk(float buttons_prev, float maxspd_mod)
-{
+{SELFPARAM();
        if (!WAS_ONGROUND(self))
        {
 #ifdef SVQC
@@ -1555,7 +1562,7 @@ void PM_walk(float buttons_prev, float maxspd_mod)
 }
 
 void PM_air(float buttons_prev, float maxspd_mod)
-{
+{SELFPARAM();
        makevectors(self.v_angle.y * '0 1 0');
        vector wishvel = v_forward * self.movement.x
                                        + v_right * self.movement.y;
@@ -1641,7 +1648,7 @@ bool IsFlying(entity a)
 }
 
 void PM_Main()
-{
+{SELFPARAM();
        int buttons = PHYS_INPUT_BUTTON_MASK(self);
 #ifdef CSQC
        self.items = getstati(STAT_ITEMS, 0, 24);
@@ -1923,7 +1930,7 @@ void SV_PlayerPhysics(void)
 #elif defined(CSQC)
 void CSQC_ClientMovement_PlayerMove_Frame(void)
 #endif
-{
+{SELFPARAM();
        PM_Main();
 
 #ifdef CSQC
index a249b238d7bf197650833c3e3d1badad89135478..d1f82991cd3308f4e5f45c70043e3f2ad076b0a9 100644 (file)
@@ -123,6 +123,7 @@ bool IsFlying(entity a);
        #define PHYS_JUMPSPEEDCAP_MAX                           cvar_string("cl_jumpspeedcap_max")
        #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS       getstati(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS)
 
+       #define PHYS_CL_TRACK_CANJUMP(s)                        getstati(STAT_MOVEVARS_CL_TRACK_CANJUMP)
        #define PHYS_TRACK_CANJUMP(s)                           getstati(STAT_MOVEVARS_TRACK_CANJUMP)
        #define PHYS_ACCELERATE                                         getstatf(STAT_MOVEVARS_ACCELERATE)
        #define PHYS_AIRACCEL_QW(s)                                     getstatf(STAT_MOVEVARS_AIRACCEL_QW)
@@ -247,6 +248,8 @@ bool IsFlying(entity a);
        .float stat_nostep;
        .float stat_jumpstep;
 
+       .bool stat_sv_track_canjump;
+
        #define PHYS_INPUT_ANGLES(s)                            s.v_angle
        #define PHYS_WORLD_ANGLES(s)                            s.angles
 
@@ -323,7 +326,8 @@ bool IsFlying(entity a);
        #define PHYS_JUMPSPEEDCAP_MAX                           autocvar_sv_jumpspeedcap_max
        #define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS       autocvar_sv_jumpspeedcap_max_disable_on_ramps
 
-       #define PHYS_TRACK_CANJUMP(s)                           s.cvar_cl_movement_track_canjump
+       #define PHYS_CL_TRACK_CANJUMP(s)                        s.cvar_cl_movement_track_canjump
+       #define PHYS_TRACK_CANJUMP(s)                           s.stat_sv_track_canjump
        #define PHYS_ACCELERATE                                         self.stat_sv_accelerate
        #define PHYS_AIRACCEL_QW(s)                                     s.stat_sv_airaccel_qw
        #define PHYS_AIRACCEL_QW_STRETCHFACTOR(s)       self.stat_sv_airaccel_qw_stretchfactor
index 74004d062bcd0cb14b88b1b91568f8e76b4cad87..3a44d71905ec36f071f671f789364f4cfd270c74 100644 (file)
@@ -1036,8 +1036,7 @@ void PlayerInfo_Details()
 #endif
 
 #ifdef CSQC
-/*
- * FIXME - crypto_* builtin functions missing in CSQC (csprogsdefs.qh:885)
+// FIXME - crypto_* builtin functions missing in CSQC (csprogsdefs.qh:885)
 void PlayerInfo_Details()
 {
         print("-- Getting detailed PlayerInfo for local player (CSQC)\n");
diff --git a/qcsrc/common/sounds/all.inc b/qcsrc/common/sounds/all.inc
new file mode 100644 (file)
index 0000000..0e5bd7f
--- /dev/null
@@ -0,0 +1,276 @@
+// Global list of sounds
+// TODO: remove uses of _sound
+
+string W_Sound(string w_snd);
+
+SOUND(ARC_FIRE, W_Sound("arc_fire"));
+SOUND(ARC_LOOP, W_Sound("arc_loop"));
+SOUND(ARC_LOOP_OVERHEAT, W_Sound("arc_loop_overheat"));
+SOUND(ARC_STOP, W_Sound("arc_stop"));
+SOUND(CAMPINGRIFLE_FIRE2, W_Sound("campingrifle_fire2"));
+SOUND(CAMPINGRIFLE_FIRE, W_Sound("campingrifle_fire"));
+SOUND(CRYLINK_FIRE2, W_Sound("crylink_fire2"));
+SOUND(CRYLINK_FIRE, W_Sound("crylink_fire"));
+SOUND(CRYLINK_IMPACT2, W_Sound("crylink_impact2"));
+SOUND(CRYLINK_IMPACT, W_Sound("crylink_impact"));
+SOUND(CRYLINK_LINKJOIN, W_Sound("crylink_linkjoin"));
+SOUND(DRYFIRE, W_Sound("dryfire"));
+SOUND(ELECTRO_BOUNCE, W_Sound("electro_bounce"));
+SOUND(ELECTRO_FIRE2, W_Sound("electro_fire2"));
+SOUND(ELECTRO_FIRE, W_Sound("electro_fire"));
+SOUND(ELECTRO_FLY, W_Sound("electro_fly"));
+SOUND(ELECTRO_IMPACT, W_Sound("electro_impact"));
+SOUND(ELECTRO_IMPACT_COMBO, W_Sound("electro_impact_combo"));
+SOUND(FIREBALL_FIRE2, W_Sound("fireball_fire2"));
+SOUND(FIREBALL_FIRE, W_Sound("fireball_fire"));
+SOUND(FIREBALL_FLY2, W_Sound("fireball_fly2"));
+SOUND(FIREBALL_FLY, W_Sound("fireball_fly"));
+SOUND(FIREBALL_IMPACT2, W_Sound("fireball_impact2"));
+SOUND(FIREBALL_PREFIRE2, W_Sound("fireball_prefire2"));
+SOUND(FLAC_FIRE, W_Sound("flac_fire"));
+SOUND(GRENADE_BOUNCE1, W_Sound("grenade_bounce1"));
+SOUND(GRENADE_BOUNCE2, W_Sound("grenade_bounce2"));
+SOUND(GRENADE_BOUNCE3, W_Sound("grenade_bounce3"));
+SOUND(GRENADE_BOUNCE4, W_Sound("grenade_bounce4"));
+SOUND(GRENADE_BOUNCE5, W_Sound("grenade_bounce5"));
+SOUND(GRENADE_BOUNCE6, W_Sound("grenade_bounce6"));
+Sound SND_GRENADE_BOUNCE_RANDOM() {
+    return Sounds[SND_GRENADE_BOUNCE1.m_id + rint(random() * 5)];
+}
+SOUND(GRENADE_FIRE, W_Sound("grenade_fire"));
+SOUND(GRENADE_IMPACT, W_Sound("grenade_impact"));
+SOUND(GRENADE_STICK, W_Sound("grenade_stick"));
+SOUND(HAGAR_BEEP, W_Sound("hagar_beep"));
+SOUND(HAGAR_FIRE, W_Sound("hagar_fire"));
+SOUND(HAGAR_LOAD, W_Sound("hagar_load"));
+SOUND(HAGEXP1, W_Sound("hagexp1"));
+SOUND(HAGEXP2, W_Sound("hagexp2"));
+SOUND(HAGEXP3, W_Sound("hagexp3"));
+Sound SND_HAGEXP_RANDOM() {
+    return Sounds[SND_HAGEXP1.m_id + rint(random() * 2)];
+}
+
+SOUND(HOOKBOMB_FIRE, W_Sound("hookbomb_fire"));
+SOUND(HOOKBOMB_IMPACT, W_Sound("hookbomb_impact"));
+SOUND(HOOK_FIRE, W_Sound("hook_fire"));
+SOUND(HOOK_IMPACT, W_Sound("hook_impact"));
+SOUND(LASERGUN_FIRE, W_Sound("lasergun_fire"));
+SOUND(LASERIMPACT, W_Sound("laserimpact"));
+SOUND(LGBEAM_FLY, W_Sound("lgbeam_fly"));
+SOUND(MINE_DET, W_Sound("mine_det"));
+SOUND(MINE_EXP, W_Sound("mine_exp"));
+SOUND(MINE_FIRE, W_Sound("mine_fire"));
+SOUND(MINE_STICK, W_Sound("mine_stick"));
+SOUND(MINE_TRIGGER, W_Sound("mine_trigger"));
+SOUND(MINSTANEXFIRE, W_Sound("minstanexfire"));
+SOUND(NEXCHARGE, W_Sound("nexcharge"));
+SOUND(NEXFIRE, W_Sound("nexfire"));
+SOUND(NEXIMPACT, W_Sound("neximpact"));
+SOUND(NEXWHOOSH1, W_Sound("nexwhoosh1"));
+SOUND(NEXWHOOSH2, W_Sound("nexwhoosh2"));
+SOUND(NEXWHOOSH3, W_Sound("nexwhoosh3"));
+Sound SND_NEXWHOOSH_RANDOM() {
+    return Sounds[SND_NEXWHOOSH1.m_id + rint(random() * 2)];
+}
+SOUND(RELOAD, W_Sound("reload")); // until weapons have individual reload sounds, precache the reload sound here
+
+SOUND(RIC1, W_Sound("ric1"));
+SOUND(RIC2, W_Sound("ric2"));
+SOUND(RIC3, W_Sound("ric3"));
+Sound SND_RIC_RANDOM() {
+    return Sounds[SND_RIC1.m_id + rint(random() * 2)];
+}
+
+SOUND(ROCKET_DET, W_Sound("rocket_det"));
+SOUND(ROCKET_FIRE, W_Sound("rocket_fire"));
+SOUND(ROCKET_FLY, W_Sound("rocket_fly"));
+SOUND(ROCKET_IMPACT, W_Sound("rocket_impact"));
+SOUND(ROCKET_MODE, W_Sound("rocket_mode"));
+SOUND(SEEKEREXP1, W_Sound("seekerexp1"));
+SOUND(SEEKEREXP2, W_Sound("seekerexp2"));
+SOUND(SEEKEREXP3, W_Sound("seekerexp3"));
+SOUND(SEEKER_FIRE, W_Sound("seeker_fire"));
+SOUND(SHOTGUN_FIRE, W_Sound("shotgun_fire"));
+SOUND(SHOTGUN_MELEE, W_Sound("shotgun_melee"));
+SOUND(STRENGTH_FIRE, W_Sound("strength_fire"));
+SOUND(TAGEXP1, W_Sound("tagexp1"));
+SOUND(TAGEXP2, W_Sound("tagexp2"));
+SOUND(TAGEXP3, W_Sound("tagexp3"));
+SOUND(TAG_FIRE, W_Sound("tag_fire"));
+SOUND(TAG_IMPACT, W_Sound("tag_impact"));
+SOUND(TAG_ROCKET_FLY, W_Sound("tag_rocket_fly"));
+SOUND(UNAVAILABLE, W_Sound("unavailable"));
+SOUND(UZI_FIRE, W_Sound("uzi_fire"));
+SOUND(WEAPONPICKUP, W_Sound("weaponpickup"));
+SOUND(WEAPONPICKUP_NEW_TOYS, W_Sound("weaponpickup_new_toys"));
+SOUND(WEAPON_SWITCH, W_Sound("weapon_switch"));
+
+SOUND(CTF_CAPTURE_NEUTRAL, "ctf/capture.ogg");
+SOUND(CTF_CAPTURE_RED, "ctf/red_capture.wav");
+SOUND(CTF_CAPTURE_BLUE, "ctf/blue_capture.wav");
+SOUND(CTF_CAPTURE_YELLOW, "ctf/yellow_capture.ogg");
+SOUND(CTF_CAPTURE_PINK, "ctf/pink_capture.ogg");
+Sound SND_CTF_CAPTURE(int teamid) {
+    switch (teamid) {
+        case NUM_TEAM_1:    return SND_CTF_CAPTURE_RED;
+        case NUM_TEAM_2:    return SND_CTF_CAPTURE_BLUE;
+        case NUM_TEAM_3:    return SND_CTF_CAPTURE_YELLOW;
+        case NUM_TEAM_4:    return SND_CTF_CAPTURE_PINK;
+        default:            return SND_CTF_CAPTURE_NEUTRAL;
+    }
+}
+
+SOUND(CTF_DROPPED_NEUTRAL,  "ctf/neutral_dropped.wav");
+SOUND(CTF_DROPPED_RED,      "ctf/red_dropped.wav");
+SOUND(CTF_DROPPED_BLUE,     "ctf/blue_dropped.wav");
+SOUND(CTF_DROPPED_YELLOW,   "ctf/yellow_dropped.wav");
+SOUND(CTF_DROPPED_PINK,     "ctf/pink_dropped.wav");
+Sound SND_CTF_DROPPED(int teamid) {
+    switch (teamid) {
+        case NUM_TEAM_1:    return SND_CTF_DROPPED_RED;
+        case NUM_TEAM_2:    return SND_CTF_DROPPED_BLUE;
+        case NUM_TEAM_3:    return SND_CTF_DROPPED_YELLOW;
+        case NUM_TEAM_4:    return SND_CTF_DROPPED_PINK;
+        default:            return SND_CTF_DROPPED_NEUTRAL;
+    }
+}
+
+SOUND(CTF_PASS, "ctf/pass.wav");
+SOUND(CTF_RESPAWN, "ctf/flag_respawn.wav");
+
+SOUND(CTF_RETURNED_NEUTRAL,  "ctf/return.wav");
+SOUND(CTF_RETURNED_RED,      "ctf/red_returned.wav");
+SOUND(CTF_RETURNED_BLUE,     "ctf/blue_returned.wav");
+SOUND(CTF_RETURNED_YELLOW,   "ctf/yellow_returned.wav");
+SOUND(CTF_RETURNED_PINK,     "ctf/pink_returned.wav");
+Sound SND_CTF_RETURNED(int teamid) {
+    switch (teamid) {
+        case NUM_TEAM_1:    return SND_CTF_RETURNED_RED;
+        case NUM_TEAM_2:    return SND_CTF_RETURNED_BLUE;
+        case NUM_TEAM_3:    return SND_CTF_RETURNED_YELLOW;
+        case NUM_TEAM_4:    return SND_CTF_RETURNED_PINK;
+        default:            return SND_CTF_RETURNED_NEUTRAL;
+    }
+}
+
+SOUND(CTF_TAKEN_NEUTRAL,  "ctf/neutral_taken.wav");
+SOUND(CTF_TAKEN_RED,      "ctf/red_taken.wav");
+SOUND(CTF_TAKEN_BLUE,     "ctf/blue_taken.wav");
+SOUND(CTF_TAKEN_YELLOW,   "ctf/yellow_taken.wav");
+SOUND(CTF_TAKEN_PINK,     "ctf/pink_taken.wav");
+Sound SND_CTF_TAKEN(int teamid) {
+    switch (teamid) {
+        case NUM_TEAM_1:    return SND_CTF_TAKEN_RED;
+        case NUM_TEAM_2:    return SND_CTF_TAKEN_BLUE;
+        case NUM_TEAM_3:    return SND_CTF_TAKEN_YELLOW;
+        case NUM_TEAM_4:    return SND_CTF_TAKEN_PINK;
+        default:            return SND_CTF_TAKEN_NEUTRAL;
+    }
+}
+
+SOUND(CTF_TOUCH, "ctf/touch.wav");
+
+SOUND(DOM_CLAIM, "domination/claim.wav");
+
+SOUND(KA_DROPPED, "keepaway/dropped.wav");
+SOUND(KA_PICKEDUP, "keepaway/pickedup.wav");
+SOUND(KA_RESPAWN, "keepaway/respawn.wav");
+SOUND(KA_TOUCH, "keepaway/touch.wav");
+
+SOUND(KH_ALARM, "kh/alarm.wav");
+SOUND(KH_CAPTURE, "kh/capture.wav");
+SOUND(KH_COLLECT, "kh/collect.wav");
+SOUND(KH_DESTROY, "kh/destroy.wav");
+SOUND(KH_DROP, "kh/drop.wav");
+
+SOUND(NB_BOUNCE, "nexball/bounce.ogg");
+SOUND(NB_DROP, "nexball/drop.ogg");
+SOUND(NB_SHOOT1, "nexball/shoot1.ogg");
+SOUND(NB_SHOOT2, "nexball/shoot2.ogg");
+SOUND(NB_STEAL, "nexball/steal.ogg");
+
+SOUND(ONS_CONTROLPOINT_BUILD, "onslaught/controlpoint_build.ogg");
+SOUND(ONS_CONTROLPOINT_BUILT, "onslaught/controlpoint_built.ogg");
+SOUND(ONS_CONTROLPOINT_UNDERATTACK, "onslaught/controlpoint_underattack.ogg");
+SOUND(ONS_DAMAGEBLOCKEDBYSHIELD, "onslaught/damageblockedbyshield.wav");
+SOUND(ONS_ELECTRICITY_EXPLODE, "onslaught/electricity_explode.ogg");
+SOUND(ONS_GENERATOR_DECAY, "onslaught/generator_decay.ogg");
+SOUND(ONS_GENERATOR_UNDERATTACK, "onslaught/generator_underattack.ogg");
+SOUND(ONS_HIT1, "onslaught/ons_hit1.ogg");
+SOUND(ONS_HIT2, "onslaught/ons_hit2.ogg");
+SOUND(ONS_SPARK1, "onslaught/ons_spark1.ogg");
+SOUND(ONS_SPARK2, "onslaught/ons_spark2.ogg");
+SOUND(ONS_SHOCKWAVE, "onslaught/shockwave.ogg");
+
+SOUND(PORTO_BOUNCE, "porto/bounce.ogg");
+SOUND(PORTO_CREATE, "porto/create.ogg");
+SOUND(PORTO_EXPIRE, "porto/expire.ogg");
+SOUND(PORTO_EXPLODE, "porto/explode.ogg");
+SOUND(PORTO_FIRE, "porto/fire.ogg");
+SOUND(PORTO_UNSUPPORTED, "porto/unsupported.ogg");
+
+SOUND(TUR_PHASER, "turrets/phaser.ogg");
+
+SOUND(VEH_ALARM, "vehicles/alarm.wav");
+SOUND(VEH_ALARM_SHIELD, "vehicles/alarm_shield.wav");
+SOUND(VEH_MISSILE_ALARM, "vehicles/missile_alarm.wav");
+
+SOUND(VEH_BUMBLEBEE_FIRE, W_Sound("flacexp3"));
+
+SOUND(VEH_RACER_BOOST, "vehicles/racer_boost.wav");
+SOUND(VEH_RACER_IDLE, "vehicles/racer_idle.wav");
+SOUND(VEH_RACER_MOVE, "vehicles/racer_move.wav");
+
+SOUND(VEH_RAPTOR_FLY, "vehicles/raptor_fly.wav");
+SOUND(VEH_RAPTOR_SPEED, "vehicles/raptor_speed.wav");
+
+SOUND(VEH_SPIDERBOT_DIE, "vehicles/spiderbot_die.wav");
+SOUND(VEH_SPIDERBOT_IDLE, "vehicles/spiderbot_idle.wav");
+SOUND(VEH_SPIDERBOT_JUMP, "vehicles/spiderbot_jump.wav");
+SOUND(VEH_SPIDERBOT_LAND, "vehicles/spiderbot_land.wav");
+SOUND(VEH_SPIDERBOT_STRAFE, "vehicles/spiderbot_strafe.wav");
+SOUND(VEH_SPIDERBOT_WALK, "vehicles/spiderbot_walk.wav");
+
+SOUND(NADE_BEEP, "overkill/grenadebip.ogg");
+
+SOUND(BUFF_LOST, "relics/relic_effect.wav");
+
+SOUND(POWEROFF, "misc/poweroff.wav");
+SOUND(POWERUP, "misc/powerup.ogg");
+SOUND(SHIELD_RESPAWN, "misc/shield_respawn.wav");
+SOUND(STRENGTH_RESPAWN, "misc/strength_respawn.wav");
+
+SOUND(ARMOR25, "misc/armor25.wav");
+SOUND(ARMORIMPACT, "misc/armorimpact.wav");
+SOUND(BODYIMPACT1, "misc/bodyimpact1.wav");
+SOUND(BODYIMPACT2, "misc/bodyimpact2.wav");
+
+SOUND(ITEMPICKUP, "misc/itempickup.ogg");
+SOUND(ITEMRESPAWNCOUNTDOWN, "misc/itemrespawncountdown.ogg");
+SOUND(ITEMRESPAWN, "misc/itemrespawn.ogg");
+SOUND(MEGAHEALTH, "misc/megahealth.ogg");
+
+SOUND(LAVA, "player/lava.wav");
+SOUND(SLIME, "player/slime.wav");
+
+SOUND(GIB, "misc/gib.wav");
+SOUND(GIB_SPLAT01, "misc/gib_splat01.wav");
+SOUND(GIB_SPLAT02, "misc/gib_splat02.wav");
+SOUND(GIB_SPLAT03, "misc/gib_splat03.wav");
+SOUND(GIB_SPLAT04, "misc/gib_splat04.wav");
+Sound SND_GIB_SPLAT_RANDOM() {
+    return Sounds[SND_GIB_SPLAT01.m_id + floor(prandom() * 4)];
+}
+
+SOUND(HIT, "misc/hit.wav");
+SOUND(TYPEHIT, "misc/typehit.wav");
+
+SOUND(SPAWN, "misc/spawn.ogg");
+
+SOUND(TALK, "misc/talk.wav");
+
+SOUND(TELEPORT, "misc/teleport.ogg");
+
+SOUND(INVSHOT, "misc/invshot.wav");
+
+SOUND(JETPACK_FLY, "misc/jetpack_fly.ogg");
diff --git a/qcsrc/common/sounds/all.qh b/qcsrc/common/sounds/all.qh
new file mode 100644 (file)
index 0000000..90858f3
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef SOUNDS_ALL_H
+#define SOUNDS_ALL_H
+
+#include "../teams.qh"
+
+// Play all sounds via sound7, for access to the extra channels.
+// Otherwise, channels 8 to 15 would be blocked for a weird QW feature.
+#ifdef SVQC
+    #define _sound(e, c, s, v, a) do { \
+        entity __e = e; \
+        if (!sound_allowed(MSG_BROADCAST, __e)) break; \
+        sound7(__e, c, s, v, a, 0, 0); \
+    } while (0)
+#else
+    #define _sound(e, c, s, v, a) sound7(e, c, s, v, a, 0, 0)
+#endif
+#define sound(e, c, s, v, a) _sound(e, c, s.sound_str(), v, a)
+// Used in places where a string is required
+#define SND(id) (SND_##id.sound_str())
+
+REGISTRY(Sounds, BIT(8))
+REGISTER_REGISTRY(RegisterSounds)
+
+CLASS(Sound, Object)
+    ATTRIB(Sound, m_id, int, 0)
+    ATTRIB(Sound, sound_str, string(), func_null)
+    CONSTRUCTOR(Sound, string() path)
+    {
+        CONSTRUCT(Sound);
+        this.sound_str = path;
+    }
+    METHOD(Sound, sound_precache, void(entity this)) {
+        string s = this.sound_str();
+        if (s && s != "" && !fexists(strcat("sound/", s))) {
+            LOG_WARNINGF("Missing sound: \"%s\"\n", s);
+            return;
+        }
+        LOG_TRACEF("precache_sound(\"%s\")\n", s);
+        precache_sound(s);
+    }
+ENDCLASS(Sound)
+
+#define SOUND(name, path) \
+    string SND_##name##_get() { return path; } \
+    REGISTER(RegisterSounds, SND, Sounds, name, m_id, NEW(Sound, SND_##name##_get))
+
+STATIC_INIT(RegisterSounds_precache) {
+    FOREACH(Sounds, true, LAMBDA({
+        it.sound_precache(it);
+    }));
+}
+
+SOUND(Null, "misc/null.wav");
+#include "all.inc"
+
+#endif
index eff0eff804ef1f07621f138f78f03266e8096a62..9bdcb5773a5e4bcff57fe8079b53542babfa2bef 100644 (file)
@@ -245,10 +245,10 @@ const int STAT_GAMEPLAYFIX_EASIERWATERJUMP            = 190;
 const int STAT_MOVEVARS_FRICTION_SLICK                = 191;
 const int STAT_MOVEVARS_FRICTION_ONLAND               = 192;
 const int STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS  = 193;
-// 194 empty?
+const int STAT_MOVEVARS_TRACK_CANJUMP                 = 194;
 // 195 empty?
 const int STAT_DOUBLEJUMP                             = 196;
-const int STAT_MOVEVARS_TRACK_CANJUMP                 = 197;
+const int STAT_MOVEVARS_CL_TRACK_CANJUMP              = 197;
 const int STAT_MULTIJUMP_ADD                          = 198;
 const int STAT_MULTIJUMP_SPEED                        = 199;
 const int STAT_MULTIJUMP                              = 200;
index 9fb2f56c9d7ee322c457dfbd25699f8c61350e02..8c7000d933ee1c8fd4418912dd8b7e0bbcc909d2 100644 (file)
@@ -1,7 +1,7 @@
 #ifdef SVQC
 .float height;
 void func_bobbing_controller_think()
-{
+{SELFPARAM();
        vector v;
        self.nextthink = time + 0.1;
 
@@ -28,7 +28,7 @@ noise : path/name of looping .wav file to play.
 dmg : Do this mutch dmg every .dmgtime intervall when blocked
 dmgtime : See above.
 */
-void spawnfunc_func_bobbing()
+spawnfunc(func_bobbing)
 {
        entity controller;
        if (self.noise != "")
index b70d8b600938f5e8ac1fc253aad1083310c00806..af9a6b4233124190ad4ab1a417d8f6562739190b 100644 (file)
@@ -5,7 +5,7 @@
 #include "../../../server/g_subs.qh"
 #include "../../../server/g_damage.qh"
 #include "../../../server/bot/bot.qh"
-#include "../../common/csqcmodel_settings.qh"
+#include "../../../common/csqcmodel_settings.qh"
 #include "../../../csqcmodellib/sv_model.qh"
 #include "../../../server/weapons/common.qh"
 
@@ -50,13 +50,13 @@ void func_breakable_damage(entity inflictor, entity attacker, float damage, int
 // - basically func_assault_destructible for general gameplay use
 //
 void LaunchDebris (string debrisname, vector force)
-{
+{SELFPARAM();
        entity dbr = spawn();
        setorigin(dbr, self.absmin
                   + '1 0 0' * random() * (self.absmax.x - self.absmin.x)
                   + '0 1 0' * random() * (self.absmax.y - self.absmin.y)
                   + '0 0 1' * random() * (self.absmax.z - self.absmin.z));
-       setmodel (dbr, debrisname );
+       _setmodel (dbr, debrisname );
        dbr.skin = self.debrisskin;
        dbr.colormap = self.colormap; // inherit team colors
        dbr.owner = self; // do not be affected by our own explosion
@@ -78,7 +78,7 @@ void LaunchDebris (string debrisname, vector force)
 }
 
 void func_breakable_colormod()
-{
+{SELFPARAM();
        float h;
        if (!(self.spawnflags & 2))
                return;
@@ -90,11 +90,11 @@ void func_breakable_colormod()
        else
                self.colormod = '1 1 1';
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 void func_breakable_look_destroyed()
-{
+{SELFPARAM();
        float floorZ;
 
        if(self.solid == SOLID_BSP) // in case a misc_follow moved me, save the current origin first
@@ -108,30 +108,30 @@ void func_breakable_look_destroyed()
                        setorigin(self,((self.absmax+self.absmin)*.5));
                        self.origin_z = floorZ;
                }
-               setmodel(self, self.mdl_dead);
+               _setmodel(self, self.mdl_dead);
                self.effects &= ~EF_NODRAW;
        }
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 
        self.solid = SOLID_NOT;
 }
 
 void func_breakable_look_restore()
-{
-       setmodel(self, self.mdl);
+{SELFPARAM();
+       _setmodel(self, self.mdl);
        self.effects &= ~EF_NODRAW;
 
        if(self.mdl_dead != "") // only do this if we use mdl_dead, to behave better with misc_follow
                setorigin(self, self.dropped_origin);
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 
        self.solid = SOLID_BSP;
 }
 
 void func_breakable_behave_destroyed()
-{
+{SELFPARAM();
        self.health = self.max_health;
        self.takedamage = DAMAGE_NO;
        self.bot_attack = false;
@@ -145,7 +145,7 @@ void func_breakable_behave_destroyed()
 }
 
 void func_breakable_behave_restore()
-{
+{SELFPARAM();
        self.health = self.max_health;
        if(self.sprite)
        {
@@ -162,11 +162,11 @@ void func_breakable_behave_restore()
        self.nextthink = 0; // cancel auto respawn
        func_breakable_colormod();
        if (self.noise1)
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
 }
 
 void func_breakable_init_for_player(entity player)
-{
+{SELFPARAM();
        if (self.noise1 && self.state == 0 && clienttype(player) == CLIENTTYPE_REAL)
        {
                msg_entity = player;
@@ -175,23 +175,24 @@ void func_breakable_init_for_player(entity player)
 }
 
 void func_breakable_destroyed()
-{
+{SELFPARAM();
        func_breakable_look_destroyed();
        func_breakable_behave_destroyed();
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 void func_breakable_restore()
-{
+{SELFPARAM();
        func_breakable_look_restore();
        func_breakable_behave_restore();
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 vector debrisforce; // global, set before calling this
-void func_breakable_destroy() {
+void func_breakable_destroy()
+{SELFPARAM();
        float n, i;
        string oldmsg;
 
@@ -206,7 +207,7 @@ void func_breakable_destroy() {
        func_breakable_destroyed();
 
        if(self.noise)
-               sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
 
        if(self.dmg)
                RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, world, self.dmg_force, DEATH_HURTTRIGGER, world);
@@ -227,7 +228,7 @@ void func_breakable_destroy() {
 }
 
 void func_breakable_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.state == 1)
                return;
        if(self.spawnflags & DOOR_NOSPLASH)
@@ -253,7 +254,7 @@ void func_breakable_damage(entity inflictor, entity attacker, float damage, int
 }
 
 void func_breakable_reset()
-{
+{SELFPARAM();
        self.team = self.team_saved;
        func_breakable_look_restore();
        if(self.spawnflags & 1)
@@ -261,11 +262,11 @@ void func_breakable_reset()
        else
                func_breakable_behave_restore();
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 // destructible walls that can be used to trigger target_objective_decrease
-void spawnfunc_func_breakable()
+spawnfunc(func_breakable)
 {
        float n, i;
        if(!self.health)
@@ -330,11 +331,11 @@ void spawnfunc_func_breakable()
        self.init_for_player_needed = 1;
        self.init_for_player = func_breakable_init_for_player;
 
-       CSQCMODEL_AUTOINIT();
+       CSQCMODEL_AUTOINIT(self);
 }
 
 // for use in maps with a "model" key set
-void spawnfunc_misc_breakablemodel() {
-       spawnfunc_func_breakable();
+spawnfunc(misc_breakablemodel) {
+       spawnfunc_func_breakable(this);
 }
 #endif
index b641d9446252890935a608795aff02c1ebb62829..75cfb94c690cf09d51c5ad8eaa1211bf5012043c 100644 (file)
@@ -2,7 +2,7 @@
 #define TRIGGERS_FUNC_BREAKABLE_H
 
 #ifdef SVQC
-void spawnfunc_func_breakable();
+spawnfunc(func_breakable);
 #endif
 
 #endif
index bb8875b4221ace9b5bd83c25fac38d3fc3be7b27..ab1cff538ef2e1bbbd6c020208578ce326ae7a03 100644 (file)
@@ -5,7 +5,7 @@ void() button_wait;
 void() button_return;
 
 void button_wait()
-{
+{SELFPARAM();
        self.state = STATE_TOP;
        self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
        self.SUB_THINK = button_return;
@@ -15,12 +15,12 @@ void button_wait()
 }
 
 void button_done()
-{
+{SELFPARAM();
        self.state = STATE_BOTTOM;
 }
 
 void button_return()
-{
+{SELFPARAM();
        self.state = STATE_DOWN;
        SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, button_done);
        self.frame = 0;                 // use normal textures
@@ -36,7 +36,7 @@ void button_blocked()
 
 
 void button_fire()
-{
+{SELFPARAM();
        self.health = self.max_health;
        self.takedamage = DAMAGE_NO;    // will be reset upon return
 
@@ -44,14 +44,14 @@ void button_fire()
                return;
 
        if (self.noise != "")
-               sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
 
        self.state = STATE_UP;
        SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, button_wait);
 }
 
 void button_reset()
-{
+{SELFPARAM();
        self.health = self.max_health;
        setorigin(self, self.pos1);
        self.frame = 0;                 // use normal textures
@@ -61,7 +61,7 @@ void button_reset()
 }
 
 void button_use()
-{
+{SELFPARAM();
        if(self.active != ACTIVE_ACTIVE)
                return;
 
@@ -70,7 +70,7 @@ void button_use()
 }
 
 void button_touch()
-{
+{SELFPARAM();
        if (!other)
                return;
        if (!other.iscreature)
@@ -84,7 +84,7 @@ void button_touch()
 }
 
 void button_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.spawnflags & DOOR_NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
@@ -112,7 +112,7 @@ When a button is touched, it moves some distance in the direction of it's angle,
 2) metallic click
 3) in-out
 */
-void spawnfunc_func_button()
+spawnfunc(func_button)
 {
        SetMovedir ();
 
index 6ed01b0c59c91f7e47ee88f45b97b2d47e91de7a..b8c1310d8ca70dc148977d113d3eb4983d8d814d 100644 (file)
@@ -1,5 +1,5 @@
 void conveyor_think()
-{
+{SELFPARAM();
 #ifdef CSQC
        // TODO: check if this is what is causing the glitchiness when switching between them
        float dt = time - self.move_time;
@@ -57,20 +57,20 @@ void conveyor_think()
 #ifdef SVQC
 
 void conveyor_use()
-{
+{SELFPARAM();
        self.state = !self.state;
 
        self.SendFlags |= 2;
 }
 
 void conveyor_reset()
-{
+{SELFPARAM();
        self.state = (self.spawnflags & 1);
 
        self.SendFlags |= 2;
 }
 
-bool conveyor_send(entity to, int sf)
+bool conveyor_send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_CONVEYOR);
        WriteByte(MSG_ENTITY, sf);
@@ -107,7 +107,7 @@ bool conveyor_send(entity to, int sf)
 }
 
 void conveyor_init()
-{
+{SELFPARAM();
        if (!self.speed)
                self.speed = 200;
        self.movedir = self.movedir * self.speed;
@@ -129,14 +129,14 @@ void conveyor_init()
        self.SendFlags |= 1;
 }
 
-void spawnfunc_trigger_conveyor()
+spawnfunc(trigger_conveyor)
 {
        SetMovedir();
        EXACTTRIGGER_INIT;
        conveyor_init();
 }
 
-void spawnfunc_func_conveyor()
+spawnfunc(func_conveyor)
 {
        SetMovedir();
        InitMovingBrushTrigger();
@@ -146,9 +146,11 @@ void spawnfunc_func_conveyor()
 
 #elif defined(CSQC)
 
+void conveyor_draw(entity this) { WITH(entity, self, this, conveyor_think()); }
+
 void conveyor_init()
-{
-       self.draw = conveyor_think;
+{SELFPARAM();
+       self.draw = conveyor_draw;
        self.drawmask = MASK_NORMAL;
 
        self.movetype = MOVETYPE_NONE;
@@ -159,7 +161,7 @@ void conveyor_init()
 }
 
 void ent_conveyor()
-{
+{SELFPARAM();
        float sf = ReadByte();
 
        if(sf & 1)
index 4c56815d2ffc3488a089a23c27ab56b26d6176a8..c55754bdbe30f2fe03b47e76cbf0a60c3fb73769 100644 (file)
@@ -26,7 +26,7 @@ void() door_rotating_go_down;
 void() door_rotating_go_up;
 
 void door_blocked()
-{
+{SELFPARAM();
        if((self.spawnflags & 8)
 #ifdef SVQC
                && (other.takedamage != DAMAGE_NO)
@@ -85,9 +85,9 @@ void door_blocked()
 }
 
 void door_hit_top()
-{
+{SELFPARAM();
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = STATE_TOP;
        if (self.spawnflags & DOOR_TOGGLE)
                return;         // don't come down automatically
@@ -102,16 +102,16 @@ void door_hit_top()
 }
 
 void door_hit_bottom()
-{
+{SELFPARAM();
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = STATE_BOTTOM;
 }
 
 void door_go_down()
-{
+{SELFPARAM();
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        if (self.max_health)
        {
                self.takedamage = DAMAGE_YES;
@@ -123,7 +123,7 @@ void door_go_down()
 }
 
 void door_go_up()
-{
+{SELFPARAM();
        if (self.state == STATE_UP)
                return;         // already going up
 
@@ -134,7 +134,7 @@ void door_go_up()
        }
 
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        self.state = STATE_UP;
        SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, door_hit_top);
 
@@ -155,7 +155,7 @@ ACTIVATION FUNCTIONS
 */
 
 float door_check_keys(void)
-{
+{SELFPARAM();
        local entity door;
 
 
@@ -180,7 +180,7 @@ float door_check_keys(void)
                if (other.key_door_messagetime <= time)
                {
 
-                       play2(other, "misc/talk.wav");
+                       play2(other, SND(TALK));
                        Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(door.itemkeys));
                        other.key_door_messagetime = time + 2;
                }
@@ -190,7 +190,7 @@ float door_check_keys(void)
                // no keys were used
                if (other.key_door_messagetime <= time)
                {
-                       play2(other, "misc/talk.wav");
+                       play2(other, SND(TALK));
                        Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(door.itemkeys));
 
                        other.key_door_messagetime = time + 2;
@@ -202,7 +202,7 @@ float door_check_keys(void)
        {
 #ifdef SVQC
                // door is now unlocked
-               play2(other, "misc/talk.wav");
+               play2(other, SND(TALK));
                Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_UNLOCKED);
 #endif
                return true;
@@ -212,15 +212,12 @@ float door_check_keys(void)
 }
 
 void door_fire()
-{
-       entity  oself;
+{SELFPARAM();
        entity  starte;
 
        if (self.owner != self)
                objerror ("door_fire: self.owner != self");
 
-       oself = self;
-
        if (self.spawnflags & DOOR_TOGGLE)
        {
                if (self.state == STATE_UP || self.state == STATE_TOP)
@@ -236,9 +233,9 @@ void door_fire()
                                {
                                        door_rotating_go_down ();
                                }
-                               self = self.enemy;
+                               setself(self.enemy);
                        } while ( (self != starte) && (self != world) );
-                       self = oself;
+                       setself(this);
                        return;
                }
        }
@@ -265,29 +262,23 @@ void door_fire()
                                door_rotating_go_up ();
                        }
                }
-               self = self.enemy;
+               setself(self.enemy);
        } while ( (self != starte) && (self != world) );
-       self = oself;
+       setself(this);
 }
 
 void door_use()
-{
-       entity oself;
-
+{SELFPARAM();
        //dprint("door_use (model: ");dprint(self.model);dprint(")\n");
 
        if (self.owner)
        {
-               oself = self;
-               self = self.owner;
-               door_fire ();
-               self = oself;
+               WITH(entity, self, self.owner, door_fire());
        }
 }
 
 void door_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
-       entity oself;
+{SELFPARAM();
        if(self.spawnflags & DOOR_NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
@@ -301,12 +292,9 @@ void door_damage(entity inflictor, entity attacker, float damage, int deathtype,
 
        if (self.health <= 0)
        {
-               oself = self;
-               self = self.owner;
-               self.health = self.max_health;
-               self.takedamage = DAMAGE_NO;    // wil be reset upon return
-               door_use ();
-               self = oself;
+               self.owner.health = self.owner.max_health;
+               self.owner.takedamage = DAMAGE_NO;      // wil be reset upon return
+               WITH(entity, self, self.owner, door_use());
        }
 }
 
@@ -320,7 +308,7 @@ Prints messages
 */
 
 void door_touch()
-{
+{SELFPARAM();
        if (!IS_PLAYER(other))
                return;
        if (self.owner.attack_finished_single > time)
@@ -333,13 +321,13 @@ void door_touch()
        {
                if (IS_CLIENT(other))
                        centerprint(other, self.owner.message);
-               play2(other, "misc/talk.wav");
+               play2(other, SND(TALK));
        }
 #endif
 }
 
 void door_generic_plat_blocked()
-{
+{SELFPARAM();
 
        if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
 #ifdef SVQC
@@ -377,9 +365,9 @@ void door_generic_plat_blocked()
 }
 
 void door_rotating_hit_top()
-{
+{SELFPARAM();
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = STATE_TOP;
        if (self.spawnflags & DOOR_TOGGLE)
                return;         // don't come down automatically
@@ -388,9 +376,9 @@ void door_rotating_hit_top()
 }
 
 void door_rotating_hit_bottom()
-{
+{SELFPARAM();
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        if (self.lip==666) // self.lip is used to remember reverse opening direction for door_rotating
        {
                self.pos2 = '0 0 0' - self.pos2;
@@ -400,9 +388,9 @@ void door_rotating_hit_bottom()
 }
 
 void door_rotating_go_down()
-{
+{SELFPARAM();
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        if (self.max_health)
        {
                self.takedamage = DAMAGE_YES;
@@ -414,7 +402,7 @@ void door_rotating_go_down()
 }
 
 void door_rotating_go_up()
-{
+{SELFPARAM();
        if (self.state == STATE_UP)
                return;         // already going up
 
@@ -424,7 +412,7 @@ void door_rotating_go_up()
                return;
        }
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        self.state = STATE_UP;
        SUB_CalcAngleMove (self.pos2, TSPEED_LINEAR, self.speed, door_rotating_hit_top);
 
@@ -445,7 +433,7 @@ Spawned if a door lacks a real activator
 */
 
 void door_trigger_touch()
-{
+{SELFPARAM();
        if (other.health < 1)
 #ifdef SVQC
                if (!((other.iscreature || (other.flags & FL_PROJECTILE)) && !PHYS_DEAD(other)))
@@ -465,12 +453,12 @@ void door_trigger_touch()
 
        activator = other;
 
-       self = self.owner;
+       setself(self.owner);
        door_use ();
 }
 
 void spawn_field(vector fmins, vector fmaxs)
-{
+{SELFPARAM();
        entity  trigger;
        vector  t1 = fmins, t2 = fmaxs;
 
@@ -500,7 +488,7 @@ LinkDoors
 */
 
 entity LinkDoors_nextent(entity cur, entity near, entity pass)
-{
+{SELFPARAM();
        while((cur = find(cur, classname, self.classname)) && ((cur.spawnflags & 4) || cur.enemy))
        {
        }
@@ -524,7 +512,7 @@ bool LinkDoors_isconnected(entity e1, entity e2, entity pass)
 void door_link();
 #endif
 void LinkDoors()
-{
+{SELFPARAM();
        entity  t;
        vector  cmins, cmaxs;
 
@@ -647,7 +635,7 @@ FIXME: only one sound set available at the time being
 */
 
 float door_send(entity to, float sf)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_DOOR);
        WriteByte(MSG_ENTITY, sf);
 
@@ -709,7 +697,7 @@ void door_link()
 #endif
 
 void door_init_startopen()
-{
+{SELFPARAM();
        SUB_SETORIGIN(self, self.pos2);
        self.pos2 = self.pos1;
        self.pos1 = self.origin;
@@ -720,7 +708,7 @@ void door_init_startopen()
 }
 
 void door_reset()
-{
+{SELFPARAM();
        SUB_SETORIGIN(self, self.pos1);
        self.SUB_VELOCITY = '0 0 0';
        self.state = STATE_BOTTOM;
@@ -735,7 +723,7 @@ void door_reset()
 #ifdef SVQC
 
 // spawnflags require key (for now only func_door)
-void spawnfunc_func_door()
+spawnfunc(func_door)
 {
        // Quake 1 keys compatibility
        if (self.spawnflags & SPAWNFLAGS_GOLD_KEY)
@@ -807,15 +795,15 @@ void spawnfunc_func_door()
 
 #elif defined(CSQC)
 
-void door_draw()
+void door_draw(entity this)
 {
        Movetype_Physics_NoMatchServer();
 
-       trigger_draw_generic();
+       trigger_draw_generic(this);
 }
 
 void ent_door()
-{
+{SELFPARAM();
        float sf = ReadByte();
 
        if(sf & SF_TRIGGER_INIT)
@@ -824,7 +812,7 @@ void ent_door()
                self.spawnflags = ReadByte();
 
                self.mdl = strzone(ReadString());
-               setmodel(self, self.mdl);
+               _setmodel(self, self.mdl);
 
                trigger_common_read(true);
 
index bdf05a00936b48e2fe3c12d8b5c8f54c29c25094..e01a7e73e299e6288652471a283eb9a4cb03a25c 100644 (file)
@@ -28,7 +28,7 @@ FIXME: only one sound set available at the time being
 */
 
 void door_rotating_reset()
-{
+{SELFPARAM();
        self.angles = self.pos1;
        self.avelocity = '0 0 0';
        self.state = STATE_BOTTOM;
@@ -37,14 +37,14 @@ void door_rotating_reset()
 }
 
 void door_rotating_init_startopen()
-{
+{SELFPARAM();
        self.angles = self.movedir;
        self.pos2 = '0 0 0';
        self.pos1 = self.movedir;
 }
 
 
-void spawnfunc_func_door_rotating()
+spawnfunc(func_door_rotating)
 {
 
        //if (!self.deathtype) // map makers can override this
index a0a44bbb92d417dcad7a46b4f63c9bf4475bbc9f..8686c671f7c097c3a5307ecca54e478ef2b3734b 100644 (file)
@@ -14,7 +14,7 @@ const float SECRET_NO_SHOOT = 8;              // only opened by trigger
 const float SECRET_YES_SHOOT = 16;     // shootable even if targeted
 
 void fd_secret_use()
-{
+{SELFPARAM();
        float temp;
        string message_save;
 
@@ -35,7 +35,7 @@ void fd_secret_use()
        // Make a sound, wait a little...
 
        if (self.noise1 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.SUB_NEXTTHINK = self.SUB_LTIME + 0.1;
 
        temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
@@ -60,7 +60,7 @@ void fd_secret_use()
        self.dest2 = self.dest1 + v_forward * self.t_length;
        SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move1);
        if (self.noise2 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
 }
 
 void fd_secret_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
@@ -70,26 +70,26 @@ void fd_secret_damage(entity inflictor, entity attacker, float damage, int death
 
 // Wait after first movement...
 void fd_secret_move1()
-{
+{SELFPARAM();
        self.SUB_NEXTTHINK = self.SUB_LTIME + 1.0;
        self.think = fd_secret_move2;
        if (self.noise3 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
 }
 
 // Start moving sideways w/sound...
 void fd_secret_move2()
-{
+{SELFPARAM();
        if (self.noise2 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        SUB_CalcMove(self.dest2, TSPEED_LINEAR, self.speed, fd_secret_move3);
 }
 
 // Wait here until time to go back...
 void fd_secret_move3()
-{
+{SELFPARAM();
        if (self.noise3 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
        if (!(self.spawnflags & SECRET_OPEN_ONCE))
        {
                self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
@@ -99,30 +99,30 @@ void fd_secret_move3()
 
 // Move backward...
 void fd_secret_move4()
-{
+{SELFPARAM();
        if (self.noise2 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move5);
 }
 
 // Wait 1 second...
 void fd_secret_move5()
-{
+{SELFPARAM();
        self.SUB_NEXTTHINK = self.SUB_LTIME + 1.0;
        self.think = fd_secret_move6;
        if (self.noise3 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
 }
 
 void fd_secret_move6()
-{
+{SELFPARAM();
        if (self.noise2 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        SUB_CalcMove(self.oldorigin, TSPEED_LINEAR, self.speed, fd_secret_done);
 }
 
 void fd_secret_done()
-{
+{SELFPARAM();
        if (self.spawnflags&SECRET_YES_SHOOT)
        {
                self.health = 10000;
@@ -130,11 +130,11 @@ void fd_secret_done()
                //self.th_pain = fd_secret_use;
        }
        if (self.noise3 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
 }
 
 void secret_blocked()
-{
+{SELFPARAM();
        if (time < self.attack_finished_single)
                return;
        self.attack_finished_single = time + 0.5;
@@ -149,7 +149,7 @@ Prints messages
 ================
 */
 void secret_touch()
-{
+{SELFPARAM();
        if (!other.iscreature)
                return;
        if (self.attack_finished_single > time)
@@ -161,12 +161,12 @@ void secret_touch()
        {
                if (IS_CLIENT(other))
                        centerprint(other, self.message);
-               play2(other, "misc/talk.wav");
+               play2(other, SND(TALK));
        }
 }
 
 void secret_reset()
-{
+{SELFPARAM();
        if (self.spawnflags&SECRET_YES_SHOOT)
        {
                self.health = 10000;
@@ -194,7 +194,7 @@ If a secret door has a targetname, it will only be opened by it's botton or trig
 3) base
 */
 
-void spawnfunc_func_door_secret()
+spawnfunc(func_door_secret)
 {
        /*if (!self.deathtype) // map makers can override this
                self.deathtype = " got in the way";*/
index 19dceef25307b68d623ee388fd255cb21401fb35..2b3d07f6ea41dbc57dc441861290f00895fb5502 100644 (file)
@@ -11,7 +11,7 @@ dmgtime: See above.
 */
 
 void func_fourier_controller_think()
-{
+{SELFPARAM();
        vector v;
        float n, i, t;
 
@@ -39,7 +39,7 @@ void func_fourier_controller_think()
                self.owner.velocity = (v - self.owner.origin) * 10;
 }
 
-void spawnfunc_func_fourier()
+spawnfunc(func_fourier)
 {
        entity controller;
        if (self.noise != "")
index 5a96b9bb6e68f05f02162e3f2a64e353946064f2..c27dd2ce08604e576c642d855d03fbbc2af67a67 100644 (file)
@@ -1,5 +1,5 @@
 void func_ladder_touch()
-{
+{SELFPARAM();
 #ifdef SVQC
        if (!other.iscreature)
                return;
@@ -18,7 +18,7 @@ void func_ladder_touch()
 }
 
 #ifdef SVQC
-float func_ladder_send(entity to, float sf)
+bool func_ladder_send(entity this, entity to, float sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_LADDER);
 
@@ -39,7 +39,7 @@ void func_ladder_link()
        //self.model = "null";
 }
 
-void spawnfunc_func_ladder()
+spawnfunc(func_ladder)
 {
        self.mdl = self.model;
        EXACTTRIGGER_INIT;
@@ -48,7 +48,7 @@ void spawnfunc_func_ladder()
        func_ladder_link();
 }
 
-void spawnfunc_func_water()
+spawnfunc(func_water)
 {
        self.mdl = self.model;
        EXACTTRIGGER_INIT;
@@ -61,7 +61,7 @@ void spawnfunc_func_water()
 .float speed;
 
 void ent_func_ladder()
-{
+{SELFPARAM();
        self.classname = strzone(ReadString());
        self.skin = ReadByte();
        self.speed = ReadByte();
index 7d3eff7c9f474a25b62975a0602e05367039598a..d8bab869e2f743310b01163fb23c96c3e773c941 100644 (file)
@@ -1,7 +1,7 @@
 #ifdef SVQC
 .float freq;
 void func_pendulum_controller_think()
-{
+{SELFPARAM();
        float v;
        self.nextthink = time + 0.1;
 
@@ -21,7 +21,7 @@ void func_pendulum_controller_think()
        }
 }
 
-void spawnfunc_func_pendulum()
+spawnfunc(func_pendulum)
 {
        entity controller;
        if (self.noise != "")
index d36b1c6a372daa44c8c8f3f970e87b74f6ba83ef..fc62341a85a3a09b65b158d09d6e4d2fce92cf40 100644 (file)
@@ -8,7 +8,7 @@ void plat_delayedinit()
 }
 
 float plat_send(entity to, float sf)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_PLAT);
        WriteByte(MSG_ENTITY, sf);
 
@@ -59,7 +59,7 @@ void plat_link()
        //Net_LinkEntity(self, 0, false, plat_send);
 }
 
-void spawnfunc_func_plat()
+spawnfunc(func_plat)
 {
        if (self.sounds == 0)
                self.sounds = 2;
@@ -127,14 +127,14 @@ void spawnfunc_func_plat()
        InitializeEntity(self, plat_delayedinit, INITPRIO_FINDTARGET);
 }
 #elif defined(CSQC)
-void plat_draw()
+void plat_draw(entity this)
 {
        Movetype_Physics_NoMatchServer();
        //Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
 }
 
 void ent_plat()
-{
+{SELFPARAM();
        float sf = ReadByte();
 
        if(sf & SF_TRIGGER_INIT)
@@ -145,7 +145,7 @@ void ent_plat()
                self.spawnflags = ReadByte();
 
                self.model = strzone(ReadString());
-               setmodel(self, self.model);
+               _setmodel(self, self.model);
 
                trigger_common_read(true);
 
index 654db0f72ae1ba4cf979572e93718a7a5af7f692..a4f31b2fd81c0e2b25e4597b0234b3c327a1329c 100644 (file)
@@ -5,7 +5,7 @@
 #ifdef SVQC
 // NOTE: also contains func_sparks
 
-float pointparticles_SendEntity(entity to, float fl)
+bool pointparticles_SendEntity(entity this, entity to, float fl)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_POINTPARTICLES);
 
@@ -89,13 +89,13 @@ float pointparticles_SendEntity(entity to, float fl)
 }
 
 void pointparticles_use()
-{
+{SELFPARAM();
        self.state = !self.state;
        self.SendFlags |= 2;
 }
 
 void pointparticles_think()
-{
+{SELFPARAM();
        if(self.origin != self.oldorigin)
        {
                self.SendFlags |= 4;
@@ -105,17 +105,17 @@ void pointparticles_think()
 }
 
 void pointparticles_reset()
-{
+{SELFPARAM();
        if(self.spawnflags & 1)
                self.state = 1;
        else
                self.state = 0;
 }
 
-void spawnfunc_func_pointparticles()
+spawnfunc(func_pointparticles)
 {
        if(self.model != "")
-               setmodel(self, self.model);
+               _setmodel(self, self.model);
        if(self.noise != "")
                precache_sound (self.noise);
 
@@ -157,7 +157,7 @@ void spawnfunc_func_pointparticles()
        self.nextthink = time;
 }
 
-void spawnfunc_func_sparks()
+spawnfunc(func_sparks)
 {
        // self.cnt is the amount of sparks that one burst will spawn
        if(self.cnt < 1) {
@@ -179,11 +179,11 @@ void spawnfunc_func_sparks()
        self.wait = 0;
        self.cnt = 0; // use mdl
 
-       spawnfunc_func_pointparticles();
+       spawnfunc_func_pointparticles(this);
 }
 #elif defined(CSQC)
 
-void Draw_PointParticles()
+void Draw_PointParticles(entity this)
 {
        float n, i, fail;
        vector p;
@@ -230,7 +230,7 @@ void Draw_PointParticles()
                        if(self.noise != "")
                        {
                                setorigin(self, p);
-                               sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten);
+                               _sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten);
                        }
                        self.just_toggled = 0;
                }
@@ -244,7 +244,7 @@ void Draw_PointParticles()
 }
 
 void Ent_PointParticles_Remove()
-{
+{SELFPARAM();
        if(self.noise)
                strunzone(self.noise);
        self.noise = string_null;
@@ -254,7 +254,7 @@ void Ent_PointParticles_Remove()
 }
 
 void Ent_PointParticles()
-{
+{SELFPARAM();
        float i;
        vector v;
        int f = ReadByte();
index deb5ee58bfd94e3598ffad20c21444111e6dfe7b..18c2c0a0fb91c9cb9adecb5fc5bb5a253530e93b 100644 (file)
@@ -1,5 +1,5 @@
 #ifdef SVQC
-float rainsnow_SendEntity(entity to, float sf)
+bool rainsnow_SendEntity(entity this, entity to, float sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_RAINSNOW);
        WriteByte(MSG_ENTITY, self.state);
@@ -12,7 +12,7 @@ float rainsnow_SendEntity(entity to, float sf)
        WriteShort(MSG_ENTITY, compressShortVector(self.dest));
        WriteShort(MSG_ENTITY, self.count);
        WriteByte(MSG_ENTITY, self.cnt);
-       return 1;
+       return true;
 }
 
 /*QUAKED spawnfunc_func_rain (0 .5 .8) ?
@@ -26,7 +26,7 @@ Keys:
 "count"
  adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
 */
-void spawnfunc_func_rain()
+spawnfunc(func_rain)
 {
        self.dest = self.velocity;
        self.velocity = '0 0 0';
@@ -64,7 +64,7 @@ Keys:
 "count"
  adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
 */
-void spawnfunc_func_snow()
+spawnfunc(func_snow)
 {
        self.dest = self.velocity;
        self.velocity = '0 0 0';
@@ -90,18 +90,18 @@ void spawnfunc_func_snow()
        Net_LinkEntity(self, false, 0, rainsnow_SendEntity);
 }
 #elif defined(CSQC)
-void Draw_Rain()
+void Draw_Rain(entity this)
 {
     te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
 }
 
-void Draw_Snow()
+void Draw_Snow(entity this)
 {
     te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, floor(self.count * drawframetime + random()), self.glow_color);
 }
 
 void Ent_RainOrSnow()
-{
+{SELFPARAM();
        self.impulse = ReadByte(); // Rain, Snow, or Whatever
        self.origin_x = ReadCoord();
        self.origin_y = ReadCoord();
index 93d4a30cedaa14ee2de8078890f9e29a8cc025d3..be2c7ed9c3d3828c972cfb592d764223f69c9d87 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 void func_rotating_setactive(float astate)
-{
+{SELFPARAM();
 
        if (astate == ACTIVE_TOGGLE)
        {
@@ -26,7 +26,7 @@ dmg     : Do this mutch dmg every .dmgtime intervall when blocked
 dmgtime : See above.
 */
 
-void spawnfunc_func_rotating()
+spawnfunc(func_rotating)
 {
        if (self.noise != "")
        {
index 30c406f61e46d94f10640757ab691d351128ff2f..859cdf53df00517d0f9c45cd56d5d6464dacc5d4 100644 (file)
@@ -1,8 +1,8 @@
 #ifdef SVQC
-void spawnfunc_func_stardust()
+spawnfunc(func_stardust)
 {
        self.effects = EF_STARDUST;
 
-       CSQCMODEL_AUTOINIT();
+       CSQCMODEL_AUTOINIT(self);
 }
 #endif
index 0de3489381fa2dba5b27b8b6f58fed55f44a1f55..a75ac4192ee1b7bd6a7afe274fd0612b82bcc8bd 100644 (file)
@@ -1,12 +1,8 @@
 .float train_wait_turning;
 void() train_next;
 void train_wait()
-{
-       entity oldself;
-       oldself = self;
-       self = self.enemy;
-       SUB_UseTargets();
-       self = oldself;
+{SELFPARAM();
+       WITH(entity, self, self.enemy, SUB_UseTargets());
        self.enemy = world;
 
        // if turning is enabled, the train will turn toward the next point while waiting
@@ -53,7 +49,7 @@ void train_wait()
 }
 
 void train_next()
-{
+{SELFPARAM();
        entity targ, cp = world;
        vector cp_org = '0 0 0';
 
@@ -102,12 +98,12 @@ void train_next()
        }
 
        if(self.noise != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
+               _sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
 }
 
 #ifdef SVQC
 float train_send(entity to, float sf)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_TRAIN);
        WriteByte(MSG_ENTITY, sf);
 
@@ -166,7 +162,7 @@ void train_link()
 }
 
 void func_train_find()
-{
+{SELFPARAM();
        entity targ;
        targ = find(world, targetname, self.target);
        self.target = targ.target;
@@ -187,7 +183,7 @@ speed : speed the train moves (can be overridden by each spawnfunc_path_corner)
 target : targetname of first spawnfunc_path_corner (starts here)
 */
 #ifdef SVQC
-void spawnfunc_func_train()
+spawnfunc(func_train)
 {
        if (self.noise != "")
                precache_sound(self.noise);
@@ -229,14 +225,14 @@ void spawnfunc_func_train()
        // TODO make a reset function for this one
 }
 #elif defined(CSQC)
-void train_draw()
+void train_draw(entity this)
 {
        //Movetype_Physics_NoMatchServer();
        Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
 }
 
 void ent_train()
-{
+{SELFPARAM();
        float sf = ReadByte();
 
        if(sf & SF_TRIGGER_INIT)
@@ -246,7 +242,7 @@ void ent_train()
                self.spawnflags = ReadByte();
 
                self.model = strzone(ReadString());
-               setmodel(self, self.model);
+               _setmodel(self, self.model);
 
                trigger_common_read(true);
 
index 521ac8780e73300df8099ee7208b8e8035296690..57d3a0636fafefb5f7036c2c0ef2f5cfa1e235f8 100644 (file)
@@ -58,7 +58,7 @@ vector func_vectormamamam_origin(entity o, float t)
 }
 
 void func_vectormamamam_controller_think()
-{
+{SELFPARAM();
        self.nextthink = time + 0.1;
 
        if(self.owner.active != ACTIVE_ACTIVE)
@@ -72,7 +72,7 @@ void func_vectormamamam_controller_think()
 }
 
 void func_vectormamamam_findtarget()
-{
+{SELFPARAM();
        if(self.target != "")
                self.wp00 = find(world, targetname, self.target);
 
@@ -98,7 +98,7 @@ void func_vectormamamam_findtarget()
        controller.think = func_vectormamamam_controller_think;
 }
 
-void spawnfunc_func_vectormamamam()
+spawnfunc(func_vectormamamam)
 {
        if (self.noise != "")
        {
index 4294eac2aad6f2f577e5a46cb63d2548557b5f6d..ccac77b6c9c402b7340c68ad12263531a066a486 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 bool corner_send(entity to, int sf)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_CORNER);
 
        WriteString(MSG_ENTITY, self.platmovetype);
@@ -26,7 +26,7 @@ void corner_link()
        //Net_LinkEntity(self, false, 0, corner_send);
 }
 
-void spawnfunc_path_corner()
+spawnfunc(path_corner)
 {
        // setup values for overriding train movement
        // if a second value does not exist, both start and end speeds are the single value specified
@@ -37,7 +37,7 @@ void spawnfunc_path_corner()
 #elif defined(CSQC)
 
 void corner_remove()
-{
+{SELFPARAM();
        if(self.target) { strunzone(self.target); }
        self.target = string_null;
 
@@ -58,7 +58,7 @@ void corner_remove()
 }
 
 void ent_corner()
-{
+{SELFPARAM();
        self.platmovetype = strzone(ReadString());
 
        self.origin_x = ReadCoord();
index bfeb865c1df47187ecd458688c297af5da7a3a28..842248a4b31f0acc93a7b91f32a784dea7c1978c 100644 (file)
@@ -2,7 +2,7 @@
 
 #ifdef SVQC
 void follow_init()
-{
+{SELFPARAM();
        entity src, dst;
        src = world;
        dst = world;
@@ -62,7 +62,7 @@ void follow_init()
        }
 }
 
-void spawnfunc_misc_follow()
+spawnfunc(misc_follow)
 {
        InitializeEntity(self, follow_init, INITPRIO_FINDTARGET);
 }
index a7fb07815356973eee23bdee3c88a0878f312434..3b9996db6daea61a447dfa6005827d9f2cb1ff00 100644 (file)
@@ -1,6 +1,6 @@
 #if defined(CSQC)
        #include "../../../client/_all.qh"
-       #include "../../buffs.qh"
+       #include "../../buffs/all.qh"
        #include "../../../csqcmodellib/interpolate.qh"
        #include "../../../client/main.qh"
        #include "../../../csqcmodellib/cl_model.qh"
@@ -11,7 +11,7 @@
 #ifdef SVQC
 .float modelscale;
 void misc_laser_aim()
-{
+{SELFPARAM();
        vector a;
        if(self.enemy)
        {
@@ -50,16 +50,15 @@ void misc_laser_aim()
 }
 
 void misc_laser_init()
-{
+{SELFPARAM();
        if(self.target != "")
                self.enemy = find(world, targetname, self.target);
 }
 
 .entity pusher;
 void misc_laser_think()
-{
+{SELFPARAM();
        vector o;
-       entity oldself;
        entity hitent;
        vector hitloc;
 
@@ -98,11 +97,8 @@ void misc_laser_think()
                        {
                                self.count = 1;
 
-                               oldself = self;
-                               self = self.enemy;
-                               activator = self.pusher;
-                               SUB_UseTargets();
-                               self = oldself;
+                               activator = self.enemy.pusher;
+                               WITH(entity, self, self.enemy, SUB_UseTargets());
                        }
                }
                else
@@ -111,11 +107,8 @@ void misc_laser_think()
                        {
                                self.count = 0;
 
-                               oldself = self;
-                               self = self.enemy;
-                               activator = self.pusher;
-                               SUB_UseTargets();
-                               self = oldself;
+                               activator = self.enemy.pusher;
+                               WITH(entity, self, self.enemy, SUB_UseTargets());
                        }
                }
        }
@@ -130,7 +123,7 @@ void misc_laser_think()
        }
 }
 
-float laser_SendEntity(entity to, float fl)
+bool laser_SendEntity(entity this, entity to, float fl)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_LASER);
        fl = fl - (fl & 0xF0); // use that bit to indicate finite length laser
@@ -196,21 +189,21 @@ Keys:
  damage per second (-1 for a laser that kills immediately)
 */
 void laser_use()
-{
+{SELFPARAM();
        self.state = !self.state;
        self.SendFlags |= 4;
        misc_laser_aim();
 }
 
 void laser_reset()
-{
+{SELFPARAM();
        if(self.spawnflags & 1)
                self.state = 1;
        else
                self.state = 0;
 }
 
-void spawnfunc_misc_laser()
+spawnfunc(misc_laser)
 {
        if(self.mdl)
        {
@@ -279,7 +272,7 @@ class(Laser) .float alpha;
 class(Laser) .float scale; // scaling factor of the thickness
 class(Laser) .float modelscale; // scaling factor of the dlight
 
-void Draw_Laser()
+void Draw_Laser(entity this)
 {
        if(!self.state)
                return;
@@ -331,7 +324,7 @@ void Draw_Laser()
 }
 
 void Ent_Laser()
-{
+{SELFPARAM();
        InterpolateOrigin_Undo();
 
        // 30 bytes, or 13 bytes for just moving
index b80ce827d7dbf54da3b263764fbe1748e12747e4..00752cfa59c5faa92a39756d31272ceec224e03a 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 
-void spawnfunc_info_teleport_destination (void)
+spawnfunc(info_teleport_destination)
 {
        self.classname = "info_teleport_destination";
 
@@ -17,14 +17,14 @@ void spawnfunc_info_teleport_destination (void)
                objerror ("^3Teleport destination without a targetname");
 }
 
-void spawnfunc_misc_teleporter_dest (void)
+spawnfunc(misc_teleporter_dest)
 {
-       spawnfunc_info_teleport_destination();
+       spawnfunc_info_teleport_destination(this);
 }
 
-void spawnfunc_target_teleporter (void)
+spawnfunc(target_teleporter)
 {
-       spawnfunc_info_teleport_destination();
+       spawnfunc_info_teleport_destination(this);
 }
 
 #endif
index b837d7c5a8788c43d36d019e08919dfe4d9966e4..dc568cae09224c001b4b1ba5c61f48bb5dede01a 100644 (file)
@@ -1,5 +1,5 @@
 void generic_plat_blocked()
-{
+{SELFPARAM();
 #ifdef SVQC
        if(self.dmg && other.takedamage != DAMAGE_NO)
        {
@@ -17,7 +17,7 @@ void generic_plat_blocked()
 }
 
 void plat_spawn_inside_trigger()
-{
+{SELFPARAM();
        entity trigger;
        vector tmin, tmax;
 
@@ -64,8 +64,8 @@ void plat_spawn_inside_trigger()
 }
 
 void plat_hit_top()
-{
-       sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+       _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = 1;
 
        self.SUB_THINK = plat_go_down;
@@ -73,27 +73,27 @@ void plat_hit_top()
 }
 
 void plat_hit_bottom()
-{
-       sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+       _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = 2;
 }
 
 void plat_go_down()
-{
-       sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+       _sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
        self.state = 3;
        SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, plat_hit_bottom);
 }
 
 void plat_go_up()
-{
-       sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+       _sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
        self.state = 4;
        SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, plat_hit_top);
 }
 
 void plat_center_touch()
-{
+{SELFPARAM();
 #ifdef SVQC
        if (!other.iscreature)
                return;
@@ -107,7 +107,7 @@ void plat_center_touch()
                return;
 #endif
 
-       self = self.enemy;
+       setself(self.enemy);
        if (self.state == 2)
                plat_go_up ();
        else if (self.state == 1)
@@ -115,7 +115,7 @@ void plat_center_touch()
 }
 
 void plat_outside_touch()
-{
+{SELFPARAM();
 #ifdef SVQC
        if (!other.iscreature)
                return;
@@ -127,13 +127,13 @@ void plat_outside_touch()
                return;
 #endif
 
-       self = self.enemy;
+       setself(self.enemy);
        if (self.state == 1)
                plat_go_down ();
 }
 
 void plat_trigger_use()
-{
+{SELFPARAM();
 #ifdef SVQC
        if (self.think)
                return;         // already activated
@@ -146,7 +146,7 @@ void plat_trigger_use()
 
 
 void plat_crush()
-{
+{SELFPARAM();
        if((self.spawnflags & 4) && (other.takedamage != DAMAGE_NO))
        { // KIll Kill Kill!!
 #ifdef SVQC
@@ -176,7 +176,7 @@ void plat_crush()
 }
 
 void plat_use()
-{
+{SELFPARAM();
        self.use = func_null;
        if (self.state != 4)
                objerror ("plat_use: not in up state");
@@ -186,7 +186,7 @@ void plat_use()
 .string sound1, sound2;
 
 void plat_reset()
-{
+{SELFPARAM();
        IFTARGETED
        {
                setorigin (self, self.pos1);
index fa7c1c5e451b28f67a41eab1068c8d8c49cfa35f..d9de97301b9d068d8569bf1f8503723201918083 100644 (file)
@@ -13,7 +13,7 @@ Applies some friction to self
 */
 .float friction;
 void SUB_Friction (void)
-{
+{SELFPARAM();
        self.SUB_NEXTTHINK = time;
        if(self.SUB_FLAGS & FL_ONGROUND)
                self.SUB_VELOCITY = self.SUB_VELOCITY * (1 - frametime * self.friction);
@@ -46,7 +46,7 @@ void SUB_VanishOrRemove (entity ent)
 }
 
 void SUB_SetFade_Think (void)
-{
+{SELFPARAM();
        if(self.alpha == 0)
                self.alpha = 1;
        self.SUB_THINK = SUB_SetFade_Think;
@@ -81,7 +81,7 @@ self.SUB_ORIGIN traveling at speed
 ===============
 */
 void SUB_CalcMoveDone (void)
-{
+{SELFPARAM();
        // After moving, set origin to exact final destination
 
        SUB_SETORIGIN (self, self.finaldest);
@@ -93,7 +93,7 @@ void SUB_CalcMoveDone (void)
 
 .float platmovetype_turn;
 void SUB_CalcMove_controller_think (void)
-{
+{SELFPARAM();
        entity oldself;
        float traveltime;
        float phasepos;
@@ -123,9 +123,11 @@ void SUB_CalcMove_controller_think (void)
                        destangle_x = -destangle_x; // flip up / down orientation
 
                        // take the shortest distance for the angles
-                       SUB_ANGLES(self.owner)_x -= 360 * floor((SUB_ANGLES(self.owner)_x - destangle_x) / 360 + 0.5);
-                       SUB_ANGLES(self.owner)_y -= 360 * floor((SUB_ANGLES(self.owner)_y - destangle_y) / 360 + 0.5);
-                       SUB_ANGLES(self.owner)_z -= 360 * floor((SUB_ANGLES(self.owner)_z - destangle_z) / 360 + 0.5);
+                       vector v = SUB_ANGLES(self.owner);
+                       v.x -= 360 * floor((v.x - destangle_x) / 360 + 0.5);
+                       v.y -= 360 * floor((v.y - destangle_y) / 360 + 0.5);
+                       v.z -= 360 * floor((v.z - destangle_z) / 360 + 0.5);
+                       SUB_ANGLES(self.owner) = v;
                        angloc = destangle - SUB_ANGLES(self.owner);
                        angloc = angloc * (1 / PHYS_INPUT_FRAMETIME); // so it arrives for the next frame
                        self.owner.SUB_AVELOCITY = angloc;
@@ -144,7 +146,7 @@ void SUB_CalcMove_controller_think (void)
                // derivative: delta + 2 * delta2 (e.g. for angle positioning)
                oldself = self;
                self.owner.SUB_THINK = self.think1;
-               self = self.owner;
+               setself(self.owner);
                remove(oldself);
                self.SUB_THINK();
        }
@@ -185,7 +187,7 @@ float TSPEED_END = 2;
 // TODO average too?
 
 void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float tspeed, void() func)
-{
+{SELFPARAM();
        float   traveltime;
        entity controller;
 
@@ -238,13 +240,13 @@ void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float
        self.SUB_NEXTTHINK = self.SUB_LTIME + traveltime;
 
        // invoke controller
-       self = controller;
+       setself(controller);
        self.think();
-       self = self.owner;
+       setself(self.owner);
 }
 
 void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func)
-{
+{SELFPARAM();
        vector  delta;
        float   traveltime;
 
@@ -293,15 +295,8 @@ void SUB_CalcMove (vector tdest, float tspeedtype, float tspeed, void() func)
 }
 
 void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed, void() func)
-{
-       entity  oldself;
-
-       oldself = self;
-       self = ent;
-
-       SUB_CalcMove (tdest, tspeedtype, tspeed, func);
-
-       self = oldself;
+{SELFPARAM();
+       WITH(entity, self, ent, SUB_CalcMove(tdest, tspeedtype, tspeed, func));
 }
 
 /*
@@ -315,7 +310,7 @@ The calling function should make sure self.SUB_THINK is valid
 ===============
 */
 void SUB_CalcAngleMoveDone (void)
-{
+{SELFPARAM();
        // After rotating, set angle to exact final angle
        self.angles = self.finalangle;
        self.SUB_AVELOCITY = '0 0 0';
@@ -326,7 +321,7 @@ void SUB_CalcAngleMoveDone (void)
 
 // FIXME: I fixed this function only for rotation around the main axes
 void SUB_CalcAngleMove (vector destangle, float tspeedtype, float tspeed, void() func)
-{
+{SELFPARAM();
        vector  delta;
        float   traveltime;
 
@@ -368,13 +363,6 @@ void SUB_CalcAngleMove (vector destangle, float tspeedtype, float tspeed, void()
 }
 
 void SUB_CalcAngleMoveEnt (entity ent, vector destangle, float tspeedtype, float tspeed, void() func)
-{
-       entity  oldself;
-
-       oldself = self;
-       self = ent;
-
-       SUB_CalcAngleMove (destangle, tspeedtype, tspeed, func);
-
-       self = oldself;
+{SELFPARAM();
+       WITH(entity, self, ent, SUB_CalcAngleMove (destangle, tspeedtype, tspeed, func));
 }
index ea8ef3057425b28b9e260785a314da659bfbad7a..98491820f215da9636d2ce8cd72e7bbffc2e7aaa 100644 (file)
        #define SUB_FLAGS               move_flags
 
        void SUB_SETORIGIN(entity s, vector v)
-       {
+       {SELFPARAM();
                s.move_origin = v;
-               entity oldself = self;
-               self = s;
-               _Movetype_LinkEdict(true);
-               self = oldself;
+               WITH(entity, self, s, _Movetype_LinkEdict(true));
        }
 
 #endif
index 8e5c31bfea8a43ec01ea5b1ac53c4d0933e8cf0a..51e360e0c587c277dfecfd56f4a88e7a5d32d70c 100644 (file)
@@ -3,8 +3,9 @@
 .entity chlevel_targ;
 
 
-void spawnfunc_target_changelevel_use()
+void target_changelevel_use()
 {
+       SELFPARAM();
        if(self.spawnflags & 2)
        {
                // simply don't react if a non-player triggers it
@@ -35,9 +36,9 @@ void spawnfunc_target_changelevel_use()
                localcmd(strcat("changelevel ", self.chmap, "\n"));
 }
 
-void spawnfunc_target_changelevel()
+spawnfunc(target_changelevel)
 {
-       self.use = spawnfunc_target_changelevel_use;
+       self.use = target_changelevel_use;
 
        if(!self.count) { self.count = 0.7; }
 }
index 1430cabd81ee3364a9998ff3721aca30a7a47627..14512c794cfc960d92555e9e327c4c25f6c71d40 100644 (file)
@@ -1,12 +1,12 @@
 #ifdef SVQC
-void spawnfunc_target_location()
+spawnfunc(target_location)
 {
     self.classname = "target_location";
     // location name in netname
     // eventually support: count, teamgame selectors, line of sight?
 }
 
-void spawnfunc_info_location()
+spawnfunc(info_location)
 {
     self.classname = "target_location";
     self.message = self.netname;
index b3a5a24330763d13152eb088cecb0dfd9ff445df..41edbb718740193adce9252fbdc55666c64c6d6d 100644 (file)
@@ -19,7 +19,7 @@
 // when triggered, the music is overridden for activator until lifetime (or forever, if lifetime is 0)
 // when targetname is not set, THIS ONE is default
 void target_music_sendto(float to, float is)
-{
+{SELFPARAM();
        WriteByte(to, SVC_TEMPENTITY);
        WriteByte(to, TE_CSQC_TARGET_MUSIC);
        WriteShort(to, num_for_edict(self));
@@ -30,7 +30,7 @@ void target_music_sendto(float to, float is)
        WriteString(to, self.noise);
 }
 void target_music_reset()
-{
+{SELFPARAM();
        if(self.targetname == "")
                target_music_sendto(MSG_ALL, 1);
 }
@@ -46,7 +46,7 @@ void target_music_use()
        entity head;
        FOR_EACH_SPEC(head) if(head.enemy == activator) { msg_entity = head; target_music_sendto(MSG_ONE, 1); }
 }
-void spawnfunc_target_music()
+spawnfunc(target_music)
 {
        self.use = target_music_use;
        self.reset = target_music_reset;
@@ -58,9 +58,10 @@ void spawnfunc_target_music()
                target_music_sendto(MSG_INIT, 0);
 }
 void TargetMusic_RestoreGame()
-{
-       for(self = world; (self = find(self, classname, "target_music")); )
+{SELFPARAM();
+       for(entity e = world; (e = find(e, classname, "target_music")); )
        {
+               setself(e);
                if(self.targetname == "")
                        target_music_sendto(MSG_INIT, 1);
                else
@@ -75,7 +76,7 @@ void TargetMusic_RestoreGame()
 // spawnflags:
 //   1 = START_OFF
 // when triggered, it is disabled/enabled for everyone
-float trigger_music_SendEntity(entity to, float sf)
+bool trigger_music_SendEntity(entity this, entity to, float sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_MUSIC);
        sf &= ~0x80;
@@ -115,19 +116,19 @@ float trigger_music_SendEntity(entity to, float sf)
        return 1;
 }
 void trigger_music_reset()
-{
+{SELFPARAM();
        self.cnt = !(self.spawnflags & 1);
        self.SendFlags |= 0x80;
 }
 void trigger_music_use()
-{
+{SELFPARAM();
        self.cnt = !self.cnt;
        self.SendFlags |= 0x80;
 }
-void spawnfunc_trigger_music()
+spawnfunc(trigger_music)
 {
        if(self.model != "")
-               setmodel(self, self.model);
+               _setmodel(self, self.model);
        if(!self.volume)
                self.volume = 1;
        if(!self.modelindex)
@@ -181,9 +182,9 @@ void TargetMusic_Advance()
                if(vol != vol0)
                {
                        if(vol0 < 0)
-                               sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
+                               _sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
                        else
-                               sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
+                               _sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
                        e.lastvol = vol;
                }
        }
@@ -222,7 +223,7 @@ void Net_TargetMusic()
                        strunzone(e.noise);
                e.noise = strzone(noi);
                precache_sound(e.noise);
-               sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
+               _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);
@@ -255,7 +256,7 @@ void Net_TargetMusic()
 }
 
 void Ent_TriggerMusic_Think()
-{
+{SELFPARAM();
        if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, self, world))
        {
                music_trigger = self;
@@ -264,14 +265,14 @@ void Ent_TriggerMusic_Think()
 }
 
 void Ent_TriggerMusic_Remove()
-{
+{SELFPARAM();
        if(self.noise)
                strunzone(self.noise);
        self.noise = string_null;
 }
 
 void Ent_ReadTriggerMusic()
-{
+{SELFPARAM();
        int f = ReadByte();
        if(f & 4)
        {
@@ -309,7 +310,7 @@ void Ent_ReadTriggerMusic()
                if(self.noise != s)
                {
                        precache_sound(self.noise);
-                       sound(self, CH_BGM_SINGLE, self.noise, 0, ATTEN_NONE);
+                       _sound(self, CH_BGM_SINGLE, self.noise, 0, ATTEN_NONE);
                        if(getsoundtime(self, CH_BGM_SINGLE) < 0)
                        {
                                LOG_TRACEF("Cannot initialize sound %s\n", self.noise);
index da7aeda71e9c628055b7223b9299eb9ba87d0625..10fe3c764afb24b3152cd052346cecc2457b7e42 100644 (file)
@@ -23,22 +23,21 @@ float target_spawn_spawnfunc_field;
 float target_spawn_count;
 
 void target_spawn_helper_setmodel()
-{
-       setmodel(self, self.model);
+{SELFPARAM();
+       _setmodel(self, self.model);
 }
 
 void target_spawn_helper_setsize()
-{
+{SELFPARAM();
        setsize(self, self.mins, self.maxs);
 }
 
 void target_spawn_edit_entity(entity e, string msg, entity kt, entity t2, entity t3, entity t4, entity act)
-{
+{SELFPARAM();
        float i, n, valuefieldpos;
        string key, value, valuefield, valueoffset, valueoffsetrandom;
        entity valueent;
        vector data, data2;
-       entity oldself;
        entity oldactivator;
 
        n = tokenize_console(msg);
@@ -220,15 +219,10 @@ void target_spawn_edit_entity(entity e, string msg, entity kt, entity t2, entity
                                value = strcat("target_spawn_helper", value);
                        putentityfieldstring(target_spawn_spawnfunc_field, e, value);
 
-                       oldself = self;
                        oldactivator = activator;
 
-                       self = e;
                        activator = act;
-
-                       self.target_spawn_spawnfunc();
-
-                       self = oldself;
+                       WITH(entity, self, e, e.target_spawn_spawnfunc());
                        activator = oldactivator;
 
                        // We called an external function, so we have to re-tokenize msg.
@@ -244,7 +238,7 @@ void target_spawn_edit_entity(entity e, string msg, entity kt, entity t2, entity
 }
 
 void target_spawn_useon(entity e)
-{
+{SELFPARAM();
        self.target_spawn_activator = activator;
        target_spawn_edit_entity(
                e,
@@ -258,7 +252,7 @@ void target_spawn_useon(entity e)
 }
 
 float target_spawn_cancreate()
-{
+{SELFPARAM();
        float c;
        entity e;
 
@@ -277,7 +271,7 @@ float target_spawn_cancreate()
 }
 
 void target_spawn_use()
-{
+{SELFPARAM();
        entity e;
 
        if(self.target == "")
@@ -286,6 +280,7 @@ void target_spawn_use()
                if(!target_spawn_cancreate())
                        return;
                e = spawn();
+               e.spawnfunc_checked = true;
                target_spawn_useon(e);
                e.target_spawn_id = self.target_spawn_id;
        }
@@ -304,7 +299,7 @@ void target_spawn_use()
 }
 
 void target_spawn_spawnfirst()
-{
+{SELFPARAM();
        activator = self.target_spawn_activator;
        if(self.spawnflags & 2)
                target_spawn_use();
@@ -338,7 +333,7 @@ void initialize_field_db()
        }
 }
 
-void spawnfunc_target_spawn()
+spawnfunc(target_spawn)
 {
        initialize_field_db();
        self.use = target_spawn_use;
index 7be8b91b4c2920cabe64093d1500ed0360cae748..0b3767ff654c856a13d9e6a515dc13020c5abd4f 100644 (file)
@@ -2,21 +2,20 @@
 // TODO add a way to do looped sounds with sound(); then complete this entity
 void target_speaker_use_off();
 void target_speaker_use_activator()
-{
+{SELFPARAM();
        if (!IS_REAL_CLIENT(activator))
                return;
        string snd;
        if(substring(self.noise, 0, 1) == "*")
        {
-               var .string sample;
-               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
+               var .string sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
                if(GetPlayerSoundSampleField_notFound)
-                       snd = "misc/null.wav";
-               else if(activator.sample == "")
-                       snd = "misc/null.wav";
+                       snd = SND(Null);
+               else if(activator.(sample) == "")
+                       snd = SND(Null);
                else
                {
-                       tokenize_console(activator.sample);
+                       tokenize_console(activator.(sample));
                        float n;
                        n = stof(argv(1));
                        if(n > 0)
@@ -31,19 +30,18 @@ void target_speaker_use_activator()
        soundto(MSG_ONE, self, CH_TRIGGER, snd, VOL_BASE * self.volume, self.atten);
 }
 void target_speaker_use_on()
-{
+{SELFPARAM();
        string snd;
        if(substring(self.noise, 0, 1) == "*")
        {
-               var .string sample;
-               sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
+               var .string sample = GetVoiceMessageSampleField(substring(self.noise, 1, -1));
                if(GetPlayerSoundSampleField_notFound)
-                       snd = "misc/null.wav";
-               else if(activator.sample == "")
-                       snd = "misc/null.wav";
+                       snd = SND(Null);
+               else if(activator.(sample) == "")
+                       snd = SND(Null);
                else
                {
-                       tokenize_console(activator.sample);
+                       tokenize_console(activator.(sample));
                        float n;
                        n = stof(argv(1));
                        if(n > 0)
@@ -54,17 +52,17 @@ void target_speaker_use_on()
        }
        else
                snd = self.noise;
-       sound(self, CH_TRIGGER_SINGLE, snd, VOL_BASE * self.volume, self.atten);
+       _sound(self, CH_TRIGGER_SINGLE, snd, VOL_BASE * self.volume, self.atten);
        if(self.spawnflags & 3)
                self.use = target_speaker_use_off;
 }
 void target_speaker_use_off()
-{
-       sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASE * self.volume, self.atten);
+{SELFPARAM();
+       sound(self, CH_TRIGGER_SINGLE, SND_Null, VOL_BASE * self.volume, self.atten);
        self.use = target_speaker_use_on;
 }
 void target_speaker_reset()
-{
+{SELFPARAM();
        if(self.spawnflags & 1) // LOOPED_ON
        {
                if(self.use == target_speaker_use_on)
@@ -77,7 +75,7 @@ void target_speaker_reset()
        }
 }
 
-void spawnfunc_target_speaker()
+spawnfunc(target_speaker)
 {
        // TODO: "*" prefix to sound file name
        // TODO: wait and random (just, HOW? random is not a field)
index c173d80eefe6867261105b427a509ea850ba2c51..1d1816a7741e988f46f9ee70f6773efc5843fe6f 100644 (file)
@@ -10,7 +10,7 @@ void target_voicescript_clear(entity pl)
 }
 
 void target_voicescript_use()
-{
+{SELFPARAM();
        if(activator.voicescript != self)
        {
                activator.voicescript = self;
@@ -73,7 +73,7 @@ void target_voicescript_next(entity pl)
        }
 }
 
-void spawnfunc_target_voicescript()
+spawnfunc(target_voicescript)
 {
        // netname: directory of the sound files
        // message: list of "sound file" duration "sound file" duration, a *, and again a list
index 3421311691863f31a23274c4bf73a02fe8af7372..94f2bd26bc99b897a88a45002f27a6a83a7b3f78 100644 (file)
@@ -63,7 +63,7 @@ void spawn_tdeath(vector v0, entity e, vector v)
 }
 
 void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
-{
+{SELFPARAM();
        entity telefragger;
        vector from;
 
@@ -79,7 +79,7 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle
                if(self.pushltime < time) // only show one teleport effect per teleporter per 0.2 seconds, for better fps
                {
                        if(tflags & TELEPORT_FLAG_SOUND)
-                               sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
+                               sound (player, CH_TRIGGER, SND_TELEPORT, VOL_BASE, ATTEN_NORM);
                        if(tflags & TELEPORT_FLAG_PARTICLES)
                        {
                                Send_Effect(EFFECT_TELEPORT, player.origin, '0 0 0', 1);
@@ -179,7 +179,7 @@ entity Simple_TeleportPlayer(entity teleporter, entity player)
 }
 
 void teleport_findtarget (void)
-{
+{SELFPARAM();
        entity e;
        float n;
 
@@ -224,15 +224,12 @@ entity Teleport_Find(vector mi, vector ma)
 }
 
 void WarpZone_PostTeleportPlayer_Callback(entity pl)
-{
+{SELFPARAM();
        makevectors(pl.angles);
        Reset_ArcBeam(pl, v_forward);
        UpdateCSQCProjectileAfterTeleport(pl);
        {
-               entity oldself = self;
-               self = pl;
-               anticheat_fixangle();
-               self = oldself;
+               WITH(entity, self, pl, anticheat_fixangle());
        }
        // "disown" projectiles after teleport
        if(pl.owner)
index bf1d9b2da76f672c4f554ed9d262e3cb1624cbd1..41f9f79ecc4d245d8c1f7790158a9efc11cfeb26 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 void counter_use()
-{
+{SELFPARAM();
        self.count -= 1;
        if (self.count < 0)
                return;
@@ -24,7 +24,7 @@ void counter_use()
 }
 
 void counter_reset()
-{
+{SELFPARAM();
        self.count = self.cnt;
        multi_reset();
 }
@@ -36,7 +36,7 @@ If nomessage is not set, t will print "1 more.. " etc when triggered and "sequen
 
 After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
 */
-void spawnfunc_trigger_counter()
+spawnfunc(trigger_counter)
 {
        self.wait = -1;
        if (!self.count)
index b01efe3bba0737df4059022ad5390e5ca0866235..eb0c0af7754a252ce0ef5ac301f220314f345f34 100644 (file)
@@ -1,17 +1,17 @@
 #ifdef SVQC
 void delay_use()
-{
+{SELFPARAM();
     self.think = SUB_UseTargets;
    self.nextthink = self.wait;
 }
 
 void delay_reset()
-{
+{SELFPARAM();
        self.think = func_null;
        self.nextthink = 0;
 }
 
-void spawnfunc_trigger_delay()
+spawnfunc(trigger_delay)
 {
     if(!self.wait)
         self.wait = 1;
index 2a0432c97827790b3a6a0a483f4e86a830a26851..a1f13d277e5f87e68d3391323596d0d9072cc659 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 void trigger_disablerelay_use()
-{
+{SELFPARAM();
        entity e;
 
        float a, b;
@@ -24,7 +24,7 @@ void trigger_disablerelay_use()
                LOG_INFO("Invalid use of trigger_disablerelay: ", ftos(a), " relays were on, ", ftos(b), " relays were off!\n");
 }
 
-void spawnfunc_trigger_disablerelay()
+spawnfunc(trigger_disablerelay)
 {
        self.use = trigger_disablerelay_use;
 }
index 12d8a5940a245a7b6f55a11626df815803c1b39c..e039173fb01ea752cbfae4361181cb65895282c4 100644 (file)
@@ -3,17 +3,20 @@
 "Flip-flop" trigger gate... lets only every second trigger event through
 */
 void flipflop_use()
-{
+{SELFPARAM();
     self.state = !self.state;
     if(self.state)
         SUB_UseTargets();
 }
 
-void spawnfunc_trigger_flipflop()
+void _spawnfunc_trigger_flipflop();
+spawnfunc(trigger_flipflop)
 {
     if(self.spawnflags & 1)
         self.state = 1;
     self.use = flipflop_use;
-    self.reset = spawnfunc_trigger_flipflop; // perfect resetter
+    self.reset = _spawnfunc_trigger_flipflop; // perfect resetter
 }
+void _spawnfunc_trigger_flipflop() { SELFPARAM(); spawnfunc_trigger_flipflop(this); }
+
 #endif
index 3ad419d22fc287388949f7a5c0ba2842a13d4216..30e6ebae7015e6a25af19d7f8b82335b6571cec4 100644 (file)
@@ -1,15 +1,16 @@
 #ifdef SVQC
 void gamestart_use()
-{
+{SELFPARAM();
        activator = self;
        SUB_UseTargets();
        remove(self);
 }
 
-void spawnfunc_trigger_gamestart()
+void _spawnfunc_trigger_gamestart();
+spawnfunc(trigger_gamestart)
 {
        self.use = gamestart_use;
-       self.reset2 = spawnfunc_trigger_gamestart;
+       self.reset2 = _spawnfunc_trigger_gamestart;
 
        if(self.wait)
        {
@@ -19,4 +20,6 @@ void spawnfunc_trigger_gamestart()
        else
                InitializeEntity(self, gamestart_use, INITPRIO_FINDTARGET);
 }
+void _spawnfunc_trigger_gamestart() { SELFPARAM(); spawnfunc_trigger_gamestart(this); }
+
 #endif
index a709a1f2a7cb22d91a132a20707193baec3ccbaf..a6b3eedde651521db1a84c409b00940cec16c6a3 100644 (file)
@@ -13,7 +13,7 @@ void trigger_gravity_remove(entity own)
        own.trigger_gravity_check = world;
 }
 void trigger_gravity_check_think()
-{
+{SELFPARAM();
        // This spawns when a player enters the gravity zone and checks if he left.
        // Each frame, self.count is set to 2 by trigger_gravity_touch() and decreased by 1 here.
        // It the player has left the gravity trigger, this will be allowed to reach 0 and indicate that.
@@ -33,12 +33,12 @@ void trigger_gravity_check_think()
 }
 
 void trigger_gravity_use()
-{
+{SELFPARAM();
        self.state = !self.state;
 }
 
 void trigger_gravity_touch()
-{
+{SELFPARAM();
        float g;
 
        if(self.state != true)
@@ -80,12 +80,12 @@ void trigger_gravity_touch()
        {
                other.gravity = g;
                if(self.noise != "")
-                       sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+                       _sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
                UpdateCSQCProjectile(self.owner);
        }
 }
 
-void spawnfunc_trigger_gravity()
+spawnfunc(trigger_gravity)
 {
        if(self.gravity == 1)
                return;
index 6d68610b5cf8ddb5afb7c2101a0b3ffacdb83f5b..5d4f2d0b3a2cf26a15508c630cc47bb19f90cc38 100644 (file)
@@ -1,7 +1,7 @@
 #ifdef SVQC
 .float triggerhealtime;
 void trigger_heal_touch()
-{
+{SELFPARAM();
        if (self.active != ACTIVE_ACTIVE)
                return;
 
@@ -19,13 +19,13 @@ void trigger_heal_touch()
                        {
                                other.health = min(other.health + self.health, self.max_health);
                                other.pauserothealth_finished = max(other.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
-                               sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+                               _sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
                        }
                }
        }
 }
 
-void spawnfunc_trigger_heal()
+spawnfunc(trigger_heal)
 {
        self.active = ACTIVE_ACTIVE;
 
index 3a15a77ff4d4c3ff69fb1813c3d25886378684a6..535ba8500d29743d138a27aca5ea980132110644 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 void trigger_hurt_use()
-{
+{SELFPARAM();
        if(IS_PLAYER(activator))
                self.enemy = activator;
        else
@@ -9,7 +9,7 @@ void trigger_hurt_use()
 
 .float triggerhurttime;
 void trigger_hurt_touch()
-{
+{SELFPARAM();
        if (self.active != ACTIVE_ACTIVE)
                return;
 
@@ -57,7 +57,7 @@ defalt dmg = 5
 .entity trigger_hurt_next;
 entity trigger_hurt_last;
 entity trigger_hurt_first;
-void spawnfunc_trigger_hurt()
+spawnfunc(trigger_hurt)
 {
        EXACTTRIGGER_INIT;
        self.active = ACTIVE_ACTIVE;
index 7b8ebcfde91e67627c4ca76b6494441d87fc59a5..c40fed3a8387bc1da25a54f180de0efdafa3c197 100644 (file)
@@ -1,6 +1,6 @@
 // targeted (directional) mode
 void trigger_impulse_touch1()
-{
+{SELFPARAM();
        entity targ;
        float pushdeltatime;
        float str;
@@ -54,7 +54,7 @@ void trigger_impulse_touch1()
 
 // Directionless (accelerator/decelerator) mode
 void trigger_impulse_touch2()
-{
+{SELFPARAM();
        float pushdeltatime;
 
        if (self.active != ACTIVE_ACTIVE)
@@ -79,7 +79,7 @@ void trigger_impulse_touch2()
 
 // Spherical (gravity/repulsor) mode
 void trigger_impulse_touch3()
-{
+{SELFPARAM();
        float pushdeltatime;
        float str;
 
@@ -132,7 +132,7 @@ in directional and sperical mode. For damper/accelerator mode this is not nesses
 */
 #ifdef SVQC
 bool trigger_impulse_send(entity to, int sf)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
 
        WriteCoord(MSG_ENTITY, self.radius);
@@ -150,7 +150,7 @@ void trigger_impulse_link()
        //Net_LinkEntity(self, 0, false, trigger_impulse_send);
 }
 
-void spawnfunc_trigger_impulse()
+spawnfunc(trigger_impulse)
 {
        self.active = ACTIVE_ACTIVE;
 
@@ -181,7 +181,7 @@ void spawnfunc_trigger_impulse()
 }
 #elif defined(CSQC)
 void ent_trigger_impulse()
-{
+{SELFPARAM();
        self.radius = ReadCoord();
        self.strength = ReadCoord();
        self.falloff = ReadByte();
index 47f08d3acb321a0a50a2404d8d0cd2a34c519eb1..a5482402891c433fec98f9ebc0f1b2b797af8559 100644 (file)
@@ -5,7 +5,7 @@
 #include "../../movetypes/movetypes.qh"
 
 void trigger_push_use()
-{
+{SELFPARAM();
        if(teamplay)
        {
                self.team = activator.team;
@@ -128,7 +128,7 @@ vector trigger_push_calculatevelocity(vector org, entity tgt, float ht)
 }
 
 void trigger_push_touch()
-{
+{SELFPARAM();
        if (self.active == ACTIVE_NOT)
                return;
 
@@ -182,7 +182,7 @@ void trigger_push_touch()
                {
                        // flash when activated
                        Send_Effect(EFFECT_JUMPPAD, other.origin, other.velocity, 1);
-                       sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+                       _sound (other, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
                        self.pushltime = time + 0.2;
                }
                if(IS_REAL_CLIENT(other) || IS_BOT_CLIENT(other))
@@ -218,12 +218,8 @@ void trigger_push_touch()
 
        if(self.enemy.target)
        {
-               entity oldself;
-               oldself = self;
                activator = other;
-               self = self.enemy;
-               SUB_UseTargets();
-               self = oldself;
+               WITH(entity, self, self.enemy, SUB_UseTargets());
        }
 
        if (other.flags & FL_PROJECTILE)
@@ -257,7 +253,7 @@ void trigger_push_link();
 void trigger_push_updatelink();
 #endif
 void trigger_push_findtarget()
-{
+{SELFPARAM();
        entity t;
        vector org;
 
@@ -321,7 +317,7 @@ void trigger_push_findtarget()
 
 #ifdef SVQC
 float trigger_push_send(entity to, float sf)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_PUSH);
        WriteByte(MSG_ENTITY, sf);
 
@@ -345,7 +341,7 @@ float trigger_push_send(entity to, float sf)
 }
 
 void trigger_push_updatelink()
-{
+{SELFPARAM();
        self.SendFlags |= 1;
 }
 
@@ -367,7 +363,7 @@ void trigger_push_link()
  *            values to target a point on the ceiling.
  *   movedir: if target is not set, this * speed * 10 is the velocity to be reached.
  */
-void spawnfunc_trigger_push()
+spawnfunc(trigger_push)
 {
        SetMovedir ();
 
@@ -391,7 +387,7 @@ void spawnfunc_trigger_push()
 }
 
 
-float target_push_send(entity to, float sf)
+bool target_push_send(entity this, entity to, float sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_TARGET_PUSH);
 
@@ -405,21 +401,21 @@ float target_push_send(entity to, float sf)
 }
 
 void target_push_link()
-{
+{SELFPARAM();
        Net_LinkEntity(self, false, 0, target_push_send);
        self.SendFlags |= 1; // update
 }
 
-void spawnfunc_target_push() { target_push_link(); }
-void spawnfunc_info_notnull() { target_push_link(); }
-void spawnfunc_target_position() { target_push_link(); }
+spawnfunc(target_push) { target_push_link(); }
+spawnfunc(info_notnull) { target_push_link(); }
+spawnfunc(target_position) { target_push_link(); }
 
 #endif
 
 #ifdef CSQC
 
 void ent_trigger_push()
-{
+{SELFPARAM();
        float sf = ReadByte();
 
        if(sf & 1)
@@ -449,7 +445,7 @@ void ent_trigger_push()
 }
 
 void target_push_remove()
-{
+{SELFPARAM();
        if(self.classname)
                strunzone(self.classname);
        self.classname = string_null;
@@ -460,7 +456,7 @@ void target_push_remove()
 }
 
 void ent_target_push()
-{
+{SELFPARAM();
        self.classname = "push_target";
        self.cnt = ReadByte();
        self.targetname = strzone(ReadString());
index bb0f4750eebbc2af005c12a86123bb02470270d7..efce0df62d95600473019f016e4ac656ad0699f9 100644 (file)
@@ -59,10 +59,10 @@ void trigger_push_findtarget();
  *   movedir: if target is not set, this * speed * 10 is the velocity to be reached.
  */
 #ifdef SVQC
-void spawnfunc_trigger_push();
+spawnfunc(trigger_push);
 
-void spawnfunc_target_push();
-void spawnfunc_info_notnull();
-void spawnfunc_target_position();
+spawnfunc(target_push);
+spawnfunc(info_notnull);
+spawnfunc(target_position);
 #endif
 #endif
index ec27d4b77fb9348363153f8ca81214e4867c695f..365c6f5a908d01a7ea8a3f7f76a51ce2545e0b70 100644 (file)
@@ -2,8 +2,7 @@
  * trigger given targets
  */
 void trigger_keylock_trigger(string s)
-{
-       entity stemp = self;
+{SELFPARAM();
        entity otemp = other;
        entity atemp = activator;
 
@@ -11,13 +10,13 @@ void trigger_keylock_trigger(string s)
        for(t = world; (t = find(t, targetname, s)); )
                if(t.use)
                {
-                       self = t;
-                       other = stemp;
+                       setself(t);
+                       other = this;
                        activator = atemp;
                        self.use();
                }
 
-       self = stemp;
+       setself(this);
        other = otemp;
        activator = atemp;
 }
@@ -33,7 +32,7 @@ void trigger_keylock_kill(string s)
 }
 
 void trigger_keylock_touch()
-{
+{SELFPARAM();
        bool key_used = false;
        bool started_delay = false;
 
@@ -97,7 +96,7 @@ void trigger_keylock_touch()
 
 #ifdef SVQC
 bool trigger_keylock_send(entity to, int sf)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_KEYLOCK);
 
        WriteInt24_t(MSG_ENTITY, self.itemkeys);
@@ -133,7 +132,7 @@ wait: prevent triggering again for this amount of time (default: 5) - applies to
 If spawned without any key specified in itemkeys, this trigger will display an error and remove itself.
 message2 and noise2 will be resent to the player every 2 seconds while he is in the trigger zone.
 */
-void spawnfunc_trigger_keylock(void)
+spawnfunc(trigger_keylock)
 {
        if(!self.itemkeys) { remove(self); return; }
 
@@ -147,7 +146,7 @@ void spawnfunc_trigger_keylock(void)
                if(self.sounds == 1)
                        self.noise = "misc/secret.wav";
                else if(self.sounds == 2)
-                       self.noise = "misc/talk.wav";
+                       self.noise = SND(TALK);
                else //if (self.sounds == 3) {
                        self.noise = "misc/trigger1.wav";
        }
@@ -158,7 +157,7 @@ void spawnfunc_trigger_keylock(void)
 
        // set closed sourd
        if(self.noise2 == "")
-               self.noise2 = "misc/talk.wav";
+               self.noise2 = SND(TALK);
 
        // delay between triggering message2 and trigger2
        if(!self.wait) { self.wait = 5; }
@@ -176,7 +175,7 @@ void spawnfunc_trigger_keylock(void)
 }
 #elif defined(CSQC)
 void keylock_remove()
-{
+{SELFPARAM();
        if(self.target) { strunzone(self.target); }
        self.target = string_null;
 
@@ -197,7 +196,7 @@ void keylock_remove()
 }
 
 void ent_keylock()
-{
+{SELFPARAM();
        self.itemkeys = ReadInt24_t();
        self.height = ReadByte();
 
index f14b75c3124b983856400b620faf2af7dbc517ce..c20514e1a61f8e9cff3b0355c77bee16d10fce4f 100644 (file)
@@ -2,10 +2,9 @@
 float magicear_matched;
 float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
 string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin)
-{
+{SELFPARAM();
        float domatch, dotrigger, matchstart, l;
        string s, msg;
-       entity oldself;
        string savemessage;
 
        magicear_matched = false;
@@ -29,14 +28,13 @@ string trigger_magicear_processmessage(entity ear, entity source, float teamsay,
 
                if(dotrigger)
                {
-                       oldself = self;
                        activator = source;
-                       self = ear;
+                       setself(ear);
                        savemessage = self.message;
                        self.message = string_null;
                        SUB_UseTargets();
                        self.message = savemessage;
-                       self = oldself;
+                       setself(this);
                }
 
                if(ear.netname != "")
@@ -120,14 +118,13 @@ string trigger_magicear_processmessage(entity ear, entity source, float teamsay,
 
        if(dotrigger)
        {
-               oldself = self;
                activator = source;
-               self = ear;
+               setself(ear);
                savemessage = self.message;
                self.message = string_null;
                SUB_UseTargets();
                self.message = savemessage;
-               self = oldself;
+               setself(this);
        }
 
        if(ear.spawnflags & 16)
@@ -165,7 +162,7 @@ string trigger_magicear_processmessage_forallears(entity source, float teamsay,
        return msgin;
 }
 
-void spawnfunc_trigger_magicear()
+spawnfunc(trigger_magicear)
 {
        self.enemy = magicears;
        magicears = self;
index 45ce761e035d85a5b344828e26170458b1b514c5..d81f6e371958c9d3b8680567cf6817af849eefe7 100644 (file)
@@ -3,7 +3,7 @@
 "Mono-flop" trigger gate... turns one trigger event into one "on" and one "off" event, separated by a delay of "wait"
 */
 void monoflop_use()
-{
+{SELFPARAM();
        self.nextthink = time + self.wait;
        self.enemy = activator;
        if(self.state)
@@ -12,7 +12,7 @@ void monoflop_use()
        SUB_UseTargets();
 }
 void monoflop_fixed_use()
-{
+{SELFPARAM();
        if(self.state)
                return;
        self.nextthink = time + self.wait;
@@ -22,19 +22,19 @@ void monoflop_fixed_use()
 }
 
 void monoflop_think()
-{
+{SELFPARAM();
        self.state = 0;
        activator = self.enemy;
        SUB_UseTargets();
 }
 
 void monoflop_reset()
-{
+{SELFPARAM();
        self.state = 0;
        self.nextthink = 0;
 }
 
-void spawnfunc_trigger_monoflop()
+spawnfunc(trigger_monoflop)
 {
        if(!self.wait)
                self.wait = 1;
index 0e9a02016ca4fd7109561683785891a32e227444..3261520d7a19e951ebdd198c7293facdf38a1de0 100644 (file)
@@ -3,7 +3,7 @@
 #ifdef SVQC
 // the wait time has passed, so set back up for another activation
 void multi_wait()
-{
+{SELFPARAM();
        if (self.max_health)
        {
                self.health = self.max_health;
@@ -17,7 +17,7 @@ void multi_wait()
 // self.enemy should be set to the activator so it can be held through a delay
 // so wait for the delay time before firing
 void multi_trigger()
-{
+{SELFPARAM();
        if (self.nextthink > time)
        {
                return;         // allready been triggered
@@ -32,7 +32,7 @@ void multi_trigger()
        }
 
        if (self.noise)
-               sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+               _sound (self.enemy, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
 
 // don't trigger again until reset
        self.takedamage = DAMAGE_NO;
@@ -58,14 +58,14 @@ void multi_trigger()
 }
 
 void multi_use()
-{
+{SELFPARAM();
        self.goalentity = other;
        self.enemy = activator;
        multi_trigger();
 }
 
 void multi_touch()
-{
+{SELFPARAM();
        if(!(self.spawnflags & 2))
        if(!other.iscreature)
                        return;
@@ -96,7 +96,7 @@ void multi_touch()
 }
 
 void multi_eventdamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if (!self.takedamage)
                return;
        if(self.spawnflags & DOOR_NOSPLASH)
@@ -112,7 +112,7 @@ void multi_eventdamage (entity inflictor, entity attacker, float damage, int dea
 }
 
 void multi_reset()
-{
+{SELFPARAM();
        if ( !(self.spawnflags & SPAWNFLAG_NOTOUCH) )
                self.touch = multi_touch;
        if (self.max_health)
@@ -139,7 +139,7 @@ sounds
 4)
 set "message" to text string
 */
-void spawnfunc_trigger_multiple()
+spawnfunc(trigger_multiple)
 {
        self.reset = multi_reset;
        if (self.sounds == 1)
@@ -149,8 +149,7 @@ void spawnfunc_trigger_multiple()
        }
        else if (self.sounds == 2)
        {
-               precache_sound ("misc/talk.wav");
-               self.noise = "misc/talk.wav";
+               self.noise = SND(TALK);
        }
        else if (self.sounds == 3)
        {
@@ -202,9 +201,9 @@ sounds
 4)
 set "message" to text string
 */
-void spawnfunc_trigger_once()
+spawnfunc(trigger_once)
 {
-       self.wait = -1;
-       spawnfunc_trigger_multiple();
+       this.wait = -1;
+       spawnfunc_trigger_multiple(this);
 }
 #endif
index df14a518e61fb73faecab94a6bb58eb52dadc03b..5e72a96a2fe478d74523c3c53183524b873dda27 100644 (file)
@@ -2,5 +2,5 @@
 void multi_trigger();
 void multi_reset();
 
-void spawnfunc_trigger_once();
+spawnfunc(trigger_once);
 #endif
index 02a258e87f13a92a942f70f5c2427129f4457928..78b3383fc0422f787fa68c075bd6bdd9c5514dd9 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 void multivibrator_send()
-{
+{SELFPARAM();
        float newstate;
        float cyclestart;
 
@@ -20,7 +20,7 @@ void multivibrator_send()
 }
 
 void multivibrator_toggle()
-{
+{SELFPARAM();
        if(self.nextthink == 0)
        {
                multivibrator_send();
@@ -37,7 +37,7 @@ void multivibrator_toggle()
 }
 
 void multivibrator_reset()
-{
+{SELFPARAM();
        if(!(self.spawnflags & 1))
                self.nextthink = 0; // wait for a trigger event
        else
@@ -55,7 +55,7 @@ respawntime: "off" cycle time (default: same as wait)
 -------- SPAWNFLAGS --------
 START_ON: assume it is already turned on (when targeted)
 */
-void spawnfunc_trigger_multivibrator()
+spawnfunc(trigger_multivibrator)
 {
        if(!self.wait)
                self.wait = 1;
index e037028aee59990cc514a8f374805ed5c30a0977..178daad90e06b78904abc187d5e60f3f3aeda720 100644 (file)
@@ -1,10 +1,12 @@
 #ifdef SVQC
+void _spawnfunc_trigger_relay();
 /*QUAKED spawnfunc_trigger_relay (.5 .5 .5) (-8 -8 -8) (8 8 8)
 This fixed size trigger cannot be touched, it can only be fired by other events.  It can contain killtargets, targets, delays, and messages.
 */
-void spawnfunc_trigger_relay()
+spawnfunc(trigger_relay)
 {
        self.use = SUB_UseTargets;
-       self.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully
+       self.reset = _spawnfunc_trigger_relay; // this spawnfunc resets fully
 }
+void _spawnfunc_trigger_relay() { SELFPARAM(); spawnfunc_trigger_relay(this); }
 #endif
index 83c0103d09fe4ad2a2d61eaad361e49c48ac0e98..147b6178a1e15abdeef8c6e924e295ce2137cfa1 100644 (file)
@@ -1,43 +1,39 @@
 #ifdef SVQC
 void relay_activators_use()
-{
-       entity trg, os;
-
-       os = self;
-
-       for(trg = world; (trg = find(trg, targetname, os.target)); )
+{SELFPARAM();
+       for(entity trg = world; (trg = find(trg, targetname, this.target)); )
        {
-               self = trg;
+               setself(trg);
                if (trg.setactive)
-                       trg.setactive(os.cnt);
+                       trg.setactive(this.cnt);
                else
                {
                        //bprint("Not using setactive\n");
-                       if(os.cnt == ACTIVE_TOGGLE)
+                       if(this.cnt == ACTIVE_TOGGLE)
                                if(trg.active == ACTIVE_ACTIVE)
                                        trg.active = ACTIVE_NOT;
                                else
                                        trg.active = ACTIVE_ACTIVE;
                        else
-                               trg.active = os.cnt;
+                               trg.active = this.cnt;
                }
        }
-       self = os;
+       setself(this);
 }
 
-void spawnfunc_relay_activate()
+spawnfunc(relay_activate)
 {
        self.cnt = ACTIVE_ACTIVE;
        self.use = relay_activators_use;
 }
 
-void spawnfunc_relay_deactivate()
+spawnfunc(relay_deactivate)
 {
        self.cnt = ACTIVE_NOT;
        self.use = relay_activators_use;
 }
 
-void spawnfunc_relay_activatetoggle()
+spawnfunc(relay_activatetoggle)
 {
        self.cnt = ACTIVE_TOGGLE;
        self.use = relay_activators_use;
index ade56c1e8b48fe4ec78b3515668980ffd21f191f..e45996bd855695593b1717e83e8b7f7551c700ad 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 void trigger_relay_if_use()
-{
+{SELFPARAM();
        float n;
        n = self.count;
 
@@ -13,7 +13,7 @@ void trigger_relay_if_use()
                SUB_UseTargets();
 }
 
-void spawnfunc_trigger_relay_if()
+spawnfunc(trigger_relay_if)
 {
        self.use = trigger_relay_if_use;
 }
index 8a77cef0515afe654cf5621dc90e9ed80ac2b268..ab2b87aaa0da62276a72ed52f0cc74e81a119d1d 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 void trigger_relay_teamcheck_use()
-{
+{SELFPARAM();
        if(activator.team)
        {
                if(self.spawnflags & 2)
@@ -22,11 +22,11 @@ void trigger_relay_teamcheck_use()
 }
 
 void trigger_relay_teamcheck_reset()
-{
+{SELFPARAM();
        self.team = self.team_saved;
 }
 
-void spawnfunc_trigger_relay_teamcheck()
+spawnfunc(trigger_relay_teamcheck)
 {
        self.team_saved = self.team;
        self.use = trigger_relay_teamcheck_use;
index b93ab03d0a4ded5fcb90f76e2cef41c1963bb195..d16d2773c193442fe04b83943e47b7c9ad8a5652 100644 (file)
@@ -9,7 +9,8 @@
 
 #ifdef SVQC
 
-void secrets_setstatus() {
+void secrets_setstatus()
+{SELFPARAM();
        self.stat_secrets_total = secrets_total;
        self.stat_secrets_found = secrets_found;
 }
@@ -17,7 +18,8 @@ void secrets_setstatus() {
 /**
  * A secret has been found (maybe :P)
  */
-void trigger_secret_touch() {
+void trigger_secret_touch()
+{SELFPARAM();
        // only a player can trigger this
        if (!IS_PLAYER(other))
                return;
@@ -49,7 +51,8 @@ killtarget: remove all entities with this targetname when triggered
 You should create a common/trigger textured brush covering the entrance to a secret room/area.
 Trigger secret can only be trigger by a player's touch and can not be a target itself.
 */
-void spawnfunc_trigger_secret() {
+spawnfunc(trigger_secret)
+{
        // FIXME: should it be disabled in most modes?
 
        // update secrets count
@@ -75,7 +78,7 @@ void spawnfunc_trigger_secret() {
 
        // convert this trigger to trigger_once
        self.classname = "trigger_once";
-       spawnfunc_trigger_once();
+       spawnfunc_trigger_once(this);
 
        // take over the touch() function, so we can mark secret as found
        self.touch = trigger_secret_touch;
index b99332b984533c9853a79b0618c859e4c5a78eff..2ae068d824f648bd3a98c776a708fbd23e1c018a 100644 (file)
@@ -21,7 +21,7 @@
 .entity swampslug;
 
 #ifdef SVQC
-void spawnfunc_trigger_swamp(void);
+spawnfunc(trigger_swamp);
 #endif
 void swamp_touch(void);
 void swampslug_think();
@@ -38,7 +38,7 @@ void swampslug_think();
 * I do it this way becuz there is no "untouch" event.
 */
 void swampslug_think(void)
-{
+{SELFPARAM();
        //Slowly kill the slug
        self.health = self.health - 1;
 
@@ -62,7 +62,7 @@ void swampslug_think(void)
 }
 
 void swamp_touch(void)
-{
+{SELFPARAM();
        // If whatever thats touching the swamp is not a player
        // or if its a dead player, just dont care abt it.
        if(!IS_PLAYER(other) || PHYS_DEAD(other))
@@ -95,7 +95,7 @@ void swamp_touch(void)
 
 #ifdef SVQC
 float swamp_send(entity to, float sf)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_LADDER);
 
        WriteByte(MSG_ENTITY, self.dmg); // can probably get away with using a single byte here
@@ -108,7 +108,7 @@ float swamp_send(entity to, float sf)
 }
 
 void swamp_link()
-{
+{SELFPARAM();
        Net_LinkEntity(self, false, 0, func_ladder_send);
 }
 
@@ -116,7 +116,7 @@ void swamp_link()
 Players gettin into the swamp will
 get slowd down and damaged
 */
-void spawnfunc_trigger_swamp(void)
+spawnfunc(trigger_swamp)
 {
        // Init stuff
        EXACTTRIGGER_INIT;
@@ -136,7 +136,7 @@ void spawnfunc_trigger_swamp(void)
 #elif defined(CSQC)
 
 void ent_swamp()
-{
+{SELFPARAM();
        self.dmg = ReadByte();
        self.swamp_slowdown = ReadByte();
        self.swamp_interval = ReadByte();
index d983cf3aec1d23842ef0f5367e268f4b86fa3fb9..95bd7fbbd4ff0ab788035aff177c7e0d52d47e95 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SVQC
 void trigger_teleport_use()
-{
+{SELFPARAM();
        if(teamplay)
                self.team = activator.team;
 #ifdef SVQC
@@ -9,8 +9,7 @@ void trigger_teleport_use()
 }
 
 void Teleport_Touch (void)
-{
-       entity oldself;
+{SELFPARAM();
        string s;
 
        if (self.active != ACTIVE_ACTIVE)
@@ -38,21 +37,17 @@ void Teleport_Touch (void)
        if(IS_PLAYER(other))
                RemoveGrapplingHook(other);
 
-       entity e;
-       e = Simple_TeleportPlayer(self, other);
+       entity e = Simple_TeleportPlayer(self, other);
 
        activator = other;
        s = self.target; self.target = string_null;
        SUB_UseTargets();
        if (!self.target) self.target = s;
 
-       oldself = self;
-       self = e;
-       SUB_UseTargets();
-       self = oldself;
+       WITH(entity, self, e, SUB_UseTargets());
 }
 
-void spawnfunc_trigger_teleport()
+spawnfunc(trigger_teleport)
 {
        self.angles = '0 0 0';
 
index 62c37a0f49630664ccbe8a7209b58f2082abd4ff..65deb3963d804c6ce7b9e71e2cc7a4cdc659958b 100644 (file)
@@ -9,7 +9,7 @@
 #ifdef SVQC
 
 void viewloc_think()
-{
+{SELFPARAM();
        entity e;
 
        // we abuse this method, rather than using normal .touch, because touch isn't reliable with multiple clients inside the same trigger, and can't "untouch" entities
@@ -38,7 +38,7 @@ void viewloc_think()
        self.nextthink = time;
 }
 
-bool trigger_viewloc_send(entity to, int sf)
+bool trigger_viewloc_send(entity this, entity to, int sf)
 {
        // CSQC doesn't need to know our origin (yet), as we're only available for referencing
        WriteByte(MSG_ENTITY, ENT_CLIENT_VIEWLOC_TRIGGER);
@@ -54,7 +54,7 @@ bool trigger_viewloc_send(entity to, int sf)
 }
 
 void viewloc_init()
-{
+{SELFPARAM();
        entity e;
        for(e = world; (e = find(e, targetname, self.target)); )
                if(e.classname == "target_viewlocation_start")
@@ -80,7 +80,7 @@ void viewloc_init()
        self.nextthink = time;
 }
 
-void spawnfunc_trigger_viewlocation()
+spawnfunc(trigger_viewlocation)
 {
        // we won't check target2 here yet, as it may not even need to exist
        if(self.target == "") { LOG_INFO("^1FAIL!\n"); remove(self); return; }
@@ -89,7 +89,7 @@ void spawnfunc_trigger_viewlocation()
        InitializeEntity(self, viewloc_init, INITPRIO_FINDTARGET);
 }
 
-bool viewloc_send(entity to, int sf)
+bool viewloc_send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_VIEWLOC);
 
@@ -108,19 +108,19 @@ bool viewloc_send(entity to, int sf)
 
 .float angle;
 void viewloc_link()
-{
+{SELFPARAM();
        if(self.angle)
                self.angles_y = self.angle;
        Net_LinkEntity(self, false, 0, viewloc_send);
 }
 
-void spawnfunc_target_viewlocation_start()
+spawnfunc(target_viewlocation_start)
 {
        self.classname = "target_viewlocation_start";
        self.cnt = 1;
        viewloc_link();
 }
-void spawnfunc_target_viewlocation_end()
+spawnfunc(target_viewlocation_end)
 {
        self.classname = "target_viewlocation_end";
        self.cnt = 2;
@@ -128,18 +128,18 @@ void spawnfunc_target_viewlocation_end()
 }
 
 // compatibility
-void spawnfunc_target_viewlocation() { spawnfunc_target_viewlocation_start(); }
+spawnfunc(target_viewlocation) { spawnfunc_target_viewlocation_start(this); }
 
 #elif defined(CSQC)
 
 void trigger_viewloc_updatelink()
-{
+{SELFPARAM();
        self.enemy = findfloat(world, entnum, self.cnt);
        self.goalentity = findfloat(world, entnum, self.count);
 }
 
 void ent_viewloc_trigger()
-{
+{SELFPARAM();
        float point1 = ReadShort();
        float point2 = ReadShort();
 
@@ -162,7 +162,7 @@ void ent_viewloc_trigger()
 }
 
 void ent_viewloc()
-{
+{SELFPARAM();
        self.cnt = ReadByte();
 
        self.origin_x = ReadCoord();
index 1e7715a91b58a70ef8472f980ea8a9a094c16214..b97d2b1d9d94c6e8239482da45ae5a3360f11501 100644 (file)
@@ -3,7 +3,7 @@ void SUB_DontUseTargets() { }
 void() SUB_UseTargets;
 
 void DelayThink()
-{
+{SELFPARAM();
        activator = self.enemy;
        SUB_UseTargets ();
        remove(self);
@@ -22,7 +22,7 @@ void FixSize(entity e)
 
 #ifdef SVQC
 void trigger_common_write(bool withtarget)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, self.warpzone_isboxy);
        WriteByte(MSG_ENTITY, self.scale);
 
@@ -59,7 +59,7 @@ void trigger_common_write(bool withtarget)
 #elif defined(CSQC)
 
 void trigger_common_read(bool withtarget)
-{
+{SELFPARAM();
        self.warpzone_isboxy = ReadByte();
        self.scale = ReadByte();
 
@@ -96,7 +96,7 @@ void trigger_common_read(bool withtarget)
 }
 
 void trigger_remove_generic()
-{
+{SELFPARAM();
        if(self.target) { strunzone(self.target); }
        self.target = string_null;
 
@@ -137,8 +137,8 @@ match (string)self.target and call their .use function
 ==============================
 */
 void SUB_UseTargets()
-{
-       entity t, stemp, otemp, act;
+{SELFPARAM();
+       entity t, otemp, act;
        string s;
        float i;
 
@@ -173,7 +173,7 @@ void SUB_UseTargets()
        {
                centerprint(activator, self.message);
                if (self.noise == "")
-                       play2(activator, "misc/talk.wav");
+                       play2(activator, SND(TALK));
        }
 
 //
@@ -191,10 +191,9 @@ void SUB_UseTargets()
 // fire targets
 //
        act = activator;
-       stemp = self;
        otemp = other;
 
-       if(stemp.target_random)
+       if(this.target_random)
                RandomSelection_Init();
 
        for(i = 0; i < 4; ++i)
@@ -202,10 +201,10 @@ void SUB_UseTargets()
                switch(i)
                {
                        default:
-                       case 0: s = stemp.target; break;
-                       case 1: s = stemp.target2; break;
-                       case 2: s = stemp.target3; break;
-                       case 3: s = stemp.target4; break;
+                       case 0: s = this.target; break;
+                       case 1: s = this.target2; break;
+                       case 2: s = this.target3; break;
+                       case 3: s = this.target4; break;
                }
                if (s != "")
                {
@@ -215,7 +214,7 @@ void SUB_UseTargets()
                        for(t = world; (t = find(t, targetname, s)); )
                        if(t.use)
                        {
-                               if(stemp.target_random)
+                               if(this.target_random)
                                {
                                        RandomSelection_Add(t, 0, string_null, 1, 0);
                                }
@@ -223,8 +222,8 @@ void SUB_UseTargets()
                                {
                                        if (t.classname == "func_clientwall" || t.classname == "func_clientillusionary")
                                                t.antiwall_flag = aw_flag;
-                                       self = t;
-                                       other = stemp;
+                                       setself(t);
+                                       other = this;
                                        activator = act;
                                        self.use();
                                }
@@ -232,22 +231,22 @@ void SUB_UseTargets()
                }
        }
 
-       if(stemp.target_random && RandomSelection_chosen_ent)
+       if(this.target_random && RandomSelection_chosen_ent)
        {
-               self = RandomSelection_chosen_ent;
-               other = stemp;
+               setself(RandomSelection_chosen_ent);
+               other = this;
                activator = act;
                self.use();
        }
 
        activator = act;
-       self = stemp;
+       setself(this);
        other = otemp;
 }
 
 #ifdef CSQC
 void trigger_touch_generic(void() touchfunc)
-{
+{SELFPARAM();
        entity e;
        for(e = findradius((self.absmin + self.absmax) * 0.5, vlen(self.absmax - self.absmin) * 0.5 + 1); e; e = e.chain)
        if(e.isplayermodel || e.classname == "csqcprojectile")
@@ -266,7 +265,7 @@ void trigger_touch_generic(void() touchfunc)
                }
        }
 }
-void trigger_draw_generic()
+void trigger_draw_generic(entity this)
 {
        float dt = time - self.move_time;
        self.move_time = time;
diff --git a/qcsrc/common/turrets/all.inc b/qcsrc/common/turrets/all.inc
new file mode 100644 (file)
index 0000000..5c9f1e1
--- /dev/null
@@ -0,0 +1,12 @@
+#include "turret/ewheel.qc"
+#include "turret/flac.qc"
+#include "turret/fusionreactor.qc"
+#include "turret/hellion.qc"
+#include "turret/hk.qc"
+#include "turret/machinegun.qc"
+#include "turret/mlrs.qc"
+#include "turret/phaser.qc"
+#include "turret/plasma.qc"
+#include "turret/plasma_dual.qc"
+#include "turret/tesla.qc"
+#include "turret/walker.qc"
diff --git a/qcsrc/common/turrets/all.qc b/qcsrc/common/turrets/all.qc
new file mode 100644 (file)
index 0000000..d996778
--- /dev/null
@@ -0,0 +1,13 @@
+#include "all.qh"
+
+#ifdef SVQC
+#include "sv_turrets.qh"
+#endif
+
+#ifdef CSQC
+#include "cl_turrets.qh"
+#endif
+
+#define IMPLEMENTATION
+#include "all.inc"
+#undef IMPLEMENTATION
index 04bb10f6a548e67da5fba28ed487c71a1300f52c..2b9a87d421ae67d446f4f0a21758493d1c3c1a02 100644 (file)
@@ -1,12 +1,26 @@
-#include "unit/ewheel.qc"
-#include "unit/flac.qc"
-#include "unit/fusionreactor.qc"
-#include "unit/hellion.qc"
-#include "unit/hk.qc"
-#include "unit/machinegun.qc"
-#include "unit/mlrs.qc"
-#include "unit/phaser.qc"
-#include "unit/plasma.qc"
-#include "unit/plasma_dual.qc"
-#include "unit/tesla.qc"
-#include "unit/walker.qc"
+#ifndef TURRETS_ALL_H
+#define TURRETS_ALL_H
+
+#include "turret.qh"
+
+REGISTRY(Turrets, BIT(5))
+REGISTER_REGISTRY(RegisterTurrets)
+const int TUR_FIRST = 1;
+#define TUR_LAST (Turrets_COUNT - 1)
+
+#define REGISTER_TURRET(id, inst) REGISTER(RegisterTurrets, TUR, Turrets, id, m_id, inst)
+
+REGISTER_TURRET(Null, NEW(Turret));
+
+Turret get_turretinfo(int id)
+{
+    if (id >= TUR_FIRST && id <= TUR_LAST) {
+        Turret t = Turrets[id];
+        if (t) return t;
+    }
+    return TUR_Null;
+}
+
+#include "all.inc"
+
+#endif
index 924ba7ecf008fc1c8f53b384e9e9893a304c60bf..bb2bff22c8bf3179befb6610f7240773693126fe 100644 (file)
@@ -34,7 +34,7 @@ void turret_checkpoint_use()
 
 #if 0
 void turret_checkpoint_think()
-{
+{SELFPARAM();
     if(self.enemy)
         te_lightning1(self,self.origin, self.enemy.origin);
 
@@ -52,7 +52,7 @@ If the checkpoint chain in not looped, the unit will go "Roaming" when the last
 */
 //float tc_acum;
 void turret_checkpoint_init()
-{
+{SELFPARAM();
     traceline(self.origin + '0 0 16', self.origin - '0 0 1024', MOVE_WORLDONLY, self);
     setorigin(self, trace_endpos + '0 0 32');
 
@@ -67,7 +67,7 @@ void turret_checkpoint_init()
     //tc_acum += 0.25;
 }
 
-void spawnfunc_turret_checkpoint()
+spawnfunc(turret_checkpoint)
 {
     setorigin(self,self.origin);
     self.think = turret_checkpoint_init;
@@ -75,8 +75,8 @@ void spawnfunc_turret_checkpoint()
 }
 
 // Compat.
-void spawnfunc_walker_checkpoint()
+spawnfunc(walker_checkpoint)
 {
     self.classname = "turret_checkpoint";
-    spawnfunc_turret_checkpoint();
+    spawnfunc_turret_checkpoint(this);
 }
index f083e80d619e780c9afd4d7f0999753717160457..582113cf807e9b48eecc85ac0c5db3d6f2e3aaba 100644 (file)
@@ -1,5 +1,5 @@
 void turret_remove()
-{
+{SELFPARAM();
        remove(self.tur_head);
        //remove(self.enemy);
        self.tur_head = world;
@@ -7,7 +7,7 @@ void turret_remove()
 
 .vector glowmod;
 void turret_changeteam()
-{
+{SELFPARAM();
        self.glowmod = Team_ColorRGB(self.team - 1) * 2;
        self.teamradar_color = Team_ColorRGB(self.team - 1);
 
@@ -20,11 +20,11 @@ void turret_changeteam()
 }
 
 void turret_head_draw()
-{
+{SELFPARAM();
        self.drawmask = MASK_NORMAL;
 }
 
-void turret_draw()
+void turret_draw(entity this)
 {
        float dt;
 
@@ -53,7 +53,7 @@ void turret_draw()
 
 }
 
-void turret_draw2d()
+void turret_draw2d(entity this)
 {
        if(self.netname == "")
                return;
@@ -84,7 +84,7 @@ void turret_draw2d()
                o_z = 0;
                if(hud != HUD_NORMAL)
                {
-                       if((get_turretinfo(self.turretid)).spawnflags & TUR_FLAG_MOVE)
+                       if((get_turretinfo(self.m_id)).spawnflags & TUR_FLAG_MOVE)
                                txt = "gfx/vehicles/turret_moving.tga";
                        else
                                txt = "gfx/vehicles/turret_stationary.tga";
@@ -99,7 +99,7 @@ void turret_draw2d()
 
        string spriteimage = self.netname;
        float a = self.alpha * autocvar_hud_panel_fg_alpha;
-       vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
+       vector rgb = spritelookupcolor(self, spriteimage, self.teamradar_color);
 
 
        if(self.maxdistance > waypointsprite_normdistance)
@@ -202,21 +202,21 @@ void turret_draw2d()
 }
 
 void turret_construct()
-{
-       entity tur = get_turretinfo(self.turretid);
+{SELFPARAM();
+       entity tur = get_turretinfo(self.m_id);
 
        if(self.tur_head == world)
                self.tur_head = spawn();
 
-       self.netname = TUR_NAME(self.turretid);
+       self.netname = tur.turret_name;
 
        setorigin(self, self.origin);
-       setmodel(self, tur.model);
-       setmodel(self.tur_head, tur.head_model);
+       _setmodel(self, tur.model);
+       _setmodel(self.tur_head, tur.head_model);
        setsize(self, tur.mins, tur.maxs);
        setsize(self.tur_head, '0 0 0', '0 0 0');
 
-       if(self.turretid == TUR_EWHEEL)
+       if(self.m_id == TUR_EWHEEL.m_id)
                setattachment(self.tur_head, self, "");
        else
                setattachment(self.tur_head, self, "tag_head");
@@ -241,12 +241,12 @@ void turret_construct()
        self.teamradar_color = '1 0 0';
        self.alpha = 1;
 
-       TUR_ACTION(self.turretid, TR_SETUP);
+       tur.tr_setup(tur, self);
 }
 
 entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, float _explode);
 void turret_gibboom();
-void turret_gib_draw()
+void turret_gib_draw(entity this)
 {
        Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
 
@@ -269,10 +269,10 @@ void turret_gib_draw()
 }
 
 void turret_gibboom()
-{
+{SELFPARAM();
        float i;
 
-       sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+       sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
        pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, '0 0 0', 1);
 
        for (i = 1; i < 5; i = i + 1)
@@ -289,7 +289,7 @@ entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, flo
 
        gib = spawn();
        setorigin(gib, _from);
-       setmodel(gib, _model);
+       _setmodel(gib, _model);
        gib.colormod    = _cmod;
        gib.solid          = SOLID_CORPSE;
        gib.draw                = turret_gib_draw;
@@ -317,18 +317,18 @@ entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, flo
 }
 
 void turret_die()
-{
-       sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+       sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
        pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, '0 0 0', 1);
        if (!autocvar_cl_nogibs)
        {
                // Base
-               if(self.turretid == TUR_EWHEEL)
-                       turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', true);
-               else if (self.turretid == TUR_WALKER)
-                       turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', true);
-               else if (self.turretid == TUR_TESLA)
-                       turret_gibtoss((get_turretinfo(self.turretid)).model, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', false);
+               if(self.m_id == TUR_EWHEEL.m_id)
+                       turret_gibtoss((get_turretinfo(self.m_id)).model, self.origin + '0 0 18', self.velocity + '0 0 400' + '0.1 0.1 1' * (random() * 400), '-1 -1 -1', true);
+               else if (self.m_id == TUR_WALKER.m_id)
+                       turret_gibtoss((get_turretinfo(self.m_id)).model, self.origin + '0 0 18', self.velocity + '0 0 300' + '0.1 0.1 1' * (random() * 200), '-1 -1 -1', true);
+               else if (self.m_id == TUR_TESLA.m_id)
+                       turret_gibtoss((get_turretinfo(self.m_id)).model, self.origin + '0 0 18', '0 0 200', '-1 -1 -1', false);
                else
                {
                        if (random() > 0.5)
@@ -340,7 +340,7 @@ void turret_die()
                        else
                                turret_gibtoss("models/turrets/base-gib1.md3", self.origin + '0 0 8', '0 0 0', '0 0 0', true);
 
-                       entity headgib = turret_gibtoss((get_turretinfo(self.turretid)).head_model, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', true);
+                       entity headgib = turret_gibtoss((get_turretinfo(self.m_id)).head_model, self.origin + '0 0 32', '0 0 200' + randomvec() * 200, '-1 -1 -1', true);
                        if(headgib)
                        {
                                headgib.angles = headgib.move_angles = self.tur_head.angles;
@@ -351,18 +351,18 @@ void turret_die()
                }
        }
 
-       setmodel(self, "null");
-       setmodel(self.tur_head, "null");
+       setmodel(self, MDL_Null);
+       setmodel(self.tur_head, MDL_Null);
 }
 
 void ent_turret()
-{
+{SELFPARAM();
        float sf;
        sf = ReadByte();
 
        if(sf & TNSF_SETUP)
        {
-               self.turretid = ReadByte();
+               self.m_id = ReadByte();
 
                self.origin_x = ReadCoord();
                self.origin_y = ReadCoord();
index f35448e9c2212dd98506391dbced0b0133658e6d..c2a609b15ca42f1764b0115f4bd9baf4ee0257b8 100644 (file)
@@ -27,30 +27,29 @@ float T_Config_Queue_Compare(float root, float child, entity pass)
 
 void Dump_Turret_Settings(void)
 {
-       float i, x, totalsettings = 0;
-       for(i = TUR_FIRST; i <= TUR_LAST; ++i)
-       {
+       float x, totalsettings = 0;
+       FOREACH(Turrets, it != TUR_Null, LAMBDA({
                // step 1: clear the queue
                TUR_CONFIG_COUNT = 0;
                for(x = 0; x <= MAX_TUR_CONFIG; ++x)
                        { tur_config_queue[x] = string_null; }
 
                // step 2: build new queue
-               TUR_ACTION(i, TR_CONFIG);
+               it.tr_config(it);
 
                // step 3: sort queue
                heapsort(TUR_CONFIG_COUNT, T_Config_Queue_Swap, T_Config_Queue_Compare, world);
 
                // step 4: write queue
-               TUR_CONFIG_WRITETOFILE(sprintf("// {{{ #%d: %s\n", i, TUR_NAME(i)))
+               TUR_CONFIG_WRITETOFILE(sprintf("// {{{ #%d: %s\n", i, it.turret_name))
                for(x = 0; x <= TUR_CONFIG_COUNT; ++x)
                        { TUR_CONFIG_WRITETOFILE(tur_config_queue[x]) }
                TUR_CONFIG_WRITETOFILE("// }}}\n")
 
                // step 5: debug info
-               LOG_INFO(sprintf("#%d: %s: %d settings...\n", i, TUR_NAME(i), TUR_CONFIG_COUNT));
+               LOG_INFO(sprintf("#%d: %s: %d settings...\n", i, it.turret_name, TUR_CONFIG_COUNT));
                totalsettings += TUR_CONFIG_COUNT;
-       }
+       }));
 
        // clear queue now that we're finished
        TUR_CONFIG_COUNT = 0;
@@ -58,5 +57,5 @@ void Dump_Turret_Settings(void)
                { tur_config_queue[x] = string_null; }
 
        // extra information
-       LOG_INFO(sprintf("Totals: %d turrets, %d settings\n", (i - 1), totalsettings));
+       LOG_INFO(sprintf("Totals: %d turrets, %d settings\n", (Turrets_COUNT - 1), totalsettings));
 }
index 9eb69f29dd54fa804b86e94e2456e453e4dce94c..4d35ee3b38528d0ca7bfed081df868f7d602f72e 100644 (file)
@@ -7,27 +7,14 @@ void Dump_Turret_Settings(void);
 float tur_config_file;
 float tur_config_alsoprint;
 
-#define MAX_TUR_CONFIG 256
+const int MAX_TUR_CONFIG = 256;
 float TUR_CONFIG_COUNT;
 string tur_config_queue[MAX_TUR_CONFIG];
 
-#define TUR_CONFIG_QUEUE(a) { \
-       tur_config_queue[TUR_CONFIG_COUNT] = a; \
-       ++TUR_CONFIG_COUNT; }
-
 #define TUR_CONFIG_WRITETOFILE(a) { \
        fputs(tur_config_file, a); \
        if(tur_config_alsoprint) { LOG_INFO(a); } }
 
-#define TUR_CONFIG_WRITE_CVARS(turret,name) \
-               { TUR_CONFIG_QUEUE( \
-                       sprintf("set g_turrets_unit_%s_%s %g\n", #turret, #name, \
-                       cvar(sprintf("g_turrets_unit_%s_%s", #turret, #name)))) } \
-
-#define TUR_CONFIG_SETTINGS(tursettings) \
-       #define TUR_ADD_CVAR(turret,name) TUR_CONFIG_WRITE_CVARS(turret,name) \
-       tursettings \
-       #undef TUR_ADD_CVAR
 
 #endif
 
index 5b8ffede8791a463549b9a4ddeb40671166f1b2e..e1c23c7ab0e476022d01e7bf501a6cb362d612b8 100644 (file)
@@ -3,7 +3,7 @@
 
 // Generic aiming
 vector turret_aim_generic()
-{
+{SELFPARAM();
 
        vector pre_pos, prep;
        float distance, impact_time = 0, i, mintime;
@@ -165,14 +165,14 @@ float turret_targetscore_generic(entity _turret, entity _target)
 
 // Generic damage handling
 void turret_hide()
-{
+{SELFPARAM();
        self.effects   |= EF_NODRAW;
        self.nextthink = time + self.respawntime - 0.2;
        self.think       = turret_respawn;
 }
 
 void turret_die()
-{
+{SELFPARAM();
        self.deadflag             = DEAD_DEAD;
        self.tur_head.deadflag = self.deadflag;
 
@@ -188,9 +188,10 @@ void turret_die()
 // Go boom
        //RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,DEATH_TURRET,world);
 
+       Turret tur = get_turretinfo(self.m_id);
        if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
        {
-               TUR_ACTION(self.turretid, TR_DEATH);
+               tur.tr_death(tur, self);
 
                remove(self.tur_head);
                remove(self);
@@ -202,12 +203,12 @@ void turret_die()
                self.nextthink   = time + 0.2;
                self.think               = turret_hide;
 
-               TUR_ACTION(self.turretid, TR_DEATH);
+               tur.tr_death(tur, self);
        }
 }
 
 void turret_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
-{
+{SELFPARAM();
        // Enough already!
        if(self.deadflag == DEAD_DEAD)
                return;
@@ -252,7 +253,7 @@ void turret_damage (entity inflictor, entity attacker, float damage, int deathty
 
 void() turret_think;
 void turret_respawn()
-{
+{SELFPARAM();
        // Make sure all parts belong to the same team since
        // this function doubles as "teamchange" function.
        self.tur_head.team      = self.team;
@@ -275,7 +276,8 @@ void turret_respawn()
 
        self.SendFlags = TNSF_FULL_UPDATE;
 
-       TUR_ACTION(self.turretid, TR_SETUP);
+       Turret tur = get_turretinfo(self.m_id);
+       tur.tr_setup(tur, self);
 }
 
 
@@ -283,7 +285,7 @@ void turret_respawn()
 #define cvar_base "g_turrets_unit_"
 .float clientframe;
 void turrets_setframe(float _frame, float client_only)
-{
+{SELFPARAM();
        if((client_only ? self.clientframe : self.frame ) != _frame)
        {
                self.SendFlags |= TNSF_ANIM;
@@ -297,14 +299,14 @@ void turrets_setframe(float _frame, float client_only)
 
 }
 
-float turret_send(entity to, float sf)
+bool turret_send(entity this, entity to, float sf)
 {
 
        WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);
        WriteByte(MSG_ENTITY, sf);
        if(sf & TNSF_SETUP)
        {
-               WriteByte(MSG_ENTITY, self.turretid);
+               WriteByte(MSG_ENTITY, self.m_id);
 
                WriteCoord(MSG_ENTITY, self.origin_x);
                WriteCoord(MSG_ENTITY, self.origin_y);
@@ -358,8 +360,9 @@ float turret_send(entity to, float sf)
        return true;
 }
 
-void load_unit_settings(entity ent, string unitname, float is_reload)
-{
+void load_unit_settings(entity ent, float is_reload)
+{SELFPARAM();
+       string unitname = ent.netname;
        string sbase;
 
        if (ent == world)
@@ -418,12 +421,14 @@ void load_unit_settings(entity ent, string unitname, float is_reload)
        ent.track_accel_rotate  = cvar(strcat(sbase,"_track_accel_rot"));
        ent.track_blendrate  = cvar(strcat(sbase,"_track_blendrate"));
 
-       if(is_reload)
-               TUR_ACTION(self.turretid, TR_SETUP);
+       if(is_reload) {
+               Turret tur = get_turretinfo(self.m_id);
+               tur.tr_setup(tur, self);
+       }
 }
 
 void turret_projectile_explode()
-{
+{SELFPARAM();
 
        self.takedamage = DAMAGE_NO;
        self.event_damage = func_null;
@@ -445,7 +450,7 @@ void turret_projectile_touch()
 }
 
 void turret_projectile_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
-{
+{SELFPARAM();
        self.velocity  += vforce;
        self.health     -= damage;
        //self.realowner = attacker; // Dont change realowner, it does not make much sense for turrets
@@ -454,10 +459,10 @@ void turret_projectile_damage(entity inflictor, entity attacker, float damage, i
 }
 
 entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim)
-{
+{SELFPARAM();
        entity proj;
 
-       sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM);
+       _sound (self, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM);
        proj                             = spawn ();
        setorigin(proj, self.tur_shotorg);
        setsize(proj, '-0.5 -0.5 -0.5' * _size, '0.5 0.5 0.5' * _size);
@@ -493,12 +498,10 @@ entity turret_projectile(string _snd, float _size, float _health, float _death,
 ** and updated aim<->predict impact distance.
 **/
 void turret_do_updates(entity t_turret)
-{
+{SELFPARAM();
        vector enemy_pos;
-       entity oldself;
 
-       oldself = self;
-       self = t_turret;
+       setself(t_turret);
 
        enemy_pos = real_origin(self.enemy);
 
@@ -527,7 +530,7 @@ void turret_do_updates(entity t_turret)
        self.tur_impactent                       = trace_ent;
        self.tur_impacttime                     = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
 
-       self = oldself;
+       setself(this);
 }
 
 /**
@@ -536,7 +539,7 @@ void turret_do_updates(entity t_turret)
 **/
 .float turret_framecounter;
 void turret_track()
-{
+{SELFPARAM();
        vector target_angle; // This is where we want to aim
        vector move_angle;   // This is where we can aim
        float f_tmp;
@@ -834,7 +837,7 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl
 }
 
 entity turret_select_target()
-{
+{SELFPARAM();
        entity e;               // target looper entity
        float  score;   // target looper entity score
        entity e_enemy;  // currently best scoreing target
@@ -901,7 +904,7 @@ entity turret_select_target()
 ** Preforms pre-fire checks based on the uints firecheck_flags
 **/
 float turret_firecheck()
-{
+{SELFPARAM();
        // This one just dont care =)
        if (self.firecheck_flags & TFL_FIRECHECK_NO)
                return 1;
@@ -975,7 +978,7 @@ float turret_firecheck()
 }
 
 bool turret_checkfire()
-{
+{SELFPARAM();
        bool ret = false; // dummy
        if(MUTATOR_CALLHOOK(Turret_CheckFire, ret))
                return ret_bool;
@@ -984,14 +987,15 @@ bool turret_checkfire()
 }
 
 void turret_fire()
-{
+{SELFPARAM();
        if (autocvar_g_turrets_nofire != 0)
                return;
 
        if(MUTATOR_CALLHOOK(TurretFire, self))
                return;
 
-       TUR_ACTION(self.turretid, TR_ATTACK);
+       Turret info = get_turretinfo(self.m_id);
+       info.tr_attack(info);
 
        self.attack_finished_single = time + self.shot_refire;
        self.ammo -= self.shot_dmg;
@@ -1014,7 +1018,7 @@ void turret_fire()
 }
 
 void turret_think()
-{
+{SELFPARAM();
        entity e;
 
        self.nextthink = time + self.ticrate;
@@ -1119,7 +1123,8 @@ void turret_think()
                                if (turret_checkfire())
                                        turret_fire();
 
-                               TUR_ACTION(self.turretid, TR_THINK);
+                               Turret tur = get_turretinfo(self.m_id);
+                               tur.tr_think(tur);
 
                                return;
                        }
@@ -1157,7 +1162,8 @@ void turret_think()
                        if(!(self.track_flags & TFL_TRACK_NO))
                                turret_track();
 
-                       TUR_ACTION(self.turretid, TR_THINK);
+                       Turret tur = get_turretinfo(self.m_id);
+                       tur.tr_think(tur);
 
                        // And bail.
                        return;
@@ -1180,7 +1186,8 @@ void turret_think()
                        turret_fire();
        }
 
-       TUR_ACTION(self.turretid, TR_THINK);
+       Turret tur = get_turretinfo(self.m_id);
+       tur.tr_think(tur);
 }
 
 /*
@@ -1188,7 +1195,7 @@ void turret_think()
        If activator is world, the turret go inactive.
 */
 void turret_use()
-{
+{SELFPARAM();
        LOG_TRACE("Turret ",self.netname, " used by ", activator.classname, "\n");
 
        self.team = activator.team;
@@ -1201,7 +1208,7 @@ void turret_use()
 }
 
 void turret_link()
-{
+{SELFPARAM();
        Net_LinkEntity(self, true, 0, turret_send);
        self.think       = turret_think;
        self.nextthink = time;
@@ -1209,7 +1216,7 @@ void turret_link()
 }
 
 void turrets_manager_think()
-{
+{SELFPARAM();
        self.nextthink = time + 1;
 
        entity e;
@@ -1220,8 +1227,9 @@ void turrets_manager_think()
                {
                        if (IS_TURRET(e))
                        {
-                               load_unit_settings(e,e.cvar_basename,1);
-                               TUR_ACTION(self.turretid, TR_THINK);
+                               load_unit_settings(e,1);
+                               Turret tur = get_turretinfo(self.m_id);
+                               tur.tr_think(tur);
                        }
 
                        e = nextent(e);
@@ -1230,19 +1238,49 @@ void turrets_manager_think()
        }
 }
 
-float turret_initialize(float tur_id)
+void turret_initparams(entity tur)
 {
+       #define TRY(x) (x) ? (x)
+       tur.respawntime                 = max  (-1,              (TRY(tur.respawntime)               :  60                                         ));
+       tur.shot_refire                 = bound(0.01,            (TRY(tur.shot_refire)               :  1                                          ), 9999);
+       tur.shot_dmg                    = max  (1,               (TRY(tur.shot_dmg)                  :  tur.shot_refire * 50                       ));
+       tur.shot_radius                 = max  (1,               (TRY(tur.shot_radius)               :  tur.shot_dmg * 0.5                         ));
+       tur.shot_speed                  = max  (1,               (TRY(tur.shot_speed)                :  2500                                       ));
+       tur.shot_spread                 = bound(0.0001,          (TRY(tur.shot_spread)               :  0.0125                                     ), 500);
+       tur.shot_force                  = bound(0.001,           (TRY(tur.shot_force)                :  tur.shot_dmg * 0.5 + tur.shot_radius * 0.5 ), 5000);
+       tur.shot_volly                  = bound(1,               (TRY(tur.shot_volly)                :  1                                          ), floor(tur.ammo_max / tur.shot_dmg));
+       tur.shot_volly_refire           = bound(tur.shot_refire, (TRY(tur.shot_volly_refire)         :  tur.shot_refire * tur.shot_volly           ), 60);
+       tur.target_range                = bound(0,               (TRY(tur.target_range)              :  tur.shot_speed * 0.5                       ), MAX_SHOT_DISTANCE);
+       tur.target_range_min            = bound(0,               (TRY(tur.target_range_min)          :  tur.shot_radius * 2                        ), MAX_SHOT_DISTANCE);
+       tur.target_range_optimal        = bound(0,               (TRY(tur.target_range_optimal)      :  tur.target_range * 0.5                     ), MAX_SHOT_DISTANCE);
+       tur.aim_maxrotate               = bound(0,               (TRY(tur.aim_maxrotate)             :  90                                         ), 360);
+       tur.aim_maxpitch                = bound(0,               (TRY(tur.aim_maxpitch)              :  20                                         ), 90);
+       tur.aim_speed                   = bound(0.1,             (TRY(tur.aim_speed)                 :  36                                         ), 1000);
+       tur.aim_firetolerance_dist      = bound(0.1,             (TRY(tur.aim_firetolerance_dist)    :  5 + (tur.shot_radius * 2)                  ), MAX_SHOT_DISTANCE);
+       tur.target_select_rangebias     = bound(-10,             (TRY(tur.target_select_rangebias)   :  1                                          ), 10);
+       tur.target_select_samebias      = bound(-10,             (TRY(tur.target_select_samebias)    :  1                                          ), 10);
+       tur.target_select_anglebias     = bound(-10,             (TRY(tur.target_select_anglebias)   :  1                                          ), 10);
+       tur.target_select_missilebias   = bound(-10,             (TRY(tur.target_select_missilebias) :  1                                          ), 10);
+       tur.target_select_playerbias    = bound(-10,             (TRY(tur.target_select_playerbias)  :  1                                          ), 10);
+       tur.ammo_max                    = max  (tur.shot_dmg,    (TRY(tur.ammo_max)                  :  tur.shot_dmg * 10                          ));
+       tur.ammo_recharge               = max  (0,               (TRY(tur.ammo_recharge)             :  tur.shot_dmg * 0.5                         ));
+       #undef TRY
+}
+
+float turret_initialize(Turret tur)
+{SELFPARAM();
        if(!autocvar_g_turrets)
                return false;
 
-       entity e;
-       entity tur = get_turretinfo(tur_id);
-       if(tur.turretid == 0)
+       if(tur.m_id == 0)
                return false; // invalid turret
 
-       if(!self.tur_head) { TUR_ACTION(tur_id, TR_PRECACHE); } // if tur_head exists, we can assume this turret re-spawned
+       // if tur_head exists, we can assume this turret re-spawned
+       if(!self.tur_head) {
+               tur.tr_precache(tur);
+       }
 
-       e = find(world, classname, "turret_manager");
+       entity e = find(world, classname, "turret_manager");
        if(!e)
        {
                e = spawn();
@@ -1254,8 +1292,8 @@ float turret_initialize(float tur_id)
        if(!(self.spawnflags & TSF_SUSPENDED))
                builtin_droptofloor();
 
-       self.cvar_basename = tur.cvar_basename;
-       load_unit_settings(self, self.cvar_basename, 0);
+       self.netname = tur.netname;
+       load_unit_settings(self, 0);
 
        if(!self.team || !teamplay)             { self.team = MAX_SHOT_DISTANCE; }
        if(!self.ticrate)                               { self.ticrate = ((self.turret_flags & TUR_FLAG_SUPPORT) ? 0.2 : 0.1); }
@@ -1284,29 +1322,7 @@ float turret_initialize(float tur_id)
                if(!self.track_blendrate)               { self.track_blendrate = 0.35; }
        }
 
-       self.respawntime                                = max(-1, ((!self.respawntime) ? 60 : self.respawntime));
-       self.shot_refire                                = bound(0.01, ((!self.shot_refire) ? 1 : self.shot_refire), 9999);
-       self.shot_dmg                                   = max(1, ((!self.shot_dmg) ? self.shot_refire * 50 : self.shot_dmg));
-       self.shot_radius                                = max(1, ((!self.shot_radius) ? self.shot_dmg * 0.5 : self.shot_radius));
-       self.shot_speed                                 = max(1, ((!self.shot_speed) ? 2500 : self.shot_speed));
-       self.shot_spread                                = bound(0.0001, ((!self.shot_spread) ? 0.0125 : self.shot_spread), 500);
-       self.shot_force                                 = bound(0.001, ((!self.shot_force) ? self.shot_dmg * 0.5 + self.shot_radius * 0.5 : self.shot_force), 5000);
-       self.shot_volly                                 = bound(1, ((!self.shot_volly) ? 1 : self.shot_volly), floor(self.ammo_max / self.shot_dmg));
-       self.shot_volly_refire                  = bound(self.shot_refire, ((!self.shot_volly_refire) ? self.shot_refire * self.shot_volly : self.shot_volly_refire), 60);
-       self.target_range                               = bound(0, ((!self.target_range) ? self.shot_speed * 0.5 : self.target_range), MAX_SHOT_DISTANCE);
-       self.target_range_min                   = bound(0, ((!self.target_range_min) ? self.shot_radius * 2 : self.target_range_min), MAX_SHOT_DISTANCE);
-       self.target_range_optimal               = bound(0, ((!self.target_range_optimal) ? self.target_range * 0.5 : self.target_range_optimal), MAX_SHOT_DISTANCE);
-       self.aim_maxrotate                              = bound(0, ((!self.aim_maxrotate) ? 90 : self.aim_maxrotate), 360);
-       self.aim_maxpitch                               = bound(0, ((!self.aim_maxpitch) ? 20 : self.aim_maxpitch), 90);
-       self.aim_speed                                  = bound(0.1, ((!self.aim_speed) ? 36 : self.aim_speed), 1000);
-       self.aim_firetolerance_dist     = bound(0.1, ((!self.aim_firetolerance_dist) ? 5 + (self.shot_radius * 2) : self.aim_firetolerance_dist), MAX_SHOT_DISTANCE);
-       self.target_select_rangebias    = bound(-10, ((!self.target_select_rangebias) ? 1 : self.target_select_rangebias), 10);
-       self.target_select_samebias     = bound(-10, ((!self.target_select_samebias) ? 1 : self.target_select_samebias), 10);
-       self.target_select_anglebias    = bound(-10, ((!self.target_select_anglebias) ? 1 : self.target_select_anglebias), 10);
-       self.target_select_missilebias  = bound(-10, ((!self.target_select_missilebias) ? 1 : self.target_select_missilebias), 10);
-       self.target_select_playerbias   = bound(-10, ((!self.target_select_playerbias) ? 1 : self.target_select_playerbias), 10);
-       self.ammo_max                                   = max(self.shot_dmg, ((!self.ammo_max) ? self.shot_dmg * 10 : self.ammo_max));
-       self.ammo_recharge                              = max(0, ((!self.ammo_recharge) ? self.shot_dmg * 0.5 : self.ammo_recharge));
+       turret_initparams(self);
 
        self.turret_flags = TUR_FLAG_ISTURRET | (tur.spawnflags);
 
@@ -1329,14 +1345,14 @@ float turret_initialize(float tur_id)
 
        ++turret_count;
 
-       setmodel(self, tur.model);
+       _setmodel(self, tur.model);
        setsize(self, tur.mins, tur.maxs);
 
-       self.turretid                           = tur_id;
+       self.m_id                                       = tur.m_id;
        self.classname                          = "turret_main";
        self.active                                     = ACTIVE_ACTIVE;
        self.effects                            = EF_NODRAW;
-       self.netname                            = TUR_NAME(tur_id);
+       self.netname                            = tur.turret_name;
        self.ticrate                            = bound(sys_frametime, self.ticrate, 60);
        self.max_health                         = self.health;
        self.target_validate_flags      = self.target_select_flags;
@@ -1354,7 +1370,7 @@ float turret_initialize(float tur_id)
        self.nextthink                     += turret_count * sys_frametime;
 
        self.tur_head = spawn();
-       setmodel(self.tur_head, tur.head_model);
+       _setmodel(self.tur_head, tur.head_model);
        setsize(self.tur_head, '0 0 0', '0 0 0');
        setorigin(self.tur_head, '0 0 0');
        setattachment(self.tur_head, self, "tag_head");
@@ -1396,7 +1412,7 @@ float turret_initialize(float tur_id)
        turret_respawn();
        turret_tag_fire_update();
 
-       TUR_ACTION(tur_id, TR_SETUP);
+       tur.tr_setup(tur, self);
 
        if(MUTATOR_CALLHOOK(TurretSpawn, self))
                return false;
index 8bba1c4a4a6e39ff3fcd11596b3224ec5aace3a9..2d5a5f5f9d00526e67b110d8f9849a42a203efb2 100644 (file)
@@ -1,6 +1,12 @@
 #ifndef SV_TURRETS_H
 #define SV_TURRETS_H
 
+entity turret_projectile(string _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim);
+void turret_projectile_explode();
+float turret_validate_target(entity e_turret, entity e_target, float validate_flags);
+float turret_firecheck();
+entity turret_select_target();
+
 // turret fields
 .float ticrate; // interal ai think rate
 .vector aim_idle; // where to aim while idle
@@ -81,7 +87,7 @@ void turret_do_updates(entity e_turret);
 
 void turrets_setframe(float _frame, float client_only);
 
-float turret_initialize(float tur_id);
+float turret_initialize(Turret tur);
 
 /// Function to use for target evaluation. usualy turret_targetscore_generic
 .float(entity _turret, entity _target) turret_score_target;
index 65510645b130a9d5968cd7bee6fa273fd5e1d152..625746341750754f0f6336550a1eff867aaf1430 100644 (file)
@@ -1,19 +1,18 @@
-void spawnfunc_turret_targettrigger();
+spawnfunc(turret_targettrigger);
 void turret_targettrigger_touch();
 
 void turret_targettrigger_touch()
-{
+{SELFPARAM();
     entity e;
     if (self.cnt > time) return;
-    entity oldself;
-    oldself = self;
+    entity oldself = this;
 
     e = find(world, targetname, self.target);
     while (e)
     {
         if (e.turret_flags & TUR_FLAG_RECIEVETARGETS)
         {
-            self = e;
+            setself(e);
             if(e.turret_addtarget)
                 e.turret_addtarget(other,oldself);
         }
@@ -23,12 +22,12 @@ void turret_targettrigger_touch()
 
     oldself.cnt = time + 0.5;
 
-    self = oldself;
+    setself(this);
 }
 
 /*QUAKED turret_targettrigger (.5 .5 .5) ?
 */
-void spawnfunc_turret_targettrigger()
+spawnfunc(turret_targettrigger)
 {
     if(!autocvar_g_turrets) { remove(self); return; }
 
diff --git a/qcsrc/common/turrets/turret.qh b/qcsrc/common/turrets/turret.qh
new file mode 100644 (file)
index 0000000..8862f47
--- /dev/null
@@ -0,0 +1,177 @@
+#ifndef TURRET_H
+#define TURRET_H
+
+#include "../weapons/all.qh"
+
+CLASS(Turret, Object)
+    ATTRIB(Turret, m_id, int, 0)
+
+    /** short name */
+    ATTRIB(Turret, netname, string, string_null)
+    /** human readable name */
+    ATTRIB(Turret, turret_name, string, _("Turret"))
+    /** currently a copy of the model */
+    ATTRIB(Turret, mdl, string, string_null)
+    /** full name of model */
+    ATTRIB(Turret, model, string, string_null)
+    /** full name of tur_head model */
+    ATTRIB(Turret, head_model, string, string_null)
+
+    ATTRIB(Turret, spawnflags, int, 0)
+    /** turret hitbox size */
+    ATTRIB(Turret, mins, vector, '-0 -0 -0')
+    /** turret hitbox size */
+    ATTRIB(Turret, maxs, vector, '0 0 0')
+
+    METHOD(Turret, display, void(entity this, void(string name, string icon) returns)) {
+        returns(this.turret_name, string_null);
+    }
+    /** (BOTH) setup turret data */
+    METHOD(Turret, tr_setup, void(Turret this, entity it)) {
+
+    }
+    /** (SERVER) logic to run every frame */
+    METHOD(Turret, tr_think, void(Turret this)) {
+
+    }
+    /** (SERVER) called when turret dies */
+    METHOD(Turret, tr_death, void(Turret this, entity it)) {
+
+    }
+    /** (BOTH) precaches models/sounds used by this turret */
+    METHOD(Turret, tr_precache, void(Turret this)) {
+
+    }
+    ATTRIB(Turret, m_weapon, Weapon, WEP_Null)
+    /** (SERVER) called when turret attacks */
+    METHOD(Turret, tr_attack, void(Turret this)) {
+        Weapon w = this.m_weapon;
+        w.wr_think(w, self, true, false);
+    }
+    /** (ALL) */
+    METHOD(Turret, tr_config, void(Turret this)) {
+        // TODO
+    }
+ENDCLASS(Turret)
+
+// fields:
+.entity tur_head;
+
+// target selection flags
+.int target_select_flags;
+.int target_validate_flags;
+const int TFL_TARGETSELECT_NO = 2; // don't automatically find targets
+const int TFL_TARGETSELECT_LOS = 4; // require line of sight to find targets
+const int TFL_TARGETSELECT_PLAYERS = 8; // target players
+const int TFL_TARGETSELECT_MISSILES = 16; // target projectiles
+const int TFL_TARGETSELECT_TRIGGERTARGET = 32; // respond to turret_trigger_target events
+const int TFL_TARGETSELECT_ANGLELIMITS = 64; // apply extra angular limits to target selection
+const int TFL_TARGETSELECT_RANGELIMITS = 128; // limit target selection range
+const int TFL_TARGETSELECT_TEAMCHECK = 256; // don't attack teammates
+const int TFL_TARGETSELECT_NOBUILTIN = 512; // only attack targets when triggered
+const int TFL_TARGETSELECT_OWNTEAM = 1024; // only attack teammates
+const int TFL_TARGETSELECT_NOTURRETS = 2048; // don't attack other turrets
+const int TFL_TARGETSELECT_FOV = 4096; // extra limits to attack range
+const int TFL_TARGETSELECT_MISSILESONLY = 8192; // only attack missiles
+
+// aim flags
+.int aim_flags;
+const int TFL_AIM_NO = 1; // no aiming
+const int TFL_AIM_SPLASH = 2; // aim for ground around the target's feet
+const int TFL_AIM_LEAD = 4; // try to predict target movement
+const int TFL_AIM_SHOTTIMECOMPENSATE = 8; // compensate for shot traveltime when leading
+const int TFL_AIM_ZPREDICT = 16; // predict target's z position at impact
+const int TFL_AIM_SIMPLE = 32; // aim at player's current location
+
+// tracking flags
+.int track_flags;
+const int TFL_TRACK_NO = 2; // don't move head
+const int TFL_TRACK_PITCH = 4; // pitch head
+const int TFL_TRACK_ROTATE = 8; // rotate head
+
+// prefire checks
+.int firecheck_flags;
+const int TFL_FIRECHECK_DEAD = 4; // don't attack dead targets (zombies?)
+const int TFL_FIRECHECK_DISTANCES = 8; // another range check
+const int TFL_FIRECHECK_LOS = 16; // line of sight
+const int TFL_FIRECHECK_AIMDIST = 32; // consider distance impactpoint<->aimspot
+const int TFL_FIRECHECK_REALDIST = 64; // consider enemy origin<->impactpoint
+const int TFL_FIRECHECK_ANGLEDIST = 128; // consider angular diff head<->aimspot
+const int TFL_FIRECHECK_TEAMCHECK = 256; // don't attack teammates
+const int TFL_FIRECHECK_AFF = 512; // try to avoid any friendly fire
+const int TFL_FIRECHECK_AMMO_OWN = 1024; // own ammo needs to be larger than damage dealt
+const int TFL_FIRECHECK_AMMO_OTHER = 2048; // target's ammo needs to be less than max
+const int TFL_FIRECHECK_REFIRE = 4096; // check single attack finished delays
+const int TFL_FIRECHECK_NO = 16384; // no prefire checks
+
+// attack flags
+.int shoot_flags;
+const int TFL_SHOOT_NO = 64; // no attacking
+const int TFL_SHOOT_VOLLY = 2; // fire in vollies
+const int TFL_SHOOT_VOLLYALWAYS = 4; // always do a full volly, even if target is lost
+const int TFL_SHOOT_HITALLVALID = 8; // loop through all valid targets
+const int TFL_SHOOT_CLEARTARGET = 16; // lose target after attack (after volly is done if in volly mode)
+const int TFL_SHOOT_CUSTOM = 32; // custom attacking
+
+// turret capabilities
+.int turret_flags;
+const int TUR_FLAG_NONE = 0; // no abilities
+const int TUR_FLAG_SNIPER = 2; // sniping turret
+const int TUR_FLAG_SPLASH = 4; // can deal splash damage
+const int TUR_FLAG_HITSCAN = 8; // hit scan
+const int TUR_FLAG_MULTIGUN = 16; // multiple guns
+const int TUR_FLAG_GUIDED = 32; // laser guided projectiles
+const int TUR_FLAG_SLOWPROJ = 64; // turret fires slow projectiles
+const int TUR_FLAG_MEDPROJ = 128; // turret fires medium projectiles
+const int TUR_FLAG_FASTPROJ = 256; // turret fires fast projectiles
+const int TUR_FLAG_PLAYER = 512; // can damage players
+const int TUR_FLAG_MISSILE = 1024; // can damage missiles
+const int TUR_FLAG_SUPPORT = 2048; // supports other units
+const int TUR_FLAG_AMMOSOURCE = 4096; // can provide ammunition
+const int TUR_FLAG_RECIEVETARGETS = 8192; // can recieve targets from external sources
+const int TUR_FLAG_MOVE = 16384; // can move
+const int TUR_FLAG_ROAM = 32768; // roams around if not attacking
+const int TUR_FLAG_ISTURRET = 65536; // identifies this unit as a turret
+
+// ammo types
+#define ammo_flags currentammo
+const int TFL_AMMO_NONE = 64; // doesn't use ammo
+const int TFL_AMMO_ENERGY = 2; // uses power
+const int TFL_AMMO_BULLETS = 4; // uses bullets
+const int TFL_AMMO_ROCKETS = 8; // uses explosives
+const int TFL_AMMO_RECHARGE = 16; // regenerates ammo
+const int TFL_AMMO_RECIEVE = 32; // can recieve ammo from support units
+
+// damage flags
+.int damage_flags;
+const int TFL_DMG_NO = 256; // doesn't take damage
+const int TFL_DMG_YES = 2; // can be damaged
+const int TFL_DMG_TEAM = 4; // can be damaged by teammates
+const int TFL_DMG_RETALIATE = 8; // target attackers
+const int TFL_DMG_RETALIATE_TEAM = 16; // target attackers, even if on same team
+const int TFL_DMG_TARGETLOSS = 32; // loses target when damaged
+const int TFL_DMG_AIMSHAKE = 64; // damage throws off aim
+const int TFL_DMG_HEADSHAKE = 128; // damage shakes head
+const int TFL_DMG_DEATH_NORESPAWN = 256; // no re-spawning
+
+// spawn flags
+const int TSF_SUSPENDED = 1;
+const int TSF_TERRAINBASE = 2; // currently unused
+const int TSF_NO_AMMO_REGEN = 4; // disable builtin ammo regeneration
+const int TSF_NO_PATHBREAK = 8; // don't break path to chase enemies, will still fire at them if possible
+const int TSL_NO_RESPAWN = 16; // don't re-spawn
+const int TSL_ROAM = 32; // roam while idle
+
+// send flags
+const int TNSF_UPDATE       = 2;
+const int TNSF_STATUS       = 4;
+const int TNSF_SETUP        = 8;
+const int TNSF_ANG          = 16;
+const int TNSF_AVEL         = 32;
+const int TNSF_MOVE         = 64;
+.float anim_start_time;
+const int TNSF_ANIM         = 128;
+
+const int TNSF_FULL_UPDATE  = 16777215;
+
+#endif
diff --git a/qcsrc/common/turrets/turret/ewheel.qc b/qcsrc/common/turrets/turret/ewheel.qc
new file mode 100644 (file)
index 0000000..3875f1b
--- /dev/null
@@ -0,0 +1,270 @@
+#ifndef TURRET_EWHEEL_H
+#define TURRET_EWHEEL_H
+
+//#define EWHEEL_FANCYPATH
+
+#include "ewheel_weapon.qc"
+
+CLASS(EWheel, Turret)
+/* spawnflags */ ATTRIB(EWheel, spawnflags, int, TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM);
+/* mins       */ ATTRIB(EWheel, mins, vector, '-32 -32 0');
+/* maxs       */ ATTRIB(EWheel, maxs, vector, '32 32 48');
+/* modelname  */ ATTRIB(EWheel, mdl, string, "ewheel-base2.md3");
+/* model      */ ATTRIB(EWheel, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(EWheel, head_model, string, strzone(strcat("models/turrets/", "ewheel-gun1.md3")));
+/* netname    */ ATTRIB(EWheel, netname, string, "ewheel");
+/* fullname   */ ATTRIB(EWheel, turret_name, string, _("eWheel Turret"));
+    ATTRIB(EWheel, m_weapon, Weapon, WEP_EWHEEL);
+ENDCLASS(EWheel)
+REGISTER_TURRET(EWHEEL, NEW(EWheel));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "ewheel_weapon.qc"
+
+#ifdef SVQC
+
+float autocvar_g_turrets_unit_ewheel_speed_fast;
+float autocvar_g_turrets_unit_ewheel_speed_slow;
+float autocvar_g_turrets_unit_ewheel_speed_slower;
+float autocvar_g_turrets_unit_ewheel_speed_stop;
+float autocvar_g_turrets_unit_ewheel_turnrate;
+
+const float ewheel_anim_stop = 0;
+const float ewheel_anim_fwd_slow = 1;
+const float ewheel_anim_fwd_fast = 2;
+const float ewheel_anim_bck_slow = 3;
+const float ewheel_anim_bck_fast = 4;
+
+void ewheel_move_path()
+{SELFPARAM();
+#ifdef EWHEEL_FANCYPATH
+    // Are we close enougth to a path node to switch to the next?
+    if (vlen(self.origin  - self.pathcurrent.origin) < 64)
+        if (self.pathcurrent.path_next == world)
+        {
+            // Path endpoint reached
+            pathlib_deletepath(self.pathcurrent.owner);
+            self.pathcurrent = world;
+
+            if (self.pathgoal)
+            {
+                if (self.pathgoal.use)
+                    self.pathgoal.use();
+
+                if (self.pathgoal.enemy)
+                {
+                    self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
+                    self.pathgoal = self.pathgoal.enemy;
+                }
+            }
+            else
+                self.pathgoal = world;
+        }
+        else
+            self.pathcurrent = self.pathcurrent.path_next;
+
+#else
+    if (vlen(self.origin - self.pathcurrent.origin) < 64)
+        self.pathcurrent = self.pathcurrent.enemy;
+#endif
+
+    if (self.pathcurrent)
+    {
+
+        self.moveto = self.pathcurrent.origin;
+        self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
+        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+    }
+}
+
+void ewheel_move_enemy()
+{SELFPARAM();
+    float newframe;
+
+    self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
+
+    self.moveto  = self.origin + self.steerto * 128;
+
+    if (self.tur_dist_enemy > self.target_range_optimal)
+    {
+        if ( self.tur_head.spawnshieldtime < 1 )
+        {
+            newframe = ewheel_anim_fwd_fast;
+            movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
+        }
+        else if (self.tur_head.spawnshieldtime < 2)
+        {
+
+            newframe = ewheel_anim_fwd_slow;
+            movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+       }
+        else
+        {
+            newframe = ewheel_anim_fwd_slow;
+            movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
+        }
+    }
+    else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
+    {
+        newframe = ewheel_anim_bck_slow;
+        movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
+    }
+    else
+    {
+        newframe = ewheel_anim_stop;
+        movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+    }
+
+    turrets_setframe(newframe, false);
+}
+
+void ewheel_move_idle()
+{SELFPARAM();
+    if(self.frame != 0)
+    {
+        self.SendFlags |= TNSF_ANIM;
+        self.anim_start_time = time;
+    }
+
+    self.frame = 0;
+    if (vlen(self.velocity))
+        movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
+}
+
+spawnfunc(turret_ewheel) { if(!turret_initialize(TUR_EWHEEL)) remove(self); }
+
+        METHOD(EWheel, tr_think, void(EWheel thistur))
+        {
+            SELFPARAM();
+            float vz;
+            vector wish_angle, real_angle;
+
+            vz = self.velocity_z;
+
+            self.angles_x = anglemods(self.angles_x);
+            self.angles_y = anglemods(self.angles_y);
+
+            fixedmakevectors(self.angles);
+
+            wish_angle = normalize(self.steerto);
+            wish_angle = vectoangles(wish_angle);
+            real_angle = wish_angle - self.angles;
+            real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
+
+            self.tur_head.spawnshieldtime = fabs(real_angle_y);
+            real_angle_y  = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
+            self.angles_y = (self.angles_y + real_angle_y);
+
+            if(self.enemy)
+                ewheel_move_enemy();
+            else if(self.pathcurrent)
+                ewheel_move_path();
+            else
+                ewheel_move_idle();
+
+            self.velocity_z = vz;
+
+            if(vlen(self.velocity))
+                self.SendFlags |= TNSF_MOVE;
+        }
+        METHOD(EWheel, tr_death, void(EWheel this, entity it))
+        {
+            it.velocity = '0 0 0';
+
+#ifdef EWHEEL_FANCYPATH
+            if (self.pathcurrent)
+                pathlib_deletepath(it.pathcurrent.owner);
+#endif
+            it.pathcurrent = NULL;
+        }
+        METHOD(EWheel, tr_setup, void(EWheel this, entity it))
+        {
+            entity e;
+
+            if(it.movetype == MOVETYPE_WALK)
+            {
+                it.velocity = '0 0 0';
+                it.enemy = world;
+
+                setorigin(it, it.pos1);
+
+                if (it.target != "")
+                {
+                    e = find(world, targetname, it.target);
+                    if (!e)
+                    {
+                        LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
+                        it.target = "";
+                    }
+
+                    if (e.classname != "turret_checkpoint")
+                        LOG_TRACE("Warning: not a turrret path\n");
+                    else
+                    {
+
+#ifdef EWHEEL_FANCYPATH
+                        it.pathcurrent = WALKER_PATH(it.origin,e.origin);
+                        it.pathgoal = e;
+#else
+                        it.pathcurrent  = e;
+#endif
+                    }
+                }
+            }
+
+            it.iscreature                              = true;
+            it.teleportable                    = TELEPORT_NORMAL;
+            it.damagedbycontents               = true;
+            it.movetype                                = MOVETYPE_WALK;
+            it.solid                                   = SOLID_SLIDEBOX;
+            it.takedamage                              = DAMAGE_AIM;
+            it.idle_aim                                = '0 0 0';
+            it.pos1                                    = it.origin;
+            it.target_select_flags     = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+            it.target_validate_flags   = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+            it.frame                                   = it.tur_head.frame = 1;
+            it.ammo_flags                              = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+
+            // Convert from dgr / sec to dgr / tic
+            it.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
+            it.tur_head.aim_speed = it.tur_head.aim_speed / (1 / it.ticrate);
+        }
+
+#endif // SVQC
+#ifdef CSQC
+
+void ewheel_draw(entity this)
+{
+    float dt;
+
+    dt = time - self.move_time;
+    self.move_time = time;
+    if(dt <= 0)
+        return;
+
+    fixedmakevectors(self.angles);
+    setorigin(self, self.origin + self.velocity * dt);
+    self.tur_head.angles += dt * self.tur_head.move_avelocity;
+    self.angles_y = self.move_angles_y;
+
+    if (self.health < 127)
+    if(random() < 0.05)
+        te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+        METHOD(EWheel, tr_setup, void(EWheel this, entity it))
+        {
+            it.gravity         = 1;
+            it.movetype                = MOVETYPE_BOUNCE;
+            it.move_movetype   = MOVETYPE_BOUNCE;
+            it.move_origin     = it.origin;
+            it.move_time               = time;
+            it.draw                    = ewheel_draw;
+        }
+
+#endif // CSQC
+#endif
diff --git a/qcsrc/common/turrets/turret/ewheel_weapon.qc b/qcsrc/common/turrets/turret/ewheel_weapon.qc
new file mode 100644 (file)
index 0000000..86444bb
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef TURRET_EWHEEL_WEAPON_H
+#define TURRET_EWHEEL_WEAPON_H
+
+CLASS(EWheelAttack, PortoLaunch)
+/* flags     */ ATTRIB(EWheelAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(EWheelAttack, impulse, int, 5);
+/* refname   */ ATTRIB(EWheelAttack, netname, string, "turret_ewheel");
+/* wepname   */ ATTRIB(EWheelAttack, message, string, _("eWheel"));
+ENDCLASS(EWheelAttack)
+REGISTER_WEAPON(EWHEEL, NEW(EWheelAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+void turret_initparams(entity);
+METHOD(EWheelAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+    bool isPlayer = IS_PLAYER(actor);
+    if (fire1)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+        if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+        }
+
+        turret_do_updates(actor);
+
+        entity missile = turret_projectile(SND(LASERGUN_FIRE), 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, true, true);
+        missile.missile_flags = MIF_SPLASH;
+
+        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
+
+        if (!isPlayer) {
+            actor.tur_head.frame += 2;
+
+            if (actor.tur_head.frame > 3)
+                actor.tur_head.frame = 0;
+        }
+    }
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/flac.qc b/qcsrc/common/turrets/turret/flac.qc
new file mode 100644 (file)
index 0000000..1c9122f
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef TURRET_FLAC_H
+#define TURRET_FLAC_H
+
+#include "flac_weapon.qc"
+
+CLASS(Flac, Turret)
+/* spawnflags */ ATTRIB(Flac, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE);
+/* mins       */ ATTRIB(Flac, mins, vector, '-32 -32 0');
+/* maxs       */ ATTRIB(Flac, maxs, vector, '32 32 64');
+/* modelname  */ ATTRIB(Flac, mdl, string, "base.md3");
+/* model      */ ATTRIB(Flac, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(Flac, head_model, string, strzone(strcat("models/turrets/", "flac.md3")));
+/* netname    */ ATTRIB(Flac, netname, string, "flac");
+/* fullname   */ ATTRIB(Flac, turret_name, string, _("FLAC Cannon"));
+    ATTRIB(Flac, m_weapon, Weapon, WEP_FLAC);
+ENDCLASS(Flac)
+REGISTER_TURRET(FLAC, NEW(Flac));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "flac_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_flac) { if (!turret_initialize(TUR_FLAC)) remove(self); }
+
+METHOD(Flac, tr_setup, void(Flac this, entity it))
+{
+    it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+    it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+    it.damage_flags |= TFL_DMG_HEADSHAKE;
+    it.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/flac_weapon.qc b/qcsrc/common/turrets/turret/flac_weapon.qc
new file mode 100644 (file)
index 0000000..4c60805
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef TURRET_FLAC_WEAPON_H
+#define TURRET_FLAC_WEAPON_H
+
+CLASS(FlacAttack, PortoLaunch)
+/* flags     */ ATTRIB(FlacAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(FlacAttack, impulse, int, 5);
+/* refname   */ ATTRIB(FlacAttack, netname, string, "turret_flac");
+/* wepname   */ ATTRIB(FlacAttack, message, string, _("FLAC"));
+ENDCLASS(FlacAttack)
+REGISTER_WEAPON(FLAC, NEW(FlacAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+void turret_flac_projectile_think_explode();
+METHOD(FlacAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+    bool isPlayer = IS_PLAYER(actor);
+    if (fire1)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+        if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            actor.tur_impacttime = 10;
+            weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+        }
+
+        turret_tag_fire_update();
+
+        entity proj = turret_projectile(SND(HAGAR_FIRE), 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, true, true);
+        proj.missile_flags = MIF_SPLASH | MIF_PROXY;
+        proj.think       = turret_flac_projectile_think_explode;
+        proj.nextthink  = time + actor.tur_impacttime + (random() * 0.01 - random() * 0.01);
+        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
+
+        if (!isPlayer) {
+            actor.tur_head.frame = actor.tur_head.frame + 1;
+            if (actor.tur_head.frame >= 4)
+                actor.tur_head.frame = 0;
+        }
+    }
+}
+
+void turret_flac_projectile_think_explode()
+{
+    SELFPARAM();
+    if (self.enemy != world)
+    if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
+        setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
+
+#ifdef TURRET_DEBUG
+    float d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+    self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
+    self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
+#else
+    RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+#endif
+    remove(self);
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/fusionreactor.qc b/qcsrc/common/turrets/turret/fusionreactor.qc
new file mode 100644 (file)
index 0000000..1077d5c
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef TURRET_FUSIONREACTOR_H
+#define TURRET_FUSIONREACTOR_H
+
+CLASS(FusionReactor, Turret)
+/* spawnflags */ ATTRIB(FusionReactor, spawnflags, int, TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE);
+/* mins       */ ATTRIB(FusionReactor, mins, vector, '-34 -34 0');
+/* maxs       */ ATTRIB(FusionReactor, maxs, vector, '34 34 90');
+/* modelname  */ ATTRIB(FusionReactor, mdl, string, "base.md3");
+/* model      */ ATTRIB(FusionReactor, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(FusionReactor, head_model, string, strzone(strcat("models/turrets/", "reactor.md3")));
+/* netname    */ ATTRIB(FusionReactor, netname, string, "fusionreactor");
+/* fullname   */ ATTRIB(FusionReactor, turret_name, string, _("Fusion Reactor"));
+ENDCLASS(FusionReactor)
+REGISTER_TURRET(FUSIONREACTOR, NEW(FusionReactor));
+
+#endif
+
+#ifdef IMPLEMENTATION
+#ifdef SVQC
+bool turret_fusionreactor_firecheck()
+{SELFPARAM();
+    if (self.attack_finished_single > time)
+        return false;
+
+    if (self.enemy.deadflag != DEAD_NO)
+        return false;
+
+    if (self.enemy == world)
+        return false;
+
+    if (self.ammo < self.shot_dmg)
+        return false;
+
+    if (self.enemy.ammo >= self.enemy.ammo_max)
+        return false;
+
+    if (vlen(self.enemy.origin - self.origin) > self.target_range)
+        return false;
+
+    if(self.team != self.enemy.team)
+        return false;
+
+    if(!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
+        return false;
+
+    return true;
+}
+
+spawnfunc(turret_fusionreactor) { if (!turret_initialize(TUR_FUSIONREACTOR)) remove(self); }
+
+METHOD(FusionReactor, tr_attack, void(FusionReactor this))
+{
+    self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
+    vector fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
+    te_smallflash(fl_org);
+}
+METHOD(FusionReactor, tr_think, void(FusionReactor thistur))
+{
+    self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
+}
+METHOD(FusionReactor, tr_setup, void(FusionReactor this, entity it))
+{
+    it.ammo_flags                              = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
+    it.target_select_flags     = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS;
+    it.firecheck_flags         = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
+    it.shoot_flags                     = TFL_SHOOT_HITALLVALID;
+    it.aim_flags                               = TFL_AIM_NO;
+    it.track_flags                     = TFL_TRACK_NO;
+
+    it.tur_head.scale = 0.75;
+    it.tur_head.avelocity = '0 50 0';
+
+    it.turret_firecheckfunc = turret_fusionreactor_firecheck;
+}
+
+#endif
+#endif
diff --git a/qcsrc/common/turrets/turret/hellion.qc b/qcsrc/common/turrets/turret/hellion.qc
new file mode 100644 (file)
index 0000000..203be93
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef TURRET_HELLION_H
+#define TURRET_HELLION_H
+
+#include "hellion_weapon.qc"
+
+CLASS(Hellion, Turret)
+/* spawnflags */ ATTRIB(Hellion, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE);
+/* mins       */ ATTRIB(Hellion, mins, vector, '-32 -32 0');
+/* maxs       */ ATTRIB(Hellion, maxs, vector, '32 32 64');
+/* modelname  */ ATTRIB(Hellion, mdl, string, "base.md3");
+/* model      */ ATTRIB(Hellion, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(Hellion, head_model, string, strzone(strcat("models/turrets/", "hellion.md3")));
+/* netname    */ ATTRIB(Hellion, netname, string, "hellion");
+/* fullname   */ ATTRIB(Hellion, turret_name, string, _("Hellion Missile Turret"));
+    ATTRIB(Hellion, m_weapon, Weapon, WEP_HELLION);
+ENDCLASS(Hellion)
+REGISTER_TURRET(HELLION, NEW(Hellion));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "hellion_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_hellion) { if (!turret_initialize(TUR_HELLION)) remove(self); }
+
+METHOD(Hellion, tr_think, void(Hellion thistur))
+{
+    if (self.tur_head.frame != 0)
+        self.tur_head.frame += 1;
+
+    if (self.tur_head.frame >= 7)
+        self.tur_head.frame = 0;
+}
+METHOD(Hellion, tr_setup, void(Hellion this, entity it))
+{
+    it.aim_flags = TFL_AIM_SIMPLE;
+    it.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ;
+    it.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN;
+    it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+}
+
+#endif
+#endif
diff --git a/qcsrc/common/turrets/turret/hellion_weapon.qc b/qcsrc/common/turrets/turret/hellion_weapon.qc
new file mode 100644 (file)
index 0000000..491fa73
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef TURRET_HELLION_WEAPON_H
+#define TURRET_HELLION_WEAPON_H
+
+CLASS(HellionAttack, PortoLaunch)
+/* flags     */ ATTRIB(HellionAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(HellionAttack, impulse, int, 9);
+/* refname   */ ATTRIB(HellionAttack, netname, string, "turret_hellion");
+/* wepname   */ ATTRIB(HellionAttack, message, string, _("Hellion"));
+ENDCLASS(HellionAttack)
+REGISTER_WEAPON(HELLION, NEW(HellionAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_turrets_unit_hellion_shot_speed_gain;
+float autocvar_g_turrets_unit_hellion_shot_speed_max;
+
+void turret_hellion_missile_think();
+METHOD(HellionAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+    bool isPlayer = IS_PLAYER(actor);
+    if (fire1)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+        if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            actor.shot_radius = 500;
+            weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+        }
+        if (!isPlayer) {
+            if (actor.tur_head.frame != 0)
+                actor.tur_shotorg = gettaginfo(actor.tur_head, gettagindex(actor.tur_head, "tag_fire"));
+            else
+                actor.tur_shotorg = gettaginfo(actor.tur_head, gettagindex(actor.tur_head, "tag_fire2"));
+        }
+
+        entity missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE);
+        te_explosion (missile.origin);
+        missile.think          = 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;
+        if (!isPlayer) actor.tur_head.frame += 1;
+    }
+}
+
+void turret_hellion_missile_think()
+{SELFPARAM();
+    vector olddir,newdir;
+    vector pre_pos;
+    float itime;
+
+    self.nextthink = time + 0.05;
+
+    olddir = normalize(self.velocity);
+
+    if(self.max_health < time)
+        turret_projectile_explode();
+
+    // Enemy dead? just keep on the current heading then.
+    if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
+    {
+
+        // Make sure we dont return to tracking a respawned player
+        self.enemy = world;
+
+        // Turn model
+        self.angles = vectoangles(self.velocity);
+
+        if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
+            turret_projectile_explode();
+
+        // Accelerate
+        self.velocity = olddir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+        UpdateCSQCProjectile(self);
+
+        return;
+    }
+
+    // Enemy in range?
+    if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
+        turret_projectile_explode();
+
+    // Predict enemy position
+    itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
+    pre_pos = self.enemy.origin + self.enemy.velocity * itime;
+
+    pre_pos = (pre_pos + self.enemy.origin) * 0.5;
+
+    // Find out the direction to that place
+    newdir = normalize(pre_pos - self.origin);
+
+    // Turn
+    newdir = normalize(olddir + newdir * 0.35);
+
+    // Turn model
+    self.angles = vectoangles(self.velocity);
+
+    // Accelerate
+    self.velocity = newdir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
+
+    if (itime < 0.05)
+        self.think = turret_projectile_explode;
+
+    UpdateCSQCProjectile(self);
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/hk.qc b/qcsrc/common/turrets/turret/hk.qc
new file mode 100644 (file)
index 0000000..61d8318
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef TURRET_HK_H
+#define TURRET_HK_H
+
+//#define TURRET_DEBUG_HK
+
+#include "hk_weapon.qc"
+
+CLASS(HunterKiller, Turret)
+/* spawnflags */ ATTRIB(HunterKiller, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS);
+/* mins       */ ATTRIB(HunterKiller, mins, vector, '-32 -32 0');
+/* maxs       */ ATTRIB(HunterKiller, maxs, vector, '32 32 64');
+/* modelname  */ ATTRIB(HunterKiller, mdl, string, "base.md3");
+/* model      */ ATTRIB(HunterKiller, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(HunterKiller, head_model, string, strzone(strcat("models/turrets/", "hk.md3")));
+/* netname    */ ATTRIB(HunterKiller, netname, string, "hk");
+/* fullname   */ ATTRIB(HunterKiller, turret_name, string, _("Hunter-Killer Turret"));
+    ATTRIB(HunterKiller, m_weapon, Weapon, WEP_HK);
+ENDCLASS(HunterKiller)
+REGISTER_TURRET(HK, NEW(HunterKiller));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "hk_weapon.qc"
+
+#ifdef SVQC
+
+#ifdef TURRET_DEBUG_HK
+.float atime;
+#endif
+
+spawnfunc(turret_hk) { if(!turret_initialize(TUR_HK)) remove(self); }
+
+METHOD(HunterKiller, tr_think, void(HunterKiller thistur))
+{
+    if (self.tur_head.frame != 0)
+        self.tur_head.frame = self.tur_head.frame + 1;
+
+    if (self.tur_head.frame > 5)
+        self.tur_head.frame = 0;
+}
+
+float turret_hk_addtarget(entity e_target,entity e_sender);
+METHOD(HunterKiller, tr_setup, void(HunterKiller this, entity it))
+{
+    it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+    it.aim_flags = TFL_AIM_SIMPLE;
+    it.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+    it.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK  | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
+    it.shoot_flags = TFL_SHOOT_CLEARTARGET;
+    it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
+
+    it.turret_addtarget = turret_hk_addtarget;
+}
+
+float turret_hk_addtarget(entity e_target,entity e_sender)
+{SELFPARAM();
+    if (e_target)
+    {
+        if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
+        {
+            self.enemy = e_target;
+            return 1;
+        }
+    }
+
+    return 0;
+}
+
+#endif // SVQC
+#endif
diff --git a/qcsrc/common/turrets/turret/hk_weapon.qc b/qcsrc/common/turrets/turret/hk_weapon.qc
new file mode 100644 (file)
index 0000000..9fe73f8
--- /dev/null
@@ -0,0 +1,295 @@
+#ifndef TURRET_HK_WEAPON_H
+#define TURRET_HK_WEAPON_H
+
+CLASS(HunterKillerAttack, PortoLaunch)
+/* flags     */ ATTRIB(HunterKillerAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(HunterKillerAttack, impulse, int, 9);
+/* refname   */ ATTRIB(HunterKillerAttack, netname, string, "turret_hk");
+/* wepname   */ ATTRIB(HunterKillerAttack, message, string, _("Hunter-Killer"));
+ENDCLASS(HunterKillerAttack)
+REGISTER_WEAPON(HK, NEW(HunterKillerAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_turrets_unit_hk_shot_speed;
+float autocvar_g_turrets_unit_hk_shot_speed_accel;
+float autocvar_g_turrets_unit_hk_shot_speed_accel2;
+float autocvar_g_turrets_unit_hk_shot_speed_decel;
+float autocvar_g_turrets_unit_hk_shot_speed_max;
+float autocvar_g_turrets_unit_hk_shot_speed_turnrate;
+
+void turret_hk_missile_think();
+METHOD(HunterKillerAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+       bool isPlayer = IS_PLAYER(actor);
+       if (fire1)
+       if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+               if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+        }
+        entity missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE);
+        te_explosion (missile.origin);
+
+        missile.think = turret_hk_missile_think;
+        missile.nextthink = time + 0.25;
+        missile.movetype = MOVETYPE_BOUNCEMISSILE;
+        missile.velocity = actor.tur_shotdir_updated * (actor.shot_speed * 0.75);
+        missile.angles = vectoangles(missile.velocity);
+        missile.cnt = time + 30;
+        missile.ticrate = max(autocvar_sys_ticrate, 0.05);
+        missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
+
+        if (!isPlayer)
+        if (actor.tur_head.frame == 0)
+            actor.tur_head.frame = actor.tur_head.frame + 1;
+       }
+}
+
+bool hk_is_valid_target(entity e_target);
+void turret_hk_missile_think()
+{SELFPARAM();
+    vector vu, vd, vf, vl, vr, ve;  // Vector (direction)
+    float  fu, fd, ff, fl, fr, fe;  // Fraction to solid
+    vector olddir,wishdir,newdir;   // Final direction
+    float lt_for;   // Length of Trace FORwrad
+    float lt_seek;  // Length of Trace SEEK (left, right, up down)
+    float pt_seek;  // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
+    vector pre_pos;
+    float myspeed;
+    entity e;
+    float ad,edist;
+
+    self.nextthink = time + self.ticrate;
+
+    //if (self.cnt < time)
+    // turret_hk_missile_explode();
+
+    if (self.enemy.deadflag != DEAD_NO)
+        self.enemy = world;
+
+    // Pick the closest valid target.
+    if (!self.enemy)
+    {
+        e = findradius(self.origin, 5000);
+        while (e)
+        {
+            if (hk_is_valid_target(e))
+            {
+                if (!self.enemy)
+                    self.enemy = e;
+                else
+                    if (vlen(self.origin - e.origin) < vlen(self.origin - self.enemy.origin))
+                        self.enemy = e;
+            }
+            e = e.chain;
+        }
+    }
+
+    self.angles = vectoangles(self.velocity);
+    self.angles_x = self.angles_x * -1;
+    makevectors(self.angles);
+    self.angles_x = self.angles_x * -1;
+
+    if (self.enemy)
+    {
+        edist = vlen(self.origin - self.enemy.origin);
+        // Close enougth to do decent damage?
+        if ( edist <= (self.owner.shot_radius * 0.25) )
+        {
+            turret_projectile_explode();
+            return;
+        }
+
+        // Get data on enemy position
+        pre_pos = self.enemy.origin +
+                  self.enemy.velocity *
+                  min((vlen(self.enemy.origin - self.origin) / vlen(self.velocity)),0.5);
+
+        traceline(self.origin, pre_pos,true,self.enemy);
+        ve = normalize(pre_pos - self.origin);
+        fe = trace_fraction;
+
+    }
+    else
+    {
+    edist = 0;
+    ve = '0 0 0';
+        fe = 0;
+    }
+
+    if ((fe != 1) || (self.enemy == world) || (edist > 1000))
+    {
+        myspeed = vlen(self.velocity);
+
+        lt_for  = myspeed * 3;
+        lt_seek = myspeed * 2.95;
+
+        // Trace forward
+        traceline(self.origin, self.origin + v_forward * lt_for,false,self);
+        vf = trace_endpos;
+        ff = trace_fraction;
+
+        // Find angular offset
+        ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
+
+        // To close to something, Slow down!
+        if ( ((ff < 0.7) || (ad > 4)) && (myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) )
+            myspeed = max(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_decel), (autocvar_g_turrets_unit_hk_shot_speed));
+
+        // Failry clear, accelerate.
+        if ( (ff > 0.7) && (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max)) )
+            myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel), (autocvar_g_turrets_unit_hk_shot_speed_max));
+
+        // Setup trace pitch
+        pt_seek = 1 - ff;
+        pt_seek = bound(0.15,pt_seek,0.8);
+        if (ff < 0.5) pt_seek = 1;
+
+        // Trace left
+        traceline(self.origin, self.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,self);
+        vl = trace_endpos;
+        fl = trace_fraction;
+
+        // Trace right
+        traceline(self.origin,  self.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+        vr = trace_endpos;
+        fr = trace_fraction;
+
+        // Trace up
+        traceline(self.origin,  self.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+        vu = trace_endpos;
+        fu = trace_fraction;
+
+        // Trace down
+        traceline(self.origin,  self.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
+        vd = trace_endpos;
+        fd = trace_fraction;
+
+        vl = normalize(vl - self.origin);
+        vr = normalize(vr - self.origin);
+        vu = normalize(vu - self.origin);
+        vd = normalize(vd - self.origin);
+
+        // Panic tresh passed, find a single direction and turn as hard as we can
+        if (pt_seek == 1)
+        {
+            wishdir = v_right;
+            if (fl > fr) wishdir = -1 * v_right;
+            if (fu > fl) wishdir = v_up;
+            if (fd > fu) wishdir = -1 * v_up;
+        }
+        else
+        {
+            // Normalize our trace vectors to make a smooth path
+            wishdir = normalize( (vl * fl) + (vr * fr) +  (vu * fu) +  (vd * fd) );
+        }
+
+        if (self.enemy)
+        {
+            if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
+            wishdir = (wishdir * (1 - fe)) + (ve * fe);
+        }
+    }
+    else
+    {
+        // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
+        myspeed = vlen(self.velocity);
+        if (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max))
+            myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+        wishdir = ve;
+    }
+
+    if ((myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) && (self.cnt > time))
+        myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
+
+    // Ranoutagazfish?
+    if (self.cnt < time)
+    {
+        self.cnt = time + 0.25;
+        self.nextthink = 0;
+        self.movetype           = MOVETYPE_BOUNCE;
+        return;
+    }
+
+    // Calculate new heading
+    olddir = normalize(self.velocity);
+    newdir = normalize(olddir + wishdir * (autocvar_g_turrets_unit_hk_shot_speed_turnrate));
+
+    // Set heading & speed
+    self.velocity = newdir * myspeed;
+
+    // Align model with new heading
+    self.angles = vectoangles(self.velocity);
+
+
+#ifdef TURRET_DEBUG_HK
+    //if(self.atime < time) {
+    if ((fe <= 0.99)||(edist > 1000))
+    {
+        te_lightning2(world,self.origin, self.origin + vr * lt_seek);
+        te_lightning2(world,self.origin, self.origin + vl * lt_seek);
+        te_lightning2(world,self.origin, self.origin + vu * lt_seek);
+        te_lightning2(world,self.origin, self.origin + vd * lt_seek);
+        te_lightning2(world,self.origin, vf);
+    }
+    else
+    {
+        te_lightning2(world,self.origin, self.enemy.origin);
+    }
+    bprint("Speed: ", ftos(rint(myspeed)), "\n");
+    bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
+    bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
+    self.atime = time + 0.2;
+    //}
+#endif
+
+    UpdateCSQCProjectile(self);
+}
+
+bool hk_is_valid_target(entity e_target)
+{SELFPARAM();
+    if (e_target == world)
+        return 0;
+
+    // If only this was used more..
+    if (e_target.flags & FL_NOTARGET)
+        return 0;
+
+    // Cant touch this
+    if ((e_target.takedamage == DAMAGE_NO) || (e_target.health < 0))
+        return 0;
+
+    // player
+    if (IS_CLIENT(e_target))
+    {
+        if (self.owner.target_select_playerbias < 0)
+            return 0;
+
+        if (e_target.deadflag != DEAD_NO)
+            return 0;
+    }
+
+    // Missile
+    if ((e_target.flags & FL_PROJECTILE) && (self.owner.target_select_missilebias < 0))
+        return 0;
+
+    // Team check
+    if ((e_target.team == self.owner.team) || (self.owner.team == e_target.owner.team))
+        return 0;
+
+    return 1;
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/machinegun.qc b/qcsrc/common/turrets/turret/machinegun.qc
new file mode 100644 (file)
index 0000000..9911b97
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef TURRET_MACHINEGUN_H
+#define TURRET_MACHINEGUN_H
+
+#include "machinegun_weapon.qc"
+
+CLASS(MachineGunTurret, Turret)
+/* spawnflags */ ATTRIB(MachineGunTurret, spawnflags, int, TUR_FLAG_PLAYER);
+/* mins       */ ATTRIB(MachineGunTurret, mins, vector, '-32 -32 0');
+/* maxs       */ ATTRIB(MachineGunTurret, maxs, vector, '32 32 64');
+/* modelname  */ ATTRIB(MachineGunTurret, mdl, string, "base.md3");
+/* model      */ ATTRIB(MachineGunTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(MachineGunTurret, head_model, string, strzone(strcat("models/turrets/", "machinegun.md3")));
+/* netname    */ ATTRIB(MachineGunTurret, netname, string, "machinegun");
+/* fullname   */ ATTRIB(MachineGunTurret, turret_name, string, _("Machinegun Turret"));
+    ATTRIB(MachineGunTurret, m_weapon, Weapon, WEP_TUR_MACHINEGUN);
+ENDCLASS(MachineGunTurret)
+REGISTER_TURRET(MACHINEGUN, NEW(MachineGunTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "machinegun_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_machinegun) { if (!turret_initialize(TUR_MACHINEGUN)) remove(self); }
+
+METHOD(MachineGunTurret, tr_setup, void(MachineGunTurret this, entity it))
+{
+    it.damage_flags |= TFL_DMG_HEADSHAKE;
+    it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+    it.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+    it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+    it.turret_flags |= TUR_FLAG_HITSCAN;
+}
+
+#endif // SVQC
+#endif
diff --git a/qcsrc/common/turrets/turret/machinegun_weapon.qc b/qcsrc/common/turrets/turret/machinegun_weapon.qc
new file mode 100644 (file)
index 0000000..9b14898
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef TURRET_MACHINEGUN_WEAPON_H
+#define TURRET_MACHINEGUN_WEAPON_H
+
+CLASS(MachineGunTurretAttack, PortoLaunch)
+/* flags     */ ATTRIB(MachineGunTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(MachineGunTurretAttack, impulse, int, 9);
+/* refname   */ ATTRIB(MachineGunTurretAttack, netname, string, "turret_machinegun");
+/* wepname   */ ATTRIB(MachineGunTurretAttack, message, string, _("Machinegun"));
+ENDCLASS(MachineGunTurretAttack)
+REGISTER_WEAPON(TUR_MACHINEGUN, NEW(MachineGunTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+void W_MachineGun_MuzzleFlash();
+
+METHOD(MachineGunTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+    bool isPlayer = IS_PLAYER(actor);
+    if (fire1)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR(machinegun, sustained_refire))) {
+        if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+        }
+        fireBullet (actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_MACHINEGUN, 0);
+        W_MachineGun_MuzzleFlash();
+        setattachment(actor.muzzle_flash, actor.tur_head, "tag_fire");
+    }
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/mlrs.qc b/qcsrc/common/turrets/turret/mlrs.qc
new file mode 100644 (file)
index 0000000..ae2d1d4
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef TURRET_MLRS_H
+#define TURRET_MLRS_H
+
+#include "mlrs_weapon.qc"
+
+CLASS(MLRSTurret, Turret)
+/* spawnflags */ ATTRIB(MLRSTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER);
+/* mins       */ ATTRIB(MLRSTurret, mins, vector, '-32 -32 0');
+/* maxs       */ ATTRIB(MLRSTurret, maxs, vector, '32 32 64');
+/* modelname  */ ATTRIB(MLRSTurret, mdl, string, "base.md3");
+/* model      */ ATTRIB(MLRSTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(MLRSTurret, head_model, string, strzone(strcat("models/turrets/", "mlrs.md3")));
+/* netname    */ ATTRIB(MLRSTurret, netname, string, "mlrs");
+/* fullname   */ ATTRIB(MLRSTurret, turret_name, string, _("MLRS Turret"));
+    ATTRIB(MLRSTurret, m_weapon, Weapon, WEP_TUR_MLRS);
+ENDCLASS(MLRSTurret)
+REGISTER_TURRET(MLRS, NEW(MLRSTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "mlrs_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_mlrs) { if (!turret_initialize(TUR_MLRS)) remove(self); }
+
+METHOD(MLRSTurret, tr_think, void(MLRSTurret thistur))
+{
+    // 0 = full, 6 = empty
+    self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
+    if(self.tur_head.frame < 0)
+    {
+        LOG_TRACE("ammo:",ftos(self.ammo),"\n");
+        LOG_TRACE("shot_dmg:",ftos(self.shot_dmg),"\n");
+    }
+}
+METHOD(MLRSTurret, tr_setup, void(MLRSTurret this, entity it))
+{
+    it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
+    it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+
+    it.damage_flags |= TFL_DMG_HEADSHAKE;
+    it.shoot_flags  |= TFL_SHOOT_VOLLYALWAYS;
+    it.volly_counter = it.shot_volly;
+}
+
+#endif // SVQC
+#endif
diff --git a/qcsrc/common/turrets/turret/mlrs_weapon.qc b/qcsrc/common/turrets/turret/mlrs_weapon.qc
new file mode 100644 (file)
index 0000000..3b420f3
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef TURRET_MLRS_WEAPON_H
+#define TURRET_MLRS_WEAPON_H
+
+CLASS(MLRSTurretAttack, PortoLaunch)
+/* flags     */ ATTRIB(MLRSTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(MLRSTurretAttack, impulse, int, 9);
+/* refname   */ ATTRIB(MLRSTurretAttack, netname, string, "turret_mlrs");
+/* wepname   */ ATTRIB(MLRSTurretAttack, message, string, _("MLRS"));
+ENDCLASS(MLRSTurretAttack)
+REGISTER_WEAPON(TUR_MLRS, NEW(MLRSTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+METHOD(MLRSTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+    bool isPlayer = IS_PLAYER(actor);
+    if (fire1)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR(machinegun, sustained_refire))) {
+        if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            actor.shot_radius = 500;
+            weapon_thinkf(actor, WFRAME_FIRE1, 0, w_ready);
+        }
+        turret_tag_fire_update();
+        entity missile = turret_projectile(SND(ROCKET_FIRE), 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE);
+        missile.nextthink = time + max(actor.tur_impacttime,(actor.shot_radius * 2) / actor.shot_speed);
+        missile.missile_flags = MIF_SPLASH;
+        te_explosion (missile.origin);
+    }
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/phaser.qc b/qcsrc/common/turrets/turret/phaser.qc
new file mode 100644 (file)
index 0000000..24d4d30
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef TURRET_PHASER_H
+#define TURRET_PHASER_H
+
+#include "phaser_weapon.qc"
+
+CLASS(PhaserTurret, Turret)
+/* spawnflags */ ATTRIB(PhaserTurret, spawnflags, int, TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER);
+/* mins       */ ATTRIB(PhaserTurret, mins, vector, '-32 -32 0');
+/* maxs       */ ATTRIB(PhaserTurret, maxs, vector, '32 32 64');
+/* modelname  */ ATTRIB(PhaserTurret, mdl, string, "base.md3");
+/* model      */ ATTRIB(PhaserTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(PhaserTurret, head_model, string, strzone(strcat("models/turrets/", "phaser.md3")));
+/* netname    */ ATTRIB(PhaserTurret, netname, string, "phaser");
+/* fullname   */ ATTRIB(PhaserTurret, turret_name, string, _("Phaser Cannon"));
+    ATTRIB(PhaserTurret, m_weapon, Weapon, WEP_PHASER);
+ENDCLASS(PhaserTurret)
+REGISTER_TURRET(PHASER, NEW(PhaserTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "phaser_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_phaser) { if (!turret_initialize(TUR_PHASER)) remove(self); }
+
+METHOD(PhaserTurret, tr_think, void(PhaserTurret thistur))
+{
+    if (self.tur_head.frame != 0)
+    {
+        if (self.fireflag == 1)
+        {
+            if (self.tur_head.frame == 10)
+                self.tur_head.frame = 1;
+            else
+                self.tur_head.frame = self.tur_head.frame +1;
+        }
+        else if (self.fireflag == 2 )
+        {
+            self.tur_head.frame = self.tur_head.frame +1;
+            if (self.tur_head.frame == 15)
+            {
+                self.tur_head.frame = 0;
+                self.fireflag = 0;
+            }
+        }
+    }
+}
+float turret_phaser_firecheck();
+METHOD(PhaserTurret, tr_setup, void(PhaserTurret this, entity it))
+{
+    it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+    it.aim_flags = TFL_AIM_LEAD;
+
+    it.turret_firecheckfunc = turret_phaser_firecheck;
+}
+float turret_phaser_firecheck()
+{
+    SELFPARAM();
+    if (self.fireflag != 0) return 0;
+    return turret_firecheck();
+}
+
+#endif
+#endif
diff --git a/qcsrc/common/turrets/turret/phaser_weapon.qc b/qcsrc/common/turrets/turret/phaser_weapon.qc
new file mode 100644 (file)
index 0000000..2cb036b
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef TURRET_PHASER_WEAPON_H
+#define TURRET_PHASER_WEAPON_H
+
+CLASS(PhaserTurretAttack, PortoLaunch)
+/* flags     */ ATTRIB(PhaserTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(PhaserTurretAttack, impulse, int, 9);
+/* refname   */ ATTRIB(PhaserTurretAttack, netname, string, "turret_phaser");
+/* wepname   */ ATTRIB(PhaserTurretAttack, message, string, _("Phaser"));
+ENDCLASS(PhaserTurretAttack)
+REGISTER_WEAPON(PHASER, NEW(PhaserTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+void beam_think();
+
+.int fireflag;
+
+METHOD(PhaserTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+    bool isPlayer = IS_PLAYER(actor);
+    if (fire1)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+        if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            actor.shot_speed = 1;
+            weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+        }
+        entity beam = spawn();
+        beam.ticrate = 0.1; //autocvar_sys_ticrate;
+        setmodel(beam, MDL_TUR_PHASER_BEAM);
+        beam.effects = EF_LOWPRECISION;
+        beam.solid = SOLID_NOT;
+        beam.think = beam_think;
+        beam.cnt = time + actor.shot_speed;
+        beam.shot_spread = time + 2;
+        beam.nextthink = time;
+        beam.owner = actor;
+        beam.shot_dmg = actor.shot_dmg / (actor.shot_speed / beam.ticrate);
+        beam.scale = actor.target_range / 256;
+        beam.movetype = MOVETYPE_NONE;
+        beam.enemy = actor.enemy;
+        beam.bot_dodge = true;
+        beam.bot_dodgerating = beam.shot_dmg;
+        sound (beam, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
+        actor.fireflag = 1;
+
+        beam.attack_finished_single = actor.attack_finished_single;
+        actor.attack_finished_single = time; // + autocvar_sys_ticrate;
+
+        setattachment(beam,actor.tur_head, "tag_fire");
+
+        soundat (actor, trace_endpos, CH_SHOTS, SND(NEXIMPACT), VOL_BASE, ATTEN_NORM);
+        if (!isPlayer)
+        if (actor.tur_head.frame == 0)
+            actor.tur_head.frame = 1;
+    }
+}
+
+void beam_think()
+{SELFPARAM();
+    if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO))
+    {
+        self.owner.attack_finished_single = time + self.owner.shot_refire;
+        self.owner.fireflag = 2;
+        self.owner.tur_head.frame = 10;
+        sound (self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
+        remove(self);
+        return;
+    }
+
+    turret_do_updates(self.owner);
+
+    if (time - self.shot_spread > 0)
+    {
+        self.shot_spread = time + 2;
+        sound (self, CH_SHOTS_SINGLE, SND_TUR_PHASER, VOL_BASE, ATTEN_NORM);
+    }
+
+
+    self.nextthink = time + self.ticrate;
+
+    self.owner.attack_finished_single = time + frametime;
+    setself(self.owner);
+    FireImoBeam (   self.tur_shotorg,
+                    self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
+                    '-1 -1 -1' * self.shot_radius,
+                    '1 1 1' * self.shot_radius,
+                    self.shot_force,
+                    this.shot_dmg,
+                    0.75,
+                    DEATH_TURRET_PHASER);
+    setself(this);
+    self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
+
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/plasma.qc b/qcsrc/common/turrets/turret/plasma.qc
new file mode 100644 (file)
index 0000000..7c40299
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef TURRET_PLASMA_H
+#define TURRET_PLASMA_H
+
+#include "plasma_weapon.qc"
+
+CLASS(PlasmaTurret, Turret)
+/* spawnflags */ ATTRIB(PlasmaTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER);
+/* mins       */ ATTRIB(PlasmaTurret, mins, vector, '-32 -32 0');
+/* maxs       */ ATTRIB(PlasmaTurret, maxs, vector, '32 32 64');
+/* modelname  */ ATTRIB(PlasmaTurret, mdl, string, "base.md3");
+/* model      */ ATTRIB(PlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(PlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasma.md3")));
+/* netname    */ ATTRIB(PlasmaTurret, netname, string, "plasma");
+/* fullname   */ ATTRIB(PlasmaTurret, turret_name, string, _("Plasma Cannon"));
+    ATTRIB(PlasmaTurret, m_weapon, Weapon, WEP_PLASMA);
+ENDCLASS(PlasmaTurret)
+REGISTER_TURRET(PLASMA, NEW(PlasmaTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "plasma_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_plasma) { if (!turret_initialize(TUR_PLASMA)) remove(self); }
+
+METHOD(PlasmaTurret, tr_attack, void(PlasmaTurret this))
+{
+    if(g_instagib)
+    {
+        FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+                           800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
+        Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+        // teamcolor / hit beam effect
+        vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+        WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
+    }
+    else
+    {
+        super.tr_attack(this);
+    }
+    if (self.tur_head.frame == 0)
+        self.tur_head.frame = 1;
+}
+METHOD(PlasmaTurret, tr_think, void(PlasmaTurret thistur))
+{
+    if (self.tur_head.frame != 0)
+        self.tur_head.frame = self.tur_head.frame + 1;
+
+    if (self.tur_head.frame > 5)
+        self.tur_head.frame = 0;
+}
+METHOD(PlasmaTurret, tr_setup, void(PlasmaTurret this, entity it))
+{
+    it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+    it.damage_flags |= TFL_DMG_HEADSHAKE;
+    it.firecheck_flags |= TFL_FIRECHECK_AFF;
+    it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
+
+    turret_do_updates(it);
+}
+
+#endif
+#endif
diff --git a/qcsrc/common/turrets/turret/plasma_dual.qc b/qcsrc/common/turrets/turret/plasma_dual.qc
new file mode 100644 (file)
index 0000000..e1143bc
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef TURRET_PLASMA_DUAL_H
+#define TURRET_PLASMA_DUAL_H
+
+CLASS(PlasmaDualAttack, PlasmaAttack)
+/* refname   */ ATTRIB(PlasmaDualAttack, netname, string, "turret_plasma_dual");
+/* wepname   */ ATTRIB(PlasmaDualAttack, message, string, _("Dual plasma"));
+ENDCLASS(PlasmaDualAttack)
+REGISTER_WEAPON(PLASMA_DUAL, NEW(PlasmaDualAttack));
+
+CLASS(DualPlasmaTurret, PlasmaTurret)
+/* spawnflags */ ATTRIB(DualPlasmaTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER);
+/* mins       */ ATTRIB(DualPlasmaTurret, mins, vector, '-32 -32 0');
+/* maxs       */ ATTRIB(DualPlasmaTurret, maxs, vector, '32 32 64');
+/* modelname  */ ATTRIB(DualPlasmaTurret, mdl, string, "base.md3");
+/* model      */ ATTRIB(DualPlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(DualPlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasmad.md3")));
+/* netname    */ ATTRIB(DualPlasmaTurret, netname, string, "plasma_dual");
+/* fullname   */ ATTRIB(DualPlasmaTurret, turret_name, string, _("Dual Plasma Cannon"));
+    ATTRIB(DualPlasmaTurret, m_weapon, Weapon, WEP_PLASMA_DUAL);
+ENDCLASS(DualPlasmaTurret)
+REGISTER_TURRET(PLASMA_DUAL, NEW(DualPlasmaTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+spawnfunc(turret_plasma_dual) { if (!turret_initialize(TUR_PLASMA_DUAL)) remove(self); }
+
+METHOD(DualPlasmaTurret, tr_attack, void(DualPlasmaTurret this))
+{
+    if (g_instagib) {
+        FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+                           800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
+
+
+        Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
+
+        // teamcolor / hit beam effect
+        vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+        WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
+    } else {
+        super.vtblbase.tr_attack(this);
+    }
+    self.tur_head.frame += 1;
+}
+METHOD(DualPlasmaTurret, tr_think, void(DualPlasmaTurret thistur))
+{
+    if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
+        self.tur_head.frame = self.tur_head.frame + 1;
+
+    if (self.tur_head.frame > 6)
+        self.tur_head.frame = 0;
+}
+
+#endif
+#endif
diff --git a/qcsrc/common/turrets/turret/plasma_weapon.qc b/qcsrc/common/turrets/turret/plasma_weapon.qc
new file mode 100644 (file)
index 0000000..65a6630
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef TURRET_PLASMA_WEAPON_H
+#define TURRET_PLASMA_WEAPON_H
+
+CLASS(PlasmaAttack, PortoLaunch)
+/* flags     */ ATTRIB(PlasmaAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(PlasmaAttack, impulse, int, 5);
+/* refname   */ ATTRIB(PlasmaAttack, netname, string, "turret_plasma");
+/* wepname   */ ATTRIB(PlasmaAttack, message, string, _("Plasma"));
+ENDCLASS(PlasmaAttack)
+REGISTER_WEAPON(PLASMA, NEW(PlasmaAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+METHOD(PlasmaAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+       bool isPlayer = IS_PLAYER(actor);
+       if (fire1)
+       if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+               if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+        }
+        entity missile = turret_projectile(SND(HAGAR_FIRE), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, true, true);
+        missile.missile_flags = MIF_SPLASH;
+        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
+       }
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/tesla.qc b/qcsrc/common/turrets/turret/tesla.qc
new file mode 100644 (file)
index 0000000..3ae039c
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef TURRET_TESLA_H
+#define TURRET_TESLA_H
+
+#include "tesla_weapon.qc"
+
+CLASS(TeslaCoil, Turret)
+/* spawnflags */ ATTRIB(TeslaCoil, spawnflags, int, TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE);
+/* mins       */ ATTRIB(TeslaCoil, mins, vector, '-60 -60 0');
+/* maxs       */ ATTRIB(TeslaCoil, maxs, vector, '60 60 128');
+/* modelname  */ ATTRIB(TeslaCoil, mdl, string, "tesla_base.md3");
+/* model      */ ATTRIB(TeslaCoil, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(TeslaCoil, head_model, string, strzone(strcat("models/turrets/", "tesla_head.md3")));
+/* netname    */ ATTRIB(TeslaCoil, netname, string, "tesla");
+/* fullname   */ ATTRIB(TeslaCoil, turret_name, string, _("Tesla Coil"));
+    ATTRIB(TeslaCoil, m_weapon, Weapon, WEP_TESLA);
+ENDCLASS(TeslaCoil)
+REGISTER_TURRET(TESLA, NEW(TeslaCoil));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "tesla_weapon.qc"
+
+#ifdef SVQC
+
+spawnfunc(turret_tesla) { if (!turret_initialize(TUR_TESLA)) remove(self); }
+
+METHOD(TeslaCoil, tr_think, void(TeslaCoil thistur))
+{
+    if(!self.active)
+    {
+        self.tur_head.avelocity = '0 0 0';
+        return;
+    }
+
+    if(self.ammo < self.shot_dmg)
+    {
+        self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
+    }
+    else
+    {
+        self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
+
+        if(self.attack_finished_single > time)
+            return;
+
+        float f;
+        f = (self.ammo / self.ammo_max);
+        f = f * f;
+        if(f > random())
+            if(random() < 0.1)
+                te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
+    }
+}
+
+float turret_tesla_firecheck();
+METHOD(TeslaCoil, tr_setup, void(TeslaCoil this, entity it))
+{
+    it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+                         TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+    it.turret_firecheckfunc = turret_tesla_firecheck;
+    it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
+                       TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+    it.firecheck_flags = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
+    it.shoot_flags             = TFL_SHOOT_CUSTOM;
+    it.ammo_flags                      = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+    it.aim_flags                       = TFL_AIM_NO;
+    it.track_flags             = TFL_TRACK_NO;
+}
+
+float turret_tesla_firecheck()
+{SELFPARAM();
+    // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
+    float do_target_scan = 0;
+
+    if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
+        do_target_scan = 1;
+
+    // Old target (if any) invalid?
+    if(self.target_validate_time < time)
+    if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
+    {
+        self.enemy = world;
+        self.target_validate_time = time + 0.5;
+        do_target_scan = 1;
+    }
+
+    // But never more often then g_turrets_targetscan_mindelay!
+    if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
+        do_target_scan = 0;
+
+    if(do_target_scan)
+    {
+        self.enemy = turret_select_target();
+        self.target_select_time = time;
+    }
+
+    if(!turret_firecheck())
+        return 0;
+
+    if(self.enemy)
+        return 1;
+
+    return 0;
+}
+
+#endif
+#endif
diff --git a/qcsrc/common/turrets/turret/tesla_weapon.qc b/qcsrc/common/turrets/turret/tesla_weapon.qc
new file mode 100644 (file)
index 0000000..3a8eb1d
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef TURRET_TESLA_WEAPON_H
+#define TURRET_TESLA_WEAPON_H
+
+CLASS(TeslaCoilTurretAttack, PortoLaunch)
+/* flags     */ ATTRIB(TeslaCoilTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(TeslaCoilTurretAttack, impulse, int, 9);
+/* refname   */ ATTRIB(TeslaCoilTurretAttack, netname, string, "turret_tesla");
+/* wepname   */ ATTRIB(TeslaCoilTurretAttack, message, string, _("Tesla Coil"));
+ENDCLASS(TeslaCoilTurretAttack)
+REGISTER_WEAPON(TESLA, NEW(TeslaCoilTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+entity toast(entity from, float range, float damage);
+METHOD(TeslaCoilTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+    bool isPlayer = IS_PLAYER(actor);
+    if (fire1)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+        if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+        }
+
+        float d = actor.shot_dmg;
+        float r = actor.target_range;
+        entity e = spawn();
+        setorigin(e,actor.tur_shotorg);
+
+        actor.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
+
+        entity t = toast(e,r,d);
+        remove(e);
+
+        if (t == NULL) return;
+
+        actor.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
+
+        actor.attack_finished_single = time + actor.shot_refire;
+        for (int i = 0; i < 10; ++i) {
+            d *= 0.75;
+            r *= 0.85;
+            t = toast(t, r, d);
+            if (t == world) break;
+
+        }
+
+        e = findchainfloat(railgunhit, 1);
+        while (e) {
+            e.railgunhit = 0;
+            e = e.chain;
+        }
+
+    }
+}
+
+entity toast(entity from, float range, float damage)
+{SELFPARAM();
+    entity e;
+    entity etarget = world;
+    float d,dd;
+    float r;
+
+    dd = range + 1;
+
+    e = findradius(from.origin,range);
+    while (e)
+    {
+        if ((e.railgunhit != 1) && (e != from))
+        {
+            r = turret_validate_target(self,e,self.target_validate_flags);
+            if (r > 0)
+            {
+                traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
+                if (trace_fraction == 1.0)
+                {
+                    d = vlen(e.origin - from.origin);
+                    if (d < dd)
+                    {
+                        dd = d;
+                        etarget = e;
+                    }
+                }
+            }
+        }
+        e = e.chain;
+    }
+
+    if (etarget)
+    {
+        te_csqc_lightningarc(from.origin,etarget.origin);
+        Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
+        etarget.railgunhit = 1;
+    }
+
+    return etarget;
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turret/walker.qc b/qcsrc/common/turrets/turret/walker.qc
new file mode 100644 (file)
index 0000000..e629ada
--- /dev/null
@@ -0,0 +1,667 @@
+#ifndef TURRET_WALKER_H
+#define TURRET_WALKER_H
+
+//#define WALKER_FANCYPATHING
+
+#include "walker_weapon.qc"
+
+CLASS(WalkerTurret, Turret)
+/* spawnflags */ ATTRIB(WalkerTurret, spawnflags, int, TUR_FLAG_PLAYER | TUR_FLAG_MOVE);
+/* mins       */ ATTRIB(WalkerTurret, mins, vector, '-70 -70 0');
+/* maxs       */ ATTRIB(WalkerTurret, maxs, vector, '70 70 95');
+/* modelname  */ ATTRIB(WalkerTurret, mdl, string, "walker_body.md3");
+/* model      */ ATTRIB(WalkerTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
+/* head_model */ ATTRIB(WalkerTurret, head_model, string, strzone(strcat("models/turrets/", "walker_head_minigun.md3")));
+/* netname    */ ATTRIB(WalkerTurret, netname, string, "walker");
+/* fullname   */ ATTRIB(WalkerTurret, turret_name, string, _("Walker Turret"));
+    ATTRIB(WalkerTurret, m_weapon, Weapon, WEP_WALKER);
+ENDCLASS(WalkerTurret)
+REGISTER_TURRET(WALKER, NEW(WalkerTurret));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "walker_weapon.qc"
+
+#ifdef SVQC
+
+float autocvar_g_turrets_unit_walker_melee_damage;
+float autocvar_g_turrets_unit_walker_melee_force;
+float autocvar_g_turrets_unit_walker_melee_range;
+float autocvar_g_turrets_unit_walker_rocket_damage;
+float autocvar_g_turrets_unit_walker_rocket_radius;
+float autocvar_g_turrets_unit_walker_rocket_force;
+float autocvar_g_turrets_unit_walker_rocket_speed;
+float autocvar_g_turrets_unit_walker_rocket_range;
+float autocvar_g_turrets_unit_walker_rocket_range_min;
+float autocvar_g_turrets_unit_walker_rocket_refire;
+float autocvar_g_turrets_unit_walker_rocket_turnrate;
+float autocvar_g_turrets_unit_walker_speed_stop;
+float autocvar_g_turrets_unit_walker_speed_walk;
+float autocvar_g_turrets_unit_walker_speed_run;
+float autocvar_g_turrets_unit_walker_speed_jump;
+float autocvar_g_turrets_unit_walker_speed_swim;
+float autocvar_g_turrets_unit_walker_speed_roam;
+float autocvar_g_turrets_unit_walker_turn;
+float autocvar_g_turrets_unit_walker_turn_walk;
+float autocvar_g_turrets_unit_walker_turn_strafe;
+float autocvar_g_turrets_unit_walker_turn_swim;
+float autocvar_g_turrets_unit_walker_turn_run;
+
+const int ANIM_NO         = 0;
+const int ANIM_TURN       = 1;
+const int ANIM_WALK       = 2;
+const int ANIM_RUN        = 3;
+const int ANIM_STRAFE_L   = 4;
+const int ANIM_STRAFE_R   = 5;
+const int ANIM_JUMP       = 6;
+const int ANIM_LAND       = 7;
+const int ANIM_PAIN       = 8;
+const int ANIM_MELEE      = 9;
+const int ANIM_SWIM       = 10;
+const int ANIM_ROAM       = 11;
+
+.float animflag;
+.float idletime;
+
+#define WALKER_PATH(s,e) pathlib_astar(s,e)
+
+float walker_firecheck()
+{SELFPARAM();
+    if (self.animflag == ANIM_MELEE)
+        return 0;
+
+    return turret_firecheck();
+}
+
+void walker_melee_do_dmg()
+{SELFPARAM();
+    vector where;
+    entity e;
+
+    makevectors(self.angles);
+    where = self.origin + v_forward * 128;
+
+    e = findradius(where,32);
+    while (e)
+    {
+        if (turret_validate_target(self, e, self.target_validate_flags))
+            if (e != self && e.owner != self)
+                Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
+
+        e = e.chain;
+    }
+}
+
+void walker_setnoanim()
+{SELFPARAM();
+    turrets_setframe(ANIM_NO, false);
+    self.animflag = self.frame;
+}
+void walker_rocket_explode()
+{SELFPARAM();
+    RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, world, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET, world);
+    remove (self);
+}
+
+void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
+{SELFPARAM();
+    self.health = self.health - damage;
+    self.velocity = self.velocity + vforce;
+
+    if (self.health <= 0)
+        W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
+}
+
+#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
+void walker_rocket_loop();
+void walker_rocket_think()
+{SELFPARAM();
+    vector newdir;
+    float edist;
+    float itime;
+    float m_speed;
+
+    self.nextthink = time;
+
+    edist = vlen(self.enemy.origin - self.origin);
+
+    // Simulate crude guidance
+    if (self.cnt < time)
+    {
+        if (edist < 1000)
+            self.tur_shotorg = randomvec() * min(edist, 64);
+        else
+            self.tur_shotorg = randomvec() * min(edist, 256);
+
+        self.cnt = time + 0.5;
+    }
+
+    if (edist < 128)
+        self.tur_shotorg = '0 0 0';
+
+    if (self.max_health < time)
+    {
+        self.think       = walker_rocket_explode;
+        self.nextthink  = time;
+        return;
+    }
+
+    if (self.shot_dmg != 1337 && random() < 0.01)
+    {
+        walker_rocket_loop();
+        return;
+    }
+
+    m_speed = vlen(self.velocity);
+
+    // Enemy dead? just keep on the current heading then.
+    if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
+        self.enemy = world;
+
+    if (self.enemy)
+    {
+        itime = max(edist / m_speed, 1);
+        newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
+    }
+    else
+        newdir  = normalize(self.velocity);
+
+    WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop3()
+{SELFPARAM();
+    vector newdir;
+    self.nextthink = time;
+
+    if (self.max_health < time)
+    {
+        self.think = walker_rocket_explode;
+        return;
+    }
+
+    if (vlen(self.origin - self.tur_shotorg) < 100 )
+    {
+        self.think = walker_rocket_think;
+        return;
+    }
+
+    newdir = steerlib_pull(self.tur_shotorg);
+    WALKER_ROCKET_MOVE;
+
+    self.angles = vectoangles(self.velocity);
+}
+
+void walker_rocket_loop2()
+{SELFPARAM();
+    vector newdir;
+
+    self.nextthink = time;
+
+    if (self.max_health < time)
+    {
+        self.think = walker_rocket_explode;
+        return;
+    }
+
+    if (vlen(self.origin - self.tur_shotorg) < 100 )
+    {
+        self.tur_shotorg = self.origin - '0 0 200';
+        self.think = walker_rocket_loop3;
+        return;
+    }
+
+    newdir = steerlib_pull(self.tur_shotorg);
+    WALKER_ROCKET_MOVE;
+}
+
+void walker_rocket_loop()
+{SELFPARAM();
+    self.nextthink = time;
+    self.tur_shotorg = self.origin + '0 0 300';
+    self.think = walker_rocket_loop2;
+    self.shot_dmg = 1337;
+}
+
+void walker_fire_rocket(vector org)
+{SELFPARAM();
+    entity rocket;
+
+    fixedmakevectors(self.angles);
+
+    te_explosion (org);
+
+    rocket = spawn ();
+    setorigin(rocket, org);
+
+    sound (self, CH_WEAPON_A, SND_HAGAR_FIRE, VOL_BASE, ATTEN_NORM);
+    setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
+
+    rocket.classname             = "walker_rocket";
+    rocket.owner                         = self;
+    rocket.bot_dodge             = true;
+    rocket.bot_dodgerating     = 50;
+    rocket.takedamage           = DAMAGE_YES;
+    rocket.damageforcescale   = 2;
+    rocket.health                       = 25;
+    rocket.tur_shotorg         = randomvec() * 512;
+    rocket.cnt                         = time + 1;
+    rocket.enemy                         = self.enemy;
+
+    if (random() < 0.01)
+        rocket.think             = walker_rocket_loop;
+    else
+        rocket.think             = walker_rocket_think;
+
+    rocket.event_damage           = walker_rocket_damage;
+
+    rocket.nextthink             = time;
+    rocket.movetype               = MOVETYPE_FLY;
+    rocket.velocity               = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
+    rocket.angles                       = vectoangles(rocket.velocity);
+    rocket.touch                         = walker_rocket_explode;
+    rocket.flags                         = FL_PROJECTILE;
+    rocket.solid                         = SOLID_BBOX;
+    rocket.max_health           = time + 9;
+    rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
+
+    CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
+}
+
+.vector enemy_last_loc;
+.float enemy_last_time;
+void walker_move_to(vector _target, float _dist)
+{SELFPARAM();
+    switch (self.waterlevel)
+    {
+        case WATERLEVEL_NONE:
+            if (_dist > 500)
+                self.animflag = ANIM_RUN;
+            else
+                self.animflag = ANIM_WALK;
+        case WATERLEVEL_WETFEET:
+        case WATERLEVEL_SWIMMING:
+            if (self.animflag != ANIM_SWIM)
+                self.animflag = ANIM_WALK;
+            else
+                self.animflag = ANIM_SWIM;
+            break;
+        case WATERLEVEL_SUBMERGED:
+            self.animflag = ANIM_SWIM;
+    }
+
+    self.moveto = _target;
+    self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+
+    if(self.enemy)
+    {
+        self.enemy_last_loc = _target;
+        self.enemy_last_time = time;
+    }
+}
+
+void walker_move_path()
+{SELFPARAM();
+#ifdef WALKER_FANCYPATHING
+    // Are we close enougth to a path node to switch to the next?
+    if (vlen(self.origin  - self.pathcurrent.origin) < 64)
+        if (self.pathcurrent.path_next == world)
+        {
+            // Path endpoint reached
+            pathlib_deletepath(self.pathcurrent.owner);
+            self.pathcurrent = world;
+
+            if (self.pathgoal)
+            {
+                if (self.pathgoal.use)
+                    self.pathgoal.use();
+
+                if (self.pathgoal.enemy)
+                {
+                    self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
+                    self.pathgoal = self.pathgoal.enemy;
+                }
+            }
+            else
+                self.pathgoal = world;
+        }
+        else
+            self.pathcurrent = self.pathcurrent.path_next;
+
+    self.moveto = self.pathcurrent.origin;
+    self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
+    walker_move_to(self.moveto, 0);
+
+#else
+    if (vlen(self.origin - self.pathcurrent.origin) < 64)
+        self.pathcurrent = self.pathcurrent.enemy;
+
+    if(!self.pathcurrent)
+        return;
+
+    self.moveto = self.pathcurrent.origin;
+    self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+    walker_move_to(self.moveto, 0);
+#endif
+}
+
+spawnfunc(turret_walker) { if(!turret_initialize(TUR_WALKER)) remove(self); }
+
+        METHOD(WalkerTurret, tr_think, void(WalkerTurret thistur))
+        {
+            fixedmakevectors(self.angles);
+
+            if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
+                walker_move_path();
+            else if (self.enemy == world)
+            {
+                if(self.pathcurrent)
+                    walker_move_path();
+                else
+                {
+                    if(self.enemy_last_time != 0)
+                    {
+                        if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
+                            self.enemy_last_time = 0;
+                        else
+                            walker_move_to(self.enemy_last_loc, 0);
+                    }
+                    else
+                    {
+                        if(self.animflag != ANIM_NO)
+                        {
+                            traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
+
+                            if(trace_fraction != 1.0)
+                                self.tur_head.idletime = -1337;
+                            else
+                            {
+                                traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
+                                if(trace_fraction == 1.0)
+                                    self.tur_head.idletime = -1337;
+                            }
+
+                            if(self.tur_head.idletime == -1337)
+                            {
+                                self.moveto = self.origin + randomvec() * 256;
+                                self.tur_head.idletime = 0;
+                            }
+
+                            self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
+                            self.moveto_z = self.origin_z + 64;
+                            walker_move_to(self.moveto, 0);
+                        }
+
+                        if(self.idletime < time)
+                        {
+                            if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
+                            {
+                                self.idletime = time + 1 + random() * 5;
+                                self.moveto = self.origin;
+                                self.animflag = ANIM_NO;
+                            }
+                            else
+                            {
+                                self.animflag = ANIM_WALK;
+                                self.idletime = time + 4 + random() * 2;
+                                self.moveto = self.origin + randomvec() * 256;
+                                self.tur_head.moveto = self.moveto;
+                                self.tur_head.idletime = 0;
+                            }
+                        }
+                    }
+                }
+            }
+            else
+            {
+                if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
+                {
+                    vector wish_angle;
+
+                    wish_angle = angleofs(self, self.enemy);
+                    if (self.animflag != ANIM_SWIM)
+                    if (fabs(wish_angle_y) < 15)
+                    {
+                        self.moveto   = self.enemy.origin;
+                        self.steerto  = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
+                        self.animflag = ANIM_MELEE;
+                    }
+                }
+                else if (self.tur_head.attack_finished_single < time)
+                {
+                    if(self.tur_head.shot_volly)
+                    {
+                        self.animflag = ANIM_NO;
+
+                        self.tur_head.shot_volly = self.tur_head.shot_volly -1;
+                        if(self.tur_head.shot_volly == 0)
+                            self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
+                        else
+                            self.tur_head.attack_finished_single = time + 0.2;
+
+                        if(self.tur_head.shot_volly > 1)
+                            walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
+                        else
+                            walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
+                    }
+                    else
+                    {
+                        if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
+                        if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
+                            self.tur_head.shot_volly = 4;
+                    }
+                }
+                else
+                {
+                    if (self.animflag != ANIM_MELEE)
+                        walker_move_to(self.enemy.origin, self.tur_dist_enemy);
+                }
+            }
+
+            {
+                vector real_angle;
+                float turny = 0, turnx = 0;
+                float vz;
+
+                real_angle = vectoangles(self.steerto) - self.angles;
+                vz = self.velocity_z;
+
+                switch (self.animflag)
+                {
+                    case ANIM_NO:
+                        movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+                        break;
+
+                    case ANIM_TURN:
+                        turny = (autocvar_g_turrets_unit_walker_turn);
+                        movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+                        break;
+
+                    case ANIM_WALK:
+                        turny = (autocvar_g_turrets_unit_walker_turn_walk);
+                        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
+                        break;
+
+                    case ANIM_RUN:
+                        turny = (autocvar_g_turrets_unit_walker_turn_run);
+                        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
+                        break;
+
+                    case ANIM_STRAFE_L:
+                        turny = (autocvar_g_turrets_unit_walker_turn_strafe);
+                        movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+                        break;
+
+                    case ANIM_STRAFE_R:
+                        turny = (autocvar_g_turrets_unit_walker_turn_strafe);
+                        movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
+                        break;
+
+                    case ANIM_JUMP:
+                        self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
+                        break;
+
+                    case ANIM_LAND:
+                        break;
+
+                    case ANIM_PAIN:
+                        if(self.frame != ANIM_PAIN)
+                            defer(0.25, walker_setnoanim);
+
+                        break;
+
+                    case ANIM_MELEE:
+                        if(self.frame != ANIM_MELEE)
+                        {
+                            defer(0.41, walker_setnoanim);
+                            defer(0.21, walker_melee_do_dmg);
+                        }
+
+                        movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
+                        break;
+
+                    case ANIM_SWIM:
+                        turny = (autocvar_g_turrets_unit_walker_turn_swim);
+                        turnx = (autocvar_g_turrets_unit_walker_turn_swim);
+
+                        self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
+                        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
+                        vz = self.velocity_z + sin(time * 4) * 8;
+                        break;
+
+                    case ANIM_ROAM:
+                        turny = (autocvar_g_turrets_unit_walker_turn_walk);
+                        movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
+                        break;
+                }
+
+                if(turny)
+                {
+                    turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
+                    self.angles_y += turny;
+                }
+
+                if(turnx)
+                {
+                    turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
+                    self.angles_x += turnx;
+                }
+
+                self.velocity_z = vz;
+            }
+
+
+            if(self.origin != self.oldorigin)
+                self.SendFlags |= TNSF_MOVE;
+
+            self.oldorigin = self.origin;
+            turrets_setframe(self.animflag, false);
+        }
+        METHOD(WalkerTurret, tr_death, void(WalkerTurret this, entity it))
+        {
+#ifdef WALKER_FANCYPATHING
+            if (it.pathcurrent)
+                pathlib_deletepath(it.pathcurrent.owner);
+#endif
+            it.pathcurrent = NULL;
+        }
+        METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
+        {
+            it.ticrate = 0.05;
+
+            entity e;
+
+            // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
+            if(it.movetype == MOVETYPE_WALK)
+            {
+                if(it.pos1)
+                    setorigin(it, it.pos1);
+                if(it.pos2)
+                    it.angles = it.pos2;
+            }
+
+            it.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
+            it.aim_flags = TFL_AIM_LEAD;
+            it.turret_flags |= TUR_FLAG_HITSCAN;
+
+            it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+            it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+            it.iscreature = true;
+            it.teleportable = TELEPORT_NORMAL;
+            it.damagedbycontents = true;
+            it.solid = SOLID_SLIDEBOX;
+            it.takedamage = DAMAGE_AIM;
+            if(it.movetype != MOVETYPE_WALK)
+            {
+                setorigin(it, it.origin);
+                tracebox(it.origin + '0 0 128', it.mins, it.maxs, it.origin - '0 0 10000', MOVE_NORMAL, it);
+                setorigin(it, trace_endpos + '0 0 4');
+                it.pos1 = it.origin;
+                it.pos2 = it.angles;
+            }
+            it.movetype = MOVETYPE_WALK;
+            it.idle_aim = '0 0 0';
+            it.turret_firecheckfunc = walker_firecheck;
+
+            if (it.target != "")
+            {
+                e = find(world, targetname, it.target);
+                if (!e)
+                {
+                    LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n");
+                    it.target = "";
+                }
+
+                if (e.classname != "turret_checkpoint")
+                    LOG_TRACE("Warning: not a turrret path\n");
+                else
+                {
+#ifdef WALKER_FANCYPATHING
+                    it.pathcurrent = WALKER_PATH(it.origin, e.origin);
+                    it.pathgoal = e;
+#else
+                    it.pathcurrent = e;
+#endif
+                }
+            }
+        }
+
+#endif // SVQC
+#ifdef CSQC
+
+#include "../../../client/movelib.qh"
+
+void walker_draw(entity this)
+{
+    float dt;
+
+    dt = time - self.move_time;
+    self.move_time = time;
+    if(dt <= 0)
+        return;
+
+    fixedmakevectors(self.angles);
+    movelib_groundalign4point(300, 100, 0.25, 45);
+    setorigin(self, self.origin + self.velocity * dt);
+    self.tur_head.angles += dt * self.tur_head.move_avelocity;
+    self.angles_y = self.move_angles_y;
+
+    if (self.health < 127)
+    if(random() < 0.15)
+        te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
+}
+
+        METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
+        {
+            it.gravity         = 1;
+            it.movetype                = MOVETYPE_BOUNCE;
+            it.move_movetype   = MOVETYPE_BOUNCE;
+            it.move_origin     = it.origin;
+            it.move_time               = time;
+            it.draw                    = walker_draw;
+        }
+
+#endif // CSQC
+#endif
diff --git a/qcsrc/common/turrets/turret/walker_weapon.qc b/qcsrc/common/turrets/turret/walker_weapon.qc
new file mode 100644 (file)
index 0000000..9a54f81
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef TURRET_WALKER_WEAPON_H
+#define TURRET_WALKER_WEAPON_H
+
+CLASS(WalkerTurretAttack, PortoLaunch)
+/* flags     */ ATTRIB(WalkerTurretAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(WalkerTurretAttack, impulse, int, 5);
+/* refname   */ ATTRIB(WalkerTurretAttack, netname, string, "turret_walker");
+/* wepname   */ ATTRIB(WalkerTurretAttack, message, string, _("Walker"));
+ENDCLASS(WalkerTurretAttack)
+REGISTER_WEAPON(WALKER, NEW(WalkerTurretAttack));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+METHOD(WalkerTurretAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+    bool isPlayer = IS_PLAYER(actor);
+    if (fire1)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire))) {
+        if (isPlayer) {
+            turret_initparams(actor);
+            W_SetupShot_Dir(actor, v_forward, false, 0, W_Sound("electro_fire"), CH_WEAPON_B, 0);
+            actor.tur_shotdir_updated = w_shotdir;
+            actor.tur_shotorg = w_shotorg;
+            actor.tur_head = actor;
+            weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+        }
+        sound (actor, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
+        fireBullet (actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_WALK_GUN, 0);
+        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
+    }
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/turrets/turrets.qc b/qcsrc/common/turrets/turrets.qc
deleted file mode 100644 (file)
index 46ecf5b..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#include "all.qh"
-
-// TURRET PLUGIN SYSTEM
-entity turret_info[TUR_MAXCOUNT];
-entity dummy_turret_info;
-
-void turrets_common_precache()
-{
-       precache_sound (W_Sound("rocket_impact"));
-       precache_model ("models/turrets/base-gib1.md3");
-       precache_model ("models/turrets/base-gib2.md3");
-       precache_model ("models/turrets/base-gib3.md3");
-       precache_model ("models/turrets/base-gib4.md3");
-       precache_model ("models/turrets/head-gib1.md3");
-       precache_model ("models/turrets/head-gib2.md3");
-       precache_model ("models/turrets/head-gib3.md3");
-       precache_model ("models/turrets/head-gib4.md3");
-       precache_model ("models/turrets/base.md3");
-       precache_model ("models/turrets/rocket.md3");
-
-       precache_model ("models/turrets/c512.md3");
-       precache_model ("models/marker.md3");
-
-#ifdef SVQC
-       precache_sound(W_Sound("rocket_impact"));
-#endif
-
-#ifdef TURRET_DEBUG
-       precache_model ("models/turrets/c512.md3");
-       precache_model ("models/pathlib/goodsquare.md3");
-       precache_model ("models/pathlib/badsquare.md3");
-       precache_model ("models/pathlib/square.md3");
-       precache_model ("models/pathlib/edge.md3");
-#endif
-}
-
-void register_turret(float id, float(float) func, float turretflags, vector min_s, vector max_s, string modelname, string headmodelname, string shortname, string mname)
-{
-       entity e;
-       turret_info[id - 1] = e = spawn();
-       e.classname = "turret_info";
-       e.turretid = id;
-       e.netname = shortname;
-       e.turret_name = mname;
-       e.turret_func = func;
-       e.mdl = modelname;
-       e.cvar_basename = shortname;
-       e.spawnflags = turretflags;
-       e.mins = min_s;
-       e.maxs = max_s;
-       e.model = strzone(strcat("models/turrets/", modelname));
-       e.head_model = strzone(strcat("models/turrets/", headmodelname));
-
-       #ifndef MENUQC
-       turrets_common_precache();
-       #endif
-}
-float t_null(float dummy) { return 0; }
-void register_turrets_done()
-{
-       dummy_turret_info = spawn();
-       dummy_turret_info.classname = "turret_info";
-       dummy_turret_info.turretid = 0; // you can recognize dummies by this
-       dummy_turret_info.netname = "";
-       dummy_turret_info.turret_name = "Turret";
-       dummy_turret_info.turret_func = t_null;
-       dummy_turret_info.mdl = "";
-       dummy_turret_info.mins = '-0 -0 -0';
-       dummy_turret_info.maxs = '0 0 0';
-       dummy_turret_info.model = "";
-}
-entity get_turretinfo(float id)
-{
-       entity m;
-       if(id < TUR_FIRST || id > TUR_LAST)
-               return dummy_turret_info;
-       m = turret_info[id - 1];
-       if(m)
-               return m;
-       return dummy_turret_info;
-}
diff --git a/qcsrc/common/turrets/turrets.qh b/qcsrc/common/turrets/turrets.qh
deleted file mode 100644 (file)
index b3736af..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-#ifndef TURRETS_H
-#define TURRETS_H
-
-// turret requests
-#define TR_SETUP          1 // (BOTH) setup turret data
-#define TR_THINK                 2 // (SERVER) logic to run every frame
-#define TR_DEATH          3 // (SERVER) called when turret dies
-#define TR_PRECACHE       4 // (BOTH) precaches models/sounds used by this turret
-#define TR_ATTACK         5 // (SERVER) called when turret attacks
-#define TR_CONFIG         6 // (ALL)
-
-// functions:
-entity get_turretinfo(int id);
-
-// fields:
-.entity tur_head;
-
-// target selection flags
-.int target_select_flags;
-.int target_validate_flags;
-const int TFL_TARGETSELECT_NO = 2; // don't automatically find targets
-const int TFL_TARGETSELECT_LOS = 4; // require line of sight to find targets
-const int TFL_TARGETSELECT_PLAYERS = 8; // target players
-const int TFL_TARGETSELECT_MISSILES = 16; // target projectiles
-const int TFL_TARGETSELECT_TRIGGERTARGET = 32; // respond to turret_trigger_target events
-const int TFL_TARGETSELECT_ANGLELIMITS = 64; // apply extra angular limits to target selection
-const int TFL_TARGETSELECT_RANGELIMITS = 128; // limit target selection range
-const int TFL_TARGETSELECT_TEAMCHECK = 256; // don't attack teammates
-const int TFL_TARGETSELECT_NOBUILTIN = 512; // only attack targets when triggered
-const int TFL_TARGETSELECT_OWNTEAM = 1024; // only attack teammates
-const int TFL_TARGETSELECT_NOTURRETS = 2048; // don't attack other turrets
-const int TFL_TARGETSELECT_FOV = 4096; // extra limits to attack range
-const int TFL_TARGETSELECT_MISSILESONLY = 8192; // only attack missiles
-
-// aim flags
-.int aim_flags;
-const int TFL_AIM_NO = 1; // no aiming
-const int TFL_AIM_SPLASH = 2; // aim for ground around the target's feet
-const int TFL_AIM_LEAD = 4; // try to predict target movement
-const int TFL_AIM_SHOTTIMECOMPENSATE = 8; // compensate for shot traveltime when leading
-const int TFL_AIM_ZPREDICT = 16; // predict target's z position at impact
-const int TFL_AIM_SIMPLE = 32; // aim at player's current location
-
-// tracking flags
-.int track_flags;
-const int TFL_TRACK_NO = 2; // don't move head
-const int TFL_TRACK_PITCH = 4; // pitch head
-const int TFL_TRACK_ROTATE = 8; // rotate head
-
-// prefire checks
-.int firecheck_flags;
-const int TFL_FIRECHECK_DEAD = 4; // don't attack dead targets (zombies?)
-const int TFL_FIRECHECK_DISTANCES = 8; // another range check
-const int TFL_FIRECHECK_LOS = 16; // line of sight
-const int TFL_FIRECHECK_AIMDIST = 32; // consider distance impactpoint<->aimspot
-const int TFL_FIRECHECK_REALDIST = 64; // consider enemy origin<->impactpoint
-const int TFL_FIRECHECK_ANGLEDIST = 128; // consider angular diff head<->aimspot
-const int TFL_FIRECHECK_TEAMCHECK = 256; // don't attack teammates
-const int TFL_FIRECHECK_AFF = 512; // try to avoid any friendly fire
-const int TFL_FIRECHECK_AMMO_OWN = 1024; // own ammo needs to be larger than damage dealt
-const int TFL_FIRECHECK_AMMO_OTHER = 2048; // target's ammo needs to be less than max
-const int TFL_FIRECHECK_REFIRE = 4096; // check single attack finished delays
-const int TFL_FIRECHECK_NO = 16384; // no prefire checks
-
-// attack flags
-.int shoot_flags;
-const int TFL_SHOOT_NO = 64; // no attacking
-const int TFL_SHOOT_VOLLY = 2; // fire in vollies
-const int TFL_SHOOT_VOLLYALWAYS = 4; // always do a full volly, even if target is lost
-const int TFL_SHOOT_HITALLVALID = 8; // loop through all valid targets
-const int TFL_SHOOT_CLEARTARGET = 16; // lose target after attack (after volly is done if in volly mode)
-const int TFL_SHOOT_CUSTOM = 32; // custom attacking
-
-// turret capabilities
-.int turret_flags;
-const int TUR_FLAG_NONE = 0; // no abilities
-const int TUR_FLAG_SNIPER = 2; // sniping turret
-const int TUR_FLAG_SPLASH = 4; // can deal splash damage
-const int TUR_FLAG_HITSCAN = 8; // hit scan
-const int TUR_FLAG_MULTIGUN = 16; // multiple guns
-const int TUR_FLAG_GUIDED = 32; // laser guided projectiles
-const int TUR_FLAG_SLOWPROJ = 64; // turret fires slow projectiles
-const int TUR_FLAG_MEDPROJ = 128; // turret fires medium projectiles
-const int TUR_FLAG_FASTPROJ = 256; // turret fires fast projectiles
-const int TUR_FLAG_PLAYER = 512; // can damage players
-const int TUR_FLAG_MISSILE = 1024; // can damage missiles
-const int TUR_FLAG_SUPPORT = 2048; // supports other units
-const int TUR_FLAG_AMMOSOURCE = 4096; // can provide ammunition
-const int TUR_FLAG_RECIEVETARGETS = 8192; // can recieve targets from external sources
-const int TUR_FLAG_MOVE = 16384; // can move
-const int TUR_FLAG_ROAM = 32768; // roams around if not attacking
-const int TUR_FLAG_ISTURRET = 65536; // identifies this unit as a turret
-
-// ammo types
-#define ammo_flags currentammo
-const int TFL_AMMO_NONE = 64; // doesn't use ammo
-const int TFL_AMMO_ENERGY = 2; // uses power
-const int TFL_AMMO_BULLETS = 4; // uses bullets
-const int TFL_AMMO_ROCKETS = 8; // uses explosives
-const int TFL_AMMO_RECHARGE = 16; // regenerates ammo
-const int TFL_AMMO_RECIEVE = 32; // can recieve ammo from support units
-
-// damage flags
-.int damage_flags;
-const int TFL_DMG_NO = 256; // doesn't take damage
-const int TFL_DMG_YES = 2; // can be damaged
-const int TFL_DMG_TEAM = 4; // can be damaged by teammates
-const int TFL_DMG_RETALIATE = 8; // target attackers
-const int TFL_DMG_RETALIATE_TEAM = 16; // target attackers, even if on same team
-const int TFL_DMG_TARGETLOSS = 32; // loses target when damaged
-const int TFL_DMG_AIMSHAKE = 64; // damage throws off aim
-const int TFL_DMG_HEADSHAKE = 128; // damage shakes head
-const int TFL_DMG_DEATH_NORESPAWN = 256; // no re-spawning
-
-// spawn flags
-const int TSF_SUSPENDED = 1;
-const int TSF_TERRAINBASE = 2; // currently unused
-const int TSF_NO_AMMO_REGEN = 4; // disable builtin ammo regeneration
-const int TSF_NO_PATHBREAK = 8; // don't break path to chase enemies, will still fire at them if possible
-const int TSL_NO_RESPAWN = 16; // don't re-spawn
-const int TSL_ROAM = 32; // roam while idle
-
-// send flags
-const int TNSF_UPDATE       = 2;
-const int TNSF_STATUS       = 4;
-const int TNSF_SETUP        = 8;
-const int TNSF_ANG          = 16;
-const int TNSF_AVEL         = 32;
-const int TNSF_MOVE         = 64;
-.float anim_start_time;
-const int TNSF_ANIM         = 128;
-
-const int TNSF_FULL_UPDATE  = 16777215;
-
-
-// entity properties of turretinfo:
-.int turretid; // TUR_...
-.string netname; // short name
-.string turret_name; // human readable name
-.float(float) turret_func; // m_...
-.string mdl; // currently a copy of the model
-.string model; // full name of model
-.string head_model; // full name of tur_head model
-.string cvar_basename; // TODO: deprecate!
-.float spawnflags;
-.vector mins, maxs; // turret hitbox size
-
-// other useful macros
-#define TUR_ACTION(turrettype,mrequest) (get_turretinfo(turrettype)).turret_func(mrequest)
-#define TUR_NAME(turrettype) (get_turretinfo(turrettype)).turret_name
-
-// =====================
-//  Turret Registration
-// =====================
-
-float t_null(float dummy);
-void register_turret(float id, float(float) func, float turretflags, vector min_s, vector max_s, string modelname, string headmodelname, string shortname, string mname);
-void register_turrets_done();
-
-const float TUR_MAXCOUNT = 24;
-#define TUR_FIRST 1
-float TUR_COUNT;
-float TUR_LAST;
-
-#define REGISTER_TURRET_2(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname) \
-       float id; \
-       float func(float); \
-       void RegisterTurrets_##id() \
-       { \
-               TUR_LAST = (id = TUR_FIRST + TUR_COUNT); \
-               ++TUR_COUNT; \
-               register_turret(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname); \
-       } \
-       ACCUMULATE_FUNCTION(RegisterTurrets, RegisterTurrets_##id)
-#ifdef MENUQC
-#define REGISTER_TURRET(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname) \
-       REGISTER_TURRET_2(TUR_##id,t_null,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname)
-#else
-#define REGISTER_TURRET(id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname) \
-       REGISTER_TURRET_2(TUR_##id,func,turretflags,min_s,max_s,modelname,headmodelname,shortname,mname)
-#endif
-
-#define TUR_DUPECHECK(dupecheck,cvar) \
-       #ifndef dupecheck \
-               #define dupecheck \
-               float cvar; \
-       #else \
-               #error DUPLICATE TURRET CVAR: cvar \
-       #endif
-
-#define TUR_ADD_CVAR(turret,name) \
-               TUR_DUPECHECK(TUR_CVAR_##turret##_##name, autocvar_g_turrets_unit_##turret##_##name)
-
-#define TUR_CVAR(turret,name) autocvar_g_turrets_unit_##turret##_##name
-
-#include "all.qh"
-
-#undef TUR_ADD_CVAR
-#undef REGISTER_TURRET
-ACCUMULATE_FUNCTION(RegisterTurrets, register_turrets_done);
-
-#endif
diff --git a/qcsrc/common/turrets/unit/ewheel.qc b/qcsrc/common/turrets/unit/ewheel.qc
deleted file mode 100644 (file)
index 1a09611..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ EWHEEL,
-/* function   */ t_ewheel,
-/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM,
-/* mins,maxs  */ '-32 -32 0', '32 32 48',
-/* model      */ "ewheel-base2.md3",
-/* head_model */ "ewheel-gun1.md3",
-/* netname    */ "ewheel",
-/* fullname   */ _("eWheel Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_ewheel_speed_fast;
-float autocvar_g_turrets_unit_ewheel_speed_slow;
-float autocvar_g_turrets_unit_ewheel_speed_slower;
-float autocvar_g_turrets_unit_ewheel_speed_stop;
-float autocvar_g_turrets_unit_ewheel_turnrate;
-
-const float ewheel_anim_stop = 0;
-const float ewheel_anim_fwd_slow = 1;
-const float ewheel_anim_fwd_fast = 2;
-const float ewheel_anim_bck_slow = 3;
-const float ewheel_anim_bck_fast = 4;
-
-//#define EWHEEL_FANCYPATH
-void ewheel_move_path()
-{
-#ifdef EWHEEL_FANCYPATH
-    // Are we close enougth to a path node to switch to the next?
-    if (vlen(self.origin  - self.pathcurrent.origin) < 64)
-        if (self.pathcurrent.path_next == world)
-        {
-            // Path endpoint reached
-            pathlib_deletepath(self.pathcurrent.owner);
-            self.pathcurrent = world;
-
-            if (self.pathgoal)
-            {
-                if (self.pathgoal.use)
-                    self.pathgoal.use();
-
-                if (self.pathgoal.enemy)
-                {
-                    self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
-                    self.pathgoal = self.pathgoal.enemy;
-                }
-            }
-            else
-                self.pathgoal = world;
-        }
-        else
-            self.pathcurrent = self.pathcurrent.path_next;
-
-#else
-    if (vlen(self.origin - self.pathcurrent.origin) < 64)
-        self.pathcurrent = self.pathcurrent.enemy;
-#endif
-
-    if (self.pathcurrent)
-    {
-
-        self.moveto = self.pathcurrent.origin;
-        self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-
-        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
-    }
-}
-
-void ewheel_move_enemy()
-{
-    float newframe;
-
-    self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
-
-    self.moveto  = self.origin + self.steerto * 128;
-
-    if (self.tur_dist_enemy > self.target_range_optimal)
-    {
-        if ( self.tur_head.spawnshieldtime < 1 )
-        {
-            newframe = ewheel_anim_fwd_fast;
-            movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
-        }
-        else if (self.tur_head.spawnshieldtime < 2)
-        {
-
-            newframe = ewheel_anim_fwd_slow;
-            movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
-       }
-        else
-        {
-            newframe = ewheel_anim_fwd_slow;
-            movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
-        }
-    }
-    else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
-    {
-        newframe = ewheel_anim_bck_slow;
-        movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
-    }
-    else
-    {
-        newframe = ewheel_anim_stop;
-        movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
-    }
-
-    turrets_setframe(newframe, false);
-}
-
-void ewheel_move_idle()
-{
-    if(self.frame != 0)
-    {
-        self.SendFlags |= TNSF_ANIM;
-        self.anim_start_time = time;
-    }
-
-    self.frame = 0;
-    if (vlen(self.velocity))
-        movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
-}
-
-void spawnfunc_turret_ewheel() { if(!turret_initialize(TUR_EWHEEL)) remove(self); }
-
-float t_ewheel(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            float i;
-            entity _mis;
-
-            for (i = 0; i < 1; ++i)
-            {
-                turret_do_updates(self);
-
-                _mis = turret_projectile(W_Sound("lasergun_fire"), 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, TRUE, TRUE);
-                _mis.missile_flags = MIF_SPLASH;
-
-                Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
-                self.tur_head.frame += 2;
-
-                if (self.tur_head.frame > 3)
-                    self.tur_head.frame = 0;
-            }
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            float vz;
-            vector wish_angle, real_angle;
-
-            vz = self.velocity_z;
-
-            self.angles_x = anglemods(self.angles_x);
-            self.angles_y = anglemods(self.angles_y);
-
-            fixedmakevectors(self.angles);
-
-            wish_angle = normalize(self.steerto);
-            wish_angle = vectoangles(wish_angle);
-            real_angle = wish_angle - self.angles;
-            real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
-
-            self.tur_head.spawnshieldtime = fabs(real_angle_y);
-            real_angle_y  = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
-            self.angles_y = (self.angles_y + real_angle_y);
-
-            if(self.enemy)
-                ewheel_move_enemy();
-            else if(self.pathcurrent)
-                ewheel_move_path();
-            else
-                ewheel_move_idle();
-
-            self.velocity_z = vz;
-
-            if(vlen(self.velocity))
-                self.SendFlags |= TNSF_MOVE;
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-            self.velocity = '0 0 0';
-
-#ifdef EWHEEL_FANCYPATH
-            if (self.pathcurrent)
-                pathlib_deletepath(self.pathcurrent.owner);
-#endif
-            self.pathcurrent = world;
-
-            return true;
-        }
-        case TR_SETUP:
-        {
-            entity e;
-
-            if(self.movetype == MOVETYPE_WALK)
-            {
-                self.velocity = '0 0 0';
-                self.enemy = world;
-
-                setorigin(self, self.pos1);
-
-                if (self.target != "")
-                {
-                    e = find(world, targetname, self.target);
-                    if (!e)
-                    {
-                        LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
-                        self.target = "";
-                    }
-
-                    if (e.classname != "turret_checkpoint")
-                        LOG_TRACE("Warning: not a turrret path\n");
-                    else
-                    {
-
-#ifdef EWHEEL_FANCYPATH
-                        self.pathcurrent = WALKER_PATH(self.origin,e.origin);
-                        self.pathgoal = e;
-#else
-                        self.pathcurrent  = e;
-#endif
-                    }
-                }
-            }
-
-            self.iscreature                            = true;
-            self.teleportable                  = TELEPORT_NORMAL;
-            self.damagedbycontents             = true;
-            self.movetype                              = MOVETYPE_WALK;
-            self.solid                                 = SOLID_SLIDEBOX;
-            self.takedamage                            = DAMAGE_AIM;
-            self.idle_aim                              = '0 0 0';
-            self.pos1                                  = self.origin;
-            self.target_select_flags   = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
-            self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
-            self.frame                                 = self.tur_head.frame = 1;
-            self.ammo_flags                            = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
-
-            // Convert from dgr / sec to dgr / tic
-            self.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
-            self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/ewheel-base2.md3");
-            precache_model ("models/turrets/ewheel-gun1.md3");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-void ewheel_draw()
-{
-    float dt;
-
-    dt = time - self.move_time;
-    self.move_time = time;
-    if(dt <= 0)
-        return;
-
-    fixedmakevectors(self.angles);
-    setorigin(self, self.origin + self.velocity * dt);
-    self.tur_head.angles += dt * self.tur_head.move_avelocity;
-    self.angles_y = self.move_angles_y;
-
-    if (self.health < 127)
-    if(random() < 0.05)
-        te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
-}
-
-float t_ewheel(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            self.gravity               = 1;
-            self.movetype              = MOVETYPE_BOUNCE;
-            self.move_movetype = MOVETYPE_BOUNCE;
-            self.move_origin   = self.origin;
-            self.move_time             = time;
-            self.draw                  = ewheel_draw;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/flac.qc b/qcsrc/common/turrets/unit/flac.qc
deleted file mode 100644 (file)
index 3b834e4..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ FLAC,
-/* function   */ t_flac,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE,
-/* mins,maxs  */ '-32 -32 0', '32 32 64',
-/* model         */ "base.md3",
-/* head_model */ "flac.md3",
-/* netname       */ "flac",
-/* fullname   */ _("FLAC Cannon")
-);
-#else
-#ifdef SVQC
-void turret_flac_projectile_think_explode()
-{
-    if(self.enemy != world)
-    if(vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 3)
-        setorigin(self,self.enemy.origin + randomvec() * self.owner.shot_radius);
-
-#ifdef TURRET_DEBUG
-    float d;
-    d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
-    self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
-    self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
-#else
-    RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
-#endif
-    remove(self);
-}
-
-void spawnfunc_turret_flac() { if(!turret_initialize(TUR_FLAC)) remove(self); }
-
-float t_flac(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            entity proj;
-
-            turret_tag_fire_update();
-
-            proj = turret_projectile(W_Sound("hagar_fire"), 5, 0, DEATH_TURRET_FLAC, PROJECTILE_HAGAR, TRUE, TRUE);
-            Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-            proj.think   = turret_flac_projectile_think_explode;
-            proj.nextthink  = time + self.tur_impacttime + (random() * 0.01 - random() * 0.01);
-            proj.missile_flags = MIF_SPLASH | MIF_PROXY;
-
-            self.tur_head.frame = self.tur_head.frame + 1;
-            if (self.tur_head.frame >= 4)
-                self.tur_head.frame = 0;
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
-            self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-            self.damage_flags |= TFL_DMG_HEADSHAKE;
-            self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/base.md3");
-            precache_model ("models/turrets/flac.md3");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_flac(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/fusionreactor.qc b/qcsrc/common/turrets/unit/fusionreactor.qc
deleted file mode 100644 (file)
index ca4c3e2..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ FUSIONREACTOR,
-/* function   */ t_fusionreactor,
-/* spawnflags */ TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE,
-/* mins,maxs  */ '-34 -34 0', '34 34 90',
-/* model         */ "base.md3",
-/* head_model */ "reactor.md3",
-/* netname       */ "fusionreactor",
-/* fullname   */ _("Fusion Reactor")
-);
-#else
-#ifdef SVQC
-bool turret_fusionreactor_firecheck()
-{
-    if (self.attack_finished_single > time)
-        return false;
-
-    if (self.enemy.deadflag != DEAD_NO)
-        return false;
-
-    if (self.enemy == world)
-        return false;
-
-    if (self.ammo < self.shot_dmg)
-        return false;
-
-    if (self.enemy.ammo >= self.enemy.ammo_max)
-        return false;
-
-    if (vlen(self.enemy.origin - self.origin) > self.target_range)
-        return false;
-
-    if(self.team != self.enemy.team)
-        return false;
-
-    if(!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
-        return false;
-
-    return true;
-}
-
-void spawnfunc_turret_fusionreactor() { if(!turret_initialize(TUR_FUSIONREACTOR)) remove(self); }
-
-float t_fusionreactor(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            vector fl_org;
-
-            self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
-            fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
-            te_smallflash(fl_org);
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.ammo_flags                            = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
-            self.target_select_flags   = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS;
-            self.firecheck_flags               = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
-            self.shoot_flags                   = TFL_SHOOT_HITALLVALID;
-            self.aim_flags                             = TFL_AIM_NO;
-            self.track_flags                   = TFL_TRACK_NO;
-
-            self.tur_head.scale = 0.75;
-            self.tur_head.avelocity = '0 50 0';
-
-            self.turret_firecheckfunc = turret_fusionreactor_firecheck;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/base.md3");
-            precache_model ("models/turrets/reactor.md3");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_fusionreactor(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/hellion.qc b/qcsrc/common/turrets/unit/hellion.qc
deleted file mode 100644 (file)
index 882f852..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ HELLION,
-/* function   */ t_hellion,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
-/* mins,maxs  */ '-32 -32 0', '32 32 64',
-/* model         */ "base.md3",
-/* head_model */ "hellion.md3",
-/* netname       */ "hellion",
-/* fullname   */ _("Hellion Missile Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_hellion_shot_speed_gain;
-float autocvar_g_turrets_unit_hellion_shot_speed_max;
-
-void turret_hellion_missile_think()
-{
-    vector olddir,newdir;
-    vector pre_pos;
-    float itime;
-
-    self.nextthink = time + 0.05;
-
-    olddir = normalize(self.velocity);
-
-    if(self.max_health < time)
-        turret_projectile_explode();
-
-    // Enemy dead? just keep on the current heading then.
-    if ((self.enemy == world) || (self.enemy.deadflag != DEAD_NO))
-    {
-
-        // Make sure we dont return to tracking a respawned player
-        self.enemy = world;
-
-        // Turn model
-        self.angles = vectoangles(self.velocity);
-
-        if ( (vlen(self.origin - self.owner.origin)) > (self.owner.shot_radius * 5) )
-            turret_projectile_explode();
-
-        // Accelerate
-        self.velocity = olddir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
-
-        UpdateCSQCProjectile(self);
-
-        return;
-    }
-
-    // Enemy in range?
-    if (vlen(self.origin - self.enemy.origin) < self.owner.shot_radius * 0.2)
-        turret_projectile_explode();
-
-    // Predict enemy position
-    itime = vlen(self.enemy.origin - self.origin) / vlen(self.velocity);
-    pre_pos = self.enemy.origin + self.enemy.velocity * itime;
-
-    pre_pos = (pre_pos + self.enemy.origin) * 0.5;
-
-    // Find out the direction to that place
-    newdir = normalize(pre_pos - self.origin);
-
-    // Turn
-    newdir = normalize(olddir + newdir * 0.35);
-
-    // Turn model
-    self.angles = vectoangles(self.velocity);
-
-    // Accelerate
-    self.velocity = newdir * min(vlen(self.velocity) * (autocvar_g_turrets_unit_hellion_shot_speed_gain), (autocvar_g_turrets_unit_hellion_shot_speed_max));
-
-    if (itime < 0.05)
-        self.think = turret_projectile_explode;
-
-    UpdateCSQCProjectile(self);
-}
-
-void spawnfunc_turret_hellion() { if(!turret_initialize(TUR_HELLION)) remove(self); }
-
-float t_hellion(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            entity missile;
-
-            if(self.tur_head.frame != 0)
-                self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
-            else
-                self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire2"));
-
-            missile = turret_projectile(W_Sound("rocket_fire"), 6, 10, DEATH_TURRET_HELLION, PROJECTILE_ROCKET, FALSE, FALSE);
-            te_explosion (missile.origin);
-            missile.think              = 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;
-            self.tur_head.frame += 1;
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            if (self.tur_head.frame != 0)
-                self.tur_head.frame += 1;
-
-            if (self.tur_head.frame >= 7)
-                self.tur_head.frame = 0;
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.aim_flags = TFL_AIM_SIMPLE;
-            self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ;
-            self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN;
-            self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/base.md3");
-            precache_model ("models/turrets/hellion.md3");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_hellion(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/hk.qc b/qcsrc/common/turrets/unit/hk.qc
deleted file mode 100644 (file)
index fec2a69..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ HK,
-/* function   */ t_hk,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS,
-/* mins,maxs  */ '-32 -32 0', '32 32 64',
-/* model         */ "base.md3",
-/* head_model */ "hk.md3",
-/* netname       */ "hk",
-/* fullname   */ _("Hunter-Killer Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_hk_shot_speed;
-float autocvar_g_turrets_unit_hk_shot_speed_accel;
-float autocvar_g_turrets_unit_hk_shot_speed_accel2;
-float autocvar_g_turrets_unit_hk_shot_speed_decel;
-float autocvar_g_turrets_unit_hk_shot_speed_max;
-float autocvar_g_turrets_unit_hk_shot_speed_turnrate;
-
-//#define TURRET_DEBUG_HK
-
-#ifdef TURRET_DEBUG_HK
-.float atime;
-#endif
-
-float hk_is_valid_target(entity e_target)
-{
-    if (e_target == world)
-        return 0;
-
-    // If only this was used more..
-    if (e_target.flags & FL_NOTARGET)
-        return 0;
-
-    // Cant touch this
-    if ((e_target.takedamage == DAMAGE_NO) || (e_target.health < 0))
-        return 0;
-
-    // player
-    if (IS_CLIENT(e_target))
-    {
-        if (self.owner.target_select_playerbias < 0)
-            return 0;
-
-        if (e_target.deadflag != DEAD_NO)
-            return 0;
-    }
-
-    // Missile
-    if ((e_target.flags & FL_PROJECTILE) && (self.owner.target_select_missilebias < 0))
-        return 0;
-
-    // Team check
-    if ((e_target.team == self.owner.team) || (self.owner.team == e_target.owner.team))
-        return 0;
-
-    return 1;
-}
-
-void turret_hk_missile_think()
-{
-    vector vu, vd, vf, vl, vr, ve;  // Vector (direction)
-    float  fu, fd, ff, fl, fr, fe;  // Fraction to solid
-    vector olddir,wishdir,newdir;   // Final direction
-    float lt_for;   // Length of Trace FORwrad
-    float lt_seek;  // Length of Trace SEEK (left, right, up down)
-    float pt_seek;  // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
-    vector pre_pos;
-    float myspeed;
-    entity e;
-    float ad,edist;
-
-    self.nextthink = time + self.ticrate;
-
-    //if (self.cnt < time)
-    // turret_hk_missile_explode();
-
-    if (self.enemy.deadflag != DEAD_NO)
-        self.enemy = world;
-
-    // Pick the closest valid target.
-    if (!self.enemy)
-    {
-        e = findradius(self.origin, 5000);
-        while (e)
-        {
-            if (hk_is_valid_target(e))
-            {
-                if (!self.enemy)
-                    self.enemy = e;
-                else
-                    if (vlen(self.origin - e.origin) < vlen(self.origin - self.enemy.origin))
-                        self.enemy = e;
-            }
-            e = e.chain;
-        }
-    }
-
-    self.angles = vectoangles(self.velocity);
-    self.angles_x = self.angles_x * -1;
-    makevectors(self.angles);
-    self.angles_x = self.angles_x * -1;
-
-    if (self.enemy)
-    {
-        edist = vlen(self.origin - self.enemy.origin);
-        // Close enougth to do decent damage?
-        if ( edist <= (self.owner.shot_radius * 0.25) )
-        {
-            turret_projectile_explode();
-            return;
-        }
-
-        // Get data on enemy position
-        pre_pos = self.enemy.origin +
-                  self.enemy.velocity *
-                  min((vlen(self.enemy.origin - self.origin) / vlen(self.velocity)),0.5);
-
-        traceline(self.origin, pre_pos,true,self.enemy);
-        ve = normalize(pre_pos - self.origin);
-        fe = trace_fraction;
-
-    }
-    else
-    {
-    edist = 0;
-    ve = '0 0 0';
-        fe = 0;
-    }
-
-    if ((fe != 1) || (self.enemy == world) || (edist > 1000))
-    {
-        myspeed = vlen(self.velocity);
-
-        lt_for  = myspeed * 3;
-        lt_seek = myspeed * 2.95;
-
-        // Trace forward
-        traceline(self.origin, self.origin + v_forward * lt_for,false,self);
-        vf = trace_endpos;
-        ff = trace_fraction;
-
-        // Find angular offset
-        ad = vlen(vectoangles(normalize(self.enemy.origin - self.origin)) - self.angles);
-
-        // To close to something, Slow down!
-        if ( ((ff < 0.7) || (ad > 4)) && (myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) )
-            myspeed = max(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_decel), (autocvar_g_turrets_unit_hk_shot_speed));
-
-        // Failry clear, accelerate.
-        if ( (ff > 0.7) && (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max)) )
-            myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel), (autocvar_g_turrets_unit_hk_shot_speed_max));
-
-        // Setup trace pitch
-        pt_seek = 1 - ff;
-        pt_seek = bound(0.15,pt_seek,0.8);
-        if (ff < 0.5) pt_seek = 1;
-
-        // Trace left
-        traceline(self.origin, self.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,self);
-        vl = trace_endpos;
-        fl = trace_fraction;
-
-        // Trace right
-        traceline(self.origin,  self.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
-        vr = trace_endpos;
-        fr = trace_fraction;
-
-        // Trace up
-        traceline(self.origin,  self.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
-        vu = trace_endpos;
-        fu = trace_fraction;
-
-        // Trace down
-        traceline(self.origin,  self.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,self);
-        vd = trace_endpos;
-        fd = trace_fraction;
-
-        vl = normalize(vl - self.origin);
-        vr = normalize(vr - self.origin);
-        vu = normalize(vu - self.origin);
-        vd = normalize(vd - self.origin);
-
-        // Panic tresh passed, find a single direction and turn as hard as we can
-        if (pt_seek == 1)
-        {
-            wishdir = v_right;
-            if (fl > fr) wishdir = -1 * v_right;
-            if (fu > fl) wishdir = v_up;
-            if (fd > fu) wishdir = -1 * v_up;
-        }
-        else
-        {
-            // Normalize our trace vectors to make a smooth path
-            wishdir = normalize( (vl * fl) + (vr * fr) +  (vu * fu) +  (vd * fd) );
-        }
-
-        if (self.enemy)
-        {
-            if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
-            wishdir = (wishdir * (1 - fe)) + (ve * fe);
-        }
-    }
-    else
-    {
-        // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
-        myspeed = vlen(self.velocity);
-        if (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max))
-            myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
-
-        wishdir = ve;
-    }
-
-    if ((myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) && (self.cnt > time))
-        myspeed = min(myspeed * (autocvar_g_turrets_unit_hk_shot_speed_accel2),(autocvar_g_turrets_unit_hk_shot_speed_max));
-
-    // Ranoutagazfish?
-    if (self.cnt < time)
-    {
-        self.cnt = time + 0.25;
-        self.nextthink = 0;
-        self.movetype           = MOVETYPE_BOUNCE;
-        return;
-    }
-
-    // Calculate new heading
-    olddir = normalize(self.velocity);
-    newdir = normalize(olddir + wishdir * (autocvar_g_turrets_unit_hk_shot_speed_turnrate));
-
-    // Set heading & speed
-    self.velocity = newdir * myspeed;
-
-    // Align model with new heading
-    self.angles = vectoangles(self.velocity);
-
-
-#ifdef TURRET_DEBUG_HK
-    //if(self.atime < time) {
-    if ((fe <= 0.99)||(edist > 1000))
-    {
-        te_lightning2(world,self.origin, self.origin + vr * lt_seek);
-        te_lightning2(world,self.origin, self.origin + vl * lt_seek);
-        te_lightning2(world,self.origin, self.origin + vu * lt_seek);
-        te_lightning2(world,self.origin, self.origin + vd * lt_seek);
-        te_lightning2(world,self.origin, vf);
-    }
-    else
-    {
-        te_lightning2(world,self.origin, self.enemy.origin);
-    }
-    bprint("Speed: ", ftos(rint(myspeed)), "\n");
-    bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
-    bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
-    self.atime = time + 0.2;
-    //}
-#endif
-
-    UpdateCSQCProjectile(self);
-}
-
-float turret_hk_addtarget(entity e_target,entity e_sender)
-{
-    if (e_target)
-    {
-        if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
-        {
-            self.enemy = e_target;
-            return 1;
-        }
-    }
-
-    return 0;
-}
-
-void spawnfunc_turret_hk() { if(!turret_initialize(TUR_HK)) remove(self); }
-
-float t_hk(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            entity missile;
-
-            missile = turret_projectile(W_Sound("rocket_fire"), 6, 10, DEATH_TURRET_HK, PROJECTILE_ROCKET, FALSE, FALSE);
-            te_explosion (missile.origin);
-
-            missile.think                      = turret_hk_missile_think;
-            missile.nextthink          = time + 0.25;
-            missile.movetype            = MOVETYPE_BOUNCEMISSILE;
-            missile.velocity            = self.tur_shotdir_updated * (self.shot_speed * 0.75);
-            missile.angles                = vectoangles(missile.velocity);
-            missile.cnt                          = time + 30;
-            missile.ticrate              = max(autocvar_sys_ticrate, 0.05);
-            missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
-
-            if (self.tur_head.frame == 0)
-                self.tur_head.frame = self.tur_head.frame + 1;
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            if (self.tur_head.frame != 0)
-                self.tur_head.frame = self.tur_head.frame + 1;
-
-            if (self.tur_head.frame > 5)
-                self.tur_head.frame = 0;
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
-            self.aim_flags = TFL_AIM_SIMPLE;
-            self.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-            self.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK  | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
-            self.shoot_flags = TFL_SHOOT_CLEARTARGET;
-            self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
-
-            self.turret_addtarget = turret_hk_addtarget;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/base.md3");
-            precache_model ("models/turrets/hk.md3");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_hk(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/machinegun.qc b/qcsrc/common/turrets/unit/machinegun.qc
deleted file mode 100644 (file)
index 5d5d62c..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ MACHINEGUN,
-/* function   */ t_machinegun,
-/* spawnflags */ TUR_FLAG_PLAYER,
-/* mins,maxs  */ '-32 -32 0', '32 32 64',
-/* model         */ "base.md3",
-/* head_model */ "machinegun.md3",
-/* netname       */ "machinegun",
-/* fullname   */ _("Machinegun Turret")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_machinegun() { if(!turret_initialize(TUR_MACHINEGUN)) remove(self); }
-
-void W_MachineGun_MuzzleFlash(void);
-
-float t_machinegun(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0);
-
-            W_MachineGun_MuzzleFlash();
-            setattachment(self.muzzle_flash, self.tur_head, "tag_fire");
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.damage_flags |= TFL_DMG_HEADSHAKE;
-            self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-            self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
-            self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-            self.turret_flags |= TUR_FLAG_HITSCAN;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/base.md3");
-            precache_model ("models/turrets/machinegun.md3");
-            precache_sound (W_Sound("uzi_fire"));
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_machinegun(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/mlrs.qc b/qcsrc/common/turrets/unit/mlrs.qc
deleted file mode 100644 (file)
index fca6a5b..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ MLRS,
-/* function   */ t_mlrs,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
-/* mins,maxs  */ '-32 -32 0', '32 32 64',
-/* model         */ "base.md3",
-/* head_model */ "mlrs.md3",
-/* netname       */ "mlrs",
-/* fullname   */ _("MLRS Turret")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_mlrs() { if(!turret_initialize(TUR_MLRS)) remove(self); }
-
-float t_mlrs(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            entity missile;
-
-            turret_tag_fire_update();
-            missile = turret_projectile(W_Sound("rocket_fire"), 6, 10, DEATH_TURRET_MLRS, PROJECTILE_ROCKET, TRUE, TRUE);
-            missile.nextthink = time + max(self.tur_impacttime,(self.shot_radius * 2) / self.shot_speed);
-            missile.missile_flags = MIF_SPLASH;
-            te_explosion (missile.origin);
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            // 0 = full, 6 = empty
-            self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
-            if(self.tur_head.frame < 0)
-            {
-                LOG_TRACE("ammo:",ftos(self.ammo),"\n");
-                LOG_TRACE("shot_dmg:",ftos(self.shot_dmg),"\n");
-            }
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
-            self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
-
-            self.damage_flags |= TFL_DMG_HEADSHAKE;
-            self.shoot_flags  |= TFL_SHOOT_VOLLYALWAYS;
-            self.volly_counter = self.shot_volly;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/base.md3");
-            precache_model ("models/turrets/mlrs.md3");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_mlrs(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/phaser.qc b/qcsrc/common/turrets/unit/phaser.qc
deleted file mode 100644 (file)
index 7d37717..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ PHASER,
-/* function   */ t_phaser,
-/* spawnflags */ TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER,
-/* mins,maxs  */ '-32 -32 0', '32 32 64',
-/* model         */ "base.md3",
-/* head_model */ "phaser.md3",
-/* netname       */ "phaser",
-/* fullname   */ _("Phaser Cannon")
-);
-#else
-#ifdef SVQC
-.float fireflag;
-
-float turret_phaser_firecheck()
-{
-    if (self.fireflag != 0) return 0;
-    return turret_firecheck();
-}
-
-void beam_think()
-{
-    if ((time > self.cnt) || (self.owner.deadflag != DEAD_NO))
-    {
-        self.owner.attack_finished_single = time + self.owner.shot_refire;
-        self.owner.fireflag = 2;
-        self.owner.tur_head.frame = 10;
-        sound (self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
-        remove(self);
-        return;
-    }
-
-    turret_do_updates(self.owner);
-
-    if (time - self.shot_spread > 0)
-    {
-        self.shot_spread = time + 2;
-        sound (self, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
-    }
-
-
-    self.nextthink = time + self.ticrate;
-
-    self.owner.attack_finished_single = time + frametime;
-    entity oldself;
-    oldself = self;
-    self = self.owner;
-    FireImoBeam (   self.tur_shotorg,
-                    self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
-                    '-1 -1 -1' * self.shot_radius,
-                    '1 1 1' * self.shot_radius,
-                    self.shot_force,
-                    oldself.shot_dmg,
-                    0.75,
-                    DEATH_TURRET_PHASER);
-    self = oldself;
-    self.scale = vlen(self.owner.tur_shotorg - trace_endpos) / 256;
-
-}
-
-void spawnfunc_turret_phaser() { if(!turret_initialize(TUR_PHASER)) remove(self); }
-
-float t_phaser(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            entity beam;
-
-            beam = spawn();
-            beam.ticrate = 0.1; //autocvar_sys_ticrate;
-            setmodel(beam,"models/turrets/phaser_beam.md3");
-            beam.effects = EF_LOWPRECISION;
-            beam.solid = SOLID_NOT;
-            beam.think = beam_think;
-            beam.cnt = time + self.shot_speed;
-            beam.shot_spread = time + 2;
-            beam.nextthink = time;
-            beam.owner = self;
-            beam.shot_dmg = self.shot_dmg / (self.shot_speed / beam.ticrate);
-            beam.scale = self.target_range / 256;
-            beam.movetype = MOVETYPE_NONE;
-            beam.enemy = self.enemy;
-            beam.bot_dodge = true;
-            beam.bot_dodgerating = beam.shot_dmg;
-            sound (beam, CH_SHOTS_SINGLE, "turrets/phaser.wav", VOL_BASE, ATTEN_NORM);
-            self.fireflag = 1;
-
-            beam.attack_finished_single = self.attack_finished_single;
-            self.attack_finished_single = time; // + autocvar_sys_ticrate;
-
-            setattachment(beam,self.tur_head,"tag_fire");
-
-            soundat (self, trace_endpos, CH_SHOTS, W_Sound("neximpact"), VOL_BASE, ATTEN_NORM);
-
-            if (self.tur_head.frame == 0)
-                self.tur_head.frame = 1;
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            if (self.tur_head.frame != 0)
-            {
-                if (self.fireflag == 1)
-                {
-                    if (self.tur_head.frame == 10)
-                        self.tur_head.frame = 1;
-                    else
-                        self.tur_head.frame = self.tur_head.frame +1;
-                }
-                else if (self.fireflag == 2 )
-                {
-                    self.tur_head.frame = self.tur_head.frame +1;
-                    if (self.tur_head.frame == 15)
-                    {
-                        self.tur_head.frame = 0;
-                        self.fireflag = 0;
-                    }
-                }
-            }
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
-            self.aim_flags = TFL_AIM_LEAD;
-
-            self.turret_firecheckfunc = turret_phaser_firecheck;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/base.md3");
-            precache_model ("models/turrets/phaser.md3");
-            precache_model ("models/turrets/phaser_beam.md3");
-            precache_sound ("turrets/phaser.wav");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_phaser(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/plasma.qc b/qcsrc/common/turrets/unit/plasma.qc
deleted file mode 100644 (file)
index dda66f7..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ PLASMA,
-/* function   */ t_plasma,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
-/* mins,maxs  */ '-32 -32 0', '32 32 64',
-/* model         */ "base.md3",
-/* head_model */ "plasma.md3",
-/* netname       */ "plasma",
-/* fullname   */ _("Plasma Cannon")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_plasma() { if(!turret_initialize(TUR_PLASMA)) remove(self); }
-
-float t_plasma(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            if(g_instagib)
-            {
-                float flying;
-                flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
-
-                FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
-                                   800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
-
-                Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
-                // teamcolor / hit beam effect
-                vector v;
-                string s;
-                v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
-                s = strcat("TE_TEI_G3", ((self.team) ? Static_Team_ColorName_Upper(self.team) : ""));
-
-                WarpZone_TrailParticles(world, _particleeffectnum(s), self.tur_shotorg, v);
-
-                if (self.tur_head.frame == 0)
-                    self.tur_head.frame = 1;
-            }
-            else
-            {
-                entity missile = turret_projectile(W_Sound("hagar_fire"), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
-                missile.missile_flags = MIF_SPLASH;
-
-                Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-                if (self.tur_head.frame == 0)
-                    self.tur_head.frame = 1;
-            }
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            if (self.tur_head.frame != 0)
-                self.tur_head.frame = self.tur_head.frame + 1;
-
-            if (self.tur_head.frame > 5)
-                self.tur_head.frame = 0;
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
-            self.damage_flags |= TFL_DMG_HEADSHAKE;
-            self.firecheck_flags |= TFL_FIRECHECK_AFF;
-            self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
-
-            turret_do_updates(self);
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/base.md3");
-            precache_model ("models/turrets/plasma.md3");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_plasma(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/plasma_dual.qc b/qcsrc/common/turrets/unit/plasma_dual.qc
deleted file mode 100644 (file)
index ef76238..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ PLASMA_DUAL,
-/* function   */ t_plasma_dual,
-/* spawnflags */ TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER,
-/* mins,maxs  */ '-32 -32 0', '32 32 64',
-/* model         */ "base.md3",
-/* head_model */ "plasmad.md3",
-/* netname       */ "plasma_dual",
-/* fullname   */ _("Dual Plasma Cannon")
-);
-#else
-#ifdef SVQC
-void spawnfunc_turret_plasma_dual() { if(!turret_initialize(TUR_PLASMA_DUAL)) remove(self); }
-
-float t_plasma_dual(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            if(g_instagib)
-            {
-                float flying;
-                flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
-
-                FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
-                                   800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
-
-
-                Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
-                // teamcolor / hit beam effect
-                vector v;
-                string s;
-                v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
-                s = strcat(EFFECT_VAPORIZER_NEUTRAL.eent_eff_name, ((self.team) ? Static_Team_ColorName_Upper(self.team) : ""));
-
-                WarpZone_TrailParticles(world, _particleeffectnum(s), self.tur_shotorg, v);
-
-                self.tur_head.frame += 1;
-            }
-            else
-            {
-                entity missile = turret_projectile(W_Sound("hagar_fire"), 1, 0, DEATH_TURRET_PLASMA, PROJECTILE_ELECTRO_BEAM, TRUE, TRUE);
-                missile.missile_flags = MIF_SPLASH;
-                Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-                self.tur_head.frame += 1;
-            }
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
-                self.tur_head.frame = self.tur_head.frame + 1;
-
-            if (self.tur_head.frame > 6)
-                self.tur_head.frame = 0;
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
-            self.damage_flags |= TFL_DMG_HEADSHAKE;
-            self.firecheck_flags |= TFL_FIRECHECK_AFF;
-            self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
-
-            turret_do_updates(self);
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/base.md3");
-            precache_model ("models/turrets/plasmad.md3");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_plasma_dual(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/tesla.qc b/qcsrc/common/turrets/unit/tesla.qc
deleted file mode 100644 (file)
index 05dbffb..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ TESLA,
-/* function   */ t_tesla,
-/* spawnflags */ TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE,
-/* mins,maxs  */ '-60 -60 0', '60 60 128',
-/* model         */ "tesla_base.md3",
-/* head_model */ "tesla_head.md3",
-/* netname       */ "tesla",
-/* fullname   */ _("Tesla Coil")
-);
-#else
-#ifdef SVQC
-entity toast(entity from, float range, float damage)
-{
-    entity e;
-    entity etarget = world;
-    float d,dd;
-    float r;
-
-    dd = range + 1;
-
-    e = findradius(from.origin,range);
-    while (e)
-    {
-        if ((e.railgunhit != 1) && (e != from))
-        {
-            r = turret_validate_target(self,e,self.target_validate_flags);
-            if (r > 0)
-            {
-                traceline(from.origin,0.5 * (e.absmin + e.absmax),MOVE_WORLDONLY,from);
-                if (trace_fraction == 1.0)
-                {
-                    d = vlen(e.origin - from.origin);
-                    if (d < dd)
-                    {
-                        dd = d;
-                        etarget = e;
-                    }
-                }
-            }
-        }
-        e = e.chain;
-    }
-
-    if (etarget)
-    {
-        te_csqc_lightningarc(from.origin,etarget.origin);
-        Damage(etarget, self, self, damage, DEATH_TURRET_TESLA, etarget.origin, '0 0 0');
-        etarget.railgunhit = 1;
-    }
-
-    return etarget;
-}
-
-float turret_tesla_firecheck()
-{
-    // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
-    float do_target_scan = 0;
-
-    if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
-        do_target_scan = 1;
-
-    // Old target (if any) invalid?
-    if(self.target_validate_time < time)
-    if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
-    {
-        self.enemy = world;
-        self.target_validate_time = time + 0.5;
-        do_target_scan = 1;
-    }
-
-    // But never more often then g_turrets_targetscan_mindelay!
-    if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
-        do_target_scan = 0;
-
-    if(do_target_scan)
-    {
-        self.enemy = turret_select_target();
-        self.target_select_time = time;
-    }
-
-    if(!turret_firecheck())
-        return 0;
-
-    if(self.enemy)
-        return 1;
-
-    return 0;
-}
-
-void spawnfunc_turret_tesla() { if(!turret_initialize(TUR_TESLA)) remove(self); }
-
-float t_tesla(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            entity e, t;
-            float d, r, i;
-
-            d = self.shot_dmg;
-            r = self.target_range;
-            e = spawn();
-            setorigin(e,self.tur_shotorg);
-
-            self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-
-            t = toast(e,r,d);
-            remove(e);
-
-            if (t == world) return true;
-
-            self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES | TFL_TARGETSELECT_TEAMCHECK;
-
-            self.attack_finished_single = time + self.shot_refire;
-            for (i = 0; i < 10; ++i)
-            {
-                d *= 0.75;
-                r *= 0.85;
-                t = toast(t, r, d);
-                if (t == world) break;
-
-            }
-
-            e = findchainfloat(railgunhit, 1);
-            while (e)
-            {
-                e.railgunhit = 0;
-                e = e.chain;
-            }
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            if(!self.active)
-            {
-                self.tur_head.avelocity = '0 0 0';
-                return true;
-            }
-
-            if(self.ammo < self.shot_dmg)
-            {
-                self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
-            }
-            else
-            {
-                self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
-
-                if(self.attack_finished_single > time)
-                    return true;
-
-                float f;
-                f = (self.ammo / self.ammo_max);
-                f = f * f;
-                if(f > random())
-                    if(random() < 0.1)
-                        te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
-            }
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
-                                 TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-
-            self.turret_firecheckfunc = turret_tesla_firecheck;
-            self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
-                               TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
-
-            self.firecheck_flags       = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
-            self.shoot_flags           = TFL_SHOOT_CUSTOM;
-            self.ammo_flags                    = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
-            self.aim_flags                     = TFL_AIM_NO;
-            self.track_flags           = TFL_TRACK_NO;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/tesla_base.md3");
-            precache_model ("models/turrets/tesla_head.md3");
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float t_tesla(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
diff --git a/qcsrc/common/turrets/unit/walker.qc b/qcsrc/common/turrets/unit/walker.qc
deleted file mode 100644 (file)
index 4a9ca77..0000000
+++ /dev/null
@@ -1,698 +0,0 @@
-#ifdef REGISTER_TURRET
-REGISTER_TURRET(
-/* TUR_##id   */ WALKER,
-/* function   */ t_walker,
-/* spawnflags */ TUR_FLAG_PLAYER | TUR_FLAG_MOVE,
-/* mins,maxs  */ '-70 -70 0', '70 70 95',
-/* model         */ "walker_body.md3",
-/* head_model */ "walker_head_minigun.md3",
-/* netname       */ "walker",
-/* fullname   */ _("Walker Turret")
-);
-#else
-#ifdef SVQC
-float autocvar_g_turrets_unit_walker_melee_damage;
-float autocvar_g_turrets_unit_walker_melee_force;
-float autocvar_g_turrets_unit_walker_melee_range;
-float autocvar_g_turrets_unit_walker_rocket_damage;
-float autocvar_g_turrets_unit_walker_rocket_radius;
-float autocvar_g_turrets_unit_walker_rocket_force;
-float autocvar_g_turrets_unit_walker_rocket_speed;
-float autocvar_g_turrets_unit_walker_rocket_range;
-float autocvar_g_turrets_unit_walker_rocket_range_min;
-float autocvar_g_turrets_unit_walker_rocket_refire;
-float autocvar_g_turrets_unit_walker_rocket_turnrate;
-float autocvar_g_turrets_unit_walker_speed_stop;
-float autocvar_g_turrets_unit_walker_speed_walk;
-float autocvar_g_turrets_unit_walker_speed_run;
-float autocvar_g_turrets_unit_walker_speed_jump;
-float autocvar_g_turrets_unit_walker_speed_swim;
-float autocvar_g_turrets_unit_walker_speed_roam;
-float autocvar_g_turrets_unit_walker_turn;
-float autocvar_g_turrets_unit_walker_turn_walk;
-float autocvar_g_turrets_unit_walker_turn_strafe;
-float autocvar_g_turrets_unit_walker_turn_swim;
-float autocvar_g_turrets_unit_walker_turn_run;
-
-#define ANIM_NO         0
-#define ANIM_TURN       1
-#define ANIM_WALK       2
-#define ANIM_RUN        3
-#define ANIM_STRAFE_L   4
-#define ANIM_STRAFE_R   5
-#define ANIM_JUMP       6
-#define ANIM_LAND       7
-#define ANIM_PAIN       8
-#define ANIM_MELEE      9
-#define ANIM_SWIM       10
-#define ANIM_ROAM       11
-
-.float animflag;
-.float idletime;
-
-#define WALKER_PATH(s,e) pathlib_astar(s,e)
-
-float walker_firecheck()
-{
-    if (self.animflag == ANIM_MELEE)
-        return 0;
-
-    return turret_firecheck();
-}
-
-void walker_melee_do_dmg()
-{
-    vector where;
-    entity e;
-
-    makevectors(self.angles);
-    where = self.origin + v_forward * 128;
-
-    e = findradius(where,32);
-    while (e)
-    {
-        if (turret_validate_target(self, e, self.target_validate_flags))
-            if (e != self && e.owner != self)
-                Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
-
-        e = e.chain;
-    }
-}
-
-void walker_setnoanim()
-{
-    turrets_setframe(ANIM_NO, false);
-    self.animflag = self.frame;
-}
-void walker_rocket_explode()
-{
-    RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, world, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET, world);
-    remove (self);
-}
-
-void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
-{
-    self.health = self.health - damage;
-    self.velocity = self.velocity + vforce;
-
-    if (self.health <= 0)
-        W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
-}
-
-#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
-void walker_rocket_loop();
-void walker_rocket_think()
-{
-    vector newdir;
-    float edist;
-    float itime;
-    float m_speed;
-
-    self.nextthink = time;
-
-    edist = vlen(self.enemy.origin - self.origin);
-
-    // Simulate crude guidance
-    if (self.cnt < time)
-    {
-        if (edist < 1000)
-            self.tur_shotorg = randomvec() * min(edist, 64);
-        else
-            self.tur_shotorg = randomvec() * min(edist, 256);
-
-        self.cnt = time + 0.5;
-    }
-
-    if (edist < 128)
-        self.tur_shotorg = '0 0 0';
-
-    if (self.max_health < time)
-    {
-        self.think       = walker_rocket_explode;
-        self.nextthink  = time;
-        return;
-    }
-
-    if (self.shot_dmg != 1337 && random() < 0.01)
-    {
-        walker_rocket_loop();
-        return;
-    }
-
-    m_speed = vlen(self.velocity);
-
-    // Enemy dead? just keep on the current heading then.
-    if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
-        self.enemy = world;
-
-    if (self.enemy)
-    {
-        itime = max(edist / m_speed, 1);
-        newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
-    }
-    else
-        newdir  = normalize(self.velocity);
-
-    WALKER_ROCKET_MOVE;
-}
-
-void walker_rocket_loop3()
-{
-    vector newdir;
-    self.nextthink = time;
-
-    if (self.max_health < time)
-    {
-        self.think = walker_rocket_explode;
-        return;
-    }
-
-    if (vlen(self.origin - self.tur_shotorg) < 100 )
-    {
-        self.think = walker_rocket_think;
-        return;
-    }
-
-    newdir = steerlib_pull(self.tur_shotorg);
-    WALKER_ROCKET_MOVE;
-
-    self.angles = vectoangles(self.velocity);
-}
-
-void walker_rocket_loop2()
-{
-    vector newdir;
-
-    self.nextthink = time;
-
-    if (self.max_health < time)
-    {
-        self.think = walker_rocket_explode;
-        return;
-    }
-
-    if (vlen(self.origin - self.tur_shotorg) < 100 )
-    {
-        self.tur_shotorg = self.origin - '0 0 200';
-        self.think = walker_rocket_loop3;
-        return;
-    }
-
-    newdir = steerlib_pull(self.tur_shotorg);
-    WALKER_ROCKET_MOVE;
-}
-
-void walker_rocket_loop()
-{
-    self.nextthink = time;
-    self.tur_shotorg = self.origin + '0 0 300';
-    self.think = walker_rocket_loop2;
-    self.shot_dmg = 1337;
-}
-
-void walker_fire_rocket(vector org)
-{
-    entity rocket;
-
-    fixedmakevectors(self.angles);
-
-    te_explosion (org);
-
-    rocket = spawn ();
-    setorigin(rocket, org);
-
-    sound (self, CH_WEAPON_A, W_Sound("hagar_fire"), VOL_BASE, ATTEN_NORM);
-    setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
-
-    rocket.classname             = "walker_rocket";
-    rocket.owner                         = self;
-    rocket.bot_dodge             = true;
-    rocket.bot_dodgerating     = 50;
-    rocket.takedamage           = DAMAGE_YES;
-    rocket.damageforcescale   = 2;
-    rocket.health                       = 25;
-    rocket.tur_shotorg         = randomvec() * 512;
-    rocket.cnt                         = time + 1;
-    rocket.enemy                         = self.enemy;
-
-    if (random() < 0.01)
-        rocket.think             = walker_rocket_loop;
-    else
-        rocket.think             = walker_rocket_think;
-
-    rocket.event_damage           = walker_rocket_damage;
-
-    rocket.nextthink             = time;
-    rocket.movetype               = MOVETYPE_FLY;
-    rocket.velocity               = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
-    rocket.angles                       = vectoangles(rocket.velocity);
-    rocket.touch                         = walker_rocket_explode;
-    rocket.flags                         = FL_PROJECTILE;
-    rocket.solid                         = SOLID_BBOX;
-    rocket.max_health           = time + 9;
-    rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
-
-    CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
-}
-
-.vector enemy_last_loc;
-.float enemy_last_time;
-void walker_move_to(vector _target, float _dist)
-{
-    switch (self.waterlevel)
-    {
-        case WATERLEVEL_NONE:
-            if (_dist > 500)
-                self.animflag = ANIM_RUN;
-            else
-                self.animflag = ANIM_WALK;
-        case WATERLEVEL_WETFEET:
-        case WATERLEVEL_SWIMMING:
-            if (self.animflag != ANIM_SWIM)
-                self.animflag = ANIM_WALK;
-            else
-                self.animflag = ANIM_SWIM;
-            break;
-        case WATERLEVEL_SUBMERGED:
-            self.animflag = ANIM_SWIM;
-    }
-
-    self.moveto = _target;
-    self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-
-    if(self.enemy)
-    {
-        self.enemy_last_loc = _target;
-        self.enemy_last_time = time;
-    }
-}
-
-//#define WALKER_FANCYPATHING
-
-void walker_move_path()
-{
-#ifdef WALKER_FANCYPATHING
-    // Are we close enougth to a path node to switch to the next?
-    if (vlen(self.origin  - self.pathcurrent.origin) < 64)
-        if (self.pathcurrent.path_next == world)
-        {
-            // Path endpoint reached
-            pathlib_deletepath(self.pathcurrent.owner);
-            self.pathcurrent = world;
-
-            if (self.pathgoal)
-            {
-                if (self.pathgoal.use)
-                    self.pathgoal.use();
-
-                if (self.pathgoal.enemy)
-                {
-                    self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
-                    self.pathgoal = self.pathgoal.enemy;
-                }
-            }
-            else
-                self.pathgoal = world;
-        }
-        else
-            self.pathcurrent = self.pathcurrent.path_next;
-
-    self.moveto = self.pathcurrent.origin;
-    self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
-    walker_move_to(self.moveto, 0);
-
-#else
-    if (vlen(self.origin - self.pathcurrent.origin) < 64)
-        self.pathcurrent = self.pathcurrent.enemy;
-
-    if(!self.pathcurrent)
-        return;
-
-    self.moveto = self.pathcurrent.origin;
-    self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-    walker_move_to(self.moveto, 0);
-#endif
-}
-
-void spawnfunc_turret_walker() { if(!turret_initialize(TUR_WALKER)) remove(self); }
-
-float t_walker(float req)
-{
-    switch(req)
-    {
-        case TR_ATTACK:
-        {
-            sound (self, CH_WEAPON_A, W_Sound("uzi_fire"), VOL_BASE, ATTEN_NORM);
-            fireBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0);
-            Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
-
-            return true;
-        }
-        case TR_THINK:
-        {
-            fixedmakevectors(self.angles);
-
-            if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
-                walker_move_path();
-            else if (self.enemy == world)
-            {
-                if(self.pathcurrent)
-                    walker_move_path();
-                else
-                {
-                    if(self.enemy_last_time != 0)
-                    {
-                        if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
-                            self.enemy_last_time = 0;
-                        else
-                            walker_move_to(self.enemy_last_loc, 0);
-                    }
-                    else
-                    {
-                        if(self.animflag != ANIM_NO)
-                        {
-                            traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
-
-                            if(trace_fraction != 1.0)
-                                self.tur_head.idletime = -1337;
-                            else
-                            {
-                                traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
-                                if(trace_fraction == 1.0)
-                                    self.tur_head.idletime = -1337;
-                            }
-
-                            if(self.tur_head.idletime == -1337)
-                            {
-                                self.moveto = self.origin + randomvec() * 256;
-                                self.tur_head.idletime = 0;
-                            }
-
-                            self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
-                            self.moveto_z = self.origin_z + 64;
-                            walker_move_to(self.moveto, 0);
-                        }
-
-                        if(self.idletime < time)
-                        {
-                            if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
-                            {
-                                self.idletime = time + 1 + random() * 5;
-                                self.moveto = self.origin;
-                                self.animflag = ANIM_NO;
-                            }
-                            else
-                            {
-                                self.animflag = ANIM_WALK;
-                                self.idletime = time + 4 + random() * 2;
-                                self.moveto = self.origin + randomvec() * 256;
-                                self.tur_head.moveto = self.moveto;
-                                self.tur_head.idletime = 0;
-                            }
-                        }
-                    }
-                }
-            }
-            else
-            {
-                if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
-                {
-                    vector wish_angle;
-
-                    wish_angle = angleofs(self, self.enemy);
-                    if (self.animflag != ANIM_SWIM)
-                    if (fabs(wish_angle_y) < 15)
-                    {
-                        self.moveto   = self.enemy.origin;
-                        self.steerto  = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
-                        self.animflag = ANIM_MELEE;
-                    }
-                }
-                else if (self.tur_head.attack_finished_single < time)
-                {
-                    if(self.tur_head.shot_volly)
-                    {
-                        self.animflag = ANIM_NO;
-
-                        self.tur_head.shot_volly = self.tur_head.shot_volly -1;
-                        if(self.tur_head.shot_volly == 0)
-                            self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
-                        else
-                            self.tur_head.attack_finished_single = time + 0.2;
-
-                        if(self.tur_head.shot_volly > 1)
-                            walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
-                        else
-                            walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
-                    }
-                    else
-                    {
-                        if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
-                        if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
-                            self.tur_head.shot_volly = 4;
-                    }
-                }
-                else
-                {
-                    if (self.animflag != ANIM_MELEE)
-                        walker_move_to(self.enemy.origin, self.tur_dist_enemy);
-                }
-            }
-
-            {
-                vector real_angle;
-                float turny = 0, turnx = 0;
-                float vz;
-
-                real_angle = vectoangles(self.steerto) - self.angles;
-                vz = self.velocity_z;
-
-                switch (self.animflag)
-                {
-                    case ANIM_NO:
-                        movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
-                        break;
-
-                    case ANIM_TURN:
-                        turny = (autocvar_g_turrets_unit_walker_turn);
-                        movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
-                        break;
-
-                    case ANIM_WALK:
-                        turny = (autocvar_g_turrets_unit_walker_turn_walk);
-                        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
-                        break;
-
-                    case ANIM_RUN:
-                        turny = (autocvar_g_turrets_unit_walker_turn_run);
-                        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
-                        break;
-
-                    case ANIM_STRAFE_L:
-                        turny = (autocvar_g_turrets_unit_walker_turn_strafe);
-                        movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
-                        break;
-
-                    case ANIM_STRAFE_R:
-                        turny = (autocvar_g_turrets_unit_walker_turn_strafe);
-                        movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
-                        break;
-
-                    case ANIM_JUMP:
-                        self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
-                        break;
-
-                    case ANIM_LAND:
-                        break;
-
-                    case ANIM_PAIN:
-                        if(self.frame != ANIM_PAIN)
-                            defer(0.25, walker_setnoanim);
-
-                        break;
-
-                    case ANIM_MELEE:
-                        if(self.frame != ANIM_MELEE)
-                        {
-                            defer(0.41, walker_setnoanim);
-                            defer(0.21, walker_melee_do_dmg);
-                        }
-
-                        movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
-                        break;
-
-                    case ANIM_SWIM:
-                        turny = (autocvar_g_turrets_unit_walker_turn_swim);
-                        turnx = (autocvar_g_turrets_unit_walker_turn_swim);
-
-                        self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
-                        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
-                        vz = self.velocity_z + sin(time * 4) * 8;
-                        break;
-
-                    case ANIM_ROAM:
-                        turny = (autocvar_g_turrets_unit_walker_turn_walk);
-                        movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
-                        break;
-                }
-
-                if(turny)
-                {
-                    turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
-                    self.angles_y += turny;
-                }
-
-                if(turnx)
-                {
-                    turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
-                    self.angles_x += turnx;
-                }
-
-                self.velocity_z = vz;
-            }
-
-
-            if(self.origin != self.oldorigin)
-                self.SendFlags |= TNSF_MOVE;
-
-            self.oldorigin = self.origin;
-            turrets_setframe(self.animflag, false);
-
-            return true;
-        }
-        case TR_DEATH:
-        {
-#ifdef WALKER_FANCYPATHING
-            if (self.pathcurrent)
-                pathlib_deletepath(self.pathcurrent.owner);
-#endif
-            self.pathcurrent = world;
-
-            return true;
-        }
-        case TR_SETUP:
-        {
-            self.ticrate = 0.05;
-
-            entity e;
-
-            // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
-            if(self.movetype == MOVETYPE_WALK)
-            {
-                if(self.pos1)
-                    setorigin(self, self.pos1);
-                if(self.pos2)
-                    self.angles = self.pos2;
-            }
-
-            self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
-            self.aim_flags = TFL_AIM_LEAD;
-            self.turret_flags |= TUR_FLAG_HITSCAN;
-
-            self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
-            self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
-            self.iscreature = true;
-            self.teleportable = TELEPORT_NORMAL;
-            self.damagedbycontents = true;
-            self.solid = SOLID_SLIDEBOX;
-            self.takedamage = DAMAGE_AIM;
-            if(self.movetype != MOVETYPE_WALK)
-            {
-                setorigin(self, self.origin);
-                tracebox(self.origin + '0 0 128', self.mins, self.maxs, self.origin - '0 0 10000', MOVE_NORMAL, self);
-                setorigin(self, trace_endpos + '0 0 4');
-                self.pos1 = self.origin;
-                self.pos2 = self.angles;
-            }
-            self.movetype = MOVETYPE_WALK;
-            self.idle_aim = '0 0 0';
-            self.turret_firecheckfunc = walker_firecheck;
-
-            if (self.target != "")
-            {
-                e = find(world, targetname, self.target);
-                if (!e)
-                {
-                    LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n");
-                    self.target = "";
-                }
-
-                if (e.classname != "turret_checkpoint")
-                    LOG_TRACE("Warning: not a turrret path\n");
-                else
-                {
-#ifdef WALKER_FANCYPATHING
-                    self.pathcurrent = WALKER_PATH(self.origin, e.origin);
-                    self.pathgoal = e;
-#else
-                    self.pathcurrent = e;
-#endif
-                }
-            }
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            precache_model ("models/turrets/walker_body.md3");
-            precache_model ("models/turrets/walker_head_minigun.md3");
-            precache_model ("models/turrets/rocket.md3");
-            precache_sound (W_Sound("rocket_impact"));
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-#include "../../../server/movelib.qh"
-
-void walker_draw()
-{
-    float dt;
-
-    dt = time - self.move_time;
-    self.move_time = time;
-    if(dt <= 0)
-        return;
-
-    fixedmakevectors(self.angles);
-    movelib_groundalign4point(300, 100, 0.25, 45);
-    setorigin(self, self.origin + self.velocity * dt);
-    self.tur_head.angles += dt * self.tur_head.move_avelocity;
-    self.angles_y = self.move_angles_y;
-
-    if (self.health < 127)
-    if(random() < 0.15)
-        te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
-}
-
-float t_walker(float req)
-{
-    switch(req)
-    {
-        case TR_SETUP:
-        {
-            self.gravity               = 1;
-            self.movetype              = MOVETYPE_BOUNCE;
-            self.move_movetype = MOVETYPE_BOUNCE;
-            self.move_origin   = self.origin;
-            self.move_time             = time;
-            self.draw                  = walker_draw;
-
-            return true;
-        }
-        case TR_PRECACHE:
-        {
-            return true;
-        }
-    }
-
-    return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_TURRET
index 477df7b6808a4ef80eefa7bf08544ac71290a539..53c5fb74df629f2628d3e97216b1ff948b3f2a9a 100644 (file)
@@ -114,7 +114,7 @@ vector angleofs3(vector from, vector from_a, entity to)
 * NOTICE this func overwrites the global v_forward, v_right and v_up vectors.
 */
 float turret_tag_fire_update()
-{
+{SELFPARAM();
        if(!self.tur_head)
        {
                error("Call to turret_tag_fire_update with self.tur_head missing!\n");
@@ -134,7 +134,7 @@ float turret_tag_fire_update()
 void FireImoBeam (vector start, vector end, vector smin, vector smax,
                                  float bforce, float f_dmg, float f_velfactor, int deathtype)
 
-{
+{SELFPARAM();
        vector hitloc, force, endpoint, dir;
        entity ent;
 
@@ -206,7 +206,7 @@ void FireImoBeam (vector start, vector end, vector smin, vector smax,
 #ifdef TURRET_DEBUG
 void SUB_Remove();
 void marker_think()
-{
+{SELFPARAM();
        if(self.cnt)
        if(self.cnt < time)
        {
@@ -228,7 +228,7 @@ void mark_error(vector where,float lifetime)
 
        err = spawn();
        err.classname = "error_marker";
-       setmodel(err,"models/marker.md3");
+       setmodel(err, MDL_MARKER);
        setorigin(err,where);
        err.movetype = MOVETYPE_NONE;
        err.think = marker_think;
@@ -244,7 +244,7 @@ void mark_info(vector where,float lifetime)
 
        err = spawn();
        err.classname = "info_marker";
-       setmodel(err,"models/marker.md3");
+       setmodel(err, MDL_MARKER);
        setorigin(err,where);
        err.movetype = MOVETYPE_NONE;
        err.think = marker_think;
@@ -260,7 +260,7 @@ entity mark_misc(vector where,float lifetime)
 
        err = spawn();
        err.classname = "mark_misc";
-       setmodel(err,"models/marker.md3");
+       setmodel(err, MDL_MARKER);
        setorigin(err,where);
        err.movetype = MOVETYPE_NONE;
        err.think = marker_think;
@@ -271,6 +271,8 @@ entity mark_misc(vector where,float lifetime)
        return err;
 }
 
+MODEL(TUR_C512, "models/turrets/c512.md3");
+
 /*
 * Paint a v_color colord circle on target onwho
 * that fades away over f_time
@@ -280,7 +282,7 @@ void paint_target(entity onwho, float f_size, vector v_color, float f_time)
        entity e;
 
        e = spawn();
-       setmodel(e, "models/turrets/c512.md3"); // precision set above
+       setmodel(e, MDL_TUR_C512); // precision set above
        e.scale = (f_size/512);
        //setsize(e, '0 0 0', '0 0 0');
        //setattachment(e,onwho,"");
@@ -299,7 +301,7 @@ void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
        entity e;
 
        e = spawn();
-       setmodel(e, "models/turrets/c512.md3"); // precision set above
+       setmodel(e, MDL_TUR_C512); // precision set above
        e.scale = (f_size/512);
        setsize(e, '0 0 0', '0 0 0');
 
@@ -318,7 +320,7 @@ void paint_target3(vector where, float f_size, vector v_color, float f_time)
 {
        entity e;
        e = spawn();
-       setmodel(e, "models/turrets/c512.md3"); // precision set above
+       setmodel(e, MDL_TUR_C512); // precision set above
        e.scale = (f_size/512);
        setsize(e, '0 0 0', '0 0 0');
        setorigin(e,where+ '0 0 1');
index 6b43f34bf2aefedfdc40aa65012a09d2f8befe54..f796b6ebda6109c169700f78dae37989464819d6 100644 (file)
@@ -1,6 +1,47 @@
 #ifndef UTIL_POST_H
 #define UTIL_POST_H
 
+[[alias("self")]] entity __self;
+
+// Can't wrap with do-while as block may contain continue or break
+#define WITH(type, name, value, block) { \
+    type __with_save = (name); \
+    name = (value); \
+    LAMBDA(block) \
+    name = __with_save; \
+} do { } while (0)
+
+// Transition from global 'self' to local 'this'
+
+// Step 1: auto oldself
+#if 1
+#define SELFPARAM() noref entity this = __self
+#define setself(s) (__self = s)
+#define self __self
+#endif
+
+// Step 2: check SELFPARAM() is present for functions that use self
+#if 0
+#define SELFPARAM() [[alias("__self")]] noref entity this = __self
+#define setself(s) (__self = s)
+#define self this
+#endif
+
+// Step 3: const self
+#if 0
+#define SELFPARAM() noref const entity this = __self
+entity setself(entity e) { return self = e; }
+entity getself() { return self; }
+#define self getself()
+#endif
+
+// Step 4: enable when possible
+// TODO: Remove SELFPARAM in favor of a parameter
+#if 0
+#define SELFPARAM() noref const entity this = __self
+#define self this
+#endif
+
 #define spawn() new(entity)
 
 #endif
index b81fd2a6df81d409626458a4ba338a15273796f2..dfb407160c339f91f851f13b4c73343d42257b16 100644 (file)
@@ -13,7 +13,7 @@
 
 #ifndef QCC_SUPPORT_NIL
     #ifdef GMQCC
-        #define QCC_SUPPORT_NIL
+        #define QCC_SUPPORT_NIL 1
     #endif
 #endif
 
 #define FOREACH(list, cond, body) FOREACH_LIST(list, enemy, cond, body)
 
 #ifdef GMQCC
-    #define OVERLOAD(F, ...) F##_##__VA_COUNT__(__VA_ARGS__)
+    #define EVAL(...)           __VA_ARGS__
+
+    #define OVERLOAD_(F, ...)   F##_##__VA_COUNT__(__VA_ARGS__)
+    #define OVERLOAD(F, ...)    F##_##__VA_COUNT__(__VA_ARGS__)
 #else
-    #define OVERLOAD_(F,_9,_8,_7,_6,_5,_4,_3,_2,_1,n,...) F##_##n
-    #define OVERLOAD(F, ...) OVERLOAD_(F,__VA_ARGS__,9,8,7,6,5,4,3,2,1)(__VA_ARGS__)
+    #define EMPTY()
+    #define DEFER(id) id EMPTY()
+
+    #define EVAL(...)  EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
+    #define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
+    #define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
+    #define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
+    #define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
+    #define EVAL5(...) __VA_ARGS__
+
+    #define OVERLOAD___(F,_16,_15,_14,_13,_12,_11,_10,_9,_8,_7,_6,_5,_4,_3,_2,_1,n,...) F##_##n
+    #define OVERLOAD__(F, ...)  OVERLOAD___(F,##__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
+    #define OVERLOAD_(...)      DEFER(OVERLOAD__(__VA_ARGS__))
+    #define OVERLOAD(F, ...)    OVERLOAD_(F,##__VA_ARGS__)(__VA_ARGS__)
 #endif
 
 #define LAMBDA(...) { __VA_ARGS__ ; }
 
-#define MAP(f, ...) OVERLOAD(MAP, f, __VA_ARGS__)
+#define MAP(f, ...) EVAL(OVERLOAD(MAP, f, __VA_ARGS__))
 #define MAP_2(f, it) f(it)
 #define MAP_3(f, it, ...) f(it)MAP_2(f, __VA_ARGS__)
 #define MAP_4(f, it, ...) f(it)MAP_3(f, __VA_ARGS__)
 #define GET(name) name##get
 #define GETTER(type, name) type GET(name)() { return name; }
 
-#define BIT(n) (1 << (n))
-#ifndef BRANCHLESS_BITSET
-    #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) &~ (mask))
-#else
-    #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
-#endif
-
 #endif
index 439f0bffa0f9b77485362c12815b4e26ce75ac7b..c304ed88d4624c3a0c9964c9b233f58f6b3b70af 100644 (file)
@@ -41,7 +41,7 @@ string wordwrap(string s, float l)
 #ifndef MENUQC
 #ifndef CSQC
 void wordwrap_buffer_sprint(string s)
-{
+{SELFPARAM();
        wordwrap_buffer = strcat(wordwrap_buffer, s);
        if(s == "\n")
        {
@@ -51,7 +51,7 @@ void wordwrap_buffer_sprint(string s)
 }
 
 void wordwrap_sprint(string s, float l)
-{
+{SELFPARAM();
        wordwrap_buffer = "";
        wordwrap_cb(s, l, wordwrap_buffer_sprint);
        if(wordwrap_buffer != "")
@@ -72,37 +72,6 @@ string draw_UseSkinFor(string pic)
 }
 #endif
 
-string unescape(string in)
-{
-       float i, len;
-       string str, s;
-
-       // but it doesn't seem to be necessary in my tests at least
-       in = strzone(in);
-
-       len = strlen(in);
-       str = "";
-       for(i = 0; i < len; ++i)
-       {
-               s = substring(in, i, 1);
-               if(s == "\\")
-               {
-                       s = substring(in, i+1, 1);
-                       if(s == "n")
-                               str = strcat(str, "\n");
-                       else if(s == "\\")
-                               str = strcat(str, "\\");
-                       else
-                               str = strcat(str, substring(in, i, 2));
-                       ++i;
-               } else
-                       str = strcat(str, s);
-       }
-
-       strunzone(in);
-       return str;
-}
-
 void wordwrap_cb(string s, float l, void(string) callback)
 {
        string c;
@@ -168,17 +137,6 @@ void wordwrap_cb(string s, float l, void(string) callback)
        strunzone(s);
 }
 
-float dist_point_line(vector p, vector l0, vector ldir)
-{
-       ldir = normalize(ldir);
-
-       // remove the component in line direction
-       p = p - (p * ldir) * ldir;
-
-       // vlen of the remaining vector
-       return vlen(p);
-}
-
 void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(entity, entity) funcPre, void(entity, entity) funcPost, entity pass)
 {
        entity e;
@@ -208,13 +166,6 @@ void depthfirst(entity start, .entity up, .entity downleft, .entity right, void(
        }
 }
 
-float median(float a, float b, float c)
-{
-       if(a < c)
-               return bound(a, b, c);
-       return bound(c, b, a);
-}
-
 // converts a number to a string with the indicated number of decimals
 // works for up to 10 decimals!
 string ftos_decimals(float number, float decimals)
@@ -226,9 +177,9 @@ string ftos_decimals(float number, float decimals)
        return sprintf("%.*f", decimals, number);
 }
 
-vector colormapPaletteColor(float c, float isPants)
+vector colormapPaletteColor(float c, bool isPants)
 {
-       switch(c)
+       switch (c)
        {
                case  0: return '1.000000 1.000000 1.000000';
                case  1: return '1.000000 0.333333 0.000000';
@@ -246,7 +197,7 @@ vector colormapPaletteColor(float c, float isPants)
                case 13: return '0.000000 0.333333 1.000000';
                case 14: return '1.000000 0.666667 0.000000';
                case 15:
-                       if(isPants)
+                       if (isPants)
                                return
                                          '1 0 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 0.0000000000))
                                        + '0 1 0' * (0.502 + 0.498 * sin(time / 2.7182818285 + 2.0943951024))
@@ -260,26 +211,6 @@ vector colormapPaletteColor(float c, float isPants)
        }
 }
 
-// unzone the string, and return it as tempstring. Safe to be called on string_null
-string fstrunzone(string s)
-{
-       string sc;
-       if (!s)
-               return s;
-       sc = strcat(s, "");
-       strunzone(s);
-       return sc;
-}
-
-bool fexists(string f)
-{
-    int fh = fopen(f, FILE_READ);
-    if (fh < 0)
-        return false;
-    fclose(fh);
-    return true;
-}
-
 // Databases (hash tables)
 const float DB_BUCKETS = 8192;
 void db_save(float db, string pFilename)
@@ -941,103 +872,6 @@ float cvar_settemp_restore()
        return i;
 }
 
-float almost_equals(float a, float b)
-{
-       float eps;
-       eps = (max(a, -a) + max(b, -b)) * 0.001;
-       if(a - b < eps && b - a < eps)
-               return true;
-       return false;
-}
-
-float almost_in_bounds(float a, float b, float c)
-{
-       float eps;
-       eps = (max(a, -a) + max(c, -c)) * 0.001;
-       if(a > c)
-               eps = -eps;
-       return b == median(a - eps, b, c + eps);
-}
-
-float power2of(float e)
-{
-       return pow(2, e);
-}
-float log2of(float x)
-{
-       // NOTE: generated code
-       if(x > 2048)
-               if(x > 131072)
-                       if(x > 1048576)
-                               if(x > 4194304)
-                                       return 23;
-                               else
-                                       if(x > 2097152)
-                                               return 22;
-                                       else
-                                               return 21;
-                       else
-                               if(x > 524288)
-                                       return 20;
-                               else
-                                       if(x > 262144)
-                                               return 19;
-                                       else
-                                               return 18;
-               else
-                       if(x > 16384)
-                               if(x > 65536)
-                                       return 17;
-                               else
-                                       if(x > 32768)
-                                               return 16;
-                                       else
-                                               return 15;
-                       else
-                               if(x > 8192)
-                                       return 14;
-                               else
-                                       if(x > 4096)
-                                               return 13;
-                                       else
-                                               return 12;
-       else
-               if(x > 32)
-                       if(x > 256)
-                               if(x > 1024)
-                                       return 11;
-                               else
-                                       if(x > 512)
-                                               return 10;
-                                       else
-                                               return 9;
-                       else
-                               if(x > 128)
-                                       return 8;
-                               else
-                                       if(x > 64)
-                                               return 7;
-                                       else
-                                               return 6;
-               else
-                       if(x > 4)
-                               if(x > 16)
-                                       return 5;
-                               else
-                                       if(x > 8)
-                                               return 4;
-                                       else
-                                               return 3;
-                       else
-                               if(x > 2)
-                                       return 2;
-                               else
-                                       if(x > 1)
-                                               return 1;
-                                       else
-                                               return 0;
-}
-
 float rgb_mi_ma_to_hue(vector rgb, float mi, float ma)
 {
        if(mi == ma)
@@ -1182,15 +1016,6 @@ string rgb_to_hexcolor(vector rgb)
                );
 }
 
-// requires that m2>m1 in all coordinates, and that m4>m3
-float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;}
-
-// requires the same, but is a stronger condition
-float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z;}
-
-#ifndef MENUQC
-#endif
-
 float textLengthUpToWidth(string theText, float maxWidth, vector theSize, textLengthUpToWidth_widthFunction_t w)
 {
        // STOP.
@@ -1509,67 +1334,6 @@ float isGametypeInFilter(float gt, float tp, float ts, string pattern)
        return 1;
 }
 
-void shuffle(float n, swapfunc_t swap, entity pass)
-{
-       float i, j;
-       for(i = 1; i < n; ++i)
-       {
-               // swap i-th item at a random position from 0 to i
-               // proof for even distribution:
-               //   n = 1: obvious
-               //   n -> n+1:
-               //     item n+1 gets at any position with chance 1/(n+1)
-               //     all others will get their 1/n chance reduced by factor n/(n+1)
-               //     to be on place n+1, their chance will be 1/(n+1)
-               //     1/n * n/(n+1) = 1/(n+1)
-               //     q.e.d.
-               j = floor(random() * (i + 1));
-               if(j != i)
-                       swap(j, i, pass);
-       }
-}
-
-string substring_range(string s, float b, float e)
-{
-       return substring(s, b, e - b);
-}
-
-string swapwords(string str, float i, float j)
-{
-       float n;
-       string s1, s2, s3, s4, s5;
-       float si, ei, sj, ej, s0, en;
-       n = tokenizebyseparator(str, " "); // must match g_maplist processing in ShuffleMaplist and "shuffle"
-       si = argv_start_index(i);
-       sj = argv_start_index(j);
-       ei = argv_end_index(i);
-       ej = argv_end_index(j);
-       s0 = argv_start_index(0);
-       en = argv_end_index(n-1);
-       s1 = substring_range(str, s0, si);
-       s2 = substring_range(str, si, ei);
-       s3 = substring_range(str, ei, sj);
-       s4 = substring_range(str, sj, ej);
-       s5 = substring_range(str, ej, en);
-       return strcat(s1, s4, s3, s2, s5);
-}
-
-string _shufflewords_str;
-void _shufflewords_swapfunc(float i, float j, entity pass)
-{
-       _shufflewords_str = swapwords(_shufflewords_str, i, j);
-}
-string shufflewords(string str)
-{
-       float n;
-       _shufflewords_str = str;
-       n = tokenizebyseparator(str, " ");
-       shuffle(n, _shufflewords_swapfunc, world);
-       str = _shufflewords_str;
-       _shufflewords_str = string_null;
-       return str;
-}
-
 vector solve_quadratic(float a, float b, float c) // ax^2 + bx + c = 0
 {
        vector v;
@@ -1759,89 +1523,6 @@ vector decompressShotOrigin(int f)
        return v;
 }
 
-void heapsort(float n, swapfunc_t swap, comparefunc_t cmp, entity pass)
-{
-       float start, end, root, child;
-
-       // heapify
-       start = floor((n - 2) / 2);
-       while(start >= 0)
-       {
-               // siftdown(start, count-1);
-               root = start;
-               while(root * 2 + 1 <= n-1)
-               {
-                       child = root * 2 + 1;
-                       if(child < n-1)
-                               if(cmp(child, child+1, pass) < 0)
-                                       ++child;
-                       if(cmp(root, child, pass) < 0)
-                       {
-                               swap(root, child, pass);
-                               root = child;
-                       }
-                       else
-                               break;
-               }
-               // end of siftdown
-               --start;
-       }
-
-       // extract
-       end = n - 1;
-       while(end > 0)
-       {
-               swap(0, end, pass);
-               --end;
-               // siftdown(0, end);
-               root = 0;
-               while(root * 2 + 1 <= end)
-               {
-                       child = root * 2 + 1;
-                       if(child < end && cmp(child, child+1, pass) < 0)
-                               ++child;
-                       if(cmp(root, child, pass) < 0)
-                       {
-                               swap(root, child, pass);
-                               root = child;
-                       }
-                       else
-                               break;
-               }
-               // end of siftdown
-       }
-}
-
-void RandomSelection_Init()
-{
-       RandomSelection_totalweight = 0;
-       RandomSelection_chosen_ent = world;
-       RandomSelection_chosen_float = 0;
-       RandomSelection_chosen_string = string_null;
-       RandomSelection_best_priority = -1;
-}
-void RandomSelection_Add(entity e, float f, string s, float weight, float priority)
-{
-       if(priority > RandomSelection_best_priority)
-       {
-               RandomSelection_best_priority = priority;
-               RandomSelection_chosen_ent = e;
-               RandomSelection_chosen_float = f;
-               RandomSelection_chosen_string = s;
-               RandomSelection_totalweight = weight;
-       }
-       else if(priority == RandomSelection_best_priority)
-       {
-               RandomSelection_totalweight += weight;
-               if(random() * RandomSelection_totalweight <= weight)
-               {
-                       RandomSelection_chosen_ent = e;
-                       RandomSelection_chosen_float = f;
-                       RandomSelection_chosen_string = s;
-               }
-       }
-}
-
 #ifndef MENUQC
 vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype)
 {
@@ -1891,63 +1572,6 @@ string getcurrentmod()
                return argv(n - 1);
 }
 
-#ifndef MENUQC
-#ifdef CSQC
-int ReadInt24_t()
-{
-       int v = ReadShort() * 256; // note: this is signed
-       v += ReadByte(); // note: this is unsigned
-       return v;
-}
-vector ReadInt48_t()
-{
-       vector v;
-       v.x = ReadInt24_t();
-       v.y = ReadInt24_t();
-       v.z = 0;
-       return v;
-}
-vector ReadInt72_t()
-{
-       vector v;
-       v.x = ReadInt24_t();
-       v.y = ReadInt24_t();
-       v.z = ReadInt24_t();
-       return v;
-}
-#else
-void WriteInt24_t(float dst, float val)
-{
-       float v;
-       WriteShort(dst, (v = floor(val / 256)));
-       WriteByte(dst, val - v * 256); // 0..255
-}
-void WriteInt48_t(float dst, vector val)
-{
-       WriteInt24_t(dst, val.x);
-       WriteInt24_t(dst, val.y);
-}
-void WriteInt72_t(float dst, vector val)
-{
-       WriteInt24_t(dst, val.x);
-       WriteInt24_t(dst, val.y);
-       WriteInt24_t(dst, val.z);
-}
-#endif
-#endif
-
-float float2range11(float f)
-{
-       // continuous function mapping all reals into -1..1
-       return f / (fabs(f) + 1);
-}
-
-float float2range01(float f)
-{
-       // continuous function mapping all reals into 0..1
-       return 0.5 + 0.5 * float2range11(f);
-}
-
 // from the GNU Scientific Library
 float gsl_ran_gaussian_lastvalue;
 float gsl_ran_gaussian_lastvalue_set;
@@ -1969,22 +1593,6 @@ float gsl_ran_gaussian(float sigma)
        }
 }
 
-string car(string s)
-{
-       float o;
-       o = strstrofs(s, " ", 0);
-       if(o < 0)
-               return s;
-       return substring(s, 0, o);
-}
-string cdr(string s)
-{
-       float o;
-       o = strstrofs(s, " ", 0);
-       if(o < 0)
-               return string_null;
-       return substring(s, o + 1, strlen(s) - (o + 1));
-}
 float matchacl(string acl, string str)
 {
        string t, s;
@@ -2018,14 +1626,6 @@ float matchacl(string acl, string str)
        }
        return r;
 }
-float startsWith(string haystack, string needle)
-{
-       return substring(haystack, 0, strlen(needle)) == needle;
-}
-float startsWithNocase(string haystack, string needle)
-{
-       return strcasecmp(substring(haystack, 0, strlen(needle)), needle) == 0;
-}
 
 string get_model_datafilename(string m, float sk, string fil)
 {
@@ -2150,28 +1750,6 @@ float get_model_parameters(string m, float sk)
        return 1;
 }
 
-vector vec2(vector v)
-{
-       v.z = 0;
-       return v;
-}
-
-#ifndef MENUQC
-vector NearestPointOnBox(entity box, vector org)
-{
-       vector m1, m2, nearest;
-
-       m1 = box.mins + box.origin;
-       m2 = box.maxs + box.origin;
-
-       nearest.x = bound(m1_x, org.x, m2_x);
-       nearest.y = bound(m1_y, org.y, m2_y);
-       nearest.z = bound(m1_z, org.z, m2_z);
-
-       return nearest;
-}
-#endif
-
 float vercmp_recursive(string v1, string v2)
 {
        float dot1, dot2;
@@ -2223,26 +1801,6 @@ float vercmp(string v1, string v2)
        return vercmp_recursive(v1, v2);
 }
 
-float u8_strsize(string s)
-{
-       float l, i, c;
-       l = 0;
-       for(i = 0; ; ++i)
-       {
-               c = str2chr(s, i);
-               if(c <= 0)
-                       break;
-               ++l;
-               if(c >= 0x80)
-                       ++l;
-               if(c >= 0x800)
-                       ++l;
-               if(c >= 0x10000)
-                       ++l;
-       }
-       return l;
-}
-
 // x-encoding (encoding as zero length invisible string)
 const string XENCODE_2  = "xX";
 const string XENCODE_22 = "0123456789abcdefABCDEF";
@@ -2277,16 +1835,6 @@ float xdecode(string s)
        return ((a * 22 + b) * 22 + c) * 22 + d;
 }
 
-int lowestbit(int f)
-{
-       f &= ~(f * 2);
-       f &= ~(f * 4);
-       f &= ~(f * 16);
-       f &= ~(f * 256);
-       f &= ~(f * 65536);
-       return f;
-}
-
 /*
 string strlimitedlen(string input, string truncation, float strip_colors, float limit)
 {
@@ -2296,16 +1844,6 @@ string strlimitedlen(string input, string truncation, float strip_colors, float
                return strcat(substring(input, 0, (strlen(input) - strlen(truncation))), truncation);
 }*/
 
-// escape the string to make it safe for consoles
-string MakeConsoleSafe(string input)
-{
-       input = strreplace("\n", "", input);
-       input = strreplace("\\", "\\\\", input);
-       input = strreplace("$", "$$", input);
-       input = strreplace("\"", "\\\"", input);
-       return input;
-}
-
 #ifdef CSQC
 entity ReadCSQCEntity()
 {
@@ -2413,80 +1951,6 @@ void queue_to_execute_next_frame(string s)
        to_execute_next_frame = strzone(s);
 }
 
-float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
-{
-       return
-               (((     startspeedfactor + endspeedfactor - 2
-               ) * x - 2 * startspeedfactor - endspeedfactor + 3
-               ) * x + startspeedfactor
-               ) * x;
-}
-
-float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
-{
-       if(startspeedfactor < 0 || endspeedfactor < 0)
-               return false;
-
-       /*
-       // if this is the case, the possible zeros of the first derivative are outside
-       // 0..1
-       We can calculate this condition as condition
-       if(se <= 3)
-               return true;
-       */
-
-       // better, see below:
-       if(startspeedfactor <= 3 && endspeedfactor <= 3)
-               return true;
-
-       // if this is the case, the first derivative has no zeros at all
-       float se = startspeedfactor + endspeedfactor;
-       float s_e = startspeedfactor - endspeedfactor;
-       if(3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
-               return true;
-
-       // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
-       // we also get s_e <= 6 - se
-       // 3 * (se - 4)^2 + (6 - se)^2
-       // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
-       // Therefore, above "better" check works!
-
-       return false;
-
-       // known good cases:
-       // (0, [0..3])
-       // (0.5, [0..3.8])
-       // (1, [0..4])
-       // (1.5, [0..3.9])
-       // (2, [0..3.7])
-       // (2.5, [0..3.4])
-       // (3, [0..3])
-       // (3.5, [0.2..2.3])
-       // (4, 1)
-
-       /*
-          On another note:
-          inflection point is always at (2s + e - 3) / (3s + 3e - 6).
-
-          s + e - 2 == 0: no inflection
-
-          s + e > 2:
-          0 < inflection < 1 if:
-          0 < 2s + e - 3 < 3s + 3e - 6
-          2s + e > 3 and 2e + s > 3
-
-          s + e < 2:
-          0 < inflection < 1 if:
-          0 > 2s + e - 3 > 3s + 3e - 6
-          2s + e < 3 and 2e + s < 3
-
-          Therefore: there is an inflection point iff:
-          e outside (3 - s)/2 .. 3 - s*2
-
-          in other words, if (s,e) in triangle (1,1)(0,3)(0,1.5) or in triangle (1,1)(3,0)(1.5,0)
-       */
-}
-
 .float FindConnectedComponent_processing;
 void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass)
 {
@@ -2529,61 +1993,6 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
                queue_start.FindConnectedComponent_processing = 0;
 }
 
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z)
-{
-       vector result; result_x = x; result_y = y; result_z = z;
-       return result;
-}
-
-vector get_corner_position(entity box, float corner)
-{
-       switch(corner)
-       {
-               case 1: return combine_to_vector(box.absmin.x, box.absmin.y, box.absmin.z);
-               case 2: return combine_to_vector(box.absmax.x, box.absmin.y, box.absmin.z);
-               case 3: return combine_to_vector(box.absmin.x, box.absmax.y, box.absmin.z);
-               case 4: return combine_to_vector(box.absmin.x, box.absmin.y, box.absmax.z);
-               case 5: return combine_to_vector(box.absmax.x, box.absmax.y, box.absmin.z);
-               case 6: return combine_to_vector(box.absmin.x, box.absmax.y, box.absmax.z);
-               case 7: return combine_to_vector(box.absmax.x, box.absmin.y, box.absmax.z);
-               case 8: return combine_to_vector(box.absmax.x, box.absmax.y, box.absmax.z);
-               default: return '0 0 0';
-       }
-}
-#endif
-
-// color code replace, place inside of sprintf and parse the string
-string CCR(string input)
-{
-       // See the autocvar declarations in util.qh for default values
-
-       // foreground/normal colors
-       input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
-       input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
-       input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input);
-       input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input);
-
-       // "kill" colors
-       input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
-       input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input);
-       input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input);
-
-       // background colors
-       input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input);
-       input = strreplace("^N", "^7", input); // "none"-- reset to white...
-       return input;
-}
-
-vector vec3(float x, float y, float z)
-{
-       vector v;
-       v.x = x;
-       v.y = y;
-       v.z = z;
-       return v;
-}
-
 #ifndef MENUQC
 vector animfixfps(entity e, vector a, vector b)
 {
@@ -2759,18 +2168,3 @@ int Mod_Q1BSP_NativeContentsFromSuperContents(int supercontents)
        return CONTENT_EMPTY;
 }
 #endif
-
-vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
-{
-       return
-               (c - 2 * b + a) * (t * t) +
-               (b - a) * (2 * t) +
-               a;
-}
-
-vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
-{
-       return
-               (c - 2 * b + a) * (2 * t) +
-               (b - a) * 2;
-}
index e3fab47b7da6d9961c982b9eda081f71a6bbde7f..a2774aa509d1dd1909849f29cb959e95227fe2bd 100644 (file)
@@ -130,11 +130,6 @@ string getWrappedLineLen(float w, textLengthUpToLength_lenFunction_t tw);
 
 float isGametypeInFilter(float gt, float tp, float ts, string pattern);
 
-typedef void(float i1, float i2, entity pass) swapfunc_t; // is only ever called for i1 < i2
-typedef float(float i1, float i2, entity pass) comparefunc_t; // <0 for <, ==0 for ==, >0 for > (like strcmp)
-void shuffle(float n, swapfunc_t swap, entity pass);
-void heapsort(float n, swapfunc_t swap, comparefunc_t cmp, entity pass);
-
 string swapwords(string str, float i, float j);
 string shufflewords(string str);
 
@@ -157,14 +152,6 @@ string rankings_reply, ladder_reply, lsmaps_reply, maplist_reply, monsterlist_re
 string records_reply[10];
 #endif
 
-float RandomSelection_totalweight;
-float RandomSelection_best_priority;
-entity RandomSelection_chosen_ent;
-float RandomSelection_chosen_float;
-string RandomSelection_chosen_string;
-void RandomSelection_Init();
-void RandomSelection_Add(entity e, float f, string s, float weight, float priority);
-
 #ifndef MENUQC
 vector healtharmor_maxdamage(float h, float a, float armorblock, int deathtype); // returns vector: maxdamage, armorideal, 1 if fully armored
 vector healtharmor_applydamage(float a, float armorblock, int deathtype, float damage); // returns vector: take, save, 0
@@ -230,12 +217,6 @@ const float XENCODE_LEN = 5;
 string xencode(float f);
 float xdecode(string s);
 
-// Play all sounds via sound7, for access to the extra channels.
-// Otherwise, channels 8 to 15 would be blocked for a weird QW feature.
-#define sound(e,c,s,v,a) sound7(e,c,s,v,a,0,0)
-
-int lowestbit(float f);
-
 #ifdef CSQC
 entity ReadCSQCEntity();
 #endif
@@ -285,11 +266,6 @@ typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_
 typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
 void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
 
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z);
-vector get_corner_position(entity box, float corner);
-#endif
-
 // expand multiple arguments into one argument by stripping parenthesis
 #define XPD(...) __VA_ARGS__
 
@@ -297,19 +273,6 @@ vector get_corner_position(entity box, float corner);
 #define fprintf(file, ...) fputs(file, sprintf(__VA_ARGS__))
 #define bprintf(...) bprint(sprintf(__VA_ARGS__))
 
-// color code replace, place inside of sprintf and parse the string... defaults described as constants
-// foreground/normal colors
-string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green  // primary priority (important names, etc)
-string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc)
-string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue   // tertiary priority or relatively inconsequential text
-string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red    // notice/attention grabbing texting
-// "kill" colors
-string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red    // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
-string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type
-string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue   // "good" or "beneficial" text (you fragging someone, etc)
-// background color
-string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text
-
 string CCR(string input);
 
 #ifndef MENUQC
index eda4e00bbb1a20569278382f63620e234038ed2c..e4c73a4492842cebc517c466ddb7eefc31d166c6 100644 (file)
@@ -1,6 +1,6 @@
-#include "unit/spiderbot.qc"
-#include "unit/raptor.qc"
-#include "unit/racer.qc"
+#include "vehicle/spiderbot.qc"
+#include "vehicle/raptor.qc"
+#include "vehicle/racer.qc"
 #ifndef VEHICLES_NO_UNSTABLE
-       #include "unit/bumblebee.qc"
+       #include "vehicle/bumblebee.qc"
 #endif
index f0316ab1fac7f2da65c7269dcd43b56b345ff060..72d72d29d19d14a1cd7de16ce51a8399c1347d74 100644 (file)
@@ -3,33 +3,10 @@
 
 #include "all.qh"
 
-#if defined(SVQC)
-       #include "sv_vehicles.qc"
-#elif defined(CSQC)
-       #include "cl_vehicles.qc"
-#endif
-
-#define IMPLEMENTATION
-#include "all.inc"
-#undef IMPLEMENTATION
-
 #ifndef MENUQC
 STATIC_INIT(vehicles_common_initialize)
 {
-#ifdef CSQC
-       precache_model("models/vehicles/bomblet.md3");
-       precache_model("models/vehicles/clusterbomb.md3");
-       precache_model("models/vehicles/clusterbomb_fragment.md3");
-       precache_model("models/vehicles/rocket01.md3");
-       precache_model("models/vehicles/rocket02.md3");
-
-       precache_sound ("vehicles/alarm.wav");
-       precache_sound ("vehicles/alarm_shield.wav");
-#endif // CSQC
 #ifdef SVQC
-       precache_sound("onslaught/ons_hit2.wav");
-       precache_sound("onslaught/electricity_explode.wav");
-
        addstat(STAT_HUD, AS_INT, hud);
        addstat(STAT_VEHICLESTAT_HEALTH,  AS_INT, vehicle_health);
        addstat(STAT_VEHICLESTAT_SHIELD,  AS_INT, vehicle_shield);
@@ -46,11 +23,14 @@ STATIC_INIT(vehicles_common_initialize)
 }
 #endif
 
-entity get_vehicleinfo(int id)
-{
-       if (id < VEH_FIRST || id > VEH_LAST) return VEH_NULL;
-       entity m = vehicle_info[id];
-       return m ? m : VEH_NULL;
-}
+#if defined(SVQC)
+       #include "sv_vehicles.qc"
+#elif defined(CSQC)
+       #include "cl_vehicles.qc"
+#endif
+
+#define IMPLEMENTATION
+#include "all.inc"
+#undef IMPLEMENTATION
 
 #endif
index fa9e83f48531fa66231691391eade3a57781808f..a44eb2209e673768ada5904ab7043e70df5e8273 100644 (file)
@@ -1,82 +1,32 @@
 #ifndef VEHICLES_ALL_H
 #define VEHICLES_ALL_H
 
+#include "vehicle.qh"
+
+REGISTRY(Vehicles, BIT(3))
+REGISTER_REGISTRY(RegisterVehicles)
+const int VEH_FIRST = 1;
+#define VEH_LAST (Vehicles_COUNT - 1)
+
+/** If you register a new vehicle, make sure to add it to all.inc */
+#define REGISTER_VEHICLE(id, inst) REGISTER(RegisterVehicles, VEH, Vehicles, id, vehicleid, inst)
+
 #if defined(SVQC)
        #include "sv_vehicles.qh"
 #elif defined(CSQC)
        #include "cl_vehicles.qh"
 #endif
 
+REGISTER_VEHICLE(Null, NEW(Vehicle));
 
-// vehicle requests
-const int VR_SETUP          = 1; // (BOTH) setup vehicle data
-const int VR_THINK                     = 2; // (SERVER) logic to run every frame
-const int VR_DEATH          = 3; // (SERVER) called when vehicle dies
-const int VR_PRECACHE       = 4; // (BOTH) precaches models/sounds used by this vehicle
-const int VR_ENTER          = 5; // (SERVER) called when a player enters this vehicle
-const int VR_SPAWN          = 6; // (SERVER) called when the vehicle re-spawns
-const int VR_IMPACT         = 7; // (SERVER) called when a vehicle hits something
-const int VR_HUD            = 8; // (CLIENT) logic to run every frame
-
-// vehicle spawn flags (need them here for common registrations)
-const int VHF_ISVEHICLE                        = 2; /// Indicates vehicle
-const int VHF_HASSHIELD                        = 4; /// Vehicle has shileding
-const int VHF_SHIELDREGEN              = 8; /// Vehicles shield regenerates
-const int VHF_HEALTHREGEN              = 16; /// Vehicles health regenerates
-const int VHF_ENERGYREGEN              = 32; /// Vehicles energy regenerates
-const int VHF_DEATHEJECT               = 64; /// Vehicle ejects pilot upon fatal damage
-const int VHF_MOVE_GROUND              = 128; /// Vehicle moves on gound
-const int VHF_MOVE_HOVER               = 256; /// Vehicle hover close to gound
-const int VHF_MOVE_FLY                 = 512; /// Vehicle is airborn
-const int VHF_DMGSHAKE                 = 1024; /// Add random velocity each frame if health < 50%
-const int VHF_DMGROLL                  = 2048; /// Add random angles each frame if health < 50%
-const int VHF_DMGHEADROLL              = 4096; /// Add random head angles each frame if health < 50%
-const int VHF_MULTISLOT                        = 8192; /// Vehicle has multiple player slots
-const int VHF_PLAYERSLOT               = 16384; /// This ent is a player slot on a multi-person vehicle
-
-// functions:
-entity get_vehicleinfo(float id);
-
-// fields:
-.entity tur_head;
-
-
-// other useful macros
-#define VEH_ACTION(vehicletype,mrequest) (get_vehicleinfo(vehicletype)).vehicle_func(mrequest)
-#define VEH_NAME(vehicletype) (get_vehicleinfo(vehicletype)).vehicle_name
-
-// =====================
-//  Vehicle Registration
-// =====================
-
-void RegisterVehicles();
-const int VEH_MAXCOUNT = 24;
-entity vehicle_info[VEH_MAXCOUNT], vehicle_info_first, vehicle_info_last;
-int VEH_COUNT;
-const int VEH_FIRST = 1;
-#define VEH_LAST (VEH_FIRST + VEH_COUNT - 1)
-/** If you register a new vehicle, make sure to add it to all.inc */
-#define REGISTER_VEHICLE(id, class) REGISTER(RegisterVehicles, VEH, vehicle_info, VEH_COUNT, id, vehicleid, NEW(class))
-#include "vehicle.qh"
-#define REGISTER_VEHICLE_SIMPLE(id, vehicleflags, min_s, max_s, modelname, headmodelname, hudmodelname, headtag, hudtag, viewtag, shortname, vname) \
-    REGISTER_VEHICLE(id, Vehicle) {         \
-       this.netname = shortname;           \
-       this.vehicle_name = vname;          \
-       this.mdl = modelname;               \
-       this.spawnflags = vehicleflags;     \
-       this.mins = min_s;                  \
-       this.maxs = max_s;                  \
-       this.model = modelname;             \
-       this.head_model = headmodelname;    \
-       this.hud_model = hudmodelname;      \
-       this.tag_head = headtag;            \
-       this.tag_hud = hudtag;              \
-       this.tag_view = viewtag;            \
-    }                                       \
-    REGISTER_INIT(VEH, id)
-REGISTER_REGISTRY(RegisterVehicles)
-
-REGISTER_VEHICLE(NULL, Vehicle);
+Vehicle get_vehicleinfo(int id)
+{
+       if (id >= VEH_FIRST && id <= VEH_LAST) {
+               Vehicle v = Vehicles[id];
+               if (v) return v;
+       }
+       return VEH_Null;
+}
 
 #include "all.inc"
 
index 141f8fc42d59b5362e4e8bfad7712cc27c8c22fb..3472a7f1c7e7e76747e0b056ef22c31d12c589ca 100644 (file)
@@ -23,10 +23,10 @@ void vehicle_alarm(entity e, int ch, string s0und)
        if(!autocvar_cl_vehicles_alarm)
                return;
 
-       sound(e, ch, s0und, VOL_BASEVOICE, ATTEN_NONE);
+       _sound(e, ch, s0und, VOL_BASEVOICE, ATTEN_NONE);
 }
 
-void AuxiliaryXhair_Draw2D()
+void AuxiliaryXhair_Draw2D(entity this)
 {
        if (scoreboard_showscores)
                return;
@@ -73,14 +73,14 @@ void Net_AuXair2(bool bIsNew)
 }
 
 void Net_VehicleSetup()
-{
+{SELFPARAM();
        int hud_id = ReadByte();
 
        // hud_id == 0 means we exited a vehicle, so stop alarm sound/s
        if(hud_id == 0)
        {
-               sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
-               sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
+               sound(self, CH_TRIGGER_SINGLE, SND_Null, VOL_BASEVOICE, ATTEN_NONE);
+               sound(self, CH_PAIN_SINGLE, SND_Null, VOL_BASEVOICE, ATTEN_NONE);
                return;
        }
 
@@ -106,8 +106,10 @@ void Net_VehicleSetup()
        {
                AuxiliaryXhair[0].axh_image = vCROSS_BURST; // Plasma cannons
                AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Raygun
+       } else {
+               Vehicle info = get_vehicleinfo(hud_id);
+       info.vr_setup(info);
        }
-       else { VEH_ACTION(hud_id, VR_SETUP); }
 }
 
 void Vehicles_drawHUD(
@@ -119,7 +121,7 @@ void Vehicles_drawHUD(
        string iconAmmo2,
        vector colorAmmo2,
        string crosshair)
-{
+{SELFPARAM();
        if(autocvar_r_letterbox)
                return;
 
@@ -235,7 +237,7 @@ void Vehicles_drawHUD(
                if(alarm1time < time)
                {
                        alarm1time = time + 2;
-                       vehicle_alarm(self, CH_PAIN_SINGLE, "vehicles/alarm.wav");
+                       vehicle_alarm(self, CH_PAIN_SINGLE, SND(VEH_ALARM));
                }
                drawpic_skin(tmpPos, "vehicle_icon_health", tmpSize, '1 1 1', hudAlpha * blinkValue, DRAWFLAG_NORMAL);
        }
@@ -243,7 +245,7 @@ void Vehicles_drawHUD(
        {
                if(alarm1time)
                {
-                       vehicle_alarm(self, CH_PAIN_SINGLE, "misc/null.wav");
+                       vehicle_alarm(self, CH_PAIN_SINGLE, SND(Null));
                        alarm1time = 0;
                }
                drawpic_skin(tmpPos, "vehicle_icon_health", tmpSize, '1 1 1', hudAlpha, DRAWFLAG_NORMAL);
@@ -257,7 +259,7 @@ void Vehicles_drawHUD(
                if(alarm2time < time)
                {
                        alarm2time = time + 1;
-                       vehicle_alarm(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav");
+                       vehicle_alarm(self, CH_TRIGGER_SINGLE, SND(VEH_ALARM_SHIELD));
                }
                drawpic_skin(tmpPos, "vehicle_icon_shield", tmpSize, '1 1 1', hudAlpha * blinkValue, DRAWFLAG_NORMAL);
        }
@@ -265,7 +267,7 @@ void Vehicles_drawHUD(
        {
                if(alarm2time)
                {
-                       vehicle_alarm(self, CH_TRIGGER_SINGLE, "misc/null.wav");
+                       vehicle_alarm(self, CH_TRIGGER_SINGLE, SND(Null));
                        alarm2time = 0;
                }
                drawpic_skin(tmpPos, "vehicle_icon_shield", tmpSize, '1 1 1', hudAlpha, DRAWFLAG_NORMAL);
index a495f036705874843ea21d755ba2daded058ef8c..bf96d95ea367bbad6641f4343ba75a86a9ff04ab 100644 (file)
@@ -5,7 +5,7 @@ void Net_AuXair2(float bIsNew);
 
 void Net_VehicleSetup();
 
-void RaptorCBShellfragDraw();
+void RaptorCBShellfragDraw(entity this);
 void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang);
 
 #define weapon2mode getstati(STAT_VEHICLESTAT_W2MODE)
index 523156006d9c9067315533bb68a34c7fa67430a8..7108e80770cf20e235a8ca81799e56bbfda79fcd 100644 (file)
@@ -1,5 +1,5 @@
 #include "sv_vehicles.qh"
-#include "../effects.qh"
+#include "../effects/effects.qh"
 
 #if 0
 bool vehicle_send(entity to, int sf)
@@ -38,7 +38,7 @@ bool vehicle_send(entity to, int sf)
 }
 #endif
 
-bool SendAuxiliaryXhair(entity to, int sf)
+bool SendAuxiliaryXhair(entity this, entity to, int sf)
 {
 
        WriteByte(MSG_ENTITY, ENT_CLIENT_AUXILIARYXHAIR);
@@ -94,7 +94,7 @@ void CSQCVehicleSetup(entity own, int vehicle_id)
 }
 
 vector targetdrone_getnewspot()
-{
+{SELFPARAM();
        vector spot;
        int i;
        for(i = 0; i < 100; ++i)
@@ -108,7 +108,7 @@ vector targetdrone_getnewspot()
 }
 
 void vehicles_locktarget(float incr, float decr, float _lock_time)
-{
+{SELFPARAM();
        if(self.lock_target && self.lock_target.deadflag != DEAD_NO)
        {
                self.lock_target        = world;
@@ -181,7 +181,7 @@ void vehicles_locktarget(float incr, float decr, float _lock_time)
 }
 
 vector vehicles_force_fromtag_hover(string tag_name, float spring_length, float max_power)
-{
+{SELFPARAM();
        force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name));
        v_forward  = normalize(v_forward) * -1;
        traceline(force_fromtag_origin, force_fromtag_origin - (v_forward  * spring_length), MOVE_NORMAL, self);
@@ -193,7 +193,7 @@ vector vehicles_force_fromtag_hover(string tag_name, float spring_length, float
 }
 
 vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float max_power)
-{
+{SELFPARAM();
 
        force_fromtag_origin = gettaginfo(self, gettagindex(self, tag_name));
        v_forward  = normalize(v_forward) * -1;
@@ -214,7 +214,7 @@ vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float
 
 // projectile handling
 void vehicles_projectile_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        // Ignore damage from oterh projectiles from my owner (dont mess up volly's)
        if(inflictor.owner == self.owner)
                return;
@@ -231,7 +231,7 @@ void vehicles_projectile_damage(entity inflictor, entity attacker, float damage,
 }
 
 void vehicles_projectile_explode()
-{
+{SELFPARAM();
        if(self.owner && other != world)
        {
                if(other == self.owner.vehicle)
@@ -254,7 +254,7 @@ entity vehicles_projectile(string _mzlfx, string _mzlsound,
                                                   float _dmg, float _radi, float _force,  float _size,
                                                   int _deahtype, float _projtype, float _health,
                                                   bool _cull, bool _clianim, entity _owner)
-{
+{SELFPARAM();
        entity proj;
 
        proj = spawn();
@@ -289,7 +289,7 @@ entity vehicles_projectile(string _mzlfx, string _mzlsound,
                proj.flags                 = FL_PROJECTILE | FL_NOTARGET;
 
        if(_mzlsound)
-               sound (self, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM);
 
        if(_mzlfx)
                Send_Effect_(_mzlfx, proj.origin, proj.velocity, 1);
@@ -302,15 +302,15 @@ entity vehicles_projectile(string _mzlfx, string _mzlsound,
 }
 
 void vehicles_gib_explode()
-{
-       sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+{SELFPARAM();
+       sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
        Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
        Send_Effect(EFFECT_EXPLOSION_SMALL, self.wp00.origin + '0 0 64', '0 0 0', 1);
        remove(self);
 }
 
 void vehicles_gib_think()
-{
+{SELFPARAM();
        self.alpha -= 0.1;
        if(self.cnt >= time)
                remove(self);
@@ -319,9 +319,9 @@ void vehicles_gib_think()
 }
 
 entity vehicle_tossgib(entity _template, vector _vel, string _tag, bool _burn, bool _explode, float _maxtime, vector _rot)
-{
+{SELFPARAM();
        entity _gib = spawn();
-       setmodel(_gib, _template.model);
+       _setmodel(_gib, _template.model);
        setorigin(_gib, gettaginfo(self, gettagindex(self, _tag)));
        _gib.velocity = _vel;
        _gib.movetype = MOVETYPE_TOSS;
@@ -369,8 +369,8 @@ bool vehicle_addplayerslot( entity _owner,
        _slot.vehicle_hudmodel.viewmodelforclient = _slot;
        _slot.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT);
 
-       setmodel(_slot.vehicle_hudmodel, _hud_model);
-       setmodel(_slot.vehicle_viewport, "null");
+       _setmodel(_slot.vehicle_hudmodel, _hud_model);
+       setmodel(_slot.vehicle_viewport, MDL_Null);
 
        setattachment(_slot.vehicle_hudmodel, _slot, "");
        setattachment(_slot.vehicle_viewport, _slot.vehicle_hudmodel, "");
@@ -397,7 +397,7 @@ vector vehicle_aimturret(entity _vehic, vector _target, entity _turrret, string
 }
 
 void vehicles_reset_colors()
-{
+{SELFPARAM();
        entity e;
        float _effects = 0, _colormap;
        vector _glowmod, _colormod;
@@ -478,7 +478,7 @@ void vehicles_clearreturn(entity veh)
 
 void vehicles_spawn();
 void vehicles_return()
-{
+{SELFPARAM();
        Send_Effect(EFFECT_TELEPORT, self.wp00.origin + '0 0 64', '0 0 0', 1);
 
        self.wp00.think  = vehicles_spawn;
@@ -491,7 +491,7 @@ void vehicles_return()
 }
 
 void vehicles_showwp_goaway()
-{
+{SELFPARAM();
        if(self.waypointsprite_attached)
                WaypointSprite_Kill(self.waypointsprite_attached);
 
@@ -500,7 +500,7 @@ void vehicles_showwp_goaway()
 }
 
 void vehicles_showwp()
-{
+{SELFPARAM();
        entity oldself = world;
        vector rgb;
 
@@ -515,8 +515,8 @@ void vehicles_showwp()
                self.nextthink  = time +1;
 
                oldself = self;
-               self = spawn();
-               setmodel(self, "null");
+               setself(spawn());
+               setmodel(self, MDL_Null);
                self.team = oldself.wp00.team;
                self.wp00 = oldself.wp00;
                setorigin(self, oldself.wp00.pos1);
@@ -529,18 +529,18 @@ void vehicles_showwp()
                rgb = Team_ColorRGB(self.team);
        else
                rgb = '1 1 1';
-       entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
+       entity wp = WaypointSprite_Spawn(WP_Vehicle, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Vehicle);
        wp.colormod = rgb;
        if(self.waypointsprite_attached)
        {
                WaypointSprite_UpdateRule(self.waypointsprite_attached, self.wp00.team, SPRITERULE_DEFAULT);
-               if(oldself == world)
+               if(this == NULL)
                        WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, self.nextthink);
                WaypointSprite_Ping(self.waypointsprite_attached);
        }
 
-       if(oldself != world)
-               self = oldself;
+       if(this)
+               setself(this);
 }
 
 void vehicles_setreturn(entity veh)
@@ -565,13 +565,13 @@ void vehicles_setreturn(entity veh)
                ret.nextthink   = min(time + veh.respawntime, time + veh.respawntime - 1);
        }
 
-       setmodel(ret, "null");
+       setmodel(ret, MDL_Null);
        setorigin(ret, veh.pos1 + '0 0 96');
 
 }
 
 void vehicle_use()
-{
+{SELFPARAM();
        LOG_TRACE("vehicle ",self.netname, " used by ", activator.classname, "\n");
 
        self.tur_head.team = activator.team;
@@ -598,26 +598,26 @@ void vehicle_use()
 }
 
 void vehicles_regen(float timer, .float regen_field, float field_max, float rpause, float regen, float delta_time, float _healthscale)
-{
-       if(self.regen_field < field_max)
+{SELFPARAM();
+       if(self.(regen_field) < field_max)
        if(timer + rpause < time)
        {
                if(_healthscale)
                        regen = regen * (self.vehicle_health / self.max_health);
 
-               self.regen_field = min(self.regen_field + regen * delta_time, field_max);
+               self.(regen_field) = min(self.(regen_field) + regen * delta_time, field_max);
 
                if(self.owner)
-                       self.owner.regen_field = (self.regen_field / field_max) * 100;
+                       self.owner.(regen_field) = (self.(regen_field) / field_max) * 100;
        }
 }
 
 void shieldhit_think()
-{
+{SELFPARAM();
        self.alpha -= 0.1;
        if (self.alpha <= 0)
        {
-               //setmodel(self, "");
+               // setmodel(self, MDL_Null);
                self.alpha = -1;
                self.effects |= EF_NODRAW;
        }
@@ -628,7 +628,7 @@ void shieldhit_think()
 }
 
 void vehicles_painframe()
-{
+{SELFPARAM();
        if(self.owner.vehicle_health <= 50)
        if(self.pain_frame < time)
        {
@@ -650,7 +650,7 @@ void vehicles_painframe()
 }
 
 void vehicles_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        self.dmg_time = time;
 
        // WEAPONTODO
@@ -683,7 +683,7 @@ void vehicles_damage(entity inflictor, entity attacker, float damage, int deatht
                        self.vehicle_shieldent = spawn();
                        self.vehicle_shieldent.effects = EF_LOWPRECISION;
 
-                       setmodel(self.vehicle_shieldent, "models/vhshield.md3");
+                       setmodel(self.vehicle_shieldent, MDL_VEH_SHIELD);
                        setattachment(self.vehicle_shieldent, self, "");
                        setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
                        self.vehicle_shieldent.scale       = 256 / vlen(self.maxs - self.mins);
@@ -737,7 +737,8 @@ void vehicles_damage(entity inflictor, entity attacker, float damage, int deatht
 
                antilag_clear(self);
 
-               VEH_ACTION(self.vehicleid, VR_DEATH);
+               Vehicle info = get_vehicleinfo(self.vehicleid);
+               info.vr_death(info);
                vehicles_setreturn(self);
        }
 }
@@ -754,7 +755,7 @@ float vehicles_crushable(entity e)
 }
 
 void vehicles_impact(float _minspeed, float _speedfac, float _maxpain)
-{
+{SELFPARAM();
        if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
                return;
 
@@ -777,7 +778,7 @@ void vehicles_impact(float _minspeed, float _speedfac, float _maxpain)
 
 // vehicle enter/exit handling
 vector vehicles_findgoodexit(vector prefer_spot)
-{
+{SELFPARAM();
        //vector exitspot;
        float mysize;
 
@@ -825,10 +826,9 @@ vector vehicles_findgoodexit(vector prefer_spot)
 }
 
 void vehicles_exit(bool eject)
-{
+{SELFPARAM();
        entity _vehicle;
        entity _player;
-       entity _oldself = self;
 
        if(vehicles_exit_running)
        {
@@ -844,7 +844,7 @@ void vehicles_exit(bool eject)
                if (_vehicle.vehicle_flags & VHF_PLAYERSLOT)
                {
                        _vehicle.vehicle_exit(eject);
-                       self = _oldself;
+                       setself(this);
                        vehicles_exit_running = false;
                        return;
                }
@@ -854,7 +854,7 @@ void vehicles_exit(bool eject)
 
        _player = _vehicle.owner;
 
-       self = _vehicle;
+       setself(_vehicle);
 
        if (_player)
        {
@@ -908,7 +908,7 @@ void vehicles_exit(bool eject)
 
        _vehicle.team = _vehicle.tur_head.team;
 
-       sound (_vehicle, CH_TRIGGER_SINGLE, "misc/null.wav", 1, ATTEN_NORM);
+       sound (_vehicle, CH_TRIGGER_SINGLE, SND_Null, 1, ATTEN_NORM);
        _vehicle.vehicle_hudmodel.viewmodelforclient = _vehicle;
        _vehicle.phase = time + 1;
 
@@ -918,15 +918,14 @@ void vehicles_exit(bool eject)
        vehicles_reset_colors();
        _vehicle.owner = world;
 
-       CSQCMODEL_AUTOINIT();
-
-       self = _oldself;
+       CSQCMODEL_AUTOINIT(self);
 
+       setself(this);
        vehicles_exit_running = false;
 }
 
 void vehicles_touch()
-{
+{SELFPARAM();
        if(MUTATOR_CALLHOOK(VehicleTouch, self, other))
                return;
 
@@ -944,8 +943,10 @@ void vehicles_touch()
                        return; // Dont do selfdamage when hitting "soft targets".
                }
 
-               if(self.play_time < time)
-                       VEH_ACTION(self.vehicleid, VR_IMPACT);
+               if(self.play_time < time) {
+                       Vehicle info = get_vehicleinfo(self.vehicleid);
+                       info.vr_impact(info);
+               }
 
                return;
        }
@@ -957,7 +958,7 @@ void vehicles_touch()
 }
 
 bool vehicle_impulse(int imp)
-{
+{SELFPARAM();
        switch(imp)
        {
                case 17:
@@ -971,7 +972,7 @@ bool vehicle_impulse(int imp)
 }
 
 void vehicles_enter(entity pl, entity veh)
-{
+{SELFPARAM();
    // Remove this when bots know how to use vehicles
        if((IS_BOT_CLIENT(pl) && !autocvar_g_vehicles_allow_bots))
                return;
@@ -988,8 +989,7 @@ void vehicles_enter(entity pl, entity veh)
        if(veh.vehicle_flags & VHF_MULTISLOT)
        if(veh.owner)
        {
-               entity oldself = self;
-               self = veh;
+               setself(veh);
                other = pl; // TODO: fix
 
                if(!veh.gunner1)
@@ -997,7 +997,7 @@ void vehicles_enter(entity pl, entity veh)
                if(veh.gun1.vehicle_enter)
                if(veh.gun1.vehicle_enter())
                {
-                       self = oldself;
+                       setself(this);
                        return;
                }
 
@@ -1006,11 +1006,11 @@ void vehicles_enter(entity pl, entity veh)
                if(veh.gun2.vehicle_enter)
                if(veh.gun2.vehicle_enter())
                {
-                       self = oldself;
+                       setself(this);
                        return;
                }
 
-               self = oldself;
+               setself(this);
        }
 
        if(teamplay)
@@ -1114,30 +1114,31 @@ void vehicles_enter(entity pl, entity veh)
 
        MUTATOR_CALLHOOK(VehicleEnter, pl, veh);
 
-       entity oldself = self;
-       self = veh;
-       CSQCModel_UnlinkEntity();
-       VEH_ACTION(veh.vehicleid, VR_ENTER);
-       self = oldself;
+       setself(veh);
+       CSQCModel_UnlinkEntity(veh);
+       Vehicle info = get_vehicleinfo(veh.vehicleid);
+       info.vr_enter(info);
+       setself(this);
 
        antilag_clear(pl);
 }
 
 void vehicles_think()
-{
+{SELFPARAM();
        self.nextthink = time;
 
        if(self.owner)
                self.owner.vehicle_weapon2mode = self.vehicle_weapon2mode;
 
-       VEH_ACTION(self.vehicleid, VR_THINK);
+       Vehicle info = get_vehicleinfo(self.vehicleid);
+       info.vr_think(info);
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 // initialization
 void vehicles_spawn()
-{
+{SELFPARAM();
        LOG_TRACE("Spawning vehicle: ", self.classname, "\n");
 
        // disown & reset
@@ -1181,20 +1182,24 @@ void vehicles_spawn()
 
        vehicles_reset_colors();
 
-       VEH_ACTION(self.vehicleid, VR_SPAWN);
+       Vehicle info = get_vehicleinfo(self.vehicleid);
+       info.vr_spawn(info);
 
-       CSQCMODEL_AUTOINIT();
+       CSQCMODEL_AUTOINIT(self);
 }
 
 bool vehicle_initialize(entity veh, bool nodrop)
-{
+{SELFPARAM();
        if(!autocvar_g_vehicles)
                return false;
 
        if(!veh.vehicleid)
                return false;
 
-       if(!veh.tur_head) { VEH_ACTION(veh.vehicleid, VR_PRECACHE); }
+       if(!veh.tur_head) {
+               Vehicle info = get_vehicleinfo(veh.vehicleid);
+               info.vr_precache(info);
+       }
 
        if(self.targetname && self.targetname != "")
        {
@@ -1224,9 +1229,9 @@ bool vehicle_initialize(entity veh, bool nodrop)
                self.team = 0;
 
        if(self.mdl == "" || !self.mdl)
-               setmodel(self, veh.model);
+               _setmodel(self, veh.model);
        else
-               setmodel(self, self.mdl);
+               _setmodel(self, self.mdl);
 
        self.vehicle_flags |= VHF_ISVEHICLE;
 
@@ -1257,12 +1262,12 @@ bool vehicle_initialize(entity veh, bool nodrop)
        if(autocvar_g_fullbrightplayers)
                self.effects |= EF_FULLBRIGHT;
 
-       setmodel(self.vehicle_hudmodel, veh.hud_model);
-       setmodel(self.vehicle_viewport, "null");
+       _setmodel(self.vehicle_hudmodel, veh.hud_model);
+       setmodel(self.vehicle_viewport, MDL_Null);
 
        if(veh.head_model != "")
        {
-               setmodel(self.tur_head, veh.head_model);
+               _setmodel(self.tur_head, veh.head_model);
                setattachment(self.tur_head, self, veh.tag_head);
                setattachment(self.vehicle_hudmodel, self.tur_head, veh.tag_hud);
                setattachment(self.vehicle_viewport, self.vehicle_hudmodel, veh.tag_view);
@@ -1287,7 +1292,8 @@ bool vehicle_initialize(entity veh, bool nodrop)
        self.pos2 = self.angles;
        self.tur_head.team = self.team;
 
-       VEH_ACTION(veh.vehicleid, VR_SETUP);
+       Vehicle info = get_vehicleinfo(veh.vehicleid);
+       info.vr_setup(info);
 
        if(self.active == ACTIVE_NOT)
                self.nextthink = 0; // wait until activated
diff --git a/qcsrc/common/vehicles/unit/bumblebee.qc b/qcsrc/common/vehicles/unit/bumblebee.qc
deleted file mode 100644 (file)
index 7ace822..0000000
+++ /dev/null
@@ -1,1133 +0,0 @@
-#ifndef VEHICLE_BUMBLEBEE
-#define VEHICLE_BUMBLEBEE
-#include "bumblebee.qh"
-#ifndef MENUQC
-int v_bumblebee(int);
-#endif
-REGISTER_VEHICLE_SIMPLE(
-/* VEH_##id   */ BUMBLEBEE,
-/* spawnflags */ VHF_DMGSHAKE,
-/* mins,maxs  */ '-245 -130 -130', '230 130 130',
-/* model         */ "models/vehicles/bumblebee_body.dpm",
-/* head_model */ "",
-/* hud_model  */ "models/vehicles/spiderbot_cockpit.dpm",
-/* tags                  */ "", "", "tag_viewport",
-/* netname       */ "bumblebee",
-/* fullname   */ _("Bumblebee")
-) {
-    this.m_icon = "vehicle_bumble";
-#ifndef MENUQC
-    this.vehicle_func = v_bumblebee;
-#endif
-}
-#endif
-
-#ifdef IMPLEMENTATION
-
-const float BRG_SETUP = 2;
-const float BRG_START = 4;
-const float BRG_END = 8;
-
-#ifdef SVQC
-float autocvar_g_vehicle_bumblebee_speed_forward;
-float autocvar_g_vehicle_bumblebee_speed_strafe;
-float autocvar_g_vehicle_bumblebee_speed_up;
-float autocvar_g_vehicle_bumblebee_speed_down;
-float autocvar_g_vehicle_bumblebee_turnspeed;
-float autocvar_g_vehicle_bumblebee_pitchspeed;
-float autocvar_g_vehicle_bumblebee_pitchlimit;
-float autocvar_g_vehicle_bumblebee_friction;
-
-float autocvar_g_vehicle_bumblebee_energy;
-float autocvar_g_vehicle_bumblebee_energy_regen;
-float autocvar_g_vehicle_bumblebee_energy_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_health;
-float autocvar_g_vehicle_bumblebee_health_regen;
-float autocvar_g_vehicle_bumblebee_health_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_shield;
-float autocvar_g_vehicle_bumblebee_shield_regen;
-float autocvar_g_vehicle_bumblebee_shield_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_cannon_cost;
-float autocvar_g_vehicle_bumblebee_cannon_damage;
-float autocvar_g_vehicle_bumblebee_cannon_radius;
-float autocvar_g_vehicle_bumblebee_cannon_refire;
-float autocvar_g_vehicle_bumblebee_cannon_speed;
-float autocvar_g_vehicle_bumblebee_cannon_spread;
-float autocvar_g_vehicle_bumblebee_cannon_force;
-
-float autocvar_g_vehicle_bumblebee_cannon_ammo;
-float autocvar_g_vehicle_bumblebee_cannon_ammo_regen;
-float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause;
-
-float autocvar_g_vehicle_bumblebee_cannon_lock = 0;
-
-float autocvar_g_vehicle_bumblebee_cannon_turnspeed;
-float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down;
-float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up;
-float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
-float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
-
-
-float autocvar_g_vehicle_bumblebee_raygun_turnspeed;
-float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down;
-float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up;
-float autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides;
-
-float autocvar_g_vehicle_bumblebee_raygun_range;
-float autocvar_g_vehicle_bumblebee_raygun_dps;
-float autocvar_g_vehicle_bumblebee_raygun_aps;
-float autocvar_g_vehicle_bumblebee_raygun_fps;
-
-float autocvar_g_vehicle_bumblebee_raygun;
-float autocvar_g_vehicle_bumblebee_healgun_hps;
-float autocvar_g_vehicle_bumblebee_healgun_hmax;
-float autocvar_g_vehicle_bumblebee_healgun_aps;
-float autocvar_g_vehicle_bumblebee_healgun_amax;
-float autocvar_g_vehicle_bumblebee_healgun_sps;
-float autocvar_g_vehicle_bumblebee_healgun_locktime;
-
-float autocvar_g_vehicle_bumblebee_respawntime;
-
-float autocvar_g_vehicle_bumblebee_blowup_radius;
-float autocvar_g_vehicle_bumblebee_blowup_coredamage;
-float autocvar_g_vehicle_bumblebee_blowup_edgedamage;
-float autocvar_g_vehicle_bumblebee_blowup_forceintensity;
-vector autocvar_g_vehicle_bumblebee_bouncepain;
-
-bool autocvar_g_vehicle_bumblebee = 0;
-
-float bumble_raygun_send(entity to, int sf);
-
-void bumblebee_fire_cannon(entity _gun, string _tagname, entity _owner)
-{
-       vector v = gettaginfo(_gun, gettagindex(_gun, _tagname));
-       vehicles_projectile(EFFECT_BIGPLASMA_MUZZLEFLASH.eent_eff_name, W_Sound("flacexp3"),
-                                               v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed,
-                                               autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force,  0,
-                                               DEATH_VH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, true, true, _owner);
-}
-
-float bumblebee_gunner_frame()
-{
-       entity vehic    = self.vehicle.owner;
-       entity gun      = self.vehicle;
-       entity gunner   = self;
-       self = vehic;
-
-       vehic.solid = SOLID_NOT;
-       //setorigin(gunner, vehic.origin);
-       gunner.velocity = vehic.velocity;
-
-       float _in, _out;
-       vehic.angles_x *= -1;
-       makevectors(vehic.angles);
-       vehic.angles_x *= -1;
-       if(gun == vehic.gun1)
-       {
-               _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
-               _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
-               setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * 128);
-       }
-       else
-       {
-               _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
-               _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
-               setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128);
-       }
-
-       crosshair_trace(gunner);
-       vector _ct = trace_endpos;
-       vector ad;
-
-       if(autocvar_g_vehicle_bumblebee_cannon_lock)
-       {
-               if(gun.lock_time < time)
-                       gun.enemy = world;
-
-               if(trace_ent)
-                       if(trace_ent.movetype)
-                               if(trace_ent.takedamage)
-                                       if(!trace_ent.deadflag)
-                                       {
-                                               if(DIFF_TEAM(trace_ent, gunner))
-                                               {
-                                                       gun.enemy = trace_ent;
-                                                       gun.lock_time = time + 5;
-                                               }
-                                       }
-       }
-
-       if(gun.enemy)
-       {
-               float distance, impact_time;
-
-               vector vf = real_origin(gun.enemy);
-               vector _vel = gun.enemy.velocity;
-               if(gun.enemy.movetype == MOVETYPE_WALK)
-                       _vel.z *= 0.1;
-
-
-               ad = vf;
-               distance = vlen(ad - gunner.origin);
-               impact_time = distance / autocvar_g_vehicle_bumblebee_cannon_speed;
-               ad = vf + _vel * impact_time;
-               trace_endpos = ad;
-
-
-               UpdateAuxiliaryXhair(gunner, ad, '1 0 1', 1);
-               vehicle_aimturret(vehic, trace_endpos, gun, "fire",
-                                                 autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
-                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
-
-       }
-       else
-               vehicle_aimturret(vehic, _ct, gun, "fire",
-                                                 autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
-                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
-
-       if(!forbidWeaponUse(gunner))
-       if(gunner.BUTTON_ATCK)
-               if(time > gun.attack_finished_single)
-                       if(gun.vehicle_energy >= autocvar_g_vehicle_bumblebee_cannon_cost)
-                       {
-                               gun.vehicle_energy -= autocvar_g_vehicle_bumblebee_cannon_cost;
-                               bumblebee_fire_cannon(gun, "fire", gunner);
-                               gun.delay = time;
-                               gun.attack_finished_single = time + autocvar_g_vehicle_bumblebee_cannon_refire;
-                       }
-
-       VEHICLE_UPDATE_PLAYER(gunner, health, bumblebee);
-
-       if(vehic.vehicle_flags & VHF_HASSHIELD)
-               VEHICLE_UPDATE_PLAYER(gunner, shield, bumblebee);
-
-       ad = gettaginfo(gun, gettagindex(gun, "fire"));
-       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, gun);
-
-       UpdateAuxiliaryXhair(gunner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), 0);
-
-       if(vehic.owner)
-               UpdateAuxiliaryXhair(vehic.owner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), ((gunner == vehic.gunner1) ? 1 : 2));
-
-       vehic.solid = SOLID_BBOX;
-       gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
-       gunner.vehicle_energy = (gun.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
-
-       self = gunner;
-       return 1;
-}
-
-vector bumblebee_gunner_findgoodexit(vector prefer_spot, entity gunner, entity player)
-{
-       //vector exitspot;
-       float mysize;
-
-       tracebox(gunner.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, player);
-       if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
-               return prefer_spot;
-
-       mysize = 1.5 * vlen(PL_MAX - PL_MIN); // can't use gunner's size, as they don't have a size
-       float i;
-       vector v, v2;
-       v2 = 0.5 * (gunner.absmin + gunner.absmax);
-       for(i = 0; i < 100; ++i)
-       {
-               v = randomvec();
-               v_z = 0;
-               v = v2 + normalize(v) * mysize;
-               tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, player);
-               if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
-                       return v;
-       }
-
-       return prefer_spot; // this should be considered a fallback?!
-}
-
-void bumblebee_gunner_exit(int _exitflag)
-{
-       entity player = self;
-       entity gunner = player.vehicle;
-       entity vehic = gunner.owner;
-
-       if(IS_REAL_CLIENT(player))
-       {
-               msg_entity = player;
-               WriteByte(MSG_ONE, SVC_SETVIEWPORT);
-               WriteEntity(MSG_ONE, player);
-
-               WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
-               WriteAngle(MSG_ONE, 0);
-               WriteAngle(MSG_ONE, vehic.angles.y);
-               WriteAngle(MSG_ONE, 0);
-       }
-
-       CSQCVehicleSetup(player, HUD_NORMAL);
-       setsize(player, PL_MIN, PL_MAX);
-
-       player.takedamage     = DAMAGE_AIM;
-       player.solid          = SOLID_SLIDEBOX;
-       player.movetype       = MOVETYPE_WALK;
-       player.effects       &= ~EF_NODRAW;
-       player.alpha          = 1;
-       player.PlayerPhysplug = func_null;
-       player.view_ofs       = PL_VIEW_OFS;
-       player.event_damage   = PlayerDamage;
-       player.hud            = HUD_NORMAL;
-       player.teleportable       = TELEPORT_NORMAL;
-       player.switchweapon   = gunner.switchweapon;
-       player.vehicle_enter_delay = time + 2;
-
-       fixedmakevectors(vehic.angles);
-
-       if(player == vehic.gunner1) { vehic.gunner1 = world; }
-       if(player == vehic.gunner2) { vehic.gunner2 = world; v_right *= -1; }
-
-       vector spot = real_origin(gunner);
-       spot = spot + v_up * 128 + v_forward * 300 + v_right * 150;
-       spot = bumblebee_gunner_findgoodexit(spot, gunner, player);
-
-       // TODO: figure a way to move player out of the gunner
-
-       player.velocity = 0.75 * vehic.velocity + normalize(spot - vehic.origin) * 200;
-       player.velocity_z += 10;
-
-       gunner.phase = time + 5;
-       gunner.vehicle_hudmodel.viewmodelforclient = gunner;
-
-       MUTATOR_CALLHOOK(VehicleExit, player, gunner);
-
-       player.vehicle = world;
-}
-
-bool bumblebee_gunner_enter()
-{
-       entity vehic = self;
-       entity player = other;
-       entity gunner = world;
-
-       if(!vehic.gunner1 && !vehic.gunner2 && ((time >= vehic.gun1.phase) + (time >= vehic.gun2.phase)) == 2)
-       {
-               // we can have some fun
-               if(vlen(real_origin(vehic.gun2) - player.origin) < vlen(real_origin(vehic.gun1) - player.origin))
-               {
-                       gunner = vehic.gun2;
-                       vehic.gunner2 = player;
-               }
-               else
-               {
-                       gunner = vehic.gun1;
-                       vehic.gunner1 = 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; }
-
-       player.vehicle                  = gunner;
-       player.angles                   = vehic.angles;
-       player.takedamage               = DAMAGE_NO;
-       player.solid                    = SOLID_NOT;
-       player.alpha                    = -1;
-       player.movetype                 = MOVETYPE_NOCLIP;
-       player.event_damage     = func_null;
-       player.view_ofs                 = '0 0 0';
-       player.hud                              = gunner.hud;
-       player.teleportable     = false;
-       player.PlayerPhysplug   = gunner.PlayerPhysplug;
-       player.vehicle_ammo1    = vehic.vehicle_ammo1;
-       player.vehicle_ammo2    = vehic.vehicle_ammo2;
-       player.vehicle_reload1  = vehic.vehicle_reload1;
-       player.vehicle_reload2  = vehic.vehicle_reload2;
-       player.vehicle_energy   = vehic.vehicle_energy;
-       player.flags               &= ~FL_ONGROUND;
-
-       RemoveGrapplingHook(player);
-
-       gunner.switchweapon = player.switchweapon;
-       gunner.vehicle_exit = bumblebee_gunner_exit;
-       gunner.vehicle_hudmodel.viewmodelforclient = player;
-
-       if(IS_REAL_CLIENT(player))
-       {
-               msg_entity = player;
-               WriteByte(MSG_ONE,              SVC_SETVIEWPORT);
-               WriteEntity(MSG_ONE,    gunner.vehicle_viewport);
-
-               WriteByte(MSG_ONE,              SVC_SETVIEWANGLES);
-               WriteAngle(MSG_ONE,     gunner.angles_x + vehic.angles_x); // tilt
-               WriteAngle(MSG_ONE,     gunner.angles_y + vehic.angles_y); // yaw
-               WriteAngle(MSG_ONE,     0); // roll
-       }
-
-       CSQCVehicleSetup(player, player.hud);
-
-       MUTATOR_CALLHOOK(VehicleEnter, player, gunner);
-
-       return true;
-}
-
-bool vehicles_valid_pilot()
-{
-       if(IS_BOT_CLIENT(other) && !autocvar_g_vehicles_allow_bots)
-               return false;
-
-       if((!IS_PLAYER(other))
-       || (other.deadflag != DEAD_NO)
-       || (other.vehicle)
-       || (DIFF_TEAM(other, self))
-       ) { return false; }
-
-       return true;
-}
-
-void bumblebee_touch()
-{
-       if(autocvar_g_vehicles_enter) { return; }
-
-       if(self.gunner1 != world && self.gunner2 != world)
-       {
-               vehicles_touch();
-               return;
-       }
-
-       if(vehicles_valid_pilot())
-       {
-               float phase_time = (time >= self.gun1.phase) + (time >= self.gun2.phase);
-
-               if(time >= other.vehicle_enter_delay && phase_time)
-               if(bumblebee_gunner_enter())
-                       return;
-       }
-
-       vehicles_touch();
-}
-
-void bumblebee_regen()
-{
-       if(self.gun1.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
-               self.gun1.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
-                                                                          self.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
-
-       if(self.gun2.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
-               self.gun2.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
-                                                                          self.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
-
-       if(self.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(self.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime, true);
-
-       if(self.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(self.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime, false);
-
-       if(self.vehicle_flags  & VHF_ENERGYREGEN)
-               vehicles_regen(self.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime, false);
-
-}
-
-float bumblebee_pilot_frame()
-{
-       entity pilot, vehic;
-       vector newvel;
-
-       if(intermission_running)
-       {
-               self.vehicle.velocity = '0 0 0';
-               self.vehicle.avelocity = '0 0 0';
-               return 1;
-       }
-
-       pilot = self;
-       vehic = self.vehicle;
-       self   = vehic;
-
-       if(vehic.deadflag != DEAD_NO)
-       {
-               self = pilot;
-               pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
-               return 1;
-       }
-
-       bumblebee_regen();
-
-       crosshair_trace(pilot);
-
-       vector vang;
-       float ftmp;
-
-       vang = vehic.angles;
-       newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
-       vang.x *= -1;
-       newvel.x *= -1;
-       if(newvel.x > 180)  newvel.x -= 360;
-       if(newvel.x < -180) newvel.x += 360;
-       if(newvel.y > 180)  newvel.y -= 360;
-       if(newvel.y < -180) newvel.y += 360;
-
-       ftmp = shortangle_f(pilot.v_angle.y - vang.y, vang.y);
-       if(ftmp > 180)  ftmp -= 360;
-       if(ftmp < -180) ftmp += 360;
-       vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity.y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed);
-
-       // Pitch
-       ftmp = 0;
-       if(pilot.movement.x > 0 && vang.x < autocvar_g_vehicle_bumblebee_pitchlimit)
-               ftmp = 4;
-       else if(pilot.movement.x < 0 && vang.x > -autocvar_g_vehicle_bumblebee_pitchlimit)
-               ftmp = -8;
-
-       newvel.x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x , autocvar_g_vehicle_bumblebee_pitchlimit);
-       ftmp = vang.x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit);
-       vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity.x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed);
-
-       vehic.angles_x = anglemods(vehic.angles.x);
-       vehic.angles_y = anglemods(vehic.angles.y);
-       vehic.angles_z = anglemods(vehic.angles.z);
-
-       makevectors('0 1 0' * vehic.angles.y);
-       newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction;
-
-       if(pilot.movement.x != 0)
-       {
-               if(pilot.movement.x > 0)
-                       newvel += v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
-               else if(pilot.movement.x < 0)
-                       newvel -= v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
-       }
-
-       if(pilot.movement.y != 0)
-       {
-               if(pilot.movement.y < 0)
-                       newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
-               else if(pilot.movement.y > 0)
-                       newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
-               ftmp = newvel * v_right;
-               ftmp *= frametime * 0.1;
-               vehic.angles_z = bound(-15, vehic.angles.z + ftmp, 15);
-       }
-       else
-       {
-               vehic.angles_z *= 0.95;
-               if(vehic.angles.z >= -1 && vehic.angles.z <= -1)
-                       vehic.angles_z = 0;
-       }
-
-       if(pilot.BUTTON_CROUCH)
-               newvel -=   v_up * autocvar_g_vehicle_bumblebee_speed_down;
-       else if(pilot.BUTTON_JUMP)
-               newvel +=  v_up * autocvar_g_vehicle_bumblebee_speed_up;
-
-       vehic.velocity  += newvel * frametime;
-       pilot.velocity = pilot.movement  = vehic.velocity;
-
-
-       if(autocvar_g_vehicle_bumblebee_healgun_locktime)
-       {
-               if(vehic.tur_head.lock_time < time || vehic.tur_head.enemy.deadflag)
-                       vehic.tur_head.enemy = world;
-
-               if(trace_ent)
-               if(trace_ent.movetype)
-               if(trace_ent.takedamage)
-               if(!trace_ent.deadflag)
-               {
-                       if(teamplay)
-                       {
-                               if(trace_ent.team == pilot.team)
-                               {
-                                       vehic.tur_head.enemy = trace_ent;
-                                       vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
-                               }
-                       }
-                       else
-                       {
-                               vehic.tur_head.enemy = trace_ent;
-                               vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
-                       }
-               }
-
-               if(vehic.tur_head.enemy)
-               {
-                       trace_endpos = real_origin(vehic.tur_head.enemy);
-                       UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0);
-               }
-       }
-
-       vang = vehicle_aimturret(vehic, trace_endpos, self.gun3, "fire",
-                                         autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1,  autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
-                                         autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1,  autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides,  autocvar_g_vehicle_bumblebee_raygun_turnspeed);
-
-       if(!forbidWeaponUse(pilot))
-       if((pilot.BUTTON_ATCK || pilot.BUTTON_ATCK2) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime || autocvar_g_vehicle_bumblebee_raygun == 0))
-       {
-               vehic.gun3.enemy.realowner = pilot;
-               vehic.gun3.enemy.effects &= ~EF_NODRAW;
-
-               vehic.gun3.enemy.hook_start = gettaginfo(vehic.gun3, gettagindex(vehic.gun3, "fire"));
-               vehic.gun3.enemy.SendFlags |= BRG_START;
-
-               traceline(vehic.gun3.enemy.hook_start, vehic.gun3.enemy.hook_start + v_forward * autocvar_g_vehicle_bumblebee_raygun_range, MOVE_NORMAL, vehic);
-
-               if(trace_ent)
-               {
-                       if(autocvar_g_vehicle_bumblebee_raygun)
-                       {
-                               Damage(trace_ent, vehic, pilot, autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime, DEATH_GENERIC, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * sys_frametime);
-                               vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * sys_frametime;
-                       }
-                       else
-                       {
-                               if(trace_ent.deadflag == DEAD_NO)
-                                       if((teamplay && trace_ent.team == pilot.team) || !teamplay)
-                                       {
-
-                                               if(trace_ent.vehicle_flags & VHF_ISVEHICLE)
-                                               {
-                                                       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);
-
-                                                       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);
-                                               }
-                                               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);
-
-                                                       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.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, 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);
-                                                       //else ..hmmm what? ammo?
-
-                                                       trace_ent.SendFlags |= TNSF_STATUS;
-                                               }
-                                       }
-                       }
-               }
-
-               vehic.gun3.enemy.hook_end = trace_endpos;
-               setorigin(vehic.gun3.enemy, trace_endpos);
-               vehic.gun3.enemy.SendFlags |= BRG_END;
-
-               vehic.wait = time + 1;
-       }
-       else
-               vehic.gun3.enemy.effects |= EF_NODRAW;
-       /*{
-               if(vehic.gun3.enemy)
-                       remove(vehic.gun3.enemy);
-
-               vehic.gun3.enemy = world;
-       }
-       */
-
-       VEHICLE_UPDATE_PLAYER(pilot, health, bumblebee);
-       VEHICLE_UPDATE_PLAYER(pilot, energy, bumblebee);
-
-       pilot.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
-       pilot.vehicle_ammo2 = (vehic.gun2.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
-
-       if(vehic.vehicle_flags & VHF_HASSHIELD)
-               VEHICLE_UPDATE_PLAYER(pilot, shield, bumblebee);
-
-       vehic.angles_x *= -1;
-       makevectors(vehic.angles);
-       vehic.angles_x *= -1;
-       setorigin(pilot, vehic.origin + v_up * 48 + v_forward * 160);
-
-       pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
-       self = pilot;
-
-       return 1;
-}
-
-void bumblebee_land()
-{
-       float hgt;
-
-       hgt = raptor_altitude(512);
-       self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
-       self.angles_x *= 0.95;
-       self.angles_z *= 0.95;
-
-       if(hgt < 16)
-               self.think      = vehicles_think;
-
-       self.nextthink = time;
-
-       CSQCMODEL_AUTOUPDATE();
-}
-
-void bumblebee_exit(float eject)
-{
-       if(self.owner.vehicleid == VEH_BUMBLEBEE.vehicleid)
-       {
-               bumblebee_gunner_exit(eject);
-               return;
-       }
-
-       self.touch = vehicles_touch;
-
-       if(self.deadflag == DEAD_NO)
-       {
-               self.think = bumblebee_land;
-               self.nextthink  = time;
-       }
-
-       self.movetype = MOVETYPE_TOSS;
-
-       if(!self.owner)
-               return;
-
-       fixedmakevectors(self.angles);
-       vector spot;
-       if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)
-               spot = self.origin + v_up * 128 + v_forward * 300;
-       else
-               spot = self.origin + v_up * 128 - v_forward * 300;
-
-       spot = vehicles_findgoodexit(spot);
-
-       // Hide beam
-       if(self.gun3.enemy || !wasfreed(self.gun3.enemy)) {
-               self.gun3.enemy.effects |= EF_NODRAW;
-       }
-
-       self.owner.velocity = 0.75 * self.vehicle.velocity + normalize(spot - self.vehicle.origin) * 200;
-       self.owner.velocity_z += 10;
-       setorigin(self.owner, spot);
-
-       antilag_clear(self.owner);
-       self.owner = world;
-}
-
-void bumblebee_blowup()
-{
-       RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage,
-                                autocvar_g_vehicle_bumblebee_blowup_edgedamage,
-                                autocvar_g_vehicle_bumblebee_blowup_radius, self, world,
-                                autocvar_g_vehicle_bumblebee_blowup_forceintensity,
-                                DEATH_VH_BUMB_DEATH, world);
-
-       sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
-       Send_Effect(EFFECT_EXPLOSION_BIG, (self.origin + '0 0 100') + (randomvec() * 80), '0 0 0', 1);
-
-       if(self.owner.deadflag == DEAD_DYING)
-               self.owner.deadflag = DEAD_DEAD;
-
-       remove(self);
-}
-
-void bumblebee_diethink()
-{
-       if(time >= self.wait)
-               self.think = bumblebee_blowup;
-
-       if(random() < 0.1)
-       {
-               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
-               Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
-       }
-
-       self.nextthink = time + 0.1;
-}
-
-float bumble_raygun_send(entity to, float sf)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_BUMBLE_RAYGUN);
-
-       WriteByte(MSG_ENTITY, sf);
-       if(sf & BRG_SETUP)
-       {
-               WriteByte(MSG_ENTITY, num_for_edict(self.realowner));
-               WriteByte(MSG_ENTITY, self.realowner.team);
-               WriteByte(MSG_ENTITY, self.cnt);
-       }
-
-       if(sf & BRG_START)
-       {
-               WriteCoord(MSG_ENTITY, self.hook_start_x);
-               WriteCoord(MSG_ENTITY, self.hook_start_y);
-               WriteCoord(MSG_ENTITY, self.hook_start_z);
-       }
-
-       if(sf & BRG_END)
-       {
-               WriteCoord(MSG_ENTITY, self.hook_end_x);
-               WriteCoord(MSG_ENTITY, self.hook_end_y);
-               WriteCoord(MSG_ENTITY, self.hook_end_z);
-       }
-
-       return true;
-}
-
-void spawnfunc_vehicle_bumblebee()
-{
-       if(!autocvar_g_vehicle_bumblebee) { remove(self); return; }
-       if(!vehicle_initialize(VEH_BUMBLEBEE, false)) { remove(self); return; }
-}
-
-float v_bumblebee(float req)
-{
-       switch(req)
-       {
-               case VR_IMPACT:
-               {
-                       if(autocvar_g_vehicle_bumblebee_bouncepain)
-                               vehicles_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, autocvar_g_vehicle_bumblebee_bouncepain_y, autocvar_g_vehicle_bumblebee_bouncepain_z);
-
-                       return true;
-               }
-               case VR_ENTER:
-               {
-                       self.touch = bumblebee_touch;
-                       self.nextthink = 0;
-                       self.movetype = MOVETYPE_BOUNCEMISSILE;
-                       return true;
-               }
-               case VR_THINK:
-               {
-                       self.angles_z *= 0.8;
-                       self.angles_x *= 0.8;
-
-                       self.nextthink = time;
-
-                       if(!self.owner)
-                       {
-                               entity oldself = self;
-                               if(self.gunner1)
-                               {
-                                       self = self.gunner1;
-                                       oldself.gun1.vehicle_exit(VHEF_EJECT);
-                                       entity oldother = other;
-                                       other = self;
-                                       self = oldself;
-                                       self.phase = 0;
-                                       self.touch();
-                                       other = oldother;
-                                       return true;
-                               }
-
-                               if(self.gunner2)
-                               {
-                                       self = self.gunner2;
-                                       oldself.gun2.vehicle_exit(VHEF_EJECT);
-                                       entity oldother = other;
-                                       other = self;
-                                       self = oldself;
-                                       self.phase = 0;
-                                       self.touch();
-                                       other = oldother;
-                                       return true;
-                               }
-                       }
-
-                       return true;
-               }
-               case VR_DEATH:
-               {
-                       entity oldself = self;
-
-                       CSQCModel_UnlinkEntity();
-
-                       // Hide beam
-                       if(self.gun3.enemy || !wasfreed(self.gun3.enemy))
-                               self.gun3.enemy.effects |= EF_NODRAW;
-
-                       if(self.gunner1)
-                       {
-                               self = self.gunner1;
-                               oldself.gun1.vehicle_exit(VHEF_EJECT);
-                               self = oldself;
-                       }
-
-                       if(self.gunner2)
-                       {
-                               self = self.gunner2;
-                               oldself.gun2.vehicle_exit(VHEF_EJECT);
-                               self = oldself;
-                       }
-
-                       self.vehicle_exit(VHEF_EJECT);
-
-                       fixedmakevectors(self.angles);
-                       vehicle_tossgib(self.gun1, self.velocity + v_right * 300 + v_up * 100 + randomvec() * 200, "cannon_right", rint(random()), rint(random()), 6, randomvec() * 200);
-                       vehicle_tossgib(self.gun2, self.velocity + v_right * -300 + v_up * 100 + randomvec() * 200, "cannon_left", rint(random()), rint(random()), 6, randomvec() * 200);
-                       vehicle_tossgib(self.gun3, self.velocity + v_forward * 300 + v_up * -100 + randomvec() * 200, "raygun", rint(random()), rint(random()), 6, randomvec() * 300);
-
-                       entity _body = vehicle_tossgib(self, self.velocity + randomvec() * 200, "", rint(random()), rint(random()), 6, randomvec() * 100);
-
-                       if(random() > 0.5)
-                               _body.touch = bumblebee_blowup;
-                       else
-                               _body.touch = func_null;
-
-                       _body.think = bumblebee_diethink;
-                       _body.nextthink = time;
-                       _body.wait = time + 2 + (random() * 8);
-                       _body.owner = self;
-                       _body.enemy = self.enemy;
-                       _body.scale = 1.5;
-                       _body.angles = self.angles;
-
-                       Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation(self.origin, 16), '0 0 0', 1);
-
-                       self.health                     = 0;
-                       self.event_damage       = func_null;
-                       self.solid                      = SOLID_NOT;
-                       self.takedamage         = DAMAGE_NO;
-                       self.deadflag           = DEAD_DYING;
-                       self.movetype           = MOVETYPE_NONE;
-                       self.effects            = EF_NODRAW;
-                       self.colormod           = '0 0 0';
-                       self.avelocity          = '0 0 0';
-                       self.velocity           = '0 0 0';
-                       self.touch                      = func_null;
-                       self.nextthink          = 0;
-
-                       setorigin(self, self.pos1);
-                       return true;
-               }
-               case VR_SPAWN:
-               {
-                       if(!self.gun1)
-                       {
-                               // for some reason, autosizing of the shield entity refuses to work for this one so set it up in advance.
-                               self.vehicle_shieldent = spawn();
-                               self.vehicle_shieldent.effects = EF_LOWPRECISION;
-                               setmodel(self.vehicle_shieldent, "models/vhshield.md3");
-                               setattachment(self.vehicle_shieldent, self, "");
-                               setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
-                               self.vehicle_shieldent.scale       = 512 / vlen(self.maxs - self.mins);
-                               self.vehicle_shieldent.think       = shieldhit_think;
-                               self.vehicle_shieldent.alpha = -1;
-                               self.vehicle_shieldent.effects = EF_LOWPRECISION | EF_NODRAW;
-
-                               self.gun1 = spawn();
-                               self.gun2 = spawn();
-                               self.gun3 = spawn();
-
-                               self.vehicle_flags |= VHF_MULTISLOT;
-
-                               self.gun1.owner = self;
-                               self.gun2.owner = self;
-                               self.gun3.owner = self;
-
-                               self.gun1.classname = self.gun2.classname = "vehicle_playerslot";
-
-                               setmodel(self.gun1, "models/vehicles/bumblebee_plasma_right.dpm");
-                               setmodel(self.gun2, "models/vehicles/bumblebee_plasma_left.dpm");
-                               setmodel(self.gun3, "models/vehicles/bumblebee_ray.dpm");
-
-                               setattachment(self.gun1, self, "cannon_right");
-                               setattachment(self.gun2, self, "cannon_left");
-
-                               // Angled bones are no fun, messes up gun-aim; so work arround it.
-                               self.gun3.pos1 = self.angles;
-                               self.angles = '0 0 0';
-                               vector ofs = gettaginfo(self, gettagindex(self, "raygun"));
-                               ofs -= self.origin;
-                               setattachment(self.gun3, self, "");
-                               setorigin(self.gun3, ofs);
-                               self.angles = self.gun3.pos1;
-
-                               vehicle_addplayerslot(self, self.gun1, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
-                               vehicle_addplayerslot(self, self.gun2, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
-
-                               setorigin(self.vehicle_hudmodel, '50 0 -5');    // Move cockpit forward - down.
-                               setorigin(self.vehicle_viewport, '5 0 2');    // Move camera forward up
-
-                               //fixme-model-bones
-                               setorigin(self.gun1.vehicle_hudmodel, '90 -27 -23');
-                               setorigin(self.gun1.vehicle_viewport, '-85 0 50');
-                               //fixme-model-bones
-                               setorigin(self.gun2.vehicle_hudmodel, '90 27 -23');
-                               setorigin(self.gun2.vehicle_viewport, '-85 0 50');
-
-                               self.scale = 1.5;
-
-                               // Raygun beam
-                               if(self.gun3.enemy == world)
-                               {
-                                       self.gun3.enemy = spawn();
-                                       Net_LinkEntity(self.gun3.enemy, true, 0, bumble_raygun_send);
-                                       self.gun3.enemy.SendFlags = BRG_SETUP;
-                                       self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;
-                                       self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION;
-                               }
-                       }
-
-                       self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
-                       self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
-                       self.solid = SOLID_BBOX;
-                       self.movetype = MOVETYPE_TOSS;
-                       self.damageforcescale = 0.025;
-
-                       self.PlayerPhysplug = bumblebee_pilot_frame;
-
-                       setorigin(self, self.origin + '0 0 25');
-                       return true;
-               }
-               case VR_SETUP:
-               {
-                       if(autocvar_g_vehicle_bumblebee_energy)
-                       if(autocvar_g_vehicle_bumblebee_energy_regen)
-                               self.vehicle_flags |= VHF_ENERGYREGEN;
-
-                       if(autocvar_g_vehicle_bumblebee_shield)
-                               self.vehicle_flags |= VHF_HASSHIELD;
-
-                       if(autocvar_g_vehicle_bumblebee_shield_regen)
-                               self.vehicle_flags |= VHF_SHIELDREGEN;
-
-                       if(autocvar_g_vehicle_bumblebee_health_regen)
-                               self.vehicle_flags |= VHF_HEALTHREGEN;
-
-                       self.vehicle_exit = bumblebee_exit;
-                       self.respawntime = autocvar_g_vehicle_bumblebee_respawntime;
-                       self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
-                       self.max_health = self.vehicle_health;
-                       self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
-
-                       return true;
-               }
-               case VR_PRECACHE:
-               {
-                       precache_model("models/vehicles/bumblebee_body.dpm");
-                       precache_model("models/vehicles/bumblebee_plasma_left.dpm");
-                       precache_model("models/vehicles/bumblebee_plasma_right.dpm");
-                       precache_model("models/vehicles/bumblebee_ray.dpm");
-                       precache_model("models/vehicles/wakizashi_cockpit.dpm");
-                       precache_model("models/vehicles/spiderbot_cockpit.dpm");
-                       precache_model("models/vehicles/raptor_cockpit.dpm");
-                       return true;
-               }
-       }
-
-       return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-void CSQC_BUMBLE_GUN_HUD()
-{
-       Vehicles_drawHUD("vehicle_gunner", "vehicle_gunner_weapon1", string_null,
-                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
-                                        string_null, '0 0 0',
-                                        string_null);
-}
-
-void bumble_raygun_draw()
-{
-       float _len;
-       vector _dir;
-       vector _vtmp1, _vtmp2;
-
-       _len = vlen(self.origin - self.move_origin);
-       _dir = normalize(self.move_origin - self.origin);
-
-       if(self.total_damages < time)
-       {
-               boxparticles(self.traileffect, self, self.origin, self.origin + _dir * -64, _dir * -_len , _dir * -_len, 1, PARTICLES_USEALPHA);
-               boxparticles(self.lip, self, self.move_origin, self.move_origin + _dir * -64, _dir * -200 , _dir * -200, 1, PARTICLES_USEALPHA);
-               self.total_damages = time + 0.1;
-       }
-
-       float i, df, sz, al;
-       for(i = -0.1; i < 0.2; i += 0.1)
-       {
-               df = DRAWFLAG_NORMAL; //((random() < 0.5) ? DRAWFLAG_ADDITIVE : DRAWFLAG_SCREEN);
-               sz = 5 + random() * 5;
-               al = 0.25 + random() * 0.5;
-               _vtmp1 = self.origin + _dir * _len * (0.25 + i);
-               _vtmp1 += (randomvec() * (_len * 0.2) * (frametime * 2));       //self.raygun_l1;
-               Draw_CylindricLine(self.origin, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
-
-               _vtmp2 = self.origin + _dir * _len * (0.5 + i);
-               _vtmp2 += (randomvec() * (_len * 0.2) * (frametime * 5));       //self.raygun_l2;
-               Draw_CylindricLine(_vtmp1, _vtmp2, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
-
-               _vtmp1 = self.origin + _dir * _len * (0.75 + i);
-               _vtmp1 += randomvec() * (_len * 0.2) * (frametime * 10);     //self.raygun_l3;
-               Draw_CylindricLine(_vtmp2, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
-
-               Draw_CylindricLine(_vtmp1, self.move_origin +  randomvec() * 32, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
-       }
-}
-
-void bumble_raygun_read(bool bIsNew)
-{
-       int sf = ReadByte();
-
-       if(sf & BRG_SETUP)
-       {
-               self.cnt  = ReadByte();
-               self.team = ReadByte();
-               self.cnt  = ReadByte();
-
-               if(self.cnt)
-                       self.colormod = '1 0 0';
-               else
-                       self.colormod = '0 1 0';
-
-               self.traileffect = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_MUZZLEFLASH);
-               self.lip = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_IMPACT);
-
-               self.draw = bumble_raygun_draw;
-       }
-
-
-       if(sf & BRG_START)
-       {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-               setorigin(self, self.origin);
-       }
-
-       if(sf & BRG_END)
-       {
-               self.move_origin_x = ReadCoord();
-               self.move_origin_y = ReadCoord();
-               self.move_origin_z = ReadCoord();
-       }
-}
-
-float v_bumblebee(float req)
-{
-       switch(req)
-       {
-               case VR_HUD:
-               {
-                       Vehicles_drawHUD(VEH_BUMBLEBEE.m_icon, "vehicle_bumble_weapon1", "vehicle_bumble_weapon2",
-                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
-                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
-                                                        vCROSS_HEAL);
-                       return true;
-               }
-               case VR_SETUP:
-               {
-                       AuxiliaryXhair[0].axh_image = vCROSS_LOCK;  // Raygun-locked
-                       AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Gunner1
-                       AuxiliaryXhair[2].axh_image = vCROSS_BURST; // Gunner2
-                       return true;
-               }
-               case VR_PRECACHE:
-               {
-                       return true;
-               }
-       }
-
-       return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_VEHICLE
diff --git a/qcsrc/common/vehicles/unit/bumblebee.qh b/qcsrc/common/vehicles/unit/bumblebee.qh
deleted file mode 100644 (file)
index 7c387e4..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef BUMBLEBEE_H
-#define BUMBLEBEE_H
-
-#ifdef CSQC
-void bumble_raygun_read(bool bIsNew);
-
-void CSQC_BUMBLE_GUN_HUD();
-#endif
-
-#endif
diff --git a/qcsrc/common/vehicles/unit/racer.qc b/qcsrc/common/vehicles/unit/racer.qc
deleted file mode 100644 (file)
index 38b06c3..0000000
+++ /dev/null
@@ -1,880 +0,0 @@
-#ifndef VEHICLE_RACER
-#define VEHICLE_RACER
-#ifndef MENUQC
-int v_racer(int);
-#endif
-REGISTER_VEHICLE_SIMPLE(
-/* VEH_##id   */ RACER,
-/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL,
-/* mins,maxs  */ '-120 -120 -40' * 0.5, '120 120 40' * 0.5,
-/* model         */ "models/vehicles/wakizashi.dpm",
-/* head_model */ "null",
-/* hud_model  */ "models/vehicles/wakizashi_cockpit.dpm",
-/* tags                  */ "", "", "tag_viewport",
-/* netname       */ "racer",
-/* fullname   */ _("Racer")
-) {
-    this.m_icon = "vehicle_racer";
-#ifndef MENUQC
-    this.vehicle_func = v_racer;
-#endif
-}
-#endif
-
-#ifdef IMPLEMENTATION
-#ifdef SVQC
-#include "../../effects.qh"
-#include "../../triggers/trigger/impulse.qh"
-
-bool autocvar_g_vehicle_racer;
-
-float autocvar_g_vehicle_racer_speed_afterburn;
-float autocvar_g_vehicle_racer_afterburn_cost;
-
-float autocvar_g_vehicle_racer_waterburn_cost;
-float autocvar_g_vehicle_racer_waterburn_speed;
-
-float autocvar_g_vehicle_racer_water_speed_forward;
-float autocvar_g_vehicle_racer_water_speed_strafe;
-
-float autocvar_g_vehicle_racer_pitchlimit = 30;
-
-float autocvar_g_vehicle_racer_water_downforce = 0.03;
-float autocvar_g_vehicle_racer_water_upforcedamper = 15;
-
-float autocvar_g_vehicle_racer_anglestabilizer;
-float autocvar_g_vehicle_racer_downforce;
-
-float autocvar_g_vehicle_racer_speed_forward;
-float autocvar_g_vehicle_racer_speed_strafe;
-float autocvar_g_vehicle_racer_springlength;
-float autocvar_g_vehicle_racer_upforcedamper;
-float autocvar_g_vehicle_racer_friction;
-
-float autocvar_g_vehicle_racer_water_time = 5;
-
-float autocvar_g_vehicle_racer_hovertype;
-float autocvar_g_vehicle_racer_hoverpower;
-
-float autocvar_g_vehicle_racer_turnroll;
-float autocvar_g_vehicle_racer_turnspeed;
-float autocvar_g_vehicle_racer_pitchspeed;
-
-float autocvar_g_vehicle_racer_energy;
-float autocvar_g_vehicle_racer_energy_regen;
-float autocvar_g_vehicle_racer_energy_regen_pause;
-
-float autocvar_g_vehicle_racer_health;
-float autocvar_g_vehicle_racer_health_regen;
-float autocvar_g_vehicle_racer_health_regen_pause;
-
-float autocvar_g_vehicle_racer_shield;
-float autocvar_g_vehicle_racer_shield_regen;
-float autocvar_g_vehicle_racer_shield_regen_pause;
-
-float autocvar_g_vehicle_racer_cannon_cost;
-float autocvar_g_vehicle_racer_cannon_damage;
-float autocvar_g_vehicle_racer_cannon_radius;
-float autocvar_g_vehicle_racer_cannon_refire;
-float autocvar_g_vehicle_racer_cannon_speed;
-float autocvar_g_vehicle_racer_cannon_spread;
-float autocvar_g_vehicle_racer_cannon_force;
-
-float autocvar_g_vehicle_racer_rocket_accel;
-float autocvar_g_vehicle_racer_rocket_damage;
-float autocvar_g_vehicle_racer_rocket_radius;
-float autocvar_g_vehicle_racer_rocket_force;
-float autocvar_g_vehicle_racer_rocket_refire;
-float autocvar_g_vehicle_racer_rocket_speed;
-float autocvar_g_vehicle_racer_rocket_turnrate;
-
-float autocvar_g_vehicle_racer_rocket_locktarget;
-float autocvar_g_vehicle_racer_rocket_locking_time;
-float autocvar_g_vehicle_racer_rocket_locking_releasetime;
-float autocvar_g_vehicle_racer_rocket_locked_time;
-float autocvar_g_vehicle_racer_rocket_locked_maxangle;
-float autocvar_g_vehicle_racer_rocket_climbspeed;
-
-float autocvar_g_vehicle_racer_respawntime;
-
-float autocvar_g_vehicle_racer_blowup_radius;
-float autocvar_g_vehicle_racer_blowup_coredamage;
-float autocvar_g_vehicle_racer_blowup_edgedamage;
-float autocvar_g_vehicle_racer_blowup_forceintensity;
-
-float autocvar_g_vehicle_racer_bouncefactor;
-float autocvar_g_vehicle_racer_bouncestop;
-vector autocvar_g_vehicle_racer_bouncepain;
-
-.float racer_watertime;
-
-var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
-
-void racer_align4point(float _delta)
-{
-       vector push_vector;
-       float fl_push, fr_push, bl_push, br_push;
-
-       push_vector  = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
-       fr_push   = force_fromtag_normpower;
-       //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
-
-       push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
-       fl_push   = force_fromtag_normpower;
-       //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
-
-       push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
-       br_push   = force_fromtag_normpower;
-       //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
-
-       push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
-       bl_push   = force_fromtag_normpower;
-       //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
-
-       self.velocity += push_vector * _delta;
-
-       float uforce = autocvar_g_vehicle_racer_upforcedamper;
-
-       int cont = pointcontents(self.origin - '0 0 64');
-       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
-       {
-               uforce = autocvar_g_vehicle_racer_water_upforcedamper;
-
-               if(self.owner.BUTTON_CROUCH && time < self.air_finished)
-                       self.velocity_z += 30;
-               else
-                       self.velocity_z += 200;
-       }
-
-
-       // Anti ocilation
-       if(self.velocity_z > 0)
-               self.velocity_z *= 1 - uforce * _delta;
-
-       push_vector_x =  (fl_push - bl_push);
-       push_vector_x += (fr_push - br_push);
-       push_vector_x *= 360;
-
-       push_vector_z = (fr_push - fl_push);
-       push_vector_z += (br_push - bl_push);
-       push_vector_z *= 360;
-
-       // Apply angle diffrance
-       self.angles_z += push_vector_z * _delta;
-       self.angles_x += push_vector_x * _delta;
-
-       // Apply stabilizer
-       self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
-       self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
-}
-
-void racer_fire_cannon(string tagname)
-{
-       vector v;
-       entity bolt;
-
-       v = gettaginfo(self, gettagindex(self, tagname));
-       bolt = vehicles_projectile(EFFECT_RACER_MUZZLEFLASH.eent_eff_name, W_Sound("lasergun_fire"),
-                                                  v, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
-                                                  autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force,  0,
-                                                  DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, true, true, self.owner);
-
-       // Fix z-aim (for chase mode)
-       v = normalize(trace_endpos - bolt.origin);
-       v_forward_z = v_z * 0.5;
-       bolt.velocity = v_forward * autocvar_g_vehicle_racer_cannon_speed;
-}
-
-void racer_rocket_groundhugger()
-{
-       vector olddir, newdir;
-       float oldvel, newvel;
-
-       self.nextthink  = time;
-
-       if(self.owner.deadflag != DEAD_NO || self.cnt < time)
-       {
-               self.use();
-               return;
-       }
-
-       if(!self.realowner.vehicle)
-       {
-               UpdateCSQCProjectile(self);
-               return;
-       }
-
-       olddir = normalize(self.velocity);
-       oldvel = vlen(self.velocity);
-       newvel = oldvel + self.lip;
-
-       tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 64, MOVE_WORLDONLY,self);
-       if(trace_fraction <= 0.5)
-       {
-               // Hitting somethign soon, just speed ahead
-               self.velocity = olddir * newvel;
-               UpdateCSQCProjectile(self);
-               return;
-       }
-
-       traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self);
-       if(trace_fraction != 1.0)
-       {
-               newdir = normalize(trace_endpos + '0 0 64' - self.origin) * autocvar_g_vehicle_racer_rocket_turnrate;
-               self.velocity = normalize(olddir + newdir) * newvel;
-       }
-       else
-       {
-               self.velocity = olddir * newvel;
-               self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one
-       }
-
-       int cont = pointcontents(self.origin - '0 0 32');
-       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
-               self.velocity_z += 200;
-
-       UpdateCSQCProjectile(self);
-       return;
-}
-
-void racer_rocket_tracker()
-{
-       vector olddir, newdir;
-       float oldvel, newvel;
-
-       self.nextthink  = time;
-
-       if (self.owner.deadflag != DEAD_NO || self.cnt < time)
-       {
-               self.use();
-               return;
-       }
-
-       if(!self.realowner.vehicle)
-       {
-               UpdateCSQCProjectile(self);
-               return;
-       }
-
-       olddir = normalize(self.velocity);
-       oldvel = vlen(self.velocity);
-       newvel = oldvel + self.lip;
-       makevectors(vectoangles(olddir));
-
-       float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1);
-       vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact;
-
-       traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
-       newdir = normalize(predicted_origin - self.origin);
-
-       //vector
-       float height_diff = predicted_origin_z - self.origin_z;
-
-       if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle)
-       {
-               //bprint("Target lost!\n");
-               //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n");
-               self.think = racer_rocket_groundhugger;
-               return;
-       }
-
-       if(trace_fraction != 1.0 && trace_ent != self.enemy)
-               newdir_z += 16 * sys_frametime;
-
-       self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
-       self.velocity_z -= 800 * sys_frametime;
-       self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
-
-       UpdateCSQCProjectile(self);
-       return;
-}
-
-void racer_fire_rocket(string tagname, entity trg)
-{
-       vector v = gettaginfo(self, gettagindex(self, tagname));
-       entity rocket = vehicles_projectile(EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, W_Sound("rocket_fire"),
-                                                  v, v_forward * autocvar_g_vehicle_racer_rocket_speed,
-                                                  autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
-                                                  DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner);
-
-       rocket.lip                        = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
-       rocket.wait                      = autocvar_g_vehicle_racer_rocket_turnrate;
-       rocket.nextthink                = time;
-       rocket.enemy                    = trg;
-       rocket.cnt                        = time + 15;
-
-       if(trg)
-               rocket.think                    = racer_rocket_tracker;
-       else
-               rocket.think                    = racer_rocket_groundhugger;
-}
-
-float racer_frame()
-{
-       entity player, racer;
-       vector df;
-       float ftmp;
-
-       if(intermission_running)
-       {
-               self.vehicle.velocity = '0 0 0';
-               self.vehicle.avelocity = '0 0 0';
-               return 1;
-       }
-
-       player  = self;
-       racer   = self.vehicle;
-       self    = racer;
-
-       vehicles_painframe();
-
-       if(pointcontents(racer.origin) != CONTENT_WATER)
-               racer.air_finished = time + autocvar_g_vehicle_racer_water_time;
-
-       if(racer.deadflag != DEAD_NO)
-       {
-               self = player;
-               player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
-               return 1;
-       }
-
-       racer_align4point(PHYS_INPUT_TIMELENGTH);
-
-       player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0;
-
-       crosshair_trace(player);
-
-       racer.angles_x *= -1;
-
-       // Yaw
-       ftmp = autocvar_g_vehicle_racer_turnspeed * PHYS_INPUT_TIMELENGTH;
-       ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
-       racer.angles_y = anglemods(racer.angles_y + ftmp);
-
-       // Roll
-       racer.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * PHYS_INPUT_TIMELENGTH;
-
-       // Pitch
-       ftmp = autocvar_g_vehicle_racer_pitchspeed  * PHYS_INPUT_TIMELENGTH;
-       ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp);
-       racer.angles_x = bound(-autocvar_g_vehicle_racer_pitchlimit, anglemods(racer.angles_x + ftmp), autocvar_g_vehicle_racer_pitchlimit);
-
-       makevectors(racer.angles);
-       racer.angles_x *= -1;
-
-       //ftmp = racer.velocity_z;
-       df = racer.velocity * -autocvar_g_vehicle_racer_friction;
-       //racer.velocity_z = ftmp;
-
-       int cont = pointcontents(racer.origin);
-       if(vlen(player.movement) != 0)
-       {
-               if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
-               {
-                       if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_water_speed_forward : -autocvar_g_vehicle_racer_water_speed_forward); }
-                       if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_water_speed_strafe : -autocvar_g_vehicle_racer_water_speed_strafe); }
-               }
-               else
-               {
-                       if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_speed_forward : -autocvar_g_vehicle_racer_speed_forward); }
-                       if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_speed_strafe : -autocvar_g_vehicle_racer_speed_strafe); }
-               }
-
-#ifdef SVQC
-               if(self.sound_nexttime < time || self.sounds != 1)
-               {
-                       self.sounds = 1;
-                       self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav");
-                       sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_move.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-               }
-#endif
-       }
-#ifdef SVQC
-       else
-       {
-               if(self.sound_nexttime < time || self.sounds != 0)
-               {
-                       self.sounds = 0;
-                       self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav");
-                       sound (self, CH_TRIGGER_SINGLE, "vehicles/racer_idle.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-               }
-       }
-#endif
-
-       // Afterburn
-       if (PHYS_INPUT_BUTTON_JUMP(player) && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH))
-       {
-#ifdef SVQC
-               if(time - racer.wait > 0.2)
-                       pointparticles(particleeffectnum(EFFECT_RACER_BOOSTER), self.origin - v_forward * 32, v_forward  * vlen(self.velocity), 1);
-#endif
-
-               racer.wait = time;
-
-               if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
-               {
-                       racer.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * PHYS_INPUT_TIMELENGTH;
-                       df += (v_forward * autocvar_g_vehicle_racer_waterburn_speed);
-               }
-               else
-               {
-                       racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH;
-                       df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn);
-               }
-
-#ifdef SVQC
-               if(racer.invincible_finished < time)
-               {
-                       traceline(racer.origin, racer.origin - '0 0 256', MOVE_NORMAL, self);
-                       if(trace_fraction != 1.0)
-                               pointparticles(particleeffectnum(EFFECT_SMOKE_SMALL), trace_endpos, '0 0 0', 1);
-
-                       racer.invincible_finished = time + 0.1 + (random() * 0.1);
-               }
-
-               if(racer.strength_finished < time)
-               {
-                       racer.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
-                       sound (racer.tur_head, CH_TRIGGER_SINGLE, "vehicles/racer_boost.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-               }
-#endif
-       }
-       else
-       {
-               racer.strength_finished = 0;
-               sound (racer.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-       }
-
-       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
-               racer.racer_watertime = time;
-
-       float dforce = autocvar_g_vehicle_racer_downforce;
-       if(time - racer.racer_watertime <= 3)
-               dforce = autocvar_g_vehicle_racer_water_downforce;
-
-       df -= v_up * (vlen(racer.velocity) * dforce);
-       player.movement = racer.velocity += df * PHYS_INPUT_TIMELENGTH;
-
-#ifdef SVQC
-       if(!forbidWeaponUse(player))
-       if(player.BUTTON_ATCK)
-       if(time > racer.attack_finished_single)
-       if(racer.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost)
-       {
-               racer.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost;
-               racer.wait = time;
-
-               crosshair_trace(player);
-               if(racer.cnt)
-               {
-                       racer_fire_cannon("tag_fire1");
-                       racer.cnt = 0;
-               }
-               else
-               {
-                       racer_fire_cannon("tag_fire2");
-                       racer.cnt = 1;
-               }
-               racer.attack_finished_single = time + autocvar_g_vehicle_racer_cannon_refire;
-       }
-
-       if(autocvar_g_vehicle_racer_rocket_locktarget)
-       {
-               vehicles_locktarget((1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime,
-                                                (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime,
-                                                autocvar_g_vehicle_racer_rocket_locked_time);
-
-               if(self.lock_target)
-               {
-                       if(racer.lock_strength == 1)
-                               UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '1 0 0', 0);
-                       else if(self.lock_strength > 0.5)
-                               UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 1 0', 0);
-                       else if(self.lock_strength < 0.5)
-                               UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 0 1', 0);
-               }
-       }
-
-       if(!forbidWeaponUse(player))
-       if(time > racer.delay)
-       if(player.BUTTON_ATCK2)
-       {
-               racer.misc_bulletcounter += 1;
-               racer.delay = time + 0.3;
-
-               if(racer.misc_bulletcounter == 1)
-               {
-                       racer_fire_rocket("tag_rocket_r", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
-                       player.vehicle_ammo2 = 50;
-               }
-               else if(racer.misc_bulletcounter == 2)
-               {
-                       racer_fire_rocket("tag_rocket_l", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
-                       racer.lock_strength  = 0;
-                       racer.lock_target       = world;
-                       racer.misc_bulletcounter = 0;
-                       racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
-                       racer.lip = time;
-                       player.vehicle_ammo2 = 0;
-               }
-       }
-       else if(racer.misc_bulletcounter == 0)
-               player.vehicle_ammo2 = 100;
-
-       player.vehicle_reload2 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100);
-
-       if(racer.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(racer.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime, true);
-
-       if(racer.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(racer.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime, false);
-
-       if(racer.vehicle_flags  & VHF_ENERGYREGEN)
-               vehicles_regen(racer.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime, false);
-
-
-       VEHICLE_UPDATE_PLAYER(player, health, racer);
-       VEHICLE_UPDATE_PLAYER(player, energy, racer);
-
-       if(racer.vehicle_flags & VHF_HASSHIELD)
-               VEHICLE_UPDATE_PLAYER(player, shield, racer);
-
-       player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
-#endif
-
-       setorigin(player,racer.origin + '0 0 32');
-       player.velocity = racer.velocity;
-
-       self = player;
-       return 1;
-}
-
-void racer_think()
-{
-       self.nextthink = time;
-
-       float pushdeltatime = time - self.lastpushtime;
-       if (pushdeltatime > 0.15) pushdeltatime = 0;
-       self.lastpushtime = time;
-       if(!pushdeltatime) return;
-
-       tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NOMONSTERS, self);
-
-       vector df = self.velocity * -autocvar_g_vehicle_racer_friction;
-       df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2);
-
-       float forced = autocvar_g_vehicle_racer_upforcedamper;
-
-       int cont = pointcontents(self.origin - '0 0 64');
-       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
-       {
-               forced = autocvar_g_vehicle_racer_water_upforcedamper;
-               self.velocity_z += 200;
-       }
-
-       self.velocity += df * pushdeltatime;
-       if(self.velocity_z > 0)
-               self.velocity_z *= 1 - forced * pushdeltatime;
-
-       self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
-       self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
-
-       CSQCMODEL_AUTOUPDATE();
-}
-
-void racer_exit(float eject)
-{
-       vector spot;
-
-       self.think        = racer_think;
-       self.nextthink  = time;
-       self.movetype   = MOVETYPE_BOUNCE;
-       sound (self.tur_head, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-
-       if(!self.owner)
-               return;
-
-       makevectors(self.angles);
-       if(eject)
-       {
-               spot = self.origin + v_forward * 100 + '0 0 64';
-               spot = vehicles_findgoodexit(spot);
-               setorigin(self.owner , spot);
-               self.owner.velocity = (v_up + v_forward * 0.25) * 750;
-               self.owner.oldvelocity = self.owner.velocity;
-       }
-       else
-       {
-               if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
-               {
-                       self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
-                       self.owner.velocity_z += 200;
-                       spot = self.origin + v_forward * 32 + '0 0 32';
-                       spot = vehicles_findgoodexit(spot);
-               }
-               else
-               {
-                       self.owner.velocity = self.velocity * 0.5;
-                       self.owner.velocity_z += 10;
-                       spot = self.origin - v_forward * 200 + '0 0 32';
-                       spot = vehicles_findgoodexit(spot);
-               }
-               self.owner.oldvelocity = self.owner.velocity;
-               setorigin(self.owner , spot);
-       }
-       antilag_clear(self.owner);
-       self.owner = world;
-}
-
-void racer_blowup()
-{
-       self.deadflag   = DEAD_DEAD;
-       self.vehicle_exit(VHEF_NORMAL);
-
-       RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage,
-                                       autocvar_g_vehicle_racer_blowup_edgedamage,
-                                       autocvar_g_vehicle_racer_blowup_radius, world, world,
-                                       autocvar_g_vehicle_racer_blowup_forceintensity,
-                                       DEATH_VH_WAKI_DEATH, world);
-
-       self.nextthink  = time + autocvar_g_vehicle_racer_respawntime;
-       self.think        = vehicles_spawn;
-       self.movetype   = MOVETYPE_NONE;
-       self.effects    = EF_NODRAW;
-
-       self.colormod  = '0 0 0';
-       self.avelocity = '0 0 0';
-       self.velocity  = '0 0 0';
-
-       setorigin(self, self.pos1);
-}
-
-void racer_blowup_think()
-{
-       self.nextthink = time;
-
-       if(time >= self.delay)
-               racer_blowup();
-
-       CSQCMODEL_AUTOUPDATE();
-}
-
-void racer_deadtouch()
-{
-       self.avelocity_x *= 0.7;
-       self.cnt -= 1;
-       if(self.cnt <= 0)
-               racer_blowup();
-}
-
-void spawnfunc_vehicle_racer()
-{
-       if(!autocvar_g_vehicle_racer) { remove(self); return; }
-       if(!vehicle_initialize(VEH_RACER, false)) { remove(self); return; }
-}
-
-#endif // SVQC
-
-#ifdef CSQC
-#if 0
-void racer_draw()
-{
-       float pushdeltatime = time - self.lastpushtime;
-       if (pushdeltatime > 0.15) pushdeltatime = 0;
-       self.lastpushtime = time;
-       if(!pushdeltatime) return;
-
-       tracebox(self.move_origin, self.mins, self.maxs, self.move_origin - ('0 0 1' * getstatf(STAT_VEH_RACER_SPRINGLENGTH)), MOVE_NOMONSTERS, self);
-
-       vector df = self.move_velocity * -getstatf(STAT_VEH_RACER_FRICTION);
-       df_z += (1 - trace_fraction) * getstatf(STAT_VEH_RACER_HOVERPOWER) + sin(time * 2) * (getstatf(STAT_VEH_RACER_SPRINGLENGTH) * 2);
-
-       float forced = getstatf(STAT_VEH_RACER_UPFORCEDAMPER);
-
-       int cont = pointcontents(self.move_origin - '0 0 64');
-       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
-       {
-               forced = getstatf(STAT_VEH_RACER_WATER_UPFORCEDAMPER);
-               self.move_velocity_z += 200;
-       }
-
-       self.move_velocity += df * pushdeltatime;
-       if(self.move_velocity_z > 0)
-               self.move_velocity_z *= 1 - forced * pushdeltatime;
-
-       self.move_angles_x *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
-       self.move_angles_z *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
-
-       Movetype_Physics_MatchServer(false);
-}
-#endif
-#endif
-
-bool v_racer(int req)
-{
-       switch(req)
-       {
-               case VR_IMPACT:
-               {
-               #ifdef SVQC
-                       if(autocvar_g_vehicle_racer_bouncepain)
-                               vehicles_impact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z);
-               #endif
-                       return true;
-               }
-
-               case VR_ENTER:
-               {
-               #ifdef SVQC
-                       self.movetype = MOVETYPE_BOUNCE;
-                       self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health)  * 100;
-                       self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield)  * 100;
-
-                       if(self.owner.flagcarried)
-                          setorigin(self.owner.flagcarried, '-190 0 96');
-               #elif defined(CSQC)
-
-                       self.move_movetype = MOVETYPE_BOUNCE;
-               #endif
-
-                       return true;
-               }
-
-               case VR_SPAWN:
-               {
-               #ifdef SVQC
-                       if(self.scale != 0.5)
-                       {
-                               if(autocvar_g_vehicle_racer_hovertype != 0)
-                                       racer_force_from_tag = vehicles_force_fromtag_maglev;
-                               else
-                                       racer_force_from_tag = vehicles_force_fromtag_hover;
-
-                               // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel).
-                               self.scale = 0.5;
-                               setattachment(self.vehicle_hudmodel, self, "");
-                               setattachment(self.vehicle_viewport, self, "tag_viewport");
-
-                               self.mass                          = 900;
-                       }
-
-                       self.think                = racer_think;
-                       self.nextthink    = time;
-                       self.vehicle_health = autocvar_g_vehicle_racer_health;
-                       self.vehicle_shield = autocvar_g_vehicle_racer_shield;
-
-                       self.movetype     = MOVETYPE_TOSS;
-                       self.solid                = SOLID_SLIDEBOX;
-                       self.delay                = time;
-                       self.scale                = 0.5;
-
-                       self.PlayerPhysplug = racer_frame;
-
-                       self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
-                       self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
-                       self.damageforcescale = 0.5;
-                       self.vehicle_health = autocvar_g_vehicle_racer_health;
-                       self.vehicle_shield = autocvar_g_vehicle_racer_shield;
-               #endif
-                       return true;
-               }
-
-               case VR_DEATH:
-               {
-               #ifdef SVQC
-                       self.SendEntity         = func_null; // stop networking this racer (for now)
-                       self.health                     = 0;
-                       self.event_damage       = func_null;
-                       self.solid                      = SOLID_CORPSE;
-                       self.takedamage         = DAMAGE_NO;
-                       self.deadflag           = DEAD_DYING;
-                       self.movetype           = MOVETYPE_BOUNCE;
-                       self.wait                       = time;
-                       self.delay                      = 2 + time + random() * 3;
-                       self.cnt                        = 1 + random() * 2;
-                       self.touch                      = racer_deadtouch;
-
-                       Send_Effect(EFFECT_EXPLOSION_MEDIUM, self.origin, '0 0 0', 1);
-
-                       if(random() < 0.5)
-                               self.avelocity_z = 32;
-                       else
-                               self.avelocity_z = -32;
-
-                       self.avelocity_x = -vlen(self.velocity) * 0.2;
-                       self.velocity += '0 0 700';
-                       self.colormod = '-0.5 -0.5 -0.5';
-
-                       self.think = racer_blowup_think;
-                       self.nextthink = time;
-               #endif
-                       return true;
-               }
-
-#ifdef CSQC
-               case VR_HUD:
-               {
-                       Vehicles_drawHUD(VEH_RACER.m_icon, "vehicle_racer_weapon1", "vehicle_racer_weapon2",
-                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
-                                                        "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
-                                                        vCROSS_GUIDE);
-                       return true;
-               }
-#endif
-               case VR_SETUP:
-               {
-               #ifdef SVQC
-                       self.vehicle_exit = racer_exit;
-               #endif
-
-               #ifdef SVQC
-                       // we have no need to network energy
-                       if(autocvar_g_vehicle_racer_energy)
-                       if(autocvar_g_vehicle_racer_energy_regen)
-                               self.vehicle_flags |= VHF_ENERGYREGEN;
-
-                       if(autocvar_g_vehicle_racer_shield)
-                               self.vehicle_flags |= VHF_HASSHIELD;
-
-                       if(autocvar_g_vehicle_racer_shield_regen)
-                               self.vehicle_flags |= VHF_SHIELDREGEN;
-
-                       if(autocvar_g_vehicle_racer_health_regen)
-                               self.vehicle_flags |= VHF_HEALTHREGEN;
-
-                       self.respawntime = autocvar_g_vehicle_racer_respawntime;
-                       self.vehicle_health = autocvar_g_vehicle_racer_health;
-                       self.vehicle_shield = autocvar_g_vehicle_racer_shield;
-                       self.max_health = self.vehicle_health;
-               #endif
-
-               #ifdef CSQC
-                       AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Rocket
-               #endif
-                       return true;
-               }
-
-               case VR_PRECACHE:
-               {
-               #ifdef SVQC
-                       precache_sound (W_Sound("lasergun_fire"));
-                       precache_sound (W_Sound("rocket_fire"));
-
-                       precache_sound ("vehicles/racer_idle.wav");
-                       precache_sound ("vehicles/racer_move.wav");
-                       precache_sound ("vehicles/racer_boost.wav");
-
-                       precache_model ("models/vhshield.md3");
-               #endif
-               #ifndef MENUQC
-                       precache_model ("models/vehicles/wakizashi.dpm");
-                       precache_model ("models/vehicles/wakizashi_cockpit.dpm");
-               #endif
-                       return true;
-               }
-       }
-
-       return true;
-}
-
-#endif // REGISTER_VEHICLE
diff --git a/qcsrc/common/vehicles/unit/raptor.qc b/qcsrc/common/vehicles/unit/raptor.qc
deleted file mode 100644 (file)
index d2ddea7..0000000
+++ /dev/null
@@ -1,1073 +0,0 @@
-#ifndef VEHICLE_RAPTOR
-#define VEHICLE_RAPTOR
-#include "raptor.qh"
-#ifndef MENUQC
-int v_raptor(int);
-#endif
-REGISTER_VEHICLE_SIMPLE(
-/* VEH_##id   */ RAPTOR,
-/* spawnflags */ VHF_DMGSHAKE | VHF_DMGROLL,
-/* mins,maxs  */ '-80 -80 0', '80 80 70',
-/* model         */ "models/vehicles/raptor.dpm",
-/* head_model */ "",
-/* hud_model  */ "models/vehicles/raptor_cockpit.dpm",
-/* tags                  */ "", "tag_hud", "tag_camera",
-/* netname       */ "raptor",
-/* fullname   */ _("Raptor")
-) {
-    this.m_icon = "vehicle_raptor";
-#ifndef MENUQC
-    this.vehicle_func = v_raptor;
-#endif
-}
-#endif
-
-#ifdef IMPLEMENTATION
-
-#ifdef SVQC
-bool autocvar_g_vehicle_raptor;
-
-float autocvar_g_vehicle_raptor_respawntime;
-float autocvar_g_vehicle_raptor_takeofftime;
-
-float autocvar_g_vehicle_raptor_movestyle;
-float autocvar_g_vehicle_raptor_turnspeed;
-float autocvar_g_vehicle_raptor_pitchspeed;
-float autocvar_g_vehicle_raptor_pitchlimit;
-
-float autocvar_g_vehicle_raptor_speed_forward;
-float autocvar_g_vehicle_raptor_speed_strafe;
-float autocvar_g_vehicle_raptor_speed_up;
-float autocvar_g_vehicle_raptor_speed_down;
-float autocvar_g_vehicle_raptor_friction;
-
-float autocvar_g_vehicle_raptor_bomblets;
-float autocvar_g_vehicle_raptor_bomblet_alt;
-float autocvar_g_vehicle_raptor_bomblet_time;
-float autocvar_g_vehicle_raptor_bomblet_damage;
-float autocvar_g_vehicle_raptor_bomblet_spread;
-float autocvar_g_vehicle_raptor_bomblet_edgedamage;
-float autocvar_g_vehicle_raptor_bomblet_radius;
-float autocvar_g_vehicle_raptor_bomblet_force;
-float autocvar_g_vehicle_raptor_bomblet_explode_delay;
-float autocvar_g_vehicle_raptor_bombs_refire;
-
-float autocvar_g_vehicle_raptor_flare_refire;
-float autocvar_g_vehicle_raptor_flare_lifetime;
-float autocvar_g_vehicle_raptor_flare_chase;
-float autocvar_g_vehicle_raptor_flare_range;
-
-float autocvar_g_vehicle_raptor_cannon_turnspeed;
-float autocvar_g_vehicle_raptor_cannon_turnlimit;
-float autocvar_g_vehicle_raptor_cannon_pitchlimit_up;
-float autocvar_g_vehicle_raptor_cannon_pitchlimit_down;
-
-float autocvar_g_vehicle_raptor_cannon_locktarget;
-float autocvar_g_vehicle_raptor_cannon_locking_time;
-float autocvar_g_vehicle_raptor_cannon_locking_releasetime;
-float autocvar_g_vehicle_raptor_cannon_locked_time;
-float autocvar_g_vehicle_raptor_cannon_predicttarget;
-
-float autocvar_g_vehicle_raptor_cannon_cost;
-float autocvar_g_vehicle_raptor_cannon_damage;
-float autocvar_g_vehicle_raptor_cannon_radius;
-float autocvar_g_vehicle_raptor_cannon_refire;
-float autocvar_g_vehicle_raptor_cannon_speed;
-float autocvar_g_vehicle_raptor_cannon_spread;
-float autocvar_g_vehicle_raptor_cannon_force;
-
-float autocvar_g_vehicle_raptor_energy;
-float autocvar_g_vehicle_raptor_energy_regen;
-float autocvar_g_vehicle_raptor_energy_regen_pause;
-
-float autocvar_g_vehicle_raptor_health;
-float autocvar_g_vehicle_raptor_health_regen;
-float autocvar_g_vehicle_raptor_health_regen_pause;
-
-float autocvar_g_vehicle_raptor_shield;
-float autocvar_g_vehicle_raptor_shield_regen;
-float autocvar_g_vehicle_raptor_shield_regen_pause;
-
-float autocvar_g_vehicle_raptor_bouncefactor;
-float autocvar_g_vehicle_raptor_bouncestop;
-vector autocvar_g_vehicle_raptor_bouncepain;
-
-.entity bomb1;
-.entity bomb2;
-
-float raptor_altitude(float amax)
-{
-       tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * amax), MOVE_WORLDONLY, self);
-       return vlen(self.origin - trace_endpos);
-}
-
-void raptor_bomblet_boom()
-{
-       RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage,
-                                                                       autocvar_g_vehicle_raptor_bomblet_edgedamage,
-                                                                       autocvar_g_vehicle_raptor_bomblet_radius, world, world,
-                                                                       autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world);
-       remove(self);
-}
-
-void raptor_bomblet_touch()
-{
-       if(other == self.owner)
-               return;
-
-       PROJECTILE_TOUCH;
-       self.think = raptor_bomblet_boom;
-       self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay;
-}
-
-void raptor_bomb_burst()
-{
-       if(self.cnt > time)
-       if(autocvar_g_vehicle_raptor_bomblet_alt)
-       {
-               self.nextthink = time;
-               traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self);
-               if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius))
-               {
-                       UpdateCSQCProjectile(self);
-                       return;
-               }
-       }
-
-       entity bomblet;
-       float i;
-
-       Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT, 0, self);
-
-       for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i)
-       {
-               bomblet = spawn();
-               setorigin(bomblet, self.origin);
-
-               bomblet.movetype        = MOVETYPE_TOSS;
-               bomblet.touch      = raptor_bomblet_touch;
-               bomblet.think      = raptor_bomblet_boom;
-               bomblet.nextthink   = time + 5;
-               bomblet.owner      = self.owner;
-               bomblet.realowner   = self.realowner;
-               bomblet.velocity        = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity);
-
-               PROJECTILE_MAKETRIGGER(bomblet);
-               CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true);
-       }
-
-       remove(self);
-}
-
-void raptor_bombdrop()
-{
-       entity bomb_1, bomb_2;
-
-       bomb_1 = spawn();
-       bomb_2 = spawn();
-
-       setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left")));
-       setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right")));
-
-       bomb_1.movetype  = bomb_2.movetype   = MOVETYPE_BOUNCE;
-       bomb_1.velocity  = bomb_2.velocity   = self.velocity;
-       bomb_1.touch            = bomb_2.touch    = raptor_bomb_burst;
-       bomb_1.think            = bomb_2.think    = raptor_bomb_burst;
-       bomb_1.cnt                = bomb_2.cnt          = time + 10;
-
-       if(autocvar_g_vehicle_raptor_bomblet_alt)
-               bomb_1.nextthink = bomb_2.nextthink  = time;
-       else
-               bomb_1.nextthink = bomb_2.nextthink  = time + autocvar_g_vehicle_raptor_bomblet_time;
-
-       bomb_1.owner     = bomb_2.owner   = self;
-       bomb_1.realowner = bomb_2.realowner  = self.owner;
-       bomb_1.solid     = bomb_2.solid   = SOLID_BBOX;
-       bomb_1.gravity   = bomb_2.gravity       = 1;
-
-       PROJECTILE_MAKETRIGGER(bomb_1);
-       PROJECTILE_MAKETRIGGER(bomb_2);
-
-       CSQCProjectile(bomb_1, true, PROJECTILE_RAPTORBOMB, true);
-       CSQCProjectile(bomb_2, true, PROJECTILE_RAPTORBOMB, true);
-}
-
-
-void raptor_fire_cannon(entity gun, string tagname)
-{
-       vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, W_Sound("lasergun_fire"),
-                                                  gettaginfo(gun, gettagindex(gun, tagname)), normalize(v_forward + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
-                                                  autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force,  0,
-                                                  DEATH_VH_RAPT_CANNON, PROJECTILE_RAPTORCANNON, 0, true, true, self.owner);
-}
-
-void raptor_land()
-{
-       float hgt;
-
-       hgt = raptor_altitude(512);
-       self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
-       self.angles_x *= 0.95;
-       self.angles_z *= 0.95;
-
-       if(hgt < 128)
-       if(hgt > 0)
-               self.frame = (hgt / 128) * 25;
-
-       self.bomb1.gun1.avelocity_y = 90 + ((self.frame / 25) * 2000);
-       self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
-
-       if(hgt < 16)
-       {
-               self.movetype = MOVETYPE_TOSS;
-               self.think      = vehicles_think;
-               self.frame      = 0;
-       }
-
-       self.nextthink  = time;
-
-       CSQCMODEL_AUTOUPDATE();
-}
-
-void raptor_exit(float eject)
-{
-       vector spot;
-       self.tur_head.exteriormodeltoclient = world;
-
-       if(self.deadflag == DEAD_NO)
-       {
-               self.think        = raptor_land;
-               self.nextthink  = time;
-       }
-
-       if(!self.owner)
-               return;
-
-       makevectors(self.angles);
-       if(eject)
-       {
-               spot = self.origin + v_forward * 100 + '0 0 64';
-               spot = vehicles_findgoodexit(spot);
-               setorigin(self.owner , spot);
-               self.owner.velocity = (v_up + v_forward * 0.25) * 750;
-               self.owner.oldvelocity = self.owner.velocity;
-       }
-       else
-       {
-               if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
-               {
-                       self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
-                       self.owner.velocity_z += 200;
-                       spot = self.origin + v_forward * 32 + '0 0 64';
-                       spot = vehicles_findgoodexit(spot);
-               }
-               else
-               {
-                       self.owner.velocity = self.velocity * 0.5;
-                       self.owner.velocity_z += 10;
-                       spot = self.origin - v_forward * 200 + '0 0 64';
-                       spot = vehicles_findgoodexit(spot);
-               }
-               self.owner.oldvelocity = self.owner.velocity;
-               setorigin(self.owner , spot);
-       }
-
-       antilag_clear(self.owner);
-       self.owner = world;
-}
-
-void raptor_flare_touch()
-{
-       remove(self);
-}
-
-void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
-       self.health -= damage;
-       if(self.health <= 0)
-               remove(self);
-}
-
-void raptor_flare_think()
-{
-       self.nextthink = time + 0.1;
-       entity _missile = findchainentity(enemy, self.owner);
-       while(_missile)
-       {
-               if(_missile.flags & FL_PROJECTILE)
-               if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range)
-               if(random() > autocvar_g_vehicle_raptor_flare_chase)
-                       _missile.enemy = self;
-               _missile = _missile.chain;
-       }
-
-       if(self.tur_impacttime < time)
-               remove(self);
-}
-
-float raptor_frame()
-{
-       entity player, raptor;
-       float ftmp = 0;
-       vector df;
-
-       if(intermission_running)
-       {
-               self.vehicle.velocity = '0 0 0';
-               self.vehicle.avelocity = '0 0 0';
-               return 1;
-       }
-
-       player = self;
-       raptor = self.vehicle;
-       self   = raptor;
-
-       vehicles_painframe();
-       /*
-       ftmp = vlen(self.velocity);
-       if(ftmp > autocvar_g_vehicle_raptor_speed_forward)
-               ftmp = 1;
-       else
-               ftmp = ftmp / autocvar_g_vehicle_raptor_speed_forward;
-       */
-
-       if(self.sound_nexttime < time)
-       {
-               self.sound_nexttime = time + 7.955812;
-               //sound (self.tur_head, CH_TRIGGER_SINGLE, "vehicles/raptor_fly.wav", 1 - ftmp,   ATTEN_NORM );
-               sound (self, CH_TRIGGER_SINGLE, "vehicles/raptor_speed.wav", 1, ATTEN_NORM);
-               self.wait = ftmp;
-       }
-       /*
-       else if(fabs(ftmp - self.wait) > 0.2)
-       {
-               sound (self.tur_head, CH_TRIGGER_SINGLE, "", 1 - ftmp,   ATTEN_NORM );
-               sound (self, CH_TRIGGER_SINGLE, "", ftmp, ATTEN_NORM);
-               self.wait = ftmp;
-       }
-       */
-
-       if(raptor.deadflag != DEAD_NO)
-       {
-               self = player;
-               player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
-               return 1;
-       }
-       crosshair_trace(player);
-
-       //if(time - self.lastteleporttime < 1)
-       //{
-               if(raptor.angles_z > 50 || raptor.angles_z < -50)
-               {
-                       if(player.BUTTON_JUMP)
-                       {
-                               player.BUTTON_CROUCH = true;
-                               player.BUTTON_JUMP = false;
-                       }
-               }
-       //}
-
-       vector vang;
-       vang = raptor.angles;
-       df = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
-       vang_x *= -1;
-       df_x *= -1;
-       if(df_x > 180)  df_x -= 360;
-       if(df_x < -180) df_x += 360;
-       if(df_y > 180)  df_y -= 360;
-       if(df_y < -180) df_y += 360;
-
-       ftmp = shortangle_f(player.v_angle_y - vang_y, vang_y);
-       if(ftmp > 180)  ftmp -= 360; if(ftmp < -180) ftmp += 360;
-       raptor.avelocity_y = bound(-autocvar_g_vehicle_raptor_turnspeed, ftmp + raptor.avelocity_y * 0.9, autocvar_g_vehicle_raptor_turnspeed);
-
-       // Pitch
-       ftmp = 0;
-       if(player.movement_x > 0 && vang_x < autocvar_g_vehicle_raptor_pitchlimit) ftmp = 5;
-       else if(player.movement_x < 0 && vang_x > -autocvar_g_vehicle_raptor_pitchlimit) ftmp = -20;
-
-       df_x = bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x , autocvar_g_vehicle_raptor_pitchlimit);
-       ftmp = vang_x - bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x + ftmp, autocvar_g_vehicle_raptor_pitchlimit);
-       raptor.avelocity_x = bound(-autocvar_g_vehicle_raptor_pitchspeed, ftmp + raptor.avelocity_x * 0.9, autocvar_g_vehicle_raptor_pitchspeed);
-
-       raptor.angles_x = anglemods(raptor.angles_x);
-       raptor.angles_y = anglemods(raptor.angles_y);
-       raptor.angles_z = anglemods(raptor.angles_z);
-
-       if(autocvar_g_vehicle_raptor_movestyle == 1)
-               makevectors('0 1 0' * raptor.angles_y);
-       else
-               makevectors(player.v_angle);
-
-       df = raptor.velocity * -autocvar_g_vehicle_raptor_friction;
-
-       if(player.movement_x != 0)
-       {
-               if(player.movement_x > 0)
-                       df += v_forward  * autocvar_g_vehicle_raptor_speed_forward;
-               else if(player.movement_x < 0)
-                       df -= v_forward  * autocvar_g_vehicle_raptor_speed_forward;
-       }
-
-       if(player.movement_y != 0)
-       {
-               if(player.movement_y < 0)
-                       df -= v_right * autocvar_g_vehicle_raptor_speed_strafe;
-               else if(player.movement_y > 0)
-                       df += v_right * autocvar_g_vehicle_raptor_speed_strafe;
-
-               raptor.angles_z = bound(-30,raptor.angles_z + (player.movement_y / autocvar_g_vehicle_raptor_speed_strafe),30);
-       }
-       else
-       {
-               raptor.angles_z *= 0.95;
-               if(raptor.angles_z >= -1 && raptor.angles_z <= -1)
-                       raptor.angles_z = 0;
-       }
-
-       if(player.BUTTON_CROUCH)
-               df -=   v_up * autocvar_g_vehicle_raptor_speed_down;
-       else if (player.BUTTON_JUMP)
-               df +=  v_up * autocvar_g_vehicle_raptor_speed_up;
-
-       raptor.velocity  += df * frametime;
-       player.velocity = player.movement  = raptor.velocity;
-       setorigin(player, raptor.origin + '0 0 32');
-
-       player.vehicle_weapon2mode = raptor.vehicle_weapon2mode;
-
-       vector vf, ad;
-       // Target lock & predict
-       if(autocvar_g_vehicle_raptor_cannon_locktarget == 2)
-       {
-               if(raptor.gun1.lock_time < time || raptor.gun1.enemy.deadflag)
-                       raptor.gun1.enemy = world;
-
-               if(trace_ent)
-               if(trace_ent.movetype)
-               if(trace_ent.takedamage)
-               if(!trace_ent.deadflag)
-               {
-                       if(teamplay)
-                       {
-                               if(trace_ent.team != player.team)
-                               {
-                                       raptor.gun1.enemy = trace_ent;
-                                       raptor.gun1.lock_time = time + 5;
-                               }
-                       }
-                       else
-                       {
-                               raptor.gun1.enemy = trace_ent;
-                               raptor.gun1.lock_time = time + 0.5;
-                       }
-               }
-
-               if(raptor.gun1.enemy)
-               {
-                       float distance, impact_time;
-
-                       vf = real_origin(raptor.gun1.enemy);
-                       UpdateAuxiliaryXhair(player, vf, '1 0 0', 1);
-                       vector _vel = raptor.gun1.enemy.velocity;
-                       if(raptor.gun1.enemy.movetype == MOVETYPE_WALK)
-                               _vel_z *= 0.1;
-
-                       if(autocvar_g_vehicle_raptor_cannon_predicttarget)
-                       {
-                               ad = vf;
-                               distance = vlen(ad - player.origin);
-                               impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
-                               ad = vf + _vel * impact_time;
-                               trace_endpos = ad;
-                       }
-                       else
-                               trace_endpos = vf;
-               }
-       }
-       else if(autocvar_g_vehicle_raptor_cannon_locktarget == 1)
-       {
-
-               vehicles_locktarget((1 / autocvar_g_vehicle_raptor_cannon_locking_time) * frametime,
-                                                        (1 / autocvar_g_vehicle_raptor_cannon_locking_releasetime) * frametime,
-                                                        autocvar_g_vehicle_raptor_cannon_locked_time);
-
-               if(self.lock_target != world)
-               if(autocvar_g_vehicle_raptor_cannon_predicttarget)
-               if(self.lock_strength == 1)
-               {
-                       float i, distance, impact_time;
-
-                       vf = real_origin(raptor.lock_target);
-                       ad = vf;
-                       for(i = 0; i < 4; ++i)
-                       {
-                               distance = vlen(ad - raptor.origin);
-                               impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
-                               ad = vf + raptor.lock_target.velocity * impact_time;
-                       }
-                       trace_endpos = ad;
-               }
-
-               if(self.lock_target)
-               {
-                       if(raptor.lock_strength == 1)
-                               UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '1 0 0', 1);
-                       else if(self.lock_strength > 0.5)
-                               UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 1 0', 1);
-                       else if(self.lock_strength < 0.5)
-                               UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 0 1', 1);
-               }
-       }
-
-
-       vehicle_aimturret(raptor, trace_endpos, raptor.gun1, "fire1",
-                                                 autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
-                                                 autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
-
-       vehicle_aimturret(raptor, trace_endpos, raptor.gun2, "fire1",
-                                                 autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
-                                                 autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
-
-       /*
-       ad = ad * 0.5;
-       v_forward = vf * 0.5;
-       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, raptor);
-       UpdateAuxiliaryXhair(player, trace_endpos, '0 1 0', 0);
-       */
-
-       if(!forbidWeaponUse(player))
-       if(player.BUTTON_ATCK)
-       if(raptor.attack_finished_single <= time)
-       if(raptor.vehicle_energy > autocvar_g_vehicle_raptor_cannon_cost)
-       {
-               raptor.misc_bulletcounter += 1;
-               raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire;
-               if(raptor.misc_bulletcounter <= 2)
-                       raptor_fire_cannon(self.gun1, "fire1");
-               else if(raptor.misc_bulletcounter == 3)
-                       raptor_fire_cannon(self.gun2, "fire1");
-               else
-               {
-                       raptor.attack_finished_single = time + autocvar_g_vehicle_raptor_cannon_refire * 2;
-                       raptor_fire_cannon(self.gun2, "fire1");
-                       raptor.misc_bulletcounter = 0;
-               }
-               raptor.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost;
-               self.cnt = time;
-       }
-
-       if(self.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
-
-       if(self.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
-
-       if(self.vehicle_flags  & VHF_ENERGYREGEN)
-               vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
-
-       if(!forbidWeaponUse(player))
-       if(raptor.vehicle_weapon2mode == RSM_BOMB)
-       {
-               if(time > raptor.lip + autocvar_g_vehicle_raptor_bombs_refire)
-               if(player.BUTTON_ATCK2)
-               {
-                       raptor_bombdrop();
-                       raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
-                       raptor.lip   = time;
-               }
-       }
-       else
-       {
-               if(time > raptor.lip + autocvar_g_vehicle_raptor_flare_refire)
-               if(player.BUTTON_ATCK2)
-               {
-                       float i;
-                       entity _flare;
-
-                       for(i = 0; i < 3; ++i)
-                       {
-                       _flare = spawn();
-                       setmodel(_flare, "models/runematch/rune.mdl");
-                       _flare.effects = EF_LOWPRECISION | EF_FLAME;
-                       _flare.scale = 0.5;
-                       setorigin(_flare, self.origin - '0 0 16');
-                       _flare.movetype = MOVETYPE_TOSS;
-                       _flare.gravity = 0.15;
-                       _flare.velocity = 0.25 * raptor.velocity + (v_forward + randomvec() * 0.25)* -500;
-                       _flare.think = raptor_flare_think;
-                       _flare.nextthink = time;
-                       _flare.owner = raptor;
-                       _flare.solid = SOLID_CORPSE;
-                       _flare.takedamage = DAMAGE_YES;
-                       _flare.event_damage = raptor_flare_damage;
-                       _flare.health = 20;
-                       _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime;
-                       _flare.touch = raptor_flare_touch;
-                       }
-                       raptor.delay = time + autocvar_g_vehicle_raptor_flare_refire;
-                       raptor.lip   = time;
-               }
-       }
-
-       raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
-       player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
-       player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
-
-       if(self.bomb1.cnt < time)
-       {
-               entity _missile = findchainentity(enemy, raptor);
-               float _incomming = 0;
-               while(_missile)
-               {
-                       if(_missile.flags & FL_PROJECTILE)
-                       if(MISSILE_IS_TRACKING(_missile))
-                       if(vlen(self.origin - _missile.origin) < 2 * autocvar_g_vehicle_raptor_flare_range)
-                               ++_incomming;
-
-                       _missile = _missile.chain;
-               }
-
-               if(_incomming)
-                       sound(self, CH_PAIN_SINGLE, "vehicles/missile_alarm.wav", VOL_BASE, ATTEN_NONE);
-
-               self.bomb1.cnt = time + 1;
-       }
-
-
-       VEHICLE_UPDATE_PLAYER(player, health, raptor);
-       VEHICLE_UPDATE_PLAYER(player, energy, raptor);
-       if(self.vehicle_flags & VHF_HASSHIELD)
-               VEHICLE_UPDATE_PLAYER(player, shield, raptor);
-
-       player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
-
-       self = player;
-       return 1;
-}
-
-float raptor_takeoff()
-{
-       entity player, raptor;
-
-       player = self;
-       raptor = self.vehicle;
-       self   = raptor;
-
-       self.nextthink = time;
-       CSQCMODEL_AUTOUPDATE();
-       self.nextthink = 0; // will this work?
-
-       if(self.sound_nexttime < time)
-       {
-               self.sound_nexttime = time + 7.955812; //soundlength("vehicles/raptor_fly.wav");
-               sound (self, CH_TRIGGER_SINGLE, "vehicles/raptor_speed.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-       }
-
-       // Takeoff sequense
-       if(raptor.frame < 25)
-       {
-               raptor.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / sys_frametime);
-               raptor.velocity_z = min(raptor.velocity_z * 1.5, 256);
-               self.bomb1.gun1.avelocity_y = 90 + ((raptor.frame / 25) * 25000);
-               self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
-               player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
-
-               setorigin(player, raptor.origin + '0 0 32');
-       }
-       else
-               player.PlayerPhysplug = raptor_frame;
-
-       if(self.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
-
-       if(self.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
-
-       if(self.vehicle_flags  & VHF_ENERGYREGEN)
-               vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
-
-
-       raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
-       player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
-       player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
-
-       VEHICLE_UPDATE_PLAYER(player, health, raptor);
-       VEHICLE_UPDATE_PLAYER(player, energy, raptor);
-       if(self.vehicle_flags & VHF_HASSHIELD)
-               VEHICLE_UPDATE_PLAYER(player, shield, raptor);
-
-       player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
-       self = player;
-       return 1;
-}
-
-void raptor_blowup()
-{
-       self.deadflag   = DEAD_DEAD;
-       self.vehicle_exit(VHEF_NORMAL);
-       RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_RAPT_DEATH, world);
-
-       self.alpha                = -1;
-       self.movetype      = MOVETYPE_NONE;
-       self.effects            = EF_NODRAW;
-       self.colormod      = '0 0 0';
-       self.avelocity    = '0 0 0';
-       self.velocity      = '0 0 0';
-
-       setorigin(self, self.pos1);
-       self.touch = func_null;
-       self.nextthink = 0;
-}
-
-void raptor_diethink()
-{
-       if(time >= self.wait)
-               self.think = raptor_blowup;
-
-       if(random() < 0.05)
-       {
-               sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
-               Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
-       }
-       self.nextthink = time;
-
-       CSQCMODEL_AUTOUPDATE();
-}
-
-// If we dont do this ever now and then, the raptors rotors
-// stop working, presumably due to angle overflow. cute.
-void raptor_rotor_anglefix()
-{
-       self.gun1.angles_y = anglemods(self.gun1.angles_y);
-       self.gun2.angles_y = anglemods(self.gun2.angles_y);
-       self.nextthink = time + 15;
-}
-
-float raptor_impulse(float _imp)
-{
-       switch(_imp)
-       {
-               case 1:
-               case 230:
-                       self.vehicle.vehicle_weapon2mode = RSM_BOMB;
-                       CSQCVehicleSetup(self, 0);
-                       return true;
-               case 2:
-               case 231:
-                       self.vehicle.vehicle_weapon2mode = RSM_FLARE;
-                       CSQCVehicleSetup(self, 0);
-                       return true;
-
-               case 10:
-               case 15:
-               case 18:
-                       self.vehicle.vehicle_weapon2mode += 1;
-                       if(self.vehicle.vehicle_weapon2mode > RSM_LAST)
-                               self.vehicle.vehicle_weapon2mode = RSM_FIRST;
-
-                       CSQCVehicleSetup(self, 0);
-                       return true;
-               case 11:
-               case 12:
-               case 16:
-               case 19:
-                       self.vehicle.vehicle_weapon2mode -= 1;
-                       if(self.vehicle.vehicle_weapon2mode < RSM_FIRST)
-                               self.vehicle.vehicle_weapon2mode = RSM_LAST;
-
-                       CSQCVehicleSetup(self, 0);
-                       return true;
-
-               /*
-               case 17: // toss gun, could be used to exit?
-                       break;
-               case 20: // Manual minigun reload?
-                       break;
-               */
-       }
-       return false;
-}
-
-void spawnfunc_vehicle_raptor()
-{
-       if(!autocvar_g_vehicle_raptor) { remove(self); return; }
-       if(!vehicle_initialize(VEH_RAPTOR, false)) { remove(self); return; }
-}
-
-float v_raptor(float req)
-{
-       switch(req)
-       {
-               case VR_IMPACT:
-               {
-                       if(autocvar_g_vehicle_raptor_bouncepain)
-                               vehicles_impact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z);
-
-                       return true;
-               }
-               case VR_ENTER:
-               {
-                       self.vehicle_weapon2mode = RSM_BOMB;
-                       self.owner.PlayerPhysplug = raptor_takeoff;
-                       self.movetype      = MOVETYPE_BOUNCEMISSILE;
-                       self.solid                = SOLID_SLIDEBOX;
-                       self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_raptor_health) * 100;
-                       self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_raptor_shield) * 100;
-                       self.velocity_z = 1; // Nudge upwards to takeoff sequense can work.
-                       self.tur_head.exteriormodeltoclient = self.owner;
-
-                       self.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
-                       self.lip   = time;
-
-                       if(self.owner.flagcarried)
-                          setorigin(self.owner.flagcarried, '-20 0 96');
-
-                       CSQCVehicleSetup(self.owner, 0);
-                       return true;
-               }
-               case VR_THINK:
-               {
-                       return true;
-               }
-               case VR_DEATH:
-               {
-                       self.health                             = 0;
-                       self.event_damage               = func_null;
-                       self.solid                              = SOLID_CORPSE;
-                       self.takedamage                 = DAMAGE_NO;
-                       self.deadflag                   = DEAD_DYING;
-                       self.movetype                   = MOVETYPE_BOUNCE;
-                       self.think                              = raptor_diethink;
-                       self.nextthink                  = time;
-                       self.wait                               = time + 5 + (random() * 5);
-
-                       Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation (self.origin, 16), '0 0 0', 1);
-
-                       self.velocity_z += 600;
-
-                       self.avelocity = '0 0.5 1' * (random() * 400);
-                       self.avelocity -= '0 0.5 1' * (random() * 400);
-
-                       self.colormod = '-0.5 -0.5 -0.5';
-                       self.touch = raptor_blowup;
-                       return true;
-               }
-               case VR_SPAWN:
-               {
-                       if(!self.gun1)
-                       {
-                               entity spinner;
-                               vector ofs;
-
-                               //FIXME: Camera is in a bad place in HUD model.
-                               //setorigin(self.vehicle_viewport, '25 0 5');
-
-                               self.vehicles_impulse   = raptor_impulse;
-
-                               self.frame = 0;
-
-                               self.bomb1 = spawn();
-                               self.bomb2 = spawn();
-                               self.gun1  = spawn();
-                               self.gun2  = spawn();
-
-                               setmodel(self.bomb1,"models/vehicles/clusterbomb_folded.md3");
-                               setmodel(self.bomb2,"models/vehicles/clusterbomb_folded.md3");
-                               setmodel(self.gun1, "models/vehicles/raptor_gun.dpm");
-                               setmodel(self.gun2, "models/vehicles/raptor_gun.dpm");
-                               setmodel(self.tur_head, "models/vehicles/raptor_body.dpm");
-
-                               setattachment(self.bomb1, self, "bombmount_left");
-                               setattachment(self.bomb2, self, "bombmount_right");
-                               setattachment(self.tur_head, self,"root");
-
-                               // FIXMODEL Guns mounts to angled bones
-                               self.bomb1.angles = self.angles;
-                               self.angles = '0 0 0';
-                               // This messes up gun-aim, so work arround it.
-                               //setattachment(self.gun1, self, "gunmount_left");
-                               ofs = gettaginfo(self, gettagindex(self, "gunmount_left"));
-                               ofs -= self.origin;
-                               setattachment(self.gun1, self, "");
-                               setorigin(self.gun1, ofs);
-
-                               //setattachment(self.gun2, self, "gunmount_right");
-                               ofs = gettaginfo(self, gettagindex(self, "gunmount_right"));
-                               ofs -= self.origin;
-                               setattachment(self.gun2, self, "");
-                               setorigin(self.gun2, ofs);
-
-                               self.angles = self.bomb1.angles;
-                               self.bomb1.angles = '0 0 0';
-
-                               spinner = spawn();
-                               spinner.owner = self;
-                               setmodel(spinner,"models/vehicles/spinner.dpm");
-                               setattachment(spinner, self, "engine_left");
-                               spinner.movetype = MOVETYPE_NOCLIP;
-                               spinner.avelocity = '0 90 0';
-                               self.bomb1.gun1 = spinner;
-
-                               spinner = spawn();
-                               spinner.owner = self;
-                               setmodel(spinner,"models/vehicles/spinner.dpm");
-                               setattachment(spinner, self, "engine_right");
-                               spinner.movetype = MOVETYPE_NOCLIP;
-                               spinner.avelocity = '0 -90 0';
-                               self.bomb1.gun2 = spinner;
-
-                               // Sigh.
-                               self.bomb1.think = raptor_rotor_anglefix;
-                               self.bomb1.nextthink = time;
-
-                               self.mass                          = 1 ;
-                       }
-
-                       self.frame                = 0;
-                       self.vehicle_health = autocvar_g_vehicle_raptor_health;
-                       self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
-                       self.movetype      = MOVETYPE_TOSS;
-                       self.solid                = SOLID_SLIDEBOX;
-                       self.vehicle_energy = 1;
-
-                       self.PlayerPhysplug = raptor_frame;
-
-                       self.bomb1.gun1.avelocity_y = 90;
-                       self.bomb1.gun2.avelocity_y = -90;
-
-                       self.delay = time;
-
-                       self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
-                       self.bouncestop = autocvar_g_vehicle_raptor_bouncestop;
-                       self.damageforcescale = 0.25;
-                       self.vehicle_health = autocvar_g_vehicle_raptor_health;
-                       self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
-                       return true;
-               }
-               case VR_SETUP:
-               {
-                       if(autocvar_g_vehicle_raptor_shield)
-                               self.vehicle_flags |= VHF_HASSHIELD;
-
-                       if(autocvar_g_vehicle_raptor_shield_regen)
-                               self.vehicle_flags |= VHF_SHIELDREGEN;
-
-                       if(autocvar_g_vehicle_raptor_health_regen)
-                               self.vehicle_flags |= VHF_HEALTHREGEN;
-
-                       if(autocvar_g_vehicle_raptor_energy_regen)
-                               self.vehicle_flags |= VHF_ENERGYREGEN;
-
-                       self.vehicle_exit = raptor_exit;
-                       self.respawntime = autocvar_g_vehicle_raptor_respawntime;
-                       self.vehicle_health = autocvar_g_vehicle_raptor_health;
-                       self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
-                       self.max_health = self.vehicle_health;
-
-                       return true;
-               }
-               case VR_PRECACHE:
-               {
-                       precache_model ("models/vehicles/raptor.dpm");
-                       precache_model ("models/vehicles/raptor_gun.dpm");
-                       precache_model ("models/vehicles/spinner.dpm");
-                       precache_model ("models/vehicles/raptor_cockpit.dpm");
-                       precache_model ("models/vehicles/clusterbomb_folded.md3");
-                       precache_model ("models/vehicles/raptor_body.dpm");
-
-                       precache_sound ("vehicles/raptor_fly.wav");
-                       precache_sound ("vehicles/raptor_speed.wav");
-                       precache_sound ("vehicles/missile_alarm.wav");
-
-                       return true;
-               }
-       }
-
-       return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-
-void RaptorCBShellfragDraw()
-{
-       if(wasfreed(self))
-               return;
-
-       Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
-       self.move_avelocity += randomvec() * 15;
-       self.renderflags = 0;
-
-       if(self.cnt < time)
-               self.alpha = bound(0, self.nextthink - time, 1);
-
-       if(self.alpha < ALPHA_MIN_VISIBLE)
-               remove(self);
-}
-
-void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
-{
-       entity sfrag;
-
-       sfrag = spawn();
-       setmodel(sfrag, "models/vehicles/clusterbomb_fragment.md3");
-       setorigin(sfrag, _org);
-
-       sfrag.move_movetype = MOVETYPE_BOUNCE;
-       sfrag.gravity = 0.15;
-       sfrag.solid = SOLID_CORPSE;
-
-       sfrag.draw = RaptorCBShellfragDraw;
-
-       sfrag.move_origin = sfrag.origin = _org;
-       sfrag.move_velocity = _vel;
-       sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
-       sfrag.angles = self.move_angles = _ang;
-
-       sfrag.move_time = time;
-       sfrag.damageforcescale = 4;
-
-       sfrag.nextthink = time + 3;
-       sfrag.cnt = time + 2;
-       sfrag.alpha = 1;
-       sfrag.drawmask = MASK_NORMAL;
-}
-
-float v_raptor(float req)
-{
-       switch(req)
-       {
-               case VR_HUD:
-               {
-                       string crosshair;
-
-                       switch(weapon2mode)
-                       {
-                               case RSM_FLARE: crosshair = vCROSS_RAIN;  break;
-                               case RSM_BOMB:  crosshair = vCROSS_BURST; break;
-                               default:        crosshair = vCROSS_BURST;
-                       }
-
-                       Vehicles_drawHUD(VEH_RAPTOR.m_icon, "vehicle_raptor_weapon1", "vehicle_raptor_weapon2",
-                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
-                                                        "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
-                                                        crosshair);
-                       return true;
-               }
-               case VR_SETUP:
-               {
-                       AuxiliaryXhair[1].axh_image = vCROSS_LOCK;
-                       return true;
-               }
-               case VR_PRECACHE:
-               {
-                       return true;
-               }
-       }
-
-       return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_VEHICLE
diff --git a/qcsrc/common/vehicles/unit/raptor.qh b/qcsrc/common/vehicles/unit/raptor.qh
deleted file mode 100644 (file)
index f24939b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef RAPTOR_H
-#define RAPTOR_H
-
-const int RSM_FIRST = 1;
-const int RSM_BOMB = 1;
-const int RSM_FLARE = 2;
-const int RSM_LAST = 2;
-
-#endif
diff --git a/qcsrc/common/vehicles/unit/spiderbot.qc b/qcsrc/common/vehicles/unit/spiderbot.qc
deleted file mode 100644 (file)
index 973e1e5..0000000
+++ /dev/null
@@ -1,995 +0,0 @@
-#ifndef VEHICLE_SPIDERBOT
-#define VEHICLE_SPIDERBOT
-#ifndef MENUQC
-int v_spiderbot(int);
-#endif
-REGISTER_VEHICLE_SIMPLE(
-/* VEH_##id   */ SPIDERBOT,
-/* spawnflags */ VHF_DMGSHAKE,
-/* mins,maxs  */ '-75 -75 10', '75 75 125',
-/* model         */ "models/vehicles/spiderbot.dpm",
-/* head_model */ "models/vehicles/spiderbot_top.dpm",
-/* hud_model  */ "models/vehicles/spiderbot_cockpit.dpm",
-/* tags                  */ "tag_head", "tag_hud", "",
-/* netname       */ "spiderbot",
-/* fullname   */ _("Spiderbot")
-) {
-    this.m_icon = "vehicle_spider";
-#ifndef MENUQC
-    this.vehicle_func = v_spiderbot;
-#endif
-}
-#endif
-
-#ifdef IMPLEMENTATION
-
-const int SBRM_FIRST = 1;
-const int SBRM_VOLLY = 1;
-const int SBRM_GUIDE = 2;
-const int SBRM_ARTILLERY = 3;
-const int SBRM_LAST = 3;
-
-#ifdef SVQC
-bool autocvar_g_vehicle_spiderbot;
-
-float autocvar_g_vehicle_spiderbot_respawntime;
-
-float autocvar_g_vehicle_spiderbot_speed_stop;
-float autocvar_g_vehicle_spiderbot_speed_strafe;
-float autocvar_g_vehicle_spiderbot_speed_walk;
-float autocvar_g_vehicle_spiderbot_speed_run = 700;
-float autocvar_g_vehicle_spiderbot_turnspeed;
-float autocvar_g_vehicle_spiderbot_turnspeed_strafe;
-float autocvar_g_vehicle_spiderbot_movement_inertia;
-
-float autocvar_g_vehicle_spiderbot_springlength;
-float autocvar_g_vehicle_spiderbot_springup;
-float autocvar_g_vehicle_spiderbot_springblend;
-float autocvar_g_vehicle_spiderbot_tiltlimit;
-
-float autocvar_g_vehicle_spiderbot_head_pitchlimit_down;
-float autocvar_g_vehicle_spiderbot_head_pitchlimit_up;
-float autocvar_g_vehicle_spiderbot_head_turnlimit;
-float autocvar_g_vehicle_spiderbot_head_turnspeed;
-
-int autocvar_g_vehicle_spiderbot_health;
-float autocvar_g_vehicle_spiderbot_health_regen;
-float autocvar_g_vehicle_spiderbot_health_regen_pause;
-
-int autocvar_g_vehicle_spiderbot_shield;
-float autocvar_g_vehicle_spiderbot_shield_regen;
-float autocvar_g_vehicle_spiderbot_shield_regen_pause;
-
-float autocvar_g_vehicle_spiderbot_minigun_damage;
-float autocvar_g_vehicle_spiderbot_minigun_refire;
-float autocvar_g_vehicle_spiderbot_minigun_spread;
-int autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
-int autocvar_g_vehicle_spiderbot_minigun_ammo_max;
-int autocvar_g_vehicle_spiderbot_minigun_ammo_regen;
-float autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause;
-float autocvar_g_vehicle_spiderbot_minigun_force;
-float autocvar_g_vehicle_spiderbot_minigun_solidpenetration;
-
-float autocvar_g_vehicle_spiderbot_rocket_damage;
-float autocvar_g_vehicle_spiderbot_rocket_force;
-float autocvar_g_vehicle_spiderbot_rocket_radius;
-float autocvar_g_vehicle_spiderbot_rocket_speed;
-float autocvar_g_vehicle_spiderbot_rocket_spread;
-float autocvar_g_vehicle_spiderbot_rocket_refire;
-float autocvar_g_vehicle_spiderbot_rocket_refire2;
-float autocvar_g_vehicle_spiderbot_rocket_reload;
-float autocvar_g_vehicle_spiderbot_rocket_health;
-float autocvar_g_vehicle_spiderbot_rocket_noise;
-float autocvar_g_vehicle_spiderbot_rocket_turnrate;
-float autocvar_g_vehicle_spiderbot_rocket_lifetime;
-
-vector autocvar_g_vehicle_spiderbot_bouncepain;
-
-void spiderbot_rocket_artillery()
-{
-       self.nextthink = time;
-       UpdateCSQCProjectile(self);
-}
-
-void spiderbot_rocket_unguided()
-{
-       vector newdir, olddir;
-
-       self.nextthink  = time;
-
-       olddir = normalize(self.velocity);
-       newdir = normalize(self.pos1 - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
-       self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
-
-       UpdateCSQCProjectile(self);
-
-       if (self.owner.deadflag != DEAD_NO || self.cnt < time || vlen(self.pos1 - self.origin) < 16)
-               self.use();
-}
-
-void spiderbot_rocket_guided()
-{
-       vector newdir, olddir;
-
-       self.nextthink  = time;
-
-       if(!self.realowner.vehicle)
-               self.think = spiderbot_rocket_unguided;
-
-       crosshair_trace(self.realowner);
-       olddir = normalize(self.velocity);
-       newdir = normalize(trace_endpos - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
-       self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
-
-       UpdateCSQCProjectile(self);
-
-       if (self.owner.deadflag != DEAD_NO || self.cnt < time)
-               self.use();
-}
-
-void spiderbot_guide_release()
-{
-       entity rkt;
-       rkt = findchainentity(realowner, self.owner);
-       if(!rkt)
-               return;
-
-       crosshair_trace(self.owner);
-       while(rkt)
-       {
-               if(rkt.think == spiderbot_rocket_guided)
-               {
-                       rkt.pos1 = trace_endpos;
-                       rkt.think = spiderbot_rocket_unguided;
-               }
-               rkt = rkt.chain;
-       }
-}
-
-float spiberbot_calcartillery_flighttime;
-vector spiberbot_calcartillery(vector org, vector tgt, float ht)
-{
-       float grav, sdist, zdist, vs, vz, jumpheight;
-       vector sdir;
-
-       grav  = autocvar_sv_gravity;
-       zdist = tgt_z - org_z;
-       sdist = vlen(tgt - org - zdist * '0 0 1');
-       sdir  = normalize(tgt - org - zdist * '0 0 1');
-
-       // how high do we need to go?
-       jumpheight = fabs(ht);
-       if(zdist > 0)
-               jumpheight = jumpheight + zdist;
-
-       // push so high...
-       vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
-
-       // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
-       if(ht < 0)
-               if(zdist < 0)
-                       vz = -vz;
-
-       vector solution;
-       solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
-       // ALWAYS solvable because jumpheight >= zdist
-       if(!solution_z)
-               solution_y = solution_x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0)
-       if(zdist == 0)
-               solution_x = solution_y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually)
-
-       if(zdist < 0)
-       {
-               // down-jump
-               if(ht < 0)
-               {
-                       // almost straight line type
-                       // jump apex is before the jump
-                       // we must take the larger one
-                       spiberbot_calcartillery_flighttime = solution_y;
-               }
-               else
-               {
-                       // regular jump
-                       // jump apex is during the jump
-                       // we must take the larger one too
-                       spiberbot_calcartillery_flighttime = solution_y;
-               }
-       }
-       else
-       {
-               // up-jump
-               if(ht < 0)
-               {
-                       // almost straight line type
-                       // jump apex is after the jump
-                       // we must take the smaller one
-                       spiberbot_calcartillery_flighttime = solution_x;
-               }
-               else
-               {
-                       // regular jump
-                       // jump apex is during the jump
-                       // we must take the larger one
-                       spiberbot_calcartillery_flighttime = solution_y;
-               }
-       }
-       vs = sdist / spiberbot_calcartillery_flighttime;
-
-       // finally calculate the velocity
-       return sdir * vs + '0 0 1' * vz;
-}
-
-void spiderbot_rocket_do()
-{
-       vector v;
-       entity rocket = world;
-
-       if (self.wait != -10)
-       {
-               if (self.owner.BUTTON_ATCK2 && self.vehicle_weapon2mode == SBRM_GUIDE)
-               {
-                       if (self.wait == 1)
-                       if (self.tur_head.frame == 9 || self.tur_head.frame == 1)
-                       {
-                               if(self.gun2.cnt < time && self.tur_head.frame == 9)
-                                       self.tur_head.frame = 1;
-
-                               return;
-                       }
-                       self.wait = 1;
-               }
-               else
-               {
-                       if(self.wait)
-                               spiderbot_guide_release();
-
-                       self.wait = 0;
-               }
-       }
-
-       if(self.gun2.cnt > time)
-               return;
-
-       if (self.tur_head.frame >= 9)
-       {
-               self.tur_head.frame = 1;
-               self.wait = 0;
-       }
-
-       if(self.wait != -10)
-       if(!self.owner.BUTTON_ATCK2)
-               return;
-
-       if(forbidWeaponUse(self.owner))
-               return;
-
-       v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
-
-       switch(self.vehicle_weapon2mode)
-       {
-               case SBRM_VOLLY:
-                       rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, W_Sound("rocket_fire"),
-                                                                  v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
-                                                                  autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
-                                                                  DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
-                       crosshair_trace(self.owner);
-                       float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
-                       _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
-                       rocket.nextthink  = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed);
-                       rocket.think     = vehicles_projectile_explode;
-
-                       if(self.owner.BUTTON_ATCK2 && self.tur_head.frame == 1)
-                               self.wait = -10;
-                       break;
-               case SBRM_GUIDE:
-                       rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, W_Sound("rocket_fire"),
-                                                                  v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
-                                                                  autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
-                                                                  DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, self.owner);
-                       crosshair_trace(self.owner);
-                       rocket.pos1        = trace_endpos;
-                       rocket.nextthink  = time;
-                       rocket.think      = spiderbot_rocket_guided;
-
-
-               break;
-               case SBRM_ARTILLERY:
-                       rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, W_Sound("rocket_fire"),
-                                                                  v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
-                                                                  autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
-                                                                  DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
-
-                       crosshair_trace(self.owner);
-
-                       rocket.pos1        = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
-                       rocket.pos1_z      = trace_endpos_z;
-
-                       traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
-                       float h1 = 0.75 * vlen(v - trace_endpos);
-
-                       //v = trace_endpos;
-                       traceline(v , rocket.pos1 + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
-                       float h2 = 0.75 * vlen(rocket.pos1 - v);
-
-                       rocket.velocity  = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
-                       rocket.movetype  = MOVETYPE_TOSS;
-                       rocket.gravity   = 1;
-                       //rocket.think   = spiderbot_rocket_artillery;
-               break;
-       }
-       rocket.classname  = "spiderbot_rocket";
-
-       rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
-
-       self.tur_head.frame += 1;
-       if (self.tur_head.frame == 9)
-               self.attack_finished_single = autocvar_g_vehicle_spiderbot_rocket_reload;
-       else
-               self.attack_finished_single = ((self.vehicle_weapon2mode ==  SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
-
-       self.gun2.cnt = time + self.attack_finished_single;
-}
-
-.float jump_delay;
-float spiderbot_frame()
-{
-       vector ad, vf;
-       entity player, spider;
-       float ftmp;
-
-       if(intermission_running)
-       {
-               self.vehicle.velocity = '0 0 0';
-               self.vehicle.avelocity = '0 0 0';
-               return 1;
-       }
-
-       player = self;
-       spider = self.vehicle;
-       self   = spider;
-
-       vehicles_painframe();
-
-       player.BUTTON_ZOOM        = 0;
-       player.BUTTON_CROUCH    = 0;
-       player.switchweapon      = 0;
-       player.vehicle_weapon2mode = spider.vehicle_weapon2mode;
-
-
-#if 1 // 0 to enable per-gun impact aux crosshairs
-       // Avarage gun impact point's -> aux cross
-       ad = gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint01"));
-       vf = v_forward;
-       ad += gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint02"));
-       vf += v_forward;
-       ad = ad * 0.5;
-       v_forward = vf * 0.5;
-       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
-       UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
-#else
-       ad = gettaginfo(spider.gun1, gettagindex(spider.gun1, "barrels"));
-       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
-       UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
-       vf = ad;
-       ad = gettaginfo(spider.gun2, gettagindex(spider.gun2, "barrels"));
-       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
-       UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 1);
-       ad = 0.5 * (ad + vf);
-#endif
-
-       crosshair_trace(player);
-       ad = vectoangles(normalize(trace_endpos - ad));
-       ad = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(spider.angles), AnglesTransform_FromAngles(ad))) - spider.tur_head.angles;
-       ad = AnglesTransform_Normalize(ad, true);
-       //UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload2) + ('0 1 0' * (1 - player.vehicle_reload2)), 2);
-
-       // Rotate head
-       ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime;
-       ad_y = bound(-ftmp, ad_y, ftmp);
-       spider.tur_head.angles_y = bound(autocvar_g_vehicle_spiderbot_head_turnlimit * -1, spider.tur_head.angles_y + ad_y, autocvar_g_vehicle_spiderbot_head_turnlimit);
-
-       // Pitch head
-       ad_x = bound(ftmp * -1, ad_x, ftmp);
-       spider.tur_head.angles_x = bound(autocvar_g_vehicle_spiderbot_head_pitchlimit_down, spider.tur_head.angles_x + ad_x, autocvar_g_vehicle_spiderbot_head_pitchlimit_up);
-
-
-       //fixedmakevectors(spider.angles);
-       makevectors(spider.angles + '-2 0 0' * spider.angles_x);
-
-       movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend, autocvar_g_vehicle_spiderbot_tiltlimit);
-
-       if(spider.flags & FL_ONGROUND)
-               spider.jump_delay = time; // reset now so movement can begin
-
-       //if(spider.flags & FL_ONGROUND)
-       {
-               if(spider.flags & FL_ONGROUND)
-               if(spider.frame == 4 && self.tur_head.wait != 0)
-               {
-                       sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_land.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-                       spider.frame = 5;
-               }
-
-               if(!player.BUTTON_JUMP)
-                       spider.BUTTON_JUMP = 0;
-
-               if((spider.flags & FL_ONGROUND) && player.BUTTON_JUMP && !spider.BUTTON_JUMP && self.tur_head.wait < time)
-               {
-                       sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_jump.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-                       //dprint("spiderbot_jump:", ftos(soundlength("vehicles/spiderbot_jump.wav")), "\n");
-                       self.delay = 0;
-
-                       self.tur_head.wait = time + 2;
-                       spider.jump_delay = time + 2;
-                       spider.BUTTON_JUMP = 1; // set spider's jump
-                       //player.BUTTON_JUMP = 0;
-
-                       vector movefix = '0 0 0';
-                       if(player.movement_x > 0) movefix_x = 1;
-                       if(player.movement_x < 0) movefix_x = -1;
-                       if(player.movement_y > 0) movefix_y = 1;
-                       if(player.movement_y < 0) movefix_y = -1;
-
-                       vector rt = movefix_y * v_right;
-                       vector sd = movefix_x * v_forward;
-                       if(movefix_y == 0 && movefix_x == 0)
-                               sd = v_forward; // always do forward
-
-                       spider.flags &= ~FL_ONGROUND;
-
-                       spider.velocity = sd * 700 + rt * 600 + v_up * 600;
-                       spider.frame = 4;
-               }
-               else if(time >= spider.jump_delay)
-               {
-                       if(vlen(player.movement) == 0)
-                       {
-                               if(spider.flags & FL_ONGROUND)
-                               {
-                                       if(self.sound_nexttime < time || self.delay != 3)
-                                       {
-                                               self.delay = 3;
-                                               self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_idle.wav");
-                                               //dprint("spiderbot_idle:", ftos(soundlength("vehicles/spiderbot_idle.wav")), "\n");
-                                               sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_idle.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-                                       }
-                                       movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
-                                       spider.frame = 5;
-                               }
-                       }
-                       else
-                       {
-                               // Turn Body
-                               if(player.movement_x == 0 && player.movement_y != 0)
-                                       ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * sys_frametime;
-                               else
-                                       ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime;
-
-                               ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp);
-                               spider.angles_y = anglemods(spider.angles_y + ftmp);
-                               spider.tur_head.angles_y -= ftmp;
-
-                               if(player.movement_x != 0)
-                               {
-                                       if(player.movement_x > 0)
-                                       {
-                                               player.movement_x = 1;
-                                               if(spider.flags & FL_ONGROUND)
-                                                       spider.frame = 0;
-                                       }
-                                       else if(player.movement_x < 0)
-                                       {
-                                               player.movement_x = -1;
-                                               if(spider.flags & FL_ONGROUND)
-                                                       spider.frame = 1;
-                                       }
-                                       player.movement_y = 0;
-                                       float oldvelz = spider.velocity_z;
-                                       movelib_move_simple(normalize(v_forward * player.movement_x),((player.BUTTON_JUMP) ? autocvar_g_vehicle_spiderbot_speed_run : autocvar_g_vehicle_spiderbot_speed_walk),autocvar_g_vehicle_spiderbot_movement_inertia);
-                                       spider.velocity_z = oldvelz;
-                                       float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
-                                       if(spider.velocity_z <= 20) // not while jumping
-                                               spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
-                                       if(spider.flags & FL_ONGROUND)
-                                       if(self.sound_nexttime < time || self.delay != 1)
-                                       {
-                                               self.delay = 1;
-                                               self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_walk.wav");
-                                               sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_walk.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-                                               //dprint("spiderbot_walk:", ftos(soundlength("vehicles/spiderbot_walk.wav")), "\n");
-                                       }
-                               }
-                               else if(player.movement_y != 0)
-                               {
-                                       if(player.movement_y < 0)
-                                       {
-                                               player.movement_y = -1;
-                                               if(spider.flags & FL_ONGROUND)
-                                                       spider.frame = 2;
-                                       }
-                                       else if(player.movement_y > 0)
-                                       {
-                                               player.movement_y = 1;
-                                               if(spider.flags & FL_ONGROUND)
-                                                       spider.frame = 3;
-                                       }
-
-                                       float oldvelz = spider.velocity_z;
-                                       movelib_move_simple(normalize(v_right * player.movement_y),autocvar_g_vehicle_spiderbot_speed_strafe,autocvar_g_vehicle_spiderbot_movement_inertia);
-                                       spider.velocity_z = oldvelz;
-                                       float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
-                                       if(spider.velocity_z <= 20) // not while jumping
-                                               spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
-                                       if(spider.flags & FL_ONGROUND)
-                                       if(self.sound_nexttime < time || self.delay != 2)
-                                       {
-                                               self.delay = 2;
-                                               self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_strafe.wav");
-                                               sound (self, CH_TRIGGER_SINGLE, "vehicles/spiderbot_strafe.wav", VOL_VEHICLEENGINE, ATTEN_NORM);
-                                               //dprint("spiderbot_strafe:", ftos(soundlength("vehicles/spiderbot_strafe.wav")), "\n");
-                                       }
-                               }
-                       }
-               }
-       }
-
-       self.angles_x = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_x, autocvar_g_vehicle_spiderbot_tiltlimit);
-       self.angles_z = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_z, autocvar_g_vehicle_spiderbot_tiltlimit);
-
-       if(!forbidWeaponUse(player))
-       if(player.BUTTON_ATCK)
-       {
-               spider.cnt = time;
-               if(spider.vehicle_ammo1 >= autocvar_g_vehicle_spiderbot_minigun_ammo_cost && spider.tur_head.attack_finished_single <= time)
-               {
-                       entity gun;
-                       vector v;
-                       spider.misc_bulletcounter += 1;
-
-                       self = player;
-
-                       gun = (spider.misc_bulletcounter % 2) ? spider.gun1 : spider.gun2;
-
-                       v = gettaginfo(gun, gettagindex(gun, "barrels"));
-                       v_forward = normalize(v_forward);
-                       v += v_forward * 50;
-
-                       fireBullet(v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration,
-                                autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN, 0);
-
-                       sound (gun, CH_WEAPON_A, W_Sound("uzi_fire"), VOL_BASE, ATTEN_NORM);
-                       //trailparticles(self, _particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
-                       pointparticles(particleeffectnum(EFFECT_SPIDERBOT_MINIGUN_MUZZLEFLASH), v, v_forward * 2500, 1);
-
-                       self = spider;
-
-                       spider.vehicle_ammo1 -= autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
-                       spider.tur_head.attack_finished_single = time + autocvar_g_vehicle_spiderbot_minigun_refire;
-                       player.vehicle_ammo1 = (spider.vehicle_ammo1 / autocvar_g_vehicle_spiderbot_minigun_ammo_max) * 100;
-                       spider.gun1.angles_z += 45;
-                       spider.gun2.angles_z -= 45;
-                       if(spider.gun1.angles_z >= 360)
-                       {
-                               spider.gun1.angles_z = 0;
-                               spider.gun2.angles_z = 0;
-                       }
-               }
-       }
-       else
-               vehicles_regen(spider.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);
-
-
-       spiderbot_rocket_do();
-
-       if(self.vehicle_flags  & VHF_SHIELDREGEN)
-               vehicles_regen(spider.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime, true);
-
-       if(self.vehicle_flags  & VHF_HEALTHREGEN)
-               vehicles_regen(spider.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime, false);
-
-       player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
-       //player.vehicle_ammo2 = spider.tur_head.frame;
-       player.vehicle_ammo2 = (9 - spider.tur_head.frame) / 8 * 100; // Percentage, like ammo1
-
-       if(spider.gun2.cnt <= time)
-               player.vehicle_reload2 = 100;
-       else
-               player.vehicle_reload2 = 100 - ((spider.gun2.cnt - time) / spider.attack_finished_single) * 100;
-
-       setorigin(player, spider.origin + '0 0 1' * spider.maxs_z);
-       player.velocity = spider.velocity;
-
-       VEHICLE_UPDATE_PLAYER(player, health, spiderbot);
-
-       if(self.vehicle_flags & VHF_HASSHIELD)
-               VEHICLE_UPDATE_PLAYER(player, shield, spiderbot);
-
-       self = player;
-       return 1;
-}
-
-void spiderbot_exit(float eject)
-{
-       entity e;
-       vector spot;
-
-       e = findchain(classname,"spiderbot_rocket");
-       while(e)
-       {
-               if(e.owner == self.owner)
-               {
-                       e.realowner = self.owner;
-                       e.owner = world;
-               }
-               e = e.chain;
-       }
-
-       self.think = vehicles_think;
-       self.nextthink = time;
-       self.frame = 5;
-       self.movetype = MOVETYPE_WALK;
-
-       if(!self.owner)
-               return;
-
-       makevectors(self.angles);
-       if(eject)
-       {
-               spot = self.origin + v_forward * 100 + '0 0 64';
-               spot = vehicles_findgoodexit(spot);
-               setorigin(self.owner , spot);
-               self.owner.velocity = (v_up + v_forward * 0.25) * 750;
-               self.owner.oldvelocity = self.owner.velocity;
-       }
-       else
-       {
-               if(vlen(self.velocity) > autocvar_g_vehicle_spiderbot_speed_strafe)
-               {
-                       self.owner.velocity = normalize(self.velocity) * vlen(self.velocity);
-                       self.owner.velocity_z += 200;
-                       spot = self.origin + v_forward * 128 + '0 0 64';
-                       spot = vehicles_findgoodexit(spot);
-               }
-               else
-               {
-                       self.owner.velocity = self.velocity * 0.5;
-                       self.owner.velocity_z += 10;
-                       spot = self.origin + v_forward * 256 + '0 0 64';
-                       spot = vehicles_findgoodexit(spot);
-               }
-               self.owner.oldvelocity = self.owner.velocity;
-               setorigin(self.owner , spot);
-       }
-
-       antilag_clear(self.owner);
-       self.owner = world;
-}
-
-void spiderbot_headfade()
-{
-       self.think = spiderbot_headfade;
-       self.nextthink = self.fade_time;
-       self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
-
-       if(self.cnt < time || self.alpha < 0.1)
-       {
-               if(self.alpha > 0.1)
-               {
-                       sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
-                       Send_Effect(EFFECT_EXPLOSION_BIG, self.origin + '0 0 100', '0 0 0', 1);
-               }
-               remove(self);
-       }
-}
-
-void spiderbot_blowup()
-{
-       if(self.cnt > time)
-       {
-               if(random() < 0.1)
-               {
-                       sound (self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
-                       Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
-               }
-               self.nextthink = time + 0.1;
-               return;
-       }
-
-       entity h, g1, g2, b;
-       b = spawn();
-       h = spawn();
-       g1 = spawn();
-       g2 = spawn();
-
-       setmodel(b, "models/vehicles/spiderbot.dpm");
-       setmodel(h, "models/vehicles/spiderbot_top.dpm");
-       setmodel(g1, "models/vehicles/spiderbot_barrels.dpm");
-       setmodel(g2, "models/vehicles/spiderbot_barrels.dpm");
-
-       setorigin(b, self.origin);
-       b.frame = 11;
-       b.angles = self.angles;
-       setsize(b, self.mins, self.maxs);
-
-       setorigin(h, gettaginfo(self, gettagindex(self, "tag_head")));
-       h.movetype = MOVETYPE_BOUNCE;
-       h.solid = SOLID_BBOX;
-       h.velocity = v_up * (500 + random() * 500) + randomvec() * 128;
-       h.modelflags = MF_ROCKET;
-       h.effects = EF_FLAME | EF_LOWPRECISION;
-       h.avelocity = randomvec() * 360;
-
-       h.alpha = 1;
-       h.cnt = time + (3.5 * random());
-       h.fade_rate = 1 / min(self.respawntime, 10);
-       h.fade_time = time;
-       h.think = spiderbot_headfade;
-       h.nextthink = time;
-
-       setorigin(g1, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint01")));
-       g1.movetype = MOVETYPE_TOSS;
-       g1.solid = SOLID_CORPSE;
-       g1.velocity = v_forward * 700 + (randomvec() * 32);
-       g1.avelocity = randomvec() * 180;
-
-       setorigin(g2, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint02")));
-       g2.movetype = MOVETYPE_TOSS;
-       g2.solid = SOLID_CORPSE;
-       g2.velocity = v_forward * 700 + (randomvec() * 32);
-       g2.avelocity = randomvec() * 180;
-
-       h.colormod = b.colormod = g1.colormod = g2.colormod = '-2 -2 -2';
-
-       SUB_SetFade(b,  time + 5, min(self.respawntime, 1));
-       //SUB_SetFade(h,  time, min(self.respawntime, 10));
-       SUB_SetFade(g1, time, min(self.respawntime, 10));
-       SUB_SetFade(g2, time, min(self.respawntime, 10));
-
-       RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_SPID_DEATH, world);
-
-       self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
-       self.movetype = MOVETYPE_NONE;
-       self.deadflag = DEAD_DEAD;
-       self.solid = SOLID_NOT;
-       self.tur_head.effects &= ~EF_FLAME;
-       self.vehicle_hudmodel.viewmodelforclient = self;
-}
-
-bool spiderbot_impulse(int _imp)
-{
-       switch(_imp)
-       {
-               case 1:
-               case 230:
-                       self.vehicle.vehicle_weapon2mode = SBRM_VOLLY;
-                       CSQCVehicleSetup(self, 0);
-                       return true;
-               case 2:
-               case 231:
-                       self.vehicle.vehicle_weapon2mode = SBRM_GUIDE;
-                       CSQCVehicleSetup(self, 0);
-                       return true;
-               case 3:
-               case 232:
-               case 251:
-                       self.vehicle.vehicle_weapon2mode = SBRM_ARTILLERY;
-                       CSQCVehicleSetup(self, 0);
-                       return true;
-
-               case 10:
-               case 15:
-               case 18:
-                       self.vehicle.vehicle_weapon2mode += 1;
-                       if(self.vehicle.vehicle_weapon2mode > SBRM_LAST)
-                               self.vehicle.vehicle_weapon2mode = SBRM_FIRST;
-
-                       //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
-                       CSQCVehicleSetup(self, 0);
-                       return true;
-               case 11:
-               case 12:
-               case 16:
-               case 19:
-                       self.vehicle.vehicle_weapon2mode -= 1;
-                       if(self.vehicle.vehicle_weapon2mode < SBRM_FIRST)
-                               self.vehicle.vehicle_weapon2mode = SBRM_LAST;
-
-                       //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
-                       CSQCVehicleSetup(self, 0);
-                       return true;
-
-               /*
-               case 17: // toss gun, could be used to exit?
-                       break;
-               case 20: // Manual minigun reload?
-                       break;
-               */
-       }
-       return false;
-}
-
-void spawnfunc_vehicle_spiderbot()
-{
-       if(!autocvar_g_vehicle_spiderbot) { remove(self); return; }
-       if(!vehicle_initialize(VEH_SPIDERBOT, false)) { remove(self); return; }
-}
-
-float v_spiderbot(float req)
-{
-       switch(req)
-       {
-               case VR_IMPACT:
-               {
-                       if(autocvar_g_vehicle_spiderbot_bouncepain)
-                               vehicles_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z);
-
-                       return true;
-               }
-               case VR_ENTER:
-               {
-                       self.vehicle_weapon2mode = SBRM_GUIDE;
-                       self.movetype = MOVETYPE_WALK;
-                       CSQCVehicleSetup(self.owner, 0);
-                       self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100;
-                       self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100;
-
-                       if(self.owner.flagcarried)
-                       {
-                               setattachment(self.owner.flagcarried, self.tur_head, "");
-                               setorigin(self.owner.flagcarried, '-20 0 120');
-                       }
-
-                       return true;
-               }
-               case VR_THINK:
-               {
-                       if(self.flags & FL_ONGROUND)
-                               movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
-
-                       return true;
-               }
-               case VR_DEATH:
-               {
-                       self.health                             = 0;
-                       self.event_damage               = func_null;
-                       self.takedamage                 = DAMAGE_NO;
-                       self.touch                              = func_null;
-                       self.cnt                                = 3.4 + time + random() * 2;
-                       self.think                              = spiderbot_blowup;
-                       self.nextthink                  = time;
-                       self.deadflag                   = DEAD_DYING;
-                       self.frame                              = 5;
-                       self.tur_head.effects  |= EF_FLAME;
-                       self.colormod                   = self.tur_head.colormod = '-1 -1 -1';
-                       self.frame                              = 10;
-                       self.movetype                   = MOVETYPE_TOSS;
-
-                       CSQCModel_UnlinkEntity(); // networking the death scene would be a nightmare
-
-                       return true;
-               }
-               case VR_SPAWN:
-               {
-                       if(!self.gun1)
-                       {
-                               self.vehicles_impulse = spiderbot_impulse;
-                               self.gun1 = spawn();
-                               self.gun2 = spawn();
-                               setmodel(self.gun1, "models/vehicles/spiderbot_barrels.dpm");
-                               setmodel(self.gun2, "models/vehicles/spiderbot_barrels.dpm");
-                               setattachment(self.gun1, self.tur_head, "tag_hardpoint01");
-                               setattachment(self.gun2, self.tur_head, "tag_hardpoint02");
-                               self.gravity = 2;
-                               self.mass = 5000;
-                       }
-
-                       self.frame = 5;
-                       self.tur_head.frame = 1;
-                       self.movetype = MOVETYPE_WALK;
-                       self.solid = SOLID_SLIDEBOX;
-                       self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
-                       self.tur_head.angles = '0 0 0';
-                       self.vehicle_exit = spiderbot_exit;
-
-                       setorigin(self, self.pos1 + '0 0 128');
-                       self.angles = self.pos2;
-                       self.damageforcescale = 0.03;
-                       self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
-                       self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
-
-                       self.PlayerPhysplug = spiderbot_frame;
-
-                       return true;
-               }
-               case VR_SETUP:
-               {
-                       if(autocvar_g_vehicle_spiderbot_shield)
-                               self.vehicle_flags |= VHF_HASSHIELD;
-
-                       if(autocvar_g_vehicle_spiderbot_shield_regen)
-                               self.vehicle_flags |= VHF_SHIELDREGEN;
-
-                       if(autocvar_g_vehicle_spiderbot_health_regen)
-                               self.vehicle_flags |= VHF_HEALTHREGEN;
-
-                       self.respawntime = autocvar_g_vehicle_spiderbot_respawntime;
-                       self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
-                       self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
-                       self.max_health = self.vehicle_health;
-                       self.pushable = true; // spiderbot can use jumppads
-
-                       return true;
-               }
-               case VR_PRECACHE:
-               {
-                       precache_model ("models/vhshield.md3");
-                       precache_model ("models/vehicles/spiderbot.dpm");
-                       precache_model ("models/vehicles/spiderbot_top.dpm");
-                       precache_model ("models/vehicles/spiderbot_barrels.dpm");
-                       precache_model ("models/vehicles/spiderbot_cockpit.dpm");
-                       precache_model ( "models/uziflash.md3");
-
-                       precache_sound (W_Sound("uzi_fire") );
-                       precache_sound (W_Sound("rocket_impact"));
-
-                       precache_sound ("vehicles/spiderbot_die.wav");
-                       precache_sound ("vehicles/spiderbot_idle.wav");
-                       precache_sound ("vehicles/spiderbot_jump.wav");
-                       precache_sound ("vehicles/spiderbot_strafe.wav");
-                       precache_sound ("vehicles/spiderbot_walk.wav");
-                       precache_sound ("vehicles/spiderbot_land.wav");
-                       return true;
-               }
-       }
-
-       return true;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
-float autocvar_cl_vehicle_spiderbot_cross_size = 1;
-
-float v_spiderbot(float req)
-{
-       switch(req)
-       {
-               case VR_HUD:
-               {
-                       string crosshair;
-
-                       switch(weapon2mode)
-                       {
-                               case SBRM_VOLLY:     crosshair = vCROSS_BURST; break;
-                               case SBRM_GUIDE:     crosshair = vCROSS_GUIDE; break;
-                               case SBRM_ARTILLERY: crosshair = vCROSS_RAIN;  break;
-                               default:             crosshair = vCROSS_BURST;
-                       }
-
-                       Vehicles_drawHUD(VEH_SPIDERBOT.m_icon, "vehicle_spider_weapon1", "vehicle_spider_weapon2",
-                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
-                                                        "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
-                                                        crosshair);
-                       return true;
-               }
-               case VR_SETUP:
-               {
-                       AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1
-                       AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2
-
-                       return true;
-               }
-               case VR_PRECACHE:
-               {
-                       return true;
-               }
-       }
-
-       return true;
-}
-
-#endif // CSQC
-#endif // REGISTER_VEHICLE
index 7df34206fcd2c5b0462bdefe4fbef2f53d3ff2fb..80787b4ae619eb8acda9abb09e101c698be384d3 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef VEHICLE_H
 #define VEHICLE_H
 
-int v_null(int) { return 0; }
-
 CLASS(Vehicle, Object)
     ATTRIB(Vehicle, vehicleid, int, 0)
     /** hud icon */
@@ -11,8 +9,6 @@ CLASS(Vehicle, Object)
     ATTRIB(Vehicle, netname, string, "")
     /** human readable name */
     ATTRIB(Vehicle, vehicle_name, string, "Vehicle")
-    /**  */
-    ATTRIB(Vehicle, vehicle_func, int(int), v_null)
     /** full name of model */
     ATTRIB(Vehicle, model, string, "")
     /** currently a copy of the model */
@@ -35,6 +31,42 @@ CLASS(Vehicle, Object)
     ATTRIB(Vehicle, mins, vector, '-0 -0 -0')
     /** vehicle hitbox size */
     ATTRIB(Vehicle, maxs, vector, '0 0 0')
+
+    /** (BOTH) setup vehicle data */
+    METHOD(Vehicle, vr_setup, void(Vehicle)) { }
+    /** (SERVER) logic to run every frame */
+    METHOD(Vehicle, vr_think, void(Vehicle)) { }
+    /** (SERVER) called when vehicle dies */
+    METHOD(Vehicle, vr_death, void(Vehicle)) { }
+    /** (BOTH) precaches models/sounds used by this vehicle */
+    METHOD(Vehicle, vr_precache, void(Vehicle)) { }
+    /** (SERVER) called when a player enters this vehicle */
+    METHOD(Vehicle, vr_enter, void(Vehicle)) { }
+    /** (SERVER) called when the vehicle re-spawns */
+    METHOD(Vehicle, vr_spawn, void(Vehicle)) { }
+    /** (SERVER) called when a vehicle hits something */
+    METHOD(Vehicle, vr_impact, void(Vehicle)) { }
+    /** (CLIENT) logic to run every frame */
+    METHOD(Vehicle, vr_hud, void(Vehicle)) { }
 ENDCLASS(Vehicle)
 
+// vehicle spawn flags (need them here for common registrations)
+const int VHF_ISVEHICLE                        = 2; /// Indicates vehicle
+const int VHF_HASSHIELD                        = 4; /// Vehicle has shileding
+const int VHF_SHIELDREGEN              = 8; /// Vehicles shield regenerates
+const int VHF_HEALTHREGEN              = 16; /// Vehicles health regenerates
+const int VHF_ENERGYREGEN              = 32; /// Vehicles energy regenerates
+const int VHF_DEATHEJECT               = 64; /// Vehicle ejects pilot upon fatal damage
+const int VHF_MOVE_GROUND              = 128; /// Vehicle moves on gound
+const int VHF_MOVE_HOVER               = 256; /// Vehicle hover close to gound
+const int VHF_MOVE_FLY                 = 512; /// Vehicle is airborn
+const int VHF_DMGSHAKE                 = 1024; /// Add random velocity each frame if health < 50%
+const int VHF_DMGROLL                  = 2048; /// Add random angles each frame if health < 50%
+const int VHF_DMGHEADROLL              = 4096; /// Add random head angles each frame if health < 50%
+const int VHF_MULTISLOT                        = 8192; /// Vehicle has multiple player slots
+const int VHF_PLAYERSLOT               = 16384; /// This ent is a player slot on a multi-person vehicle
+
+// fields:
+.entity tur_head;
+
 #endif
diff --git a/qcsrc/common/vehicles/vehicle/bumblebee.qc b/qcsrc/common/vehicles/vehicle/bumblebee.qc
new file mode 100644 (file)
index 0000000..b64ac02
--- /dev/null
@@ -0,0 +1,975 @@
+#ifndef VEHICLE_BUMBLEBEE
+#define VEHICLE_BUMBLEBEE
+#include "bumblebee.qh"
+
+#include "bumblebee_weapons.qc"
+
+CLASS(Bumblebee, Vehicle)
+/* spawnflags */ ATTRIB(Bumblebee, spawnflags, int, VHF_DMGSHAKE);
+/* mins       */ ATTRIB(Bumblebee, mins, vector, '-245 -130 -130');
+/* maxs       */ ATTRIB(Bumblebee, maxs, vector, '230 130 130');
+/* model         */ ATTRIB(Bumblebee, mdl, string, "models/vehicles/bumblebee_body.dpm");
+/* model         */ ATTRIB(Bumblebee, model, string, "models/vehicles/bumblebee_body.dpm");
+/* head_model */ ATTRIB(Bumblebee, head_model, string, "");
+/* hud_model  */ ATTRIB(Bumblebee, hud_model, string, "models/vehicles/spiderbot_cockpit.dpm");
+/* tags       */ ATTRIB(Bumblebee, tag_head, string, "");
+/* tags       */ ATTRIB(Bumblebee, tag_hud, string, "");
+/* tags       */ ATTRIB(Bumblebee, tag_view, string, "tag_viewport");
+/* netname    */ ATTRIB(Bumblebee, netname, string, "bumblebee");
+/* fullname   */ ATTRIB(Bumblebee, vehicle_name, string, _("Bumblebee"));
+/* icon       */ ATTRIB(Bumblebee, m_icon, string, "vehicle_bumble");
+ENDCLASS(Bumblebee)
+REGISTER_VEHICLE(BUMBLEBEE, NEW(Bumblebee));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+const float BRG_SETUP = 2;
+const float BRG_START = 4;
+const float BRG_END = 8;
+
+#include "bumblebee_weapons.qc"
+
+#ifdef SVQC
+float autocvar_g_vehicle_bumblebee_speed_forward;
+float autocvar_g_vehicle_bumblebee_speed_strafe;
+float autocvar_g_vehicle_bumblebee_speed_up;
+float autocvar_g_vehicle_bumblebee_speed_down;
+float autocvar_g_vehicle_bumblebee_turnspeed;
+float autocvar_g_vehicle_bumblebee_pitchspeed;
+float autocvar_g_vehicle_bumblebee_pitchlimit;
+float autocvar_g_vehicle_bumblebee_friction;
+
+float autocvar_g_vehicle_bumblebee_energy;
+float autocvar_g_vehicle_bumblebee_energy_regen;
+float autocvar_g_vehicle_bumblebee_energy_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_health;
+float autocvar_g_vehicle_bumblebee_health_regen;
+float autocvar_g_vehicle_bumblebee_health_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_shield;
+float autocvar_g_vehicle_bumblebee_shield_regen;
+float autocvar_g_vehicle_bumblebee_shield_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_cannon_ammo;
+float autocvar_g_vehicle_bumblebee_cannon_ammo_regen;
+float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause;
+
+float autocvar_g_vehicle_bumblebee_cannon_lock = 0;
+
+float autocvar_g_vehicle_bumblebee_cannon_turnspeed;
+float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down;
+float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up;
+float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+
+
+float autocvar_g_vehicle_bumblebee_raygun_turnspeed;
+float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down;
+float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up;
+float autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides;
+
+float autocvar_g_vehicle_bumblebee_raygun_range;
+float autocvar_g_vehicle_bumblebee_raygun_dps;
+float autocvar_g_vehicle_bumblebee_raygun_aps;
+float autocvar_g_vehicle_bumblebee_raygun_fps;
+
+float autocvar_g_vehicle_bumblebee_raygun;
+float autocvar_g_vehicle_bumblebee_healgun_hps;
+float autocvar_g_vehicle_bumblebee_healgun_hmax;
+float autocvar_g_vehicle_bumblebee_healgun_aps;
+float autocvar_g_vehicle_bumblebee_healgun_amax;
+float autocvar_g_vehicle_bumblebee_healgun_sps;
+float autocvar_g_vehicle_bumblebee_healgun_locktime;
+
+float autocvar_g_vehicle_bumblebee_respawntime;
+
+float autocvar_g_vehicle_bumblebee_blowup_radius;
+float autocvar_g_vehicle_bumblebee_blowup_coredamage;
+float autocvar_g_vehicle_bumblebee_blowup_edgedamage;
+float autocvar_g_vehicle_bumblebee_blowup_forceintensity;
+vector autocvar_g_vehicle_bumblebee_bouncepain;
+
+bool autocvar_g_vehicle_bumblebee = 0;
+
+float bumblebee_gunner_frame()
+{SELFPARAM();
+       entity vehic    = self.vehicle.owner;
+       entity gun      = self.vehicle;
+       entity gunner   = self;
+       setself(vehic);
+
+       vehic.solid = SOLID_NOT;
+       //setorigin(gunner, vehic.origin);
+       gunner.velocity = vehic.velocity;
+
+       float _in, _out;
+       vehic.angles_x *= -1;
+       makevectors(vehic.angles);
+       vehic.angles_x *= -1;
+       if(gun == vehic.gun1)
+       {
+               _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+               _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+               setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * 128);
+       }
+       else
+       {
+               _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
+               _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
+               setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128);
+       }
+
+       crosshair_trace(gunner);
+       vector _ct = trace_endpos;
+       vector ad;
+
+       if(autocvar_g_vehicle_bumblebee_cannon_lock)
+       {
+               if(gun.lock_time < time)
+                       gun.enemy = world;
+
+               if(trace_ent)
+                       if(trace_ent.movetype)
+                               if(trace_ent.takedamage)
+                                       if(!trace_ent.deadflag)
+                                       {
+                                               if(DIFF_TEAM(trace_ent, gunner))
+                                               {
+                                                       gun.enemy = trace_ent;
+                                                       gun.lock_time = time + 5;
+                                               }
+                                       }
+       }
+
+       if(gun.enemy)
+       {
+               float distance, impact_time;
+
+               vector vf = real_origin(gun.enemy);
+               vector _vel = gun.enemy.velocity;
+               if(gun.enemy.movetype == MOVETYPE_WALK)
+                       _vel.z *= 0.1;
+
+
+               ad = vf;
+               distance = vlen(ad - gunner.origin);
+               impact_time = distance / autocvar_g_vehicle_bumblebee_cannon_speed;
+               ad = vf + _vel * impact_time;
+               trace_endpos = ad;
+
+
+               UpdateAuxiliaryXhair(gunner, ad, '1 0 1', 1);
+               vehicle_aimturret(vehic, trace_endpos, gun, "fire",
+                                                 autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
+                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+
+       }
+       else
+               vehicle_aimturret(vehic, _ct, gun, "fire",
+                                                 autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
+                                                 _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
+
+       if(!forbidWeaponUse(gunner))
+       if(gunner.BUTTON_ATCK)
+               if(time > gun.attack_finished_single)
+                       if(gun.vehicle_energy >= autocvar_g_vehicle_bumblebee_cannon_cost)
+                       {
+                               gun.vehicle_energy -= autocvar_g_vehicle_bumblebee_cannon_cost;
+                               bumblebee_fire_cannon(gun, "fire", gunner);
+                               gun.delay = time;
+                               gun.attack_finished_single = time + autocvar_g_vehicle_bumblebee_cannon_refire;
+                       }
+
+       VEHICLE_UPDATE_PLAYER(gunner, health, bumblebee);
+
+       if(vehic.vehicle_flags & VHF_HASSHIELD)
+               VEHICLE_UPDATE_PLAYER(gunner, shield, bumblebee);
+
+       ad = gettaginfo(gun, gettagindex(gun, "fire"));
+       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, gun);
+
+       UpdateAuxiliaryXhair(gunner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), 0);
+
+       if(vehic.owner)
+               UpdateAuxiliaryXhair(vehic.owner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), ((gunner == vehic.gunner1) ? 1 : 2));
+
+       vehic.solid = SOLID_BBOX;
+       gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
+       gunner.vehicle_energy = (gun.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
+
+       setself(gunner);
+       return 1;
+}
+
+vector bumblebee_gunner_findgoodexit(vector prefer_spot, entity gunner, entity player)
+{
+       //vector exitspot;
+       float mysize;
+
+       tracebox(gunner.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, player);
+       if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+               return prefer_spot;
+
+       mysize = 1.5 * vlen(PL_MAX - PL_MIN); // can't use gunner's size, as they don't have a size
+       float i;
+       vector v, v2;
+       v2 = 0.5 * (gunner.absmin + gunner.absmax);
+       for(i = 0; i < 100; ++i)
+       {
+               v = randomvec();
+               v_z = 0;
+               v = v2 + normalize(v) * mysize;
+               tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, player);
+               if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+                       return v;
+       }
+
+       return prefer_spot; // this should be considered a fallback?!
+}
+
+void bumblebee_gunner_exit(int _exitflag)
+{SELFPARAM();
+       entity player = self;
+       entity gunner = player.vehicle;
+       entity vehic = gunner.owner;
+
+       if(IS_REAL_CLIENT(player))
+       {
+               msg_entity = player;
+               WriteByte(MSG_ONE, SVC_SETVIEWPORT);
+               WriteEntity(MSG_ONE, player);
+
+               WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
+               WriteAngle(MSG_ONE, 0);
+               WriteAngle(MSG_ONE, vehic.angles.y);
+               WriteAngle(MSG_ONE, 0);
+       }
+
+       CSQCVehicleSetup(player, HUD_NORMAL);
+       setsize(player, PL_MIN, PL_MAX);
+
+       player.takedamage     = DAMAGE_AIM;
+       player.solid          = SOLID_SLIDEBOX;
+       player.movetype       = MOVETYPE_WALK;
+       player.effects       &= ~EF_NODRAW;
+       player.alpha          = 1;
+       player.PlayerPhysplug = func_null;
+       player.view_ofs       = PL_VIEW_OFS;
+       player.event_damage   = PlayerDamage;
+       player.hud            = HUD_NORMAL;
+       player.teleportable       = TELEPORT_NORMAL;
+       player.switchweapon   = gunner.switchweapon;
+       player.vehicle_enter_delay = time + 2;
+
+       fixedmakevectors(vehic.angles);
+
+       if(player == vehic.gunner1) { vehic.gunner1 = world; }
+       if(player == vehic.gunner2) { vehic.gunner2 = world; v_right *= -1; }
+
+       vector spot = real_origin(gunner);
+       spot = spot + v_up * 128 + v_forward * 300 + v_right * 150;
+       spot = bumblebee_gunner_findgoodexit(spot, gunner, player);
+
+       // TODO: figure a way to move player out of the gunner
+
+       player.velocity = 0.75 * vehic.velocity + normalize(spot - vehic.origin) * 200;
+       player.velocity_z += 10;
+
+       gunner.phase = time + 5;
+       gunner.vehicle_hudmodel.viewmodelforclient = gunner;
+
+       MUTATOR_CALLHOOK(VehicleExit, player, gunner);
+
+       player.vehicle = world;
+}
+
+bool bumblebee_gunner_enter()
+{SELFPARAM();
+       entity vehic = self;
+       entity player = other;
+       entity gunner = world;
+
+       if(!vehic.gunner1 && !vehic.gunner2 && ((time >= vehic.gun1.phase) + (time >= vehic.gun2.phase)) == 2)
+       {
+               // we can have some fun
+               if(vlen(real_origin(vehic.gun2) - player.origin) < vlen(real_origin(vehic.gun1) - player.origin))
+               {
+                       gunner = vehic.gun2;
+                       vehic.gunner2 = player;
+               }
+               else
+               {
+                       gunner = vehic.gun1;
+                       vehic.gunner1 = 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; }
+
+       player.vehicle                  = gunner;
+       player.angles                   = vehic.angles;
+       player.takedamage               = DAMAGE_NO;
+       player.solid                    = SOLID_NOT;
+       player.alpha                    = -1;
+       player.movetype                 = MOVETYPE_NOCLIP;
+       player.event_damage     = func_null;
+       player.view_ofs                 = '0 0 0';
+       player.hud                              = gunner.hud;
+       player.teleportable     = false;
+       player.PlayerPhysplug   = gunner.PlayerPhysplug;
+       player.vehicle_ammo1    = vehic.vehicle_ammo1;
+       player.vehicle_ammo2    = vehic.vehicle_ammo2;
+       player.vehicle_reload1  = vehic.vehicle_reload1;
+       player.vehicle_reload2  = vehic.vehicle_reload2;
+       player.vehicle_energy   = vehic.vehicle_energy;
+       player.flags               &= ~FL_ONGROUND;
+
+       RemoveGrapplingHook(player);
+
+       gunner.switchweapon = player.switchweapon;
+       gunner.vehicle_exit = bumblebee_gunner_exit;
+       gunner.vehicle_hudmodel.viewmodelforclient = player;
+
+       if(IS_REAL_CLIENT(player))
+       {
+               msg_entity = player;
+               WriteByte(MSG_ONE,              SVC_SETVIEWPORT);
+               WriteEntity(MSG_ONE,    gunner.vehicle_viewport);
+
+               WriteByte(MSG_ONE,              SVC_SETVIEWANGLES);
+               WriteAngle(MSG_ONE,     gunner.angles_x + vehic.angles_x); // tilt
+               WriteAngle(MSG_ONE,     gunner.angles_y + vehic.angles_y); // yaw
+               WriteAngle(MSG_ONE,     0); // roll
+       }
+
+       CSQCVehicleSetup(player, player.hud);
+
+       MUTATOR_CALLHOOK(VehicleEnter, player, gunner);
+
+       return true;
+}
+
+bool vehicles_valid_pilot()
+{SELFPARAM();
+       if(IS_BOT_CLIENT(other) && !autocvar_g_vehicles_allow_bots)
+               return false;
+
+       if((!IS_PLAYER(other))
+       || (other.deadflag != DEAD_NO)
+       || (other.vehicle)
+       || (DIFF_TEAM(other, self))
+       ) { return false; }
+
+       return true;
+}
+
+void bumblebee_touch()
+{SELFPARAM();
+       if(autocvar_g_vehicles_enter) { return; }
+
+       if(self.gunner1 != world && self.gunner2 != world)
+       {
+               vehicles_touch();
+               return;
+       }
+
+       if(vehicles_valid_pilot())
+       {
+               float phase_time = (time >= self.gun1.phase) + (time >= self.gun2.phase);
+
+               if(time >= other.vehicle_enter_delay && phase_time)
+               if(bumblebee_gunner_enter())
+                       return;
+       }
+
+       vehicles_touch();
+}
+
+void bumblebee_regen()
+{SELFPARAM();
+       if(self.gun1.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
+               self.gun1.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
+                                                                          self.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
+
+       if(self.gun2.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
+               self.gun2.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
+                                                                          self.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
+
+       if(self.vehicle_flags  & VHF_SHIELDREGEN)
+               vehicles_regen(self.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime, true);
+
+       if(self.vehicle_flags  & VHF_HEALTHREGEN)
+               vehicles_regen(self.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime, false);
+
+       if(self.vehicle_flags  & VHF_ENERGYREGEN)
+               vehicles_regen(self.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime, false);
+
+}
+
+float bumblebee_pilot_frame()
+{SELFPARAM();
+       entity pilot, vehic;
+       vector newvel;
+
+       if(intermission_running)
+       {
+               self.vehicle.velocity = '0 0 0';
+               self.vehicle.avelocity = '0 0 0';
+               return 1;
+       }
+
+       pilot = self;
+       vehic = self.vehicle;
+       setself(vehic);
+
+       if(vehic.deadflag != DEAD_NO)
+       {
+               setself(pilot);
+               pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
+               return 1;
+       }
+
+       bumblebee_regen();
+
+       crosshair_trace(pilot);
+
+       vector vang;
+       float ftmp;
+
+       vang = vehic.angles;
+       newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
+       vang.x *= -1;
+       newvel.x *= -1;
+       if(newvel.x > 180)  newvel.x -= 360;
+       if(newvel.x < -180) newvel.x += 360;
+       if(newvel.y > 180)  newvel.y -= 360;
+       if(newvel.y < -180) newvel.y += 360;
+
+       ftmp = shortangle_f(pilot.v_angle.y - vang.y, vang.y);
+       if(ftmp > 180)  ftmp -= 360;
+       if(ftmp < -180) ftmp += 360;
+       vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity.y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed);
+
+       // Pitch
+       ftmp = 0;
+       if(pilot.movement.x > 0 && vang.x < autocvar_g_vehicle_bumblebee_pitchlimit)
+               ftmp = 4;
+       else if(pilot.movement.x < 0 && vang.x > -autocvar_g_vehicle_bumblebee_pitchlimit)
+               ftmp = -8;
+
+       newvel.x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x , autocvar_g_vehicle_bumblebee_pitchlimit);
+       ftmp = vang.x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit);
+       vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity.x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed);
+
+       vehic.angles_x = anglemods(vehic.angles.x);
+       vehic.angles_y = anglemods(vehic.angles.y);
+       vehic.angles_z = anglemods(vehic.angles.z);
+
+       makevectors('0 1 0' * vehic.angles.y);
+       newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction;
+
+       if(pilot.movement.x != 0)
+       {
+               if(pilot.movement.x > 0)
+                       newvel += v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
+               else if(pilot.movement.x < 0)
+                       newvel -= v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
+       }
+
+       if(pilot.movement.y != 0)
+       {
+               if(pilot.movement.y < 0)
+                       newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
+               else if(pilot.movement.y > 0)
+                       newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
+               ftmp = newvel * v_right;
+               ftmp *= frametime * 0.1;
+               vehic.angles_z = bound(-15, vehic.angles.z + ftmp, 15);
+       }
+       else
+       {
+               vehic.angles_z *= 0.95;
+               if(vehic.angles.z >= -1 && vehic.angles.z <= -1)
+                       vehic.angles_z = 0;
+       }
+
+       if(pilot.BUTTON_CROUCH)
+               newvel -=   v_up * autocvar_g_vehicle_bumblebee_speed_down;
+       else if(pilot.BUTTON_JUMP)
+               newvel +=  v_up * autocvar_g_vehicle_bumblebee_speed_up;
+
+       vehic.velocity  += newvel * frametime;
+       pilot.velocity = pilot.movement  = vehic.velocity;
+
+
+       if(autocvar_g_vehicle_bumblebee_healgun_locktime)
+       {
+               if(vehic.tur_head.lock_time < time || vehic.tur_head.enemy.deadflag)
+                       vehic.tur_head.enemy = world;
+
+               if(trace_ent)
+               if(trace_ent.movetype)
+               if(trace_ent.takedamage)
+               if(!trace_ent.deadflag)
+               {
+                       if(teamplay)
+                       {
+                               if(trace_ent.team == pilot.team)
+                               {
+                                       vehic.tur_head.enemy = trace_ent;
+                                       vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
+                               }
+                       }
+                       else
+                       {
+                               vehic.tur_head.enemy = trace_ent;
+                               vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
+                       }
+               }
+
+               if(vehic.tur_head.enemy)
+               {
+                       trace_endpos = real_origin(vehic.tur_head.enemy);
+                       UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0);
+               }
+       }
+
+       vang = vehicle_aimturret(vehic, trace_endpos, self.gun3, "fire",
+                                         autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1,  autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
+                                         autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1,  autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides,  autocvar_g_vehicle_bumblebee_raygun_turnspeed);
+
+       if(!forbidWeaponUse(pilot))
+       if((pilot.BUTTON_ATCK || pilot.BUTTON_ATCK2) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime || autocvar_g_vehicle_bumblebee_raygun == 0))
+       {
+               vehic.gun3.enemy.realowner = pilot;
+               vehic.gun3.enemy.effects &= ~EF_NODRAW;
+
+               vehic.gun3.enemy.hook_start = gettaginfo(vehic.gun3, gettagindex(vehic.gun3, "fire"));
+               vehic.gun3.enemy.SendFlags |= BRG_START;
+
+               traceline(vehic.gun3.enemy.hook_start, vehic.gun3.enemy.hook_start + v_forward * autocvar_g_vehicle_bumblebee_raygun_range, MOVE_NORMAL, vehic);
+
+               if(trace_ent)
+               {
+                       if(autocvar_g_vehicle_bumblebee_raygun)
+                       {
+                               Damage(trace_ent, vehic, pilot, autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime, DEATH_GENERIC, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * sys_frametime);
+                               vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * sys_frametime;
+                       }
+                       else
+                       {
+                               if(trace_ent.deadflag == DEAD_NO)
+                                       if((teamplay && trace_ent.team == pilot.team) || !teamplay)
+                                       {
+
+                                               if(trace_ent.vehicle_flags & VHF_ISVEHICLE)
+                                               {
+                                                       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);
+
+                                                       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);
+                                               }
+                                               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);
+
+                                                       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.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, 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);
+                                                       //else ..hmmm what? ammo?
+
+                                                       trace_ent.SendFlags |= TNSF_STATUS;
+                                               }
+                                       }
+                       }
+               }
+
+               vehic.gun3.enemy.hook_end = trace_endpos;
+               setorigin(vehic.gun3.enemy, trace_endpos);
+               vehic.gun3.enemy.SendFlags |= BRG_END;
+
+               vehic.wait = time + 1;
+       }
+       else
+               vehic.gun3.enemy.effects |= EF_NODRAW;
+       /*{
+               if(vehic.gun3.enemy)
+                       remove(vehic.gun3.enemy);
+
+               vehic.gun3.enemy = world;
+       }
+       */
+
+       VEHICLE_UPDATE_PLAYER(pilot, health, bumblebee);
+       VEHICLE_UPDATE_PLAYER(pilot, energy, bumblebee);
+
+       pilot.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
+       pilot.vehicle_ammo2 = (vehic.gun2.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
+
+       if(vehic.vehicle_flags & VHF_HASSHIELD)
+               VEHICLE_UPDATE_PLAYER(pilot, shield, bumblebee);
+
+       vehic.angles_x *= -1;
+       makevectors(vehic.angles);
+       vehic.angles_x *= -1;
+       setorigin(pilot, vehic.origin + v_up * 48 + v_forward * 160);
+
+       pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
+       setself(pilot);
+
+       return 1;
+}
+
+void bumblebee_land()
+{SELFPARAM();
+       float hgt;
+
+       hgt = raptor_altitude(512);
+       self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
+       self.angles_x *= 0.95;
+       self.angles_z *= 0.95;
+
+       if(hgt < 16)
+               self.think      = vehicles_think;
+
+       self.nextthink = time;
+
+       CSQCMODEL_AUTOUPDATE(self);
+}
+
+void bumblebee_exit(float eject)
+{SELFPARAM();
+       if(self.owner.vehicleid == VEH_BUMBLEBEE.vehicleid)
+       {
+               bumblebee_gunner_exit(eject);
+               return;
+       }
+
+       self.touch = vehicles_touch;
+
+       if(self.deadflag == DEAD_NO)
+       {
+               self.think = bumblebee_land;
+               self.nextthink  = time;
+       }
+
+       self.movetype = MOVETYPE_TOSS;
+
+       if(!self.owner)
+               return;
+
+       fixedmakevectors(self.angles);
+       vector spot;
+       if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)
+               spot = self.origin + v_up * 128 + v_forward * 300;
+       else
+               spot = self.origin + v_up * 128 - v_forward * 300;
+
+       spot = vehicles_findgoodexit(spot);
+
+       // Hide beam
+       if(self.gun3.enemy || !wasfreed(self.gun3.enemy)) {
+               self.gun3.enemy.effects |= EF_NODRAW;
+       }
+
+       self.owner.velocity = 0.75 * self.vehicle.velocity + normalize(spot - self.vehicle.origin) * 200;
+       self.owner.velocity_z += 10;
+       setorigin(self.owner, spot);
+
+       antilag_clear(self.owner);
+       self.owner = world;
+}
+
+void bumblebee_blowup()
+{SELFPARAM();
+       RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage,
+                                autocvar_g_vehicle_bumblebee_blowup_edgedamage,
+                                autocvar_g_vehicle_bumblebee_blowup_radius, self, world,
+                                autocvar_g_vehicle_bumblebee_blowup_forceintensity,
+                                DEATH_VH_BUMB_DEATH, world);
+
+       sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+       Send_Effect(EFFECT_EXPLOSION_BIG, (self.origin + '0 0 100') + (randomvec() * 80), '0 0 0', 1);
+
+       if(self.owner.deadflag == DEAD_DYING)
+               self.owner.deadflag = DEAD_DEAD;
+
+       remove(self);
+}
+
+void bumblebee_diethink()
+{SELFPARAM();
+       if(time >= self.wait)
+               self.think = bumblebee_blowup;
+
+       if(random() < 0.1)
+       {
+               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+               Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+       }
+
+       self.nextthink = time + 0.1;
+}
+
+spawnfunc(vehicle_bumblebee)
+{
+       if(!autocvar_g_vehicle_bumblebee) { remove(self); return; }
+       if(!vehicle_initialize(VEH_BUMBLEBEE, false)) { remove(self); return; }
+}
+
+               METHOD(Bumblebee, vr_impact, void(Bumblebee thisveh))
+               {
+                       if(autocvar_g_vehicle_bumblebee_bouncepain)
+                               vehicles_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, autocvar_g_vehicle_bumblebee_bouncepain_y, autocvar_g_vehicle_bumblebee_bouncepain_z);
+               }
+               METHOD(Bumblebee, vr_enter, void(Bumblebee thisveh))
+               {
+                       SELFPARAM();
+                       self.touch = bumblebee_touch;
+                       self.nextthink = 0;
+                       self.movetype = MOVETYPE_BOUNCEMISSILE;
+               }
+               METHOD(Bumblebee, vr_think, void(Bumblebee thisveh))
+               {
+                       SELFPARAM();
+                       self.angles_z *= 0.8;
+                       self.angles_x *= 0.8;
+
+                       self.nextthink = time;
+
+                       if(!self.owner)
+                       {
+                               entity oldself = self;
+                               if(self.gunner1)
+                               {
+                                       setself(self.gunner1);
+                                       oldself.gun1.vehicle_exit(VHEF_EJECT);
+                                       entity oldother = other;
+                                       other = self;
+                                       setself(oldself);
+                                       self.phase = 0;
+                                       self.touch();
+                                       other = oldother;
+                                       return;
+                               }
+
+                               if(self.gunner2)
+                               {
+                                       setself(self.gunner2);
+                                       oldself.gun2.vehicle_exit(VHEF_EJECT);
+                                       entity oldother = other;
+                                       other = self;
+                                       setself(oldself);
+                                       self.phase = 0;
+                                       self.touch();
+                                       other = oldother;
+                                       return;
+                               }
+                       }
+               }
+               METHOD(Bumblebee, vr_death, void(Bumblebee thisveh))
+               {
+                       SELFPARAM();
+                       entity oldself = self;
+
+                       CSQCModel_UnlinkEntity(self);
+
+                       // Hide beam
+                       if(self.gun3.enemy || !wasfreed(self.gun3.enemy))
+                               self.gun3.enemy.effects |= EF_NODRAW;
+
+                       if(self.gunner1)
+                       {
+                               setself(self.gunner1);
+                               oldself.gun1.vehicle_exit(VHEF_EJECT);
+                               setself(oldself);
+                       }
+
+                       if(self.gunner2)
+                       {
+                               setself(self.gunner2);
+                               oldself.gun2.vehicle_exit(VHEF_EJECT);
+                               setself(oldself);
+                       }
+
+                       self.vehicle_exit(VHEF_EJECT);
+
+                       fixedmakevectors(self.angles);
+                       vehicle_tossgib(self.gun1, self.velocity + v_right * 300 + v_up * 100 + randomvec() * 200, "cannon_right", rint(random()), rint(random()), 6, randomvec() * 200);
+                       vehicle_tossgib(self.gun2, self.velocity + v_right * -300 + v_up * 100 + randomvec() * 200, "cannon_left", rint(random()), rint(random()), 6, randomvec() * 200);
+                       vehicle_tossgib(self.gun3, self.velocity + v_forward * 300 + v_up * -100 + randomvec() * 200, "raygun", rint(random()), rint(random()), 6, randomvec() * 300);
+
+                       entity _body = vehicle_tossgib(self, self.velocity + randomvec() * 200, "", rint(random()), rint(random()), 6, randomvec() * 100);
+
+                       if(random() > 0.5)
+                               _body.touch = bumblebee_blowup;
+                       else
+                               _body.touch = func_null;
+
+                       _body.think = bumblebee_diethink;
+                       _body.nextthink = time;
+                       _body.wait = time + 2 + (random() * 8);
+                       _body.owner = self;
+                       _body.enemy = self.enemy;
+                       _body.scale = 1.5;
+                       _body.angles = self.angles;
+
+                       Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation(self.origin, 16), '0 0 0', 1);
+
+                       self.health                     = 0;
+                       self.event_damage       = func_null;
+                       self.solid                      = SOLID_NOT;
+                       self.takedamage         = DAMAGE_NO;
+                       self.deadflag           = DEAD_DYING;
+                       self.movetype           = MOVETYPE_NONE;
+                       self.effects            = EF_NODRAW;
+                       self.colormod           = '0 0 0';
+                       self.avelocity          = '0 0 0';
+                       self.velocity           = '0 0 0';
+                       self.touch                      = func_null;
+                       self.nextthink          = 0;
+
+                       setorigin(self, self.pos1);
+               }
+               METHOD(Bumblebee, vr_spawn, void(Bumblebee thisveh))
+               {
+                       SELFPARAM();
+                       if(!self.gun1)
+                       {
+                               // for some reason, autosizing of the shield entity refuses to work for this one so set it up in advance.
+                               self.vehicle_shieldent = spawn();
+                               self.vehicle_shieldent.effects = EF_LOWPRECISION;
+                               setmodel(self.vehicle_shieldent, MDL_VEH_BUMBLEBEE_SHIELD);
+                               setattachment(self.vehicle_shieldent, self, "");
+                               setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
+                               self.vehicle_shieldent.scale       = 512 / vlen(self.maxs - self.mins);
+                               self.vehicle_shieldent.think       = shieldhit_think;
+                               self.vehicle_shieldent.alpha = -1;
+                               self.vehicle_shieldent.effects = EF_LOWPRECISION | EF_NODRAW;
+
+                               self.gun1 = spawn();
+                               self.gun2 = spawn();
+                               self.gun3 = spawn();
+
+                               self.vehicle_flags |= VHF_MULTISLOT;
+
+                               self.gun1.owner = self;
+                               self.gun2.owner = self;
+                               self.gun3.owner = self;
+
+                               self.gun1.classname = self.gun2.classname = "vehicle_playerslot";
+
+                               setmodel(self.gun1, MDL_VEH_BUMBLEBEE_CANNON_RIGHT);
+                               setmodel(self.gun2, MDL_VEH_BUMBLEBEE_CANNON_LEFT);
+                               setmodel(self.gun3, MDL_VEH_BUMBLEBEE_CANNON_CENTER);
+
+                               setattachment(self.gun1, self, "cannon_right");
+                               setattachment(self.gun2, self, "cannon_left");
+
+                               // Angled bones are no fun, messes up gun-aim; so work arround it.
+                               self.gun3.pos1 = self.angles;
+                               self.angles = '0 0 0';
+                               vector ofs = gettaginfo(self, gettagindex(self, "raygun"));
+                               ofs -= self.origin;
+                               setattachment(self.gun3, self, "");
+                               setorigin(self.gun3, ofs);
+                               self.angles = self.gun3.pos1;
+
+                               vehicle_addplayerslot(self, self.gun1, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
+                               vehicle_addplayerslot(self, self.gun2, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
+
+                               setorigin(self.vehicle_hudmodel, '50 0 -5');    // Move cockpit forward - down.
+                               setorigin(self.vehicle_viewport, '5 0 2');    // Move camera forward up
+
+                               //fixme-model-bones
+                               setorigin(self.gun1.vehicle_hudmodel, '90 -27 -23');
+                               setorigin(self.gun1.vehicle_viewport, '-85 0 50');
+                               //fixme-model-bones
+                               setorigin(self.gun2.vehicle_hudmodel, '90 27 -23');
+                               setorigin(self.gun2.vehicle_viewport, '-85 0 50');
+
+                               self.scale = 1.5;
+
+                               // Raygun beam
+                               if(self.gun3.enemy == world)
+                               {
+                                       self.gun3.enemy = spawn();
+                                       Net_LinkEntity(self.gun3.enemy, true, 0, bumble_raygun_send);
+                                       self.gun3.enemy.SendFlags = BRG_SETUP;
+                                       self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;
+                                       self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION;
+                               }
+                       }
+
+                       self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
+                       self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
+                       self.solid = SOLID_BBOX;
+                       self.movetype = MOVETYPE_TOSS;
+                       self.damageforcescale = 0.025;
+
+                       self.PlayerPhysplug = bumblebee_pilot_frame;
+
+                       setorigin(self, self.origin + '0 0 25');
+               }
+               METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh))
+               {
+                       SELFPARAM();
+                       if(autocvar_g_vehicle_bumblebee_energy)
+                       if(autocvar_g_vehicle_bumblebee_energy_regen)
+                               self.vehicle_flags |= VHF_ENERGYREGEN;
+
+                       if(autocvar_g_vehicle_bumblebee_shield)
+                               self.vehicle_flags |= VHF_HASSHIELD;
+
+                       if(autocvar_g_vehicle_bumblebee_shield_regen)
+                               self.vehicle_flags |= VHF_SHIELDREGEN;
+
+                       if(autocvar_g_vehicle_bumblebee_health_regen)
+                               self.vehicle_flags |= VHF_HEALTHREGEN;
+
+                       self.vehicle_exit = bumblebee_exit;
+                       self.respawntime = autocvar_g_vehicle_bumblebee_respawntime;
+                       self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
+                       self.max_health = self.vehicle_health;
+                       self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
+               }
+
+#endif // SVQC
+#ifdef CSQC
+
+void CSQC_BUMBLE_GUN_HUD()
+{
+       Vehicles_drawHUD("vehicle_gunner", "vehicle_gunner_weapon1", string_null,
+                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+                                        string_null, '0 0 0',
+                                        string_null);
+}
+
+               METHOD(Bumblebee, vr_hud, void(Bumblebee thisveh))
+               {
+                       Vehicles_drawHUD(VEH_BUMBLEBEE.m_icon, "vehicle_bumble_weapon1", "vehicle_bumble_weapon2",
+                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+                                                        vCROSS_HEAL);
+               }
+               METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh))
+               {
+                       AuxiliaryXhair[0].axh_image = vCROSS_LOCK;  // Raygun-locked
+                       AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Gunner1
+                       AuxiliaryXhair[2].axh_image = vCROSS_BURST; // Gunner2
+               }
+
+#endif
+#endif
diff --git a/qcsrc/common/vehicles/vehicle/bumblebee.qh b/qcsrc/common/vehicles/vehicle/bumblebee.qh
new file mode 100644 (file)
index 0000000..7c387e4
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef BUMBLEBEE_H
+#define BUMBLEBEE_H
+
+#ifdef CSQC
+void bumble_raygun_read(bool bIsNew);
+
+void CSQC_BUMBLE_GUN_HUD();
+#endif
+
+#endif
diff --git a/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc b/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc
new file mode 100644 (file)
index 0000000..79252e1
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef VEHICLE_BUMBLEBEE_WEAPONS_H
+#define VEHICLE_BUMBLEBEE_WEAPONS_H
+
+#include "../../weapons/all.qh"
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_bumblebee_cannon_cost;
+float autocvar_g_vehicle_bumblebee_cannon_damage;
+float autocvar_g_vehicle_bumblebee_cannon_radius;
+float autocvar_g_vehicle_bumblebee_cannon_refire;
+float autocvar_g_vehicle_bumblebee_cannon_speed;
+float autocvar_g_vehicle_bumblebee_cannon_spread;
+float autocvar_g_vehicle_bumblebee_cannon_force;
+
+bool bumble_raygun_send(entity this, entity to, int sf);
+
+void bumblebee_fire_cannon(entity _gun, string _tagname, entity _owner)
+{
+    vector v = gettaginfo(_gun, gettagindex(_gun, _tagname));
+    vehicles_projectile(EFFECT_BIGPLASMA_MUZZLEFLASH.eent_eff_name, SND(VEH_BUMBLEBEE_FIRE),
+                        v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed,
+                        autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force,  0,
+                        DEATH_VH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, true, true, _owner);
+}
+
+bool bumble_raygun_send(entity this, entity to, float sf)
+{
+    WriteByte(MSG_ENTITY, ENT_CLIENT_BUMBLE_RAYGUN);
+
+    WriteByte(MSG_ENTITY, sf);
+    if(sf & BRG_SETUP)
+    {
+        WriteByte(MSG_ENTITY, num_for_edict(self.realowner));
+        WriteByte(MSG_ENTITY, self.realowner.team);
+        WriteByte(MSG_ENTITY, self.cnt);
+    }
+
+    if(sf & BRG_START)
+    {
+        WriteCoord(MSG_ENTITY, self.hook_start_x);
+        WriteCoord(MSG_ENTITY, self.hook_start_y);
+        WriteCoord(MSG_ENTITY, self.hook_start_z);
+    }
+
+    if(sf & BRG_END)
+    {
+        WriteCoord(MSG_ENTITY, self.hook_end_x);
+        WriteCoord(MSG_ENTITY, self.hook_end_y);
+        WriteCoord(MSG_ENTITY, self.hook_end_z);
+    }
+
+    return true;
+}
+
+#endif
+
+#ifdef CSQC
+
+void bumble_raygun_draw(entity this);
+
+void bumble_raygun_read(bool bIsNew)
+{SELFPARAM();
+    int sf = ReadByte();
+
+    if(sf & BRG_SETUP)
+    {
+        self.cnt  = ReadByte();
+        self.team = ReadByte();
+        self.cnt  = ReadByte();
+
+        if(self.cnt)
+            self.colormod = '1 0 0';
+        else
+            self.colormod = '0 1 0';
+
+        self.traileffect = EFFECT_BUMBLEBEE_HEAL_MUZZLEFLASH.m_id;
+        self.lip = particleeffectnum(EFFECT_BUMBLEBEE_HEAL_IMPACT);
+
+        self.draw = bumble_raygun_draw;
+    }
+
+
+    if(sf & BRG_START)
+    {
+        self.origin_x = ReadCoord();
+        self.origin_y = ReadCoord();
+        self.origin_z = ReadCoord();
+        setorigin(self, self.origin);
+    }
+
+    if(sf & BRG_END)
+    {
+        self.move_origin_x = ReadCoord();
+        self.move_origin_y = ReadCoord();
+        self.move_origin_z = ReadCoord();
+    }
+}
+
+void bumble_raygun_draw(entity this)
+{
+    float _len;
+    vector _dir;
+    vector _vtmp1, _vtmp2;
+
+    _len = vlen(self.origin - self.move_origin);
+    _dir = normalize(self.move_origin - self.origin);
+
+    if(self.total_damages < time)
+    {
+        boxparticles(particleeffectnum(Effects[self.traileffect]), self, self.origin, self.origin + _dir * -64, _dir * -_len , _dir * -_len, 1, PARTICLES_USEALPHA);
+        boxparticles(self.lip, self, self.move_origin, self.move_origin + _dir * -64, _dir * -200 , _dir * -200, 1, PARTICLES_USEALPHA);
+        self.total_damages = time + 0.1;
+    }
+
+    float i, df, sz, al;
+    for(i = -0.1; i < 0.2; i += 0.1)
+    {
+        df = DRAWFLAG_NORMAL; //((random() < 0.5) ? DRAWFLAG_ADDITIVE : DRAWFLAG_SCREEN);
+        sz = 5 + random() * 5;
+        al = 0.25 + random() * 0.5;
+        _vtmp1 = self.origin + _dir * _len * (0.25 + i);
+        _vtmp1 += (randomvec() * (_len * 0.2) * (frametime * 2));       //self.raygun_l1;
+        Draw_CylindricLine(self.origin, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+
+        _vtmp2 = self.origin + _dir * _len * (0.5 + i);
+        _vtmp2 += (randomvec() * (_len * 0.2) * (frametime * 5));       //self.raygun_l2;
+        Draw_CylindricLine(_vtmp1, _vtmp2, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+
+        _vtmp1 = self.origin + _dir * _len * (0.75 + i);
+        _vtmp1 += randomvec() * (_len * 0.2) * (frametime * 10);     //self.raygun_l3;
+        Draw_CylindricLine(_vtmp2, _vtmp1, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+
+        Draw_CylindricLine(_vtmp1, self.move_origin +  randomvec() * 32, sz, "gfx/colors/white.tga", 1, 1, self.colormod, al, df, view_origin);
+    }
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/vehicles/vehicle/racer.qc b/qcsrc/common/vehicles/vehicle/racer.qc
new file mode 100644 (file)
index 0000000..2b5950a
--- /dev/null
@@ -0,0 +1,694 @@
+#ifndef VEHICLE_RACER
+#define VEHICLE_RACER
+
+#include "racer_weapon.qc"
+
+CLASS(Racer, Vehicle)
+/* spawnflags */ ATTRIB(Racer, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL);
+/* mins       */ ATTRIB(Racer, mins, vector, '-120 -120 -40' * 0.5);
+/* maxs       */ ATTRIB(Racer, maxs, vector, '120 120 40' * 0.5);
+/* model         */ ATTRIB(Racer, mdl, string, "models/vehicles/wakizashi.dpm");
+/* model         */ ATTRIB(Racer, model, string, "models/vehicles/wakizashi.dpm");
+/* head_model */ ATTRIB(Racer, head_model, string, "null");
+/* hud_model  */ ATTRIB(Racer, hud_model, string, "models/vehicles/wakizashi_cockpit.dpm");
+/* tags       */ ATTRIB(Racer, tag_head, string, "");
+/* tags       */ ATTRIB(Racer, tag_hud, string, "");
+/* tags       */ ATTRIB(Racer, tag_view, string, "tag_viewport");
+/* netname    */ ATTRIB(Racer, netname, string, "racer");
+/* fullname   */ ATTRIB(Racer, vehicle_name, string, _("Racer"));
+/* icon       */ ATTRIB(Racer, m_icon, string, "vehicle_racer");
+ENDCLASS(Racer)
+REGISTER_VEHICLE(RACER, NEW(Racer));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "racer_weapon.qc"
+
+#ifdef SVQC
+#include "../../effects/effects.qh"
+#include "../../triggers/trigger/impulse.qh"
+
+bool autocvar_g_vehicle_racer;
+
+float autocvar_g_vehicle_racer_speed_afterburn;
+float autocvar_g_vehicle_racer_afterburn_cost;
+
+float autocvar_g_vehicle_racer_waterburn_cost;
+float autocvar_g_vehicle_racer_waterburn_speed;
+
+float autocvar_g_vehicle_racer_water_speed_forward;
+float autocvar_g_vehicle_racer_water_speed_strafe;
+
+float autocvar_g_vehicle_racer_pitchlimit = 30;
+
+float autocvar_g_vehicle_racer_water_downforce = 0.03;
+float autocvar_g_vehicle_racer_water_upforcedamper = 15;
+
+float autocvar_g_vehicle_racer_anglestabilizer;
+float autocvar_g_vehicle_racer_downforce;
+
+float autocvar_g_vehicle_racer_speed_forward;
+float autocvar_g_vehicle_racer_speed_strafe;
+float autocvar_g_vehicle_racer_springlength;
+float autocvar_g_vehicle_racer_upforcedamper;
+float autocvar_g_vehicle_racer_friction;
+
+float autocvar_g_vehicle_racer_water_time = 5;
+
+float autocvar_g_vehicle_racer_hovertype;
+float autocvar_g_vehicle_racer_hoverpower;
+
+float autocvar_g_vehicle_racer_turnroll;
+float autocvar_g_vehicle_racer_turnspeed;
+float autocvar_g_vehicle_racer_pitchspeed;
+
+float autocvar_g_vehicle_racer_energy;
+float autocvar_g_vehicle_racer_energy_regen;
+float autocvar_g_vehicle_racer_energy_regen_pause;
+
+float autocvar_g_vehicle_racer_health;
+float autocvar_g_vehicle_racer_health_regen;
+float autocvar_g_vehicle_racer_health_regen_pause;
+
+float autocvar_g_vehicle_racer_shield;
+float autocvar_g_vehicle_racer_shield_regen;
+float autocvar_g_vehicle_racer_shield_regen_pause;
+
+float autocvar_g_vehicle_racer_rocket_locktarget;
+float autocvar_g_vehicle_racer_rocket_locking_time;
+float autocvar_g_vehicle_racer_rocket_locking_releasetime;
+float autocvar_g_vehicle_racer_rocket_locked_time;
+
+float autocvar_g_vehicle_racer_respawntime;
+
+float autocvar_g_vehicle_racer_blowup_radius;
+float autocvar_g_vehicle_racer_blowup_coredamage;
+float autocvar_g_vehicle_racer_blowup_edgedamage;
+float autocvar_g_vehicle_racer_blowup_forceintensity;
+
+float autocvar_g_vehicle_racer_bouncefactor;
+float autocvar_g_vehicle_racer_bouncestop;
+vector autocvar_g_vehicle_racer_bouncepain;
+
+.float racer_watertime;
+
+var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
+
+void racer_align4point(float _delta)
+{SELFPARAM();
+       vector push_vector;
+       float fl_push, fr_push, bl_push, br_push;
+
+       push_vector  = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
+       fr_push   = force_fromtag_normpower;
+       //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+
+       push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
+       fl_push   = force_fromtag_normpower;
+       //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+
+       push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
+       br_push   = force_fromtag_normpower;
+       //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+
+       push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
+       bl_push   = force_fromtag_normpower;
+       //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
+
+       self.velocity += push_vector * _delta;
+
+       float uforce = autocvar_g_vehicle_racer_upforcedamper;
+
+       int cont = pointcontents(self.origin - '0 0 64');
+       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+       {
+               uforce = autocvar_g_vehicle_racer_water_upforcedamper;
+
+               if(self.owner.BUTTON_CROUCH && time < self.air_finished)
+                       self.velocity_z += 30;
+               else
+                       self.velocity_z += 200;
+       }
+
+
+       // Anti ocilation
+       if(self.velocity_z > 0)
+               self.velocity_z *= 1 - uforce * _delta;
+
+       push_vector_x =  (fl_push - bl_push);
+       push_vector_x += (fr_push - br_push);
+       push_vector_x *= 360;
+
+       push_vector_z = (fr_push - fl_push);
+       push_vector_z += (br_push - bl_push);
+       push_vector_z *= 360;
+
+       // Apply angle diffrance
+       self.angles_z += push_vector_z * _delta;
+       self.angles_x += push_vector_x * _delta;
+
+       // Apply stabilizer
+       self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
+       self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
+}
+
+void racer_fire_rocket_aim(string tagname, entity trg)
+{
+       SELFPARAM();
+       vector v = gettaginfo(self, gettagindex(self, tagname));
+       racer_fire_rocket(v, v_forward, trg);
+}
+
+float racer_frame()
+{SELFPARAM();
+       entity player, racer;
+       vector df;
+       float ftmp;
+
+       if(intermission_running)
+       {
+               self.vehicle.velocity = '0 0 0';
+               self.vehicle.avelocity = '0 0 0';
+               return 1;
+       }
+
+       player  = self;
+       racer   = self.vehicle;
+       setself(racer);
+
+       vehicles_painframe();
+
+       if(pointcontents(racer.origin) != CONTENT_WATER)
+               racer.air_finished = time + autocvar_g_vehicle_racer_water_time;
+
+       if(racer.deadflag != DEAD_NO)
+       {
+               setself(player);
+               player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+               return 1;
+       }
+
+       racer_align4point(PHYS_INPUT_TIMELENGTH);
+
+       player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0;
+
+       crosshair_trace(player);
+
+       racer.angles_x *= -1;
+
+       // Yaw
+       ftmp = autocvar_g_vehicle_racer_turnspeed * PHYS_INPUT_TIMELENGTH;
+       ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
+       racer.angles_y = anglemods(racer.angles_y + ftmp);
+
+       // Roll
+       racer.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * PHYS_INPUT_TIMELENGTH;
+
+       // Pitch
+       ftmp = autocvar_g_vehicle_racer_pitchspeed  * PHYS_INPUT_TIMELENGTH;
+       ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp);
+       racer.angles_x = bound(-autocvar_g_vehicle_racer_pitchlimit, anglemods(racer.angles_x + ftmp), autocvar_g_vehicle_racer_pitchlimit);
+
+       makevectors(racer.angles);
+       racer.angles_x *= -1;
+
+       //ftmp = racer.velocity_z;
+       df = racer.velocity * -autocvar_g_vehicle_racer_friction;
+       //racer.velocity_z = ftmp;
+
+       int cont = pointcontents(racer.origin);
+       if(vlen(player.movement) != 0)
+       {
+               if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+               {
+                       if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_water_speed_forward : -autocvar_g_vehicle_racer_water_speed_forward); }
+                       if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_water_speed_strafe : -autocvar_g_vehicle_racer_water_speed_strafe); }
+               }
+               else
+               {
+                       if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_speed_forward : -autocvar_g_vehicle_racer_speed_forward); }
+                       if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_speed_strafe : -autocvar_g_vehicle_racer_speed_strafe); }
+               }
+
+#ifdef SVQC
+               if(self.sound_nexttime < time || self.sounds != 1)
+               {
+                       self.sounds = 1;
+                       self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav");
+                       sound (self, CH_TRIGGER_SINGLE, SND_VEH_RACER_MOVE, VOL_VEHICLEENGINE, ATTEN_NORM);
+               }
+#endif
+       }
+#ifdef SVQC
+       else
+       {
+               if(self.sound_nexttime < time || self.sounds != 0)
+               {
+                       self.sounds = 0;
+                       self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav");
+                       sound (self, CH_TRIGGER_SINGLE, SND_VEH_RACER_IDLE, VOL_VEHICLEENGINE, ATTEN_NORM);
+               }
+       }
+#endif
+
+       // Afterburn
+       if (PHYS_INPUT_BUTTON_JUMP(player) && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH))
+       {
+#ifdef SVQC
+               if(time - racer.wait > 0.2)
+                       pointparticles(particleeffectnum(EFFECT_RACER_BOOSTER), self.origin - v_forward * 32, v_forward  * vlen(self.velocity), 1);
+#endif
+
+               racer.wait = time;
+
+               if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+               {
+                       racer.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * PHYS_INPUT_TIMELENGTH;
+                       df += (v_forward * autocvar_g_vehicle_racer_waterburn_speed);
+               }
+               else
+               {
+                       racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH;
+                       df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn);
+               }
+
+#ifdef SVQC
+               if(racer.invincible_finished < time)
+               {
+                       traceline(racer.origin, racer.origin - '0 0 256', MOVE_NORMAL, self);
+                       if(trace_fraction != 1.0)
+                               pointparticles(particleeffectnum(EFFECT_SMOKE_SMALL), trace_endpos, '0 0 0', 1);
+
+                       racer.invincible_finished = time + 0.1 + (random() * 0.1);
+               }
+
+               if(racer.strength_finished < time)
+               {
+                       racer.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
+                       sound (racer.tur_head, CH_TRIGGER_SINGLE, SND_VEH_RACER_BOOST, VOL_VEHICLEENGINE, ATTEN_NORM);
+               }
+#endif
+       }
+       else
+       {
+               racer.strength_finished = 0;
+               sound (racer.tur_head, CH_TRIGGER_SINGLE, SND_Null, VOL_VEHICLEENGINE, ATTEN_NORM);
+       }
+
+       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+               racer.racer_watertime = time;
+
+       float dforce = autocvar_g_vehicle_racer_downforce;
+       if(time - racer.racer_watertime <= 3)
+               dforce = autocvar_g_vehicle_racer_water_downforce;
+
+       df -= v_up * (vlen(racer.velocity) * dforce);
+       player.movement = racer.velocity += df * PHYS_INPUT_TIMELENGTH;
+
+#ifdef SVQC
+       Weapon wep1 = WEP_RACER;
+       if (!forbidWeaponUse(player))
+       if (player.BUTTON_ATCK)
+       if (wep1.wr_checkammo1(wep1))
+       {
+               string tagname = (racer.cnt)
+                   ? (racer.cnt = 0, "tag_fire1")
+                   : (racer.cnt = 1, "tag_fire2");
+               vector org = gettaginfo(self, gettagindex(self, tagname));
+               w_shotorg = org;
+               w_shotdir = v_forward;
+               // Fix z-aim (for chase mode)
+               crosshair_trace(player);
+               w_shotdir.z = normalize(trace_endpos - org).z * 0.5;
+               wep1.wr_think(wep1, self, true, false);
+       }
+
+       if(autocvar_g_vehicle_racer_rocket_locktarget)
+       {
+               vehicles_locktarget((1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime,
+                                                (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime,
+                                                autocvar_g_vehicle_racer_rocket_locked_time);
+
+               if(self.lock_target)
+               {
+                       if(racer.lock_strength == 1)
+                               UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '1 0 0', 0);
+                       else if(self.lock_strength > 0.5)
+                               UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 1 0', 0);
+                       else if(self.lock_strength < 0.5)
+                               UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 0 1', 0);
+               }
+       }
+
+       if(!forbidWeaponUse(player))
+       if(time > racer.delay)
+       if(player.BUTTON_ATCK2)
+       {
+               racer.misc_bulletcounter += 1;
+               racer.delay = time + 0.3;
+
+               if(racer.misc_bulletcounter == 1)
+               {
+                       racer_fire_rocket_aim("tag_rocket_r", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
+                       player.vehicle_ammo2 = 50;
+               }
+               else if(racer.misc_bulletcounter == 2)
+               {
+                       racer_fire_rocket_aim("tag_rocket_l", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
+                       racer.lock_strength  = 0;
+                       racer.lock_target       = world;
+                       racer.misc_bulletcounter = 0;
+                       racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
+                       racer.lip = time;
+                       player.vehicle_ammo2 = 0;
+               }
+       }
+       else if(racer.misc_bulletcounter == 0)
+               player.vehicle_ammo2 = 100;
+
+       player.vehicle_reload2 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100);
+
+       if(racer.vehicle_flags  & VHF_SHIELDREGEN)
+               vehicles_regen(racer.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime, true);
+
+       if(racer.vehicle_flags  & VHF_HEALTHREGEN)
+               vehicles_regen(racer.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime, false);
+
+       if(racer.vehicle_flags  & VHF_ENERGYREGEN)
+               vehicles_regen(racer.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime, false);
+
+
+       VEHICLE_UPDATE_PLAYER(player, health, racer);
+       VEHICLE_UPDATE_PLAYER(player, energy, racer);
+
+       if(racer.vehicle_flags & VHF_HASSHIELD)
+               VEHICLE_UPDATE_PLAYER(player, shield, racer);
+
+       player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+#endif
+
+       setorigin(player,racer.origin + '0 0 32');
+       player.velocity = racer.velocity;
+
+       setself(player);
+       return 1;
+}
+
+void racer_think()
+{SELFPARAM();
+       self.nextthink = time;
+
+       float pushdeltatime = time - self.lastpushtime;
+       if (pushdeltatime > 0.15) pushdeltatime = 0;
+       self.lastpushtime = time;
+       if(!pushdeltatime) return;
+
+       tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NOMONSTERS, self);
+
+       vector df = self.velocity * -autocvar_g_vehicle_racer_friction;
+       df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2);
+
+       float forced = autocvar_g_vehicle_racer_upforcedamper;
+
+       int cont = pointcontents(self.origin - '0 0 64');
+       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+       {
+               forced = autocvar_g_vehicle_racer_water_upforcedamper;
+               self.velocity_z += 200;
+       }
+
+       self.velocity += df * pushdeltatime;
+       if(self.velocity_z > 0)
+               self.velocity_z *= 1 - forced * pushdeltatime;
+
+       self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
+       self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
+
+       CSQCMODEL_AUTOUPDATE(self);
+}
+
+void racer_exit(float eject)
+{SELFPARAM();
+       vector spot;
+
+       self.think        = racer_think;
+       self.nextthink  = time;
+       self.movetype   = MOVETYPE_BOUNCE;
+       sound (self.tur_head, CH_TRIGGER_SINGLE, SND_Null, VOL_VEHICLEENGINE, ATTEN_NORM);
+
+       if(!self.owner)
+               return;
+
+       makevectors(self.angles);
+       if(eject)
+       {
+               spot = self.origin + v_forward * 100 + '0 0 64';
+               spot = vehicles_findgoodexit(spot);
+               setorigin(self.owner , spot);
+               self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+               self.owner.oldvelocity = self.owner.velocity;
+       }
+       else
+       {
+               if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
+               {
+                       self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
+                       self.owner.velocity_z += 200;
+                       spot = self.origin + v_forward * 32 + '0 0 32';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               else
+               {
+                       self.owner.velocity = self.velocity * 0.5;
+                       self.owner.velocity_z += 10;
+                       spot = self.origin - v_forward * 200 + '0 0 32';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               self.owner.oldvelocity = self.owner.velocity;
+               setorigin(self.owner , spot);
+       }
+       antilag_clear(self.owner);
+       self.owner = world;
+}
+
+void racer_blowup()
+{SELFPARAM();
+       self.deadflag   = DEAD_DEAD;
+       self.vehicle_exit(VHEF_NORMAL);
+
+       RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage,
+                                       autocvar_g_vehicle_racer_blowup_edgedamage,
+                                       autocvar_g_vehicle_racer_blowup_radius, world, world,
+                                       autocvar_g_vehicle_racer_blowup_forceintensity,
+                                       DEATH_VH_WAKI_DEATH, world);
+
+       self.nextthink  = time + autocvar_g_vehicle_racer_respawntime;
+       self.think        = vehicles_spawn;
+       self.movetype   = MOVETYPE_NONE;
+       self.effects    = EF_NODRAW;
+       self.solid = SOLID_NOT;
+
+       self.colormod  = '0 0 0';
+       self.avelocity = '0 0 0';
+       self.velocity  = '0 0 0';
+
+       setorigin(self, self.pos1);
+}
+
+void racer_blowup_think()
+{SELFPARAM();
+       self.nextthink = time;
+
+       if(time >= self.delay)
+               racer_blowup();
+
+       CSQCMODEL_AUTOUPDATE(self);
+}
+
+void racer_deadtouch()
+{SELFPARAM();
+       self.avelocity_x *= 0.7;
+       self.cnt -= 1;
+       if(self.cnt <= 0)
+               racer_blowup();
+}
+
+spawnfunc(vehicle_racer)
+{
+       if(!autocvar_g_vehicle_racer) { remove(self); return; }
+       if(!vehicle_initialize(VEH_RACER, false)) { remove(self); return; }
+}
+
+#endif // SVQC
+
+#ifdef CSQC
+#if 0
+void racer_draw()
+{SELFPARAM();
+       float pushdeltatime = time - self.lastpushtime;
+       if (pushdeltatime > 0.15) pushdeltatime = 0;
+       self.lastpushtime = time;
+       if(!pushdeltatime) return;
+
+       tracebox(self.move_origin, self.mins, self.maxs, self.move_origin - ('0 0 1' * getstatf(STAT_VEH_RACER_SPRINGLENGTH)), MOVE_NOMONSTERS, self);
+
+       vector df = self.move_velocity * -getstatf(STAT_VEH_RACER_FRICTION);
+       df_z += (1 - trace_fraction) * getstatf(STAT_VEH_RACER_HOVERPOWER) + sin(time * 2) * (getstatf(STAT_VEH_RACER_SPRINGLENGTH) * 2);
+
+       float forced = getstatf(STAT_VEH_RACER_UPFORCEDAMPER);
+
+       int cont = pointcontents(self.move_origin - '0 0 64');
+       if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+       {
+               forced = getstatf(STAT_VEH_RACER_WATER_UPFORCEDAMPER);
+               self.move_velocity_z += 200;
+       }
+
+       self.move_velocity += df * pushdeltatime;
+       if(self.move_velocity_z > 0)
+               self.move_velocity_z *= 1 - forced * pushdeltatime;
+
+       self.move_angles_x *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
+       self.move_angles_z *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
+
+       Movetype_Physics_MatchServer(false);
+}
+#endif
+#endif
+
+               METHOD(Racer, vr_impact, void(Racer thisveh))
+               {
+               #ifdef SVQC
+                       if(autocvar_g_vehicle_racer_bouncepain)
+                               vehicles_impact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z);
+               #endif
+               }
+
+               METHOD(Racer, vr_enter, void(Racer thisveh))
+               {
+               #ifdef SVQC
+                       self.movetype = MOVETYPE_BOUNCE;
+                       self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health)  * 100;
+                       self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield)  * 100;
+
+                       if(self.owner.flagcarried)
+                          setorigin(self.owner.flagcarried, '-190 0 96');
+               #elif defined(CSQC)
+
+                       self.move_movetype = MOVETYPE_BOUNCE;
+               #endif
+               }
+
+               METHOD(Racer, vr_spawn, void(Racer thisveh))
+               {
+               #ifdef SVQC
+                       if(self.scale != 0.5)
+                       {
+                               if(autocvar_g_vehicle_racer_hovertype != 0)
+                                       racer_force_from_tag = vehicles_force_fromtag_maglev;
+                               else
+                                       racer_force_from_tag = vehicles_force_fromtag_hover;
+
+                               // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel).
+                               self.scale = 0.5;
+                               setattachment(self.vehicle_hudmodel, self, "");
+                               setattachment(self.vehicle_viewport, self, "tag_viewport");
+
+                               self.mass                          = 900;
+                       }
+
+                       self.think                = racer_think;
+                       self.nextthink    = time;
+                       self.vehicle_health = autocvar_g_vehicle_racer_health;
+                       self.vehicle_shield = autocvar_g_vehicle_racer_shield;
+
+                       self.movetype     = MOVETYPE_TOSS;
+                       self.solid                = SOLID_SLIDEBOX;
+                       self.delay                = time;
+                       self.scale                = 0.5;
+
+                       self.PlayerPhysplug = racer_frame;
+
+                       self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
+                       self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
+                       self.damageforcescale = 0.5;
+                       self.vehicle_health = autocvar_g_vehicle_racer_health;
+                       self.vehicle_shield = autocvar_g_vehicle_racer_shield;
+               #endif
+               }
+
+               METHOD(Racer, vr_death, void(Racer thisveh))
+               {
+               #ifdef SVQC
+                       self.SendEntity         = func_null; // stop networking this racer (for now)
+                       self.health                     = 0;
+                       self.event_damage       = func_null;
+                       self.solid                      = SOLID_CORPSE;
+                       self.takedamage         = DAMAGE_NO;
+                       self.deadflag           = DEAD_DYING;
+                       self.movetype           = MOVETYPE_BOUNCE;
+                       self.wait                       = time;
+                       self.delay                      = 2 + time + random() * 3;
+                       self.cnt                        = 1 + random() * 2;
+                       self.touch                      = racer_deadtouch;
+
+                       Send_Effect(EFFECT_EXPLOSION_MEDIUM, self.origin, '0 0 0', 1);
+
+                       if(random() < 0.5)
+                               self.avelocity_z = 32;
+                       else
+                               self.avelocity_z = -32;
+
+                       self.avelocity_x = -vlen(self.velocity) * 0.2;
+                       self.velocity += '0 0 700';
+                       self.colormod = '-0.5 -0.5 -0.5';
+
+                       self.think = racer_blowup_think;
+                       self.nextthink = time;
+               #endif
+               }
+
+#ifdef CSQC
+               METHOD(Racer, vr_hud, void(Racer thisveh))
+               {
+                       Vehicles_drawHUD(VEH_RACER.m_icon, "vehicle_racer_weapon1", "vehicle_racer_weapon2",
+                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+                                                        "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
+                                                        vCROSS_GUIDE);
+               }
+#endif
+               METHOD(Racer, vr_setup, void(Racer thisveh))
+               {
+               #ifdef SVQC
+                       self.vehicle_exit = racer_exit;
+               #endif
+
+               #ifdef SVQC
+                       // we have no need to network energy
+                       if(autocvar_g_vehicle_racer_energy)
+                       if(autocvar_g_vehicle_racer_energy_regen)
+                               self.vehicle_flags |= VHF_ENERGYREGEN;
+
+                       if(autocvar_g_vehicle_racer_shield)
+                               self.vehicle_flags |= VHF_HASSHIELD;
+
+                       if(autocvar_g_vehicle_racer_shield_regen)
+                               self.vehicle_flags |= VHF_SHIELDREGEN;
+
+                       if(autocvar_g_vehicle_racer_health_regen)
+                               self.vehicle_flags |= VHF_HEALTHREGEN;
+
+                       self.respawntime = autocvar_g_vehicle_racer_respawntime;
+                       self.vehicle_health = autocvar_g_vehicle_racer_health;
+                       self.vehicle_shield = autocvar_g_vehicle_racer_shield;
+                       self.max_health = self.vehicle_health;
+               #endif
+
+               #ifdef CSQC
+                       AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Rocket
+               #endif
+               }
+
+#endif
diff --git a/qcsrc/common/vehicles/vehicle/racer_weapon.qc b/qcsrc/common/vehicles/vehicle/racer_weapon.qc
new file mode 100644 (file)
index 0000000..d5a4c12
--- /dev/null
@@ -0,0 +1,211 @@
+#ifndef VEHICLE_RACER_WEAPON_H
+#define VEHICLE_RACER_WEAPON_H
+
+#include "../../weapons/all.qh"
+
+CLASS(RacerAttack, PortoLaunch)
+/* flags     */ ATTRIB(RacerAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(RacerAttack, impulse, int, 3);
+/* refname   */ ATTRIB(RacerAttack, netname, string, "racercannon");
+/* wepname   */ ATTRIB(RacerAttack, message, string, _("Racer cannon"));
+ENDCLASS(RacerAttack)
+REGISTER_WEAPON(RACER, NEW(RacerAttack));
+
+// TODO: move into implementation
+#ifdef SVQC
+float autocvar_g_vehicle_racer_rocket_refire;
+void racer_fire_rocket(vector org, vector dir, entity trg);
+#endif
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_racer_cannon_cost;
+float autocvar_g_vehicle_racer_cannon_damage;
+float autocvar_g_vehicle_racer_cannon_radius;
+float autocvar_g_vehicle_racer_cannon_refire;
+float autocvar_g_vehicle_racer_cannon_speed;
+float autocvar_g_vehicle_racer_cannon_spread;
+float autocvar_g_vehicle_racer_cannon_force;
+
+float autocvar_g_vehicle_racer_rocket_accel;
+float autocvar_g_vehicle_racer_rocket_damage;
+float autocvar_g_vehicle_racer_rocket_radius;
+float autocvar_g_vehicle_racer_rocket_force;
+float autocvar_g_vehicle_racer_rocket_speed;
+float autocvar_g_vehicle_racer_rocket_turnrate;
+
+float autocvar_g_vehicle_racer_rocket_climbspeed;
+float autocvar_g_vehicle_racer_rocket_locked_maxangle;
+
+void racer_fire_rocket(vector org, vector dir, entity trg);
+METHOD(RacerAttack, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
+{
+    bool isPlayer = IS_PLAYER(actor);
+    entity player = isPlayer ? actor : actor.owner;
+    entity veh = player.vehicle;
+    if (fire1)
+    if (weapon_prepareattack(thiswep, player, false, autocvar_g_vehicle_racer_cannon_refire)) {
+        if (veh) {
+            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);
+        vector org = w_shotorg;
+        vector dir = w_shotdir;
+        entity bolt = vehicles_projectile(EFFECT_RACER_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
+                               org, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
+                               autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force,  0,
+                               DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, true, true, player);
+        bolt.velocity = normalize(dir) * autocvar_g_vehicle_racer_cannon_speed;
+        weapon_thinkf(player, WFRAME_FIRE1, 0, w_ready);
+    }
+    if (fire2)
+    if (!isPlayer || weapon_prepareattack(thiswep, actor, false, 0.2)) {
+        if (isPlayer) W_SetupShot_Dir(actor, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
+        racer_fire_rocket(w_shotorg, w_shotdir, NULL);
+        weapon_thinkf(actor, WFRAME_FIRE2, 0, w_ready);
+    }
+}
+
+METHOD(RacerAttack, wr_checkammo1, bool(RacerAttack thiswep))
+{
+    SELFPARAM();
+    bool isPlayer = IS_PLAYER(self);
+    entity player = isPlayer ? self : self.owner;
+    entity veh = player.vehicle;
+    return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_racer_cannon_cost;
+}
+
+void racer_rocket_tracker();
+void racer_rocket_groundhugger();
+
+void racer_fire_rocket(vector org, vector dir, entity trg)
+{SELFPARAM();
+    entity rocket = vehicles_projectile(EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
+                           org, dir * autocvar_g_vehicle_racer_rocket_speed,
+                           autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
+                           DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, false, false, self.owner);
+
+    rocket.lip                   = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
+    rocket.wait                         = autocvar_g_vehicle_racer_rocket_turnrate;
+    rocket.nextthink           = time;
+    rocket.enemy                       = trg;
+    rocket.cnt                   = time + 15;
+
+    if(trg)
+        rocket.think                   = racer_rocket_tracker;
+    else
+        rocket.think                   = racer_rocket_groundhugger;
+}
+
+void racer_rocket_tracker()
+{SELFPARAM();
+    vector olddir, newdir;
+    float oldvel, newvel;
+
+    self.nextthink  = time;
+
+    if (self.owner.deadflag != DEAD_NO || self.cnt < time)
+    {
+        self.use();
+        return;
+    }
+
+    if(!self.realowner.vehicle)
+    {
+        UpdateCSQCProjectile(self);
+        return;
+    }
+
+    olddir = normalize(self.velocity);
+    oldvel = vlen(self.velocity);
+    newvel = oldvel + self.lip;
+    makevectors(vectoangles(olddir));
+
+    float time_to_impact = min(vlen(self.enemy.origin - self.origin) / vlen(self.velocity), 1);
+    vector predicted_origin = self.enemy.origin + self.enemy.velocity * time_to_impact;
+
+    traceline(self.origin, self.origin + v_forward * 64 - '0 0 32', MOVE_NORMAL, self);
+    newdir = normalize(predicted_origin - self.origin);
+
+    //vector
+    float height_diff = predicted_origin_z - self.origin_z;
+
+    if(vlen(newdir - v_forward) > autocvar_g_vehicle_racer_rocket_locked_maxangle)
+    {
+        //bprint("Target lost!\n");
+        //dprint("OF:", ftos(vlen(newdir - v_forward)), "\n");
+        self.think = racer_rocket_groundhugger;
+        return;
+    }
+
+    if(trace_fraction != 1.0 && trace_ent != self.enemy)
+        newdir_z += 16 * sys_frametime;
+
+    self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_racer_rocket_turnrate) * newvel;
+    self.velocity_z -= 800 * sys_frametime;
+    self.velocity_z += max(height_diff, autocvar_g_vehicle_racer_rocket_climbspeed) * sys_frametime ;
+
+    UpdateCSQCProjectile(self);
+    return;
+}
+
+void racer_rocket_groundhugger()
+{SELFPARAM();
+    vector olddir, newdir;
+    float oldvel, newvel;
+
+    self.nextthink  = time;
+
+    if(self.owner.deadflag != DEAD_NO || self.cnt < time)
+    {
+        self.use();
+        return;
+    }
+
+    if(!self.realowner.vehicle)
+    {
+        UpdateCSQCProjectile(self);
+        return;
+    }
+
+    olddir = normalize(self.velocity);
+    oldvel = vlen(self.velocity);
+    newvel = oldvel + self.lip;
+
+    tracebox(self.origin, self.mins, self.maxs, self.origin + olddir * 64, MOVE_WORLDONLY,self);
+    if(trace_fraction <= 0.5)
+    {
+        // Hitting somethign soon, just speed ahead
+        self.velocity = olddir * newvel;
+        UpdateCSQCProjectile(self);
+        return;
+    }
+
+    traceline(trace_endpos, trace_endpos - '0 0 64', MOVE_NORMAL, self);
+    if(trace_fraction != 1.0)
+    {
+        newdir = normalize(trace_endpos + '0 0 64' - self.origin) * autocvar_g_vehicle_racer_rocket_turnrate;
+        self.velocity = normalize(olddir + newdir) * newvel;
+    }
+    else
+    {
+        self.velocity = olddir * newvel;
+        self.velocity_z -= 1600 * sys_frametime; // 2x grav looks better for this one
+    }
+
+    int cont = pointcontents(self.origin - '0 0 32');
+    if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+        self.velocity_z += 200;
+
+    UpdateCSQCProjectile(self);
+    return;
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/vehicles/vehicle/raptor.qc b/qcsrc/common/vehicles/vehicle/raptor.qc
new file mode 100644 (file)
index 0000000..1f62337
--- /dev/null
@@ -0,0 +1,797 @@
+#ifndef VEHICLE_RAPTOR
+#define VEHICLE_RAPTOR
+#include "raptor.qh"
+
+#include "raptor_weapons.qc"
+
+CLASS(Raptor, Vehicle)
+/* spawnflags */ ATTRIB(Raptor, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL);
+/* mins       */ ATTRIB(Raptor, mins, vector, '-80 -80 0');
+/* maxs       */ ATTRIB(Raptor, maxs, vector, '80 80 70');
+/* model         */ ATTRIB(Raptor, mdl, string, "models/vehicles/raptor.dpm");
+/* model         */ ATTRIB(Raptor, model, string, "models/vehicles/raptor.dpm");
+/* head_model */ ATTRIB(Raptor, head_model, string, "");
+/* hud_model  */ ATTRIB(Raptor, hud_model, string, "models/vehicles/raptor_cockpit.dpm");
+/* tags       */ ATTRIB(Raptor, tag_head, string, "");
+/* tags       */ ATTRIB(Raptor, tag_hud, string, "tag_hud");
+/* tags       */ ATTRIB(Raptor, tag_view, string, "tag_camera");
+/* netname    */ ATTRIB(Raptor, netname, string, "raptor");
+/* fullname   */ ATTRIB(Raptor, vehicle_name, string, _("Raptor"));
+/* icon       */ ATTRIB(Raptor, m_icon, string, "vehicle_raptor");
+ENDCLASS(Raptor)
+REGISTER_VEHICLE(RAPTOR, NEW(Raptor));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#include "raptor_weapons.qc"
+
+#ifdef SVQC
+
+bool autocvar_g_vehicle_raptor;
+
+float autocvar_g_vehicle_raptor_respawntime;
+float autocvar_g_vehicle_raptor_takeofftime;
+
+float autocvar_g_vehicle_raptor_movestyle;
+float autocvar_g_vehicle_raptor_turnspeed;
+float autocvar_g_vehicle_raptor_pitchspeed;
+float autocvar_g_vehicle_raptor_pitchlimit;
+
+float autocvar_g_vehicle_raptor_speed_forward;
+float autocvar_g_vehicle_raptor_speed_strafe;
+float autocvar_g_vehicle_raptor_speed_up;
+float autocvar_g_vehicle_raptor_speed_down;
+float autocvar_g_vehicle_raptor_friction;
+
+float autocvar_g_vehicle_raptor_cannon_turnspeed;
+float autocvar_g_vehicle_raptor_cannon_turnlimit;
+float autocvar_g_vehicle_raptor_cannon_pitchlimit_up;
+float autocvar_g_vehicle_raptor_cannon_pitchlimit_down;
+
+float autocvar_g_vehicle_raptor_cannon_locktarget;
+float autocvar_g_vehicle_raptor_cannon_locking_time;
+float autocvar_g_vehicle_raptor_cannon_locking_releasetime;
+float autocvar_g_vehicle_raptor_cannon_locked_time;
+float autocvar_g_vehicle_raptor_cannon_predicttarget;
+
+float autocvar_g_vehicle_raptor_energy;
+float autocvar_g_vehicle_raptor_energy_regen;
+float autocvar_g_vehicle_raptor_energy_regen_pause;
+
+float autocvar_g_vehicle_raptor_health;
+float autocvar_g_vehicle_raptor_health_regen;
+float autocvar_g_vehicle_raptor_health_regen_pause;
+
+float autocvar_g_vehicle_raptor_shield;
+float autocvar_g_vehicle_raptor_shield_regen;
+float autocvar_g_vehicle_raptor_shield_regen_pause;
+
+float autocvar_g_vehicle_raptor_bouncefactor;
+float autocvar_g_vehicle_raptor_bouncestop;
+vector autocvar_g_vehicle_raptor_bouncepain;
+
+.entity bomb1;
+.entity bomb2;
+
+float raptor_altitude(float amax)
+{SELFPARAM();
+       tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * amax), MOVE_WORLDONLY, self);
+       return vlen(self.origin - trace_endpos);
+}
+
+void raptor_land()
+{SELFPARAM();
+       float hgt;
+
+       hgt = raptor_altitude(512);
+       self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
+       self.angles_x *= 0.95;
+       self.angles_z *= 0.95;
+
+       if(hgt < 128)
+       if(hgt > 0)
+               self.frame = (hgt / 128) * 25;
+
+       self.bomb1.gun1.avelocity_y = 90 + ((self.frame / 25) * 2000);
+       self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
+
+       if(hgt < 16)
+       {
+               self.movetype = MOVETYPE_TOSS;
+               self.think      = vehicles_think;
+               self.frame      = 0;
+       }
+
+       self.nextthink  = time;
+
+       CSQCMODEL_AUTOUPDATE(self);
+}
+
+void raptor_exit(float eject)
+{SELFPARAM();
+       vector spot;
+       self.tur_head.exteriormodeltoclient = world;
+
+       if(self.deadflag == DEAD_NO)
+       {
+               self.think        = raptor_land;
+               self.nextthink  = time;
+       }
+
+       if(!self.owner)
+               return;
+
+       makevectors(self.angles);
+       if(eject)
+       {
+               spot = self.origin + v_forward * 100 + '0 0 64';
+               spot = vehicles_findgoodexit(spot);
+               setorigin(self.owner , spot);
+               self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+               self.owner.oldvelocity = self.owner.velocity;
+       }
+       else
+       {
+               if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
+               {
+                       self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
+                       self.owner.velocity_z += 200;
+                       spot = self.origin + v_forward * 32 + '0 0 64';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               else
+               {
+                       self.owner.velocity = self.velocity * 0.5;
+                       self.owner.velocity_z += 10;
+                       spot = self.origin - v_forward * 200 + '0 0 64';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               self.owner.oldvelocity = self.owner.velocity;
+               setorigin(self.owner , spot);
+       }
+
+       antilag_clear(self.owner);
+       self.owner = world;
+}
+
+float raptor_frame()
+{SELFPARAM();
+       entity player, raptor;
+       float ftmp = 0;
+       vector df;
+
+       if(intermission_running)
+       {
+               self.vehicle.velocity = '0 0 0';
+               self.vehicle.avelocity = '0 0 0';
+               return 1;
+       }
+
+       player = self;
+       raptor = self.vehicle;
+       setself(raptor);
+
+       vehicles_painframe();
+       /*
+       ftmp = vlen(self.velocity);
+       if(ftmp > autocvar_g_vehicle_raptor_speed_forward)
+               ftmp = 1;
+       else
+               ftmp = ftmp / autocvar_g_vehicle_raptor_speed_forward;
+       */
+
+       if(self.sound_nexttime < time)
+       {
+               self.sound_nexttime = time + 7.955812;
+               //sound (self.tur_head, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_FLY, 1 - ftmp,   ATTEN_NORM );
+               sound (self, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_SPEED, 1, ATTEN_NORM);
+               self.wait = ftmp;
+       }
+       /*
+       else if(fabs(ftmp - self.wait) > 0.2)
+       {
+               sound (self.tur_head, CH_TRIGGER_SINGLE, SND_Null, 1 - ftmp,   ATTEN_NORM );
+               sound (self, CH_TRIGGER_SINGLE, SND_Null, ftmp, ATTEN_NORM);
+               self.wait = ftmp;
+       }
+       */
+
+       if(raptor.deadflag != DEAD_NO)
+       {
+               setself(player);
+               player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+               return 1;
+       }
+       crosshair_trace(player);
+
+       //if(time - self.lastteleporttime < 1)
+       //{
+               if(raptor.angles_z > 50 || raptor.angles_z < -50)
+               {
+                       if(player.BUTTON_JUMP)
+                       {
+                               player.BUTTON_CROUCH = true;
+                               player.BUTTON_JUMP = false;
+                       }
+               }
+       //}
+
+       vector vang;
+       vang = raptor.angles;
+       df = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
+       vang_x *= -1;
+       df_x *= -1;
+       if(df_x > 180)  df_x -= 360;
+       if(df_x < -180) df_x += 360;
+       if(df_y > 180)  df_y -= 360;
+       if(df_y < -180) df_y += 360;
+
+       ftmp = shortangle_f(player.v_angle_y - vang_y, vang_y);
+       if(ftmp > 180)  ftmp -= 360; if(ftmp < -180) ftmp += 360;
+       raptor.avelocity_y = bound(-autocvar_g_vehicle_raptor_turnspeed, ftmp + raptor.avelocity_y * 0.9, autocvar_g_vehicle_raptor_turnspeed);
+
+       // Pitch
+       ftmp = 0;
+       if(player.movement_x > 0 && vang_x < autocvar_g_vehicle_raptor_pitchlimit) ftmp = 5;
+       else if(player.movement_x < 0 && vang_x > -autocvar_g_vehicle_raptor_pitchlimit) ftmp = -20;
+
+       df_x = bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x , autocvar_g_vehicle_raptor_pitchlimit);
+       ftmp = vang_x - bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x + ftmp, autocvar_g_vehicle_raptor_pitchlimit);
+       raptor.avelocity_x = bound(-autocvar_g_vehicle_raptor_pitchspeed, ftmp + raptor.avelocity_x * 0.9, autocvar_g_vehicle_raptor_pitchspeed);
+
+       raptor.angles_x = anglemods(raptor.angles_x);
+       raptor.angles_y = anglemods(raptor.angles_y);
+       raptor.angles_z = anglemods(raptor.angles_z);
+
+       if(autocvar_g_vehicle_raptor_movestyle == 1)
+               makevectors('0 1 0' * raptor.angles_y);
+       else
+               makevectors(player.v_angle);
+
+       df = raptor.velocity * -autocvar_g_vehicle_raptor_friction;
+
+       if(player.movement_x != 0)
+       {
+               if(player.movement_x > 0)
+                       df += v_forward  * autocvar_g_vehicle_raptor_speed_forward;
+               else if(player.movement_x < 0)
+                       df -= v_forward  * autocvar_g_vehicle_raptor_speed_forward;
+       }
+
+       if(player.movement_y != 0)
+       {
+               if(player.movement_y < 0)
+                       df -= v_right * autocvar_g_vehicle_raptor_speed_strafe;
+               else if(player.movement_y > 0)
+                       df += v_right * autocvar_g_vehicle_raptor_speed_strafe;
+
+               raptor.angles_z = bound(-30,raptor.angles_z + (player.movement_y / autocvar_g_vehicle_raptor_speed_strafe),30);
+       }
+       else
+       {
+               raptor.angles_z *= 0.95;
+               if(raptor.angles_z >= -1 && raptor.angles_z <= -1)
+                       raptor.angles_z = 0;
+       }
+
+       if(player.BUTTON_CROUCH)
+               df -=   v_up * autocvar_g_vehicle_raptor_speed_down;
+       else if (player.BUTTON_JUMP)
+               df +=  v_up * autocvar_g_vehicle_raptor_speed_up;
+
+       raptor.velocity  += df * frametime;
+       player.velocity = player.movement  = raptor.velocity;
+       setorigin(player, raptor.origin + '0 0 32');
+
+       player.vehicle_weapon2mode = raptor.vehicle_weapon2mode;
+
+       vector vf, ad;
+       // Target lock & predict
+       if(autocvar_g_vehicle_raptor_cannon_locktarget == 2)
+       {
+               if(raptor.gun1.lock_time < time || raptor.gun1.enemy.deadflag)
+                       raptor.gun1.enemy = world;
+
+               if(trace_ent)
+               if(trace_ent.movetype)
+               if(trace_ent.takedamage)
+               if(!trace_ent.deadflag)
+               {
+                       if(teamplay)
+                       {
+                               if(trace_ent.team != player.team)
+                               {
+                                       raptor.gun1.enemy = trace_ent;
+                                       raptor.gun1.lock_time = time + 5;
+                               }
+                       }
+                       else
+                       {
+                               raptor.gun1.enemy = trace_ent;
+                               raptor.gun1.lock_time = time + 0.5;
+                       }
+               }
+
+               if(raptor.gun1.enemy)
+               {
+                       float distance, impact_time;
+
+                       vf = real_origin(raptor.gun1.enemy);
+                       UpdateAuxiliaryXhair(player, vf, '1 0 0', 1);
+                       vector _vel = raptor.gun1.enemy.velocity;
+                       if(raptor.gun1.enemy.movetype == MOVETYPE_WALK)
+                               _vel_z *= 0.1;
+
+                       if(autocvar_g_vehicle_raptor_cannon_predicttarget)
+                       {
+                               ad = vf;
+                               distance = vlen(ad - player.origin);
+                               impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
+                               ad = vf + _vel * impact_time;
+                               trace_endpos = ad;
+                       }
+                       else
+                               trace_endpos = vf;
+               }
+       }
+       else if(autocvar_g_vehicle_raptor_cannon_locktarget == 1)
+       {
+
+               vehicles_locktarget((1 / autocvar_g_vehicle_raptor_cannon_locking_time) * frametime,
+                                                        (1 / autocvar_g_vehicle_raptor_cannon_locking_releasetime) * frametime,
+                                                        autocvar_g_vehicle_raptor_cannon_locked_time);
+
+               if(self.lock_target != world)
+               if(autocvar_g_vehicle_raptor_cannon_predicttarget)
+               if(self.lock_strength == 1)
+               {
+                       float i, distance, impact_time;
+
+                       vf = real_origin(raptor.lock_target);
+                       ad = vf;
+                       for(i = 0; i < 4; ++i)
+                       {
+                               distance = vlen(ad - raptor.origin);
+                               impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
+                               ad = vf + raptor.lock_target.velocity * impact_time;
+                       }
+                       trace_endpos = ad;
+               }
+
+               if(self.lock_target)
+               {
+                       if(raptor.lock_strength == 1)
+                               UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '1 0 0', 1);
+                       else if(self.lock_strength > 0.5)
+                               UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 1 0', 1);
+                       else if(self.lock_strength < 0.5)
+                               UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 0 1', 1);
+               }
+       }
+
+
+       vehicle_aimturret(raptor, trace_endpos, raptor.gun1, "fire1",
+                                                 autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
+                                                 autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
+
+       vehicle_aimturret(raptor, trace_endpos, raptor.gun2, "fire1",
+                                                 autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
+                                                 autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
+
+       /*
+       ad = ad * 0.5;
+       v_forward = vf * 0.5;
+       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, raptor);
+       UpdateAuxiliaryXhair(player, trace_endpos, '0 1 0', 0);
+       */
+
+       Weapon wep1 = WEP_RAPTOR;
+       if(!forbidWeaponUse(player))
+       if(player.BUTTON_ATCK)
+       if (wep1.wr_checkammo1(wep1))
+       {
+               wep1.wr_think(wep1, self, true, false);
+       }
+
+       if(self.vehicle_flags  & VHF_SHIELDREGEN)
+               vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
+
+       if(self.vehicle_flags  & VHF_HEALTHREGEN)
+               vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
+
+       if(self.vehicle_flags  & VHF_ENERGYREGEN)
+               vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
+
+       Weapon wep2a = WEP_RAPTOR_BOMB;
+       if(!forbidWeaponUse(player))
+       if(raptor.vehicle_weapon2mode == RSM_BOMB)
+       {
+               if(time > raptor.lip + autocvar_g_vehicle_raptor_bombs_refire)
+               if(player.BUTTON_ATCK2)
+               {
+                       wep2a.wr_think(wep2a, self, false, true);
+                       raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
+                       raptor.lip   = time;
+               }
+       }
+       else
+       {
+               Weapon wep2b = WEP_RAPTOR_FLARE;
+               if(time > raptor.lip + autocvar_g_vehicle_raptor_flare_refire)
+               if(player.BUTTON_ATCK2)
+               {
+                       wep2b.wr_think(wep2b, self, false, true);
+                       raptor.delay = time + autocvar_g_vehicle_raptor_flare_refire;
+                       raptor.lip   = time;
+               }
+       }
+
+       raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
+       player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
+       player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
+
+       if(self.bomb1.cnt < time)
+       {
+               entity _missile = findchainentity(enemy, raptor);
+               float _incomming = 0;
+               while(_missile)
+               {
+                       if(_missile.flags & FL_PROJECTILE)
+                       if(MISSILE_IS_TRACKING(_missile))
+                       if(vlen(self.origin - _missile.origin) < 2 * autocvar_g_vehicle_raptor_flare_range)
+                               ++_incomming;
+
+                       _missile = _missile.chain;
+               }
+
+               if(_incomming)
+                       sound(self, CH_PAIN_SINGLE, SND_VEH_MISSILE_ALARM, VOL_BASE, ATTEN_NONE);
+
+               self.bomb1.cnt = time + 1;
+       }
+
+
+       VEHICLE_UPDATE_PLAYER(player, health, raptor);
+       VEHICLE_UPDATE_PLAYER(player, energy, raptor);
+       if(self.vehicle_flags & VHF_HASSHIELD)
+               VEHICLE_UPDATE_PLAYER(player, shield, raptor);
+
+       player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
+
+       setself(player);
+       return 1;
+}
+
+float raptor_takeoff()
+{SELFPARAM();
+       entity player, raptor;
+
+       player = self;
+       raptor = self.vehicle;
+       setself(raptor);
+
+       self.nextthink = time;
+       CSQCMODEL_AUTOUPDATE(self);
+       self.nextthink = 0; // will this work?
+
+       if(self.sound_nexttime < time)
+       {
+               self.sound_nexttime = time + 7.955812; //soundlength("vehicles/raptor_fly.wav");
+               sound (self, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_SPEED, VOL_VEHICLEENGINE, ATTEN_NORM);
+       }
+
+       // Takeoff sequense
+       if(raptor.frame < 25)
+       {
+               raptor.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / sys_frametime);
+               raptor.velocity_z = min(raptor.velocity_z * 1.5, 256);
+               self.bomb1.gun1.avelocity_y = 90 + ((raptor.frame / 25) * 25000);
+               self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
+               player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
+
+               setorigin(player, raptor.origin + '0 0 32');
+       }
+       else
+               player.PlayerPhysplug = raptor_frame;
+
+       if(self.vehicle_flags  & VHF_SHIELDREGEN)
+               vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
+
+       if(self.vehicle_flags  & VHF_HEALTHREGEN)
+               vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
+
+       if(self.vehicle_flags  & VHF_ENERGYREGEN)
+               vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
+
+
+       raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
+       player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
+       player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
+
+       VEHICLE_UPDATE_PLAYER(player, health, raptor);
+       VEHICLE_UPDATE_PLAYER(player, energy, raptor);
+       if(self.vehicle_flags & VHF_HASSHIELD)
+               VEHICLE_UPDATE_PLAYER(player, shield, raptor);
+
+       player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
+       setself(player);
+       return 1;
+}
+
+void raptor_blowup()
+{SELFPARAM();
+       self.deadflag   = DEAD_DEAD;
+       self.vehicle_exit(VHEF_NORMAL);
+       RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_RAPT_DEATH, world);
+
+       self.alpha                = -1;
+       self.movetype      = MOVETYPE_NONE;
+       self.effects            = EF_NODRAW;
+       self.colormod      = '0 0 0';
+       self.avelocity    = '0 0 0';
+       self.velocity      = '0 0 0';
+
+       setorigin(self, self.pos1);
+       self.touch = func_null;
+       self.nextthink = 0;
+}
+
+void raptor_diethink()
+{SELFPARAM();
+       if(time >= self.wait)
+               self.think = raptor_blowup;
+
+       if(random() < 0.05)
+       {
+               sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+               Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+       }
+       self.nextthink = time;
+
+       CSQCMODEL_AUTOUPDATE(self);
+}
+
+// If we dont do this ever now and then, the raptors rotors
+// stop working, presumably due to angle overflow. cute.
+void raptor_rotor_anglefix()
+{SELFPARAM();
+       self.gun1.angles_y = anglemods(self.gun1.angles_y);
+       self.gun2.angles_y = anglemods(self.gun2.angles_y);
+       self.nextthink = time + 15;
+}
+
+float raptor_impulse(float _imp)
+{SELFPARAM();
+       switch(_imp)
+       {
+               case 1:
+                       self.vehicle.vehicle_weapon2mode = RSM_BOMB;
+                       CSQCVehicleSetup(self, 0);
+                       return true;
+               case 2:
+                       self.vehicle.vehicle_weapon2mode = RSM_FLARE;
+                       CSQCVehicleSetup(self, 0);
+                       return true;
+
+               case 10:
+               case 15:
+               case 18:
+                       self.vehicle.vehicle_weapon2mode += 1;
+                       if(self.vehicle.vehicle_weapon2mode > RSM_LAST)
+                               self.vehicle.vehicle_weapon2mode = RSM_FIRST;
+
+                       CSQCVehicleSetup(self, 0);
+                       return true;
+               case 11:
+               case 12:
+               case 16:
+               case 19:
+                       self.vehicle.vehicle_weapon2mode -= 1;
+                       if(self.vehicle.vehicle_weapon2mode < RSM_FIRST)
+                               self.vehicle.vehicle_weapon2mode = RSM_LAST;
+
+                       CSQCVehicleSetup(self, 0);
+                       return true;
+
+               /*
+               case 17: // toss gun, could be used to exit?
+                       break;
+               case 20: // Manual minigun reload?
+                       break;
+               */
+       }
+       return false;
+}
+
+spawnfunc(vehicle_raptor)
+{
+       if(!autocvar_g_vehicle_raptor) { remove(self); return; }
+       if(!vehicle_initialize(VEH_RAPTOR, false)) { remove(self); return; }
+}
+
+               METHOD(Raptor, vr_impact, void(Raptor thisveh))
+               {
+                       if(autocvar_g_vehicle_raptor_bouncepain)
+                               vehicles_impact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z);
+               }
+               METHOD(Raptor, vr_enter, void(Raptor thisveh))
+               {
+                       self.vehicle_weapon2mode = RSM_BOMB;
+                       self.owner.PlayerPhysplug = raptor_takeoff;
+                       self.movetype      = MOVETYPE_BOUNCEMISSILE;
+                       self.solid                = SOLID_SLIDEBOX;
+                       self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_raptor_health) * 100;
+                       self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_raptor_shield) * 100;
+                       self.velocity_z = 1; // Nudge upwards to takeoff sequense can work.
+                       self.tur_head.exteriormodeltoclient = self.owner;
+
+                       self.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
+                       self.lip   = time;
+
+                       if(self.owner.flagcarried)
+                          setorigin(self.owner.flagcarried, '-20 0 96');
+
+                       CSQCVehicleSetup(self.owner, 0);
+               }
+               METHOD(Raptor, vr_death, void(Raptor thisveh))
+               {
+                       self.health                             = 0;
+                       self.event_damage               = func_null;
+                       self.solid                              = SOLID_CORPSE;
+                       self.takedamage                 = DAMAGE_NO;
+                       self.deadflag                   = DEAD_DYING;
+                       self.movetype                   = MOVETYPE_BOUNCE;
+                       self.think                              = raptor_diethink;
+                       self.nextthink                  = time;
+                       self.wait                               = time + 5 + (random() * 5);
+
+                       Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation (self.origin, 16), '0 0 0', 1);
+
+                       self.velocity_z += 600;
+
+                       self.avelocity = '0 0.5 1' * (random() * 400);
+                       self.avelocity -= '0 0.5 1' * (random() * 400);
+
+                       self.colormod = '-0.5 -0.5 -0.5';
+                       self.touch = raptor_blowup;
+               }
+               METHOD(Raptor, vr_spawn, void(Raptor thisveh))
+               {
+                       if(!self.gun1)
+                       {
+                               entity spinner;
+                               vector ofs;
+
+                               //FIXME: Camera is in a bad place in HUD model.
+                               //setorigin(self.vehicle_viewport, '25 0 5');
+
+                               self.vehicles_impulse   = raptor_impulse;
+
+                               self.frame = 0;
+
+                               self.bomb1 = spawn();
+                               self.bomb2 = spawn();
+                               self.gun1  = spawn();
+                               self.gun2  = spawn();
+
+                               setmodel(self.bomb1, MDL_VEH_RAPTOR_CB_FOLDED);
+                               setmodel(self.bomb2, MDL_VEH_RAPTOR_CB_FOLDED);
+                               setmodel(self.gun1, MDL_VEH_RAPTOR_GUN);
+                               setmodel(self.gun2, MDL_VEH_RAPTOR_GUN);
+                               setmodel(self.tur_head, MDL_VEH_RAPTOR_TAIL);
+
+                               setattachment(self.bomb1, self, "bombmount_left");
+                               setattachment(self.bomb2, self, "bombmount_right");
+                               setattachment(self.tur_head, self,"root");
+
+                               // FIXMODEL Guns mounts to angled bones
+                               self.bomb1.angles = self.angles;
+                               self.angles = '0 0 0';
+                               // This messes up gun-aim, so work arround it.
+                               //setattachment(self.gun1, self, "gunmount_left");
+                               ofs = gettaginfo(self, gettagindex(self, "gunmount_left"));
+                               ofs -= self.origin;
+                               setattachment(self.gun1, self, "");
+                               setorigin(self.gun1, ofs);
+
+                               //setattachment(self.gun2, self, "gunmount_right");
+                               ofs = gettaginfo(self, gettagindex(self, "gunmount_right"));
+                               ofs -= self.origin;
+                               setattachment(self.gun2, self, "");
+                               setorigin(self.gun2, ofs);
+
+                               self.angles = self.bomb1.angles;
+                               self.bomb1.angles = '0 0 0';
+
+                               spinner = spawn();
+                               spinner.owner = self;
+                               setmodel(spinner, MDL_VEH_RAPTOR_PROP);
+                               setattachment(spinner, self, "engine_left");
+                               spinner.movetype = MOVETYPE_NOCLIP;
+                               spinner.avelocity = '0 90 0';
+                               self.bomb1.gun1 = spinner;
+
+                               spinner = spawn();
+                               spinner.owner = self;
+                               setmodel(spinner, MDL_VEH_RAPTOR_PROP);
+                               setattachment(spinner, self, "engine_right");
+                               spinner.movetype = MOVETYPE_NOCLIP;
+                               spinner.avelocity = '0 -90 0';
+                               self.bomb1.gun2 = spinner;
+
+                               // Sigh.
+                               self.bomb1.think = raptor_rotor_anglefix;
+                               self.bomb1.nextthink = time;
+
+                               self.mass                          = 1 ;
+                       }
+
+                       self.frame                = 0;
+                       self.vehicle_health = autocvar_g_vehicle_raptor_health;
+                       self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
+                       self.movetype      = MOVETYPE_TOSS;
+                       self.solid                = SOLID_SLIDEBOX;
+                       self.vehicle_energy = 1;
+
+                       self.PlayerPhysplug = raptor_frame;
+
+                       self.bomb1.gun1.avelocity_y = 90;
+                       self.bomb1.gun2.avelocity_y = -90;
+
+                       self.delay = time;
+
+                       self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
+                       self.bouncestop = autocvar_g_vehicle_raptor_bouncestop;
+                       self.damageforcescale = 0.25;
+                       self.vehicle_health = autocvar_g_vehicle_raptor_health;
+                       self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
+               }
+               METHOD(Raptor, vr_setup, void(Raptor thisveh))
+               {
+                       if(autocvar_g_vehicle_raptor_shield)
+                               self.vehicle_flags |= VHF_HASSHIELD;
+
+                       if(autocvar_g_vehicle_raptor_shield_regen)
+                               self.vehicle_flags |= VHF_SHIELDREGEN;
+
+                       if(autocvar_g_vehicle_raptor_health_regen)
+                               self.vehicle_flags |= VHF_HEALTHREGEN;
+
+                       if(autocvar_g_vehicle_raptor_energy_regen)
+                               self.vehicle_flags |= VHF_ENERGYREGEN;
+
+                       self.vehicle_exit = raptor_exit;
+                       self.respawntime = autocvar_g_vehicle_raptor_respawntime;
+                       self.vehicle_health = autocvar_g_vehicle_raptor_health;
+                       self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
+                       self.max_health = self.vehicle_health;
+               }
+
+#endif
+#ifdef CSQC
+
+               METHOD(Raptor, vr_hud, void(Raptor thisveh))
+               {
+                       string crosshair;
+
+                       switch(weapon2mode)
+                       {
+                               case RSM_FLARE: crosshair = vCROSS_RAIN;  break;
+                               case RSM_BOMB:  crosshair = vCROSS_BURST; break;
+                               default:        crosshair = vCROSS_BURST;
+                       }
+
+                       Vehicles_drawHUD(VEH_RAPTOR.m_icon, "vehicle_raptor_weapon1", "vehicle_raptor_weapon2",
+                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+                                                        "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
+                                                        crosshair);
+               }
+               METHOD(Raptor, vr_setup, void(Raptor thisveh))
+               {
+                       AuxiliaryXhair[1].axh_image = vCROSS_LOCK;
+               }
+
+#endif
+#endif
diff --git a/qcsrc/common/vehicles/vehicle/raptor.qh b/qcsrc/common/vehicles/vehicle/raptor.qh
new file mode 100644 (file)
index 0000000..f24939b
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef RAPTOR_H
+#define RAPTOR_H
+
+const int RSM_FIRST = 1;
+const int RSM_BOMB = 1;
+const int RSM_FLARE = 2;
+const int RSM_LAST = 2;
+
+#endif
diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc
new file mode 100644 (file)
index 0000000..a5ddb7f
--- /dev/null
@@ -0,0 +1,312 @@
+#ifndef VEHICLE_RAPTOR_WEAPONS_H
+#define VEHICLE_RAPTOR_WEAPONS_H
+
+#include "../../weapons/all.qh"
+
+CLASS(RaptorCannon, PortoLaunch)
+/* flags     */ ATTRIB(RaptorCannon, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(RaptorCannon, impulse, int, 3);
+/* refname   */ ATTRIB(RaptorCannon, netname, string, "raptorcannon");
+/* wepname   */ ATTRIB(RaptorCannon, message, string, _("Raptor cannon"));
+ENDCLASS(RaptorCannon)
+REGISTER_WEAPON(RAPTOR, NEW(RaptorCannon));
+
+CLASS(RaptorBomb, PortoLaunch)
+/* flags     */ ATTRIB(RaptorBomb, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(RaptorBomb, impulse, int, 3);
+/* refname   */ ATTRIB(RaptorBomb, netname, string, "raptorbomb");
+/* wepname   */ ATTRIB(RaptorBomb, message, string, _("Raptor bomb"));
+ENDCLASS(RaptorBomb)
+REGISTER_WEAPON(RAPTOR_BOMB, NEW(RaptorBomb));
+
+CLASS(RaptorFlare, PortoLaunch)
+/* flags     */ ATTRIB(RaptorFlare, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(RaptorFlare, impulse, int, 3);
+/* refname   */ ATTRIB(RaptorFlare, netname, string, "raptorflare");
+/* wepname   */ ATTRIB(RaptorFlare, message, string, _("Raptor flare"));
+ENDCLASS(RaptorFlare)
+REGISTER_WEAPON(RAPTOR_FLARE, NEW(RaptorFlare));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_raptor_cannon_cost;
+float autocvar_g_vehicle_raptor_cannon_damage;
+float autocvar_g_vehicle_raptor_cannon_radius;
+float autocvar_g_vehicle_raptor_cannon_refire;
+float autocvar_g_vehicle_raptor_cannon_speed;
+float autocvar_g_vehicle_raptor_cannon_spread;
+float autocvar_g_vehicle_raptor_cannon_force;
+
+float autocvar_g_vehicle_raptor_bomblets;
+float autocvar_g_vehicle_raptor_bomblet_alt;
+float autocvar_g_vehicle_raptor_bomblet_time;
+float autocvar_g_vehicle_raptor_bomblet_damage;
+float autocvar_g_vehicle_raptor_bomblet_spread;
+float autocvar_g_vehicle_raptor_bomblet_edgedamage;
+float autocvar_g_vehicle_raptor_bomblet_radius;
+float autocvar_g_vehicle_raptor_bomblet_force;
+float autocvar_g_vehicle_raptor_bomblet_explode_delay;
+
+METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+    bool isPlayer = IS_PLAYER(actor);
+    entity player = isPlayer ? actor : actor.owner;
+    entity veh = player.vehicle;
+    // 1 [wait] 1 [wait] 2 [wait] 2 [wait] [wait]
+    float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + veh.misc_bulletcounter == 4);
+    if (fire1)
+    if (weapon_prepareattack(thiswep, player, false, t)) {
+        if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
+        vector org = w_shotorg;
+        vector dir = w_shotdir;
+        if (veh) {
+            veh.misc_bulletcounter += 1;
+            org = (veh.misc_bulletcounter <= 2) ? gettaginfo(veh.gun1, gettagindex(veh.gun1, "fire1"))
+              : (((veh.misc_bulletcounter == 4) ? veh.misc_bulletcounter = 0 : 0), gettaginfo(veh.gun2, gettagindex(veh.gun2, "fire1")));
+            dir = v_forward;
+            veh.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost;
+            actor.cnt = time;
+        }
+        vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
+                               org, normalize(dir + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
+                               autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force,  0,
+                               DEATH_VH_RAPT_CANNON, PROJECTILE_RAPTORCANNON, 0, true, true, player);
+        weapon_thinkf(player, WFRAME_FIRE1, 0, w_ready);
+    }
+}
+METHOD(RaptorCannon, wr_checkammo1, bool(RacerAttack thiswep)) {
+    SELFPARAM();
+    bool isPlayer = IS_PLAYER(self);
+    entity player = isPlayer ? self : self.owner;
+    entity veh = player.vehicle;
+    return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_raptor_cannon_cost;
+}
+
+float autocvar_g_vehicle_raptor_bombs_refire;
+
+void raptor_bombdrop();
+METHOD(RaptorBomb, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+    bool isPlayer = IS_PLAYER(actor);
+    entity player = isPlayer ? actor : actor.owner;
+    entity veh = player.vehicle;
+    if (fire2)
+    if (!isPlayer || weapon_prepareattack(thiswep, player, true, autocvar_g_vehicle_raptor_bombs_refire)) {
+        if (veh) setself(veh);
+        raptor_bombdrop();
+        weapon_thinkf(player, WFRAME_FIRE2, 0, w_ready);
+    }
+}
+
+float autocvar_g_vehicle_raptor_flare_refire;
+float autocvar_g_vehicle_raptor_flare_lifetime;
+float autocvar_g_vehicle_raptor_flare_chase;
+float autocvar_g_vehicle_raptor_flare_range;
+
+void raptor_flare_think();
+void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
+void raptor_flare_touch();
+
+METHOD(RaptorFlare, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2)) {
+    bool isPlayer = IS_PLAYER(actor);
+    entity player = isPlayer ? actor : actor.owner;
+    entity veh = player.vehicle;
+    if (fire2)
+    if (!isPlayer || weapon_prepareattack(thiswep, player, true, autocvar_g_vehicle_raptor_flare_refire)) {
+        for(int i = 0; i < 3; ++i) {
+            entity _flare = spawn();
+            setmodel(_flare, MDL_VEH_RAPTOR_FLARE);
+            _flare.effects = EF_LOWPRECISION | EF_FLAME;
+            _flare.scale = 0.5;
+            setorigin(_flare, actor.origin - '0 0 16');
+            _flare.movetype = MOVETYPE_TOSS;
+            _flare.gravity = 0.15;
+            _flare.velocity = 0.25 * actor.velocity + (v_forward + randomvec() * 0.25)* -500;
+            _flare.think = raptor_flare_think;
+            _flare.nextthink = time;
+            _flare.owner = veh ? veh : player;
+            _flare.solid = SOLID_CORPSE;
+            _flare.takedamage = DAMAGE_YES;
+            _flare.event_damage = raptor_flare_damage;
+            _flare.health = 20;
+            _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime;
+            _flare.touch = raptor_flare_touch;
+        }
+        weapon_thinkf(player, WFRAME_FIRE2, 0, w_ready);
+    }
+}
+
+
+void raptor_bomblet_boom()
+{SELFPARAM();
+    RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage,
+                                    autocvar_g_vehicle_raptor_bomblet_edgedamage,
+                                    autocvar_g_vehicle_raptor_bomblet_radius, world, world,
+                                    autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world);
+    remove(self);
+}
+
+void raptor_bomblet_touch()
+{SELFPARAM();
+    if(other == self.owner)
+        return;
+
+    PROJECTILE_TOUCH;
+    self.think = raptor_bomblet_boom;
+    self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay;
+}
+
+void raptor_bomb_burst()
+{SELFPARAM();
+    if(self.cnt > time)
+    if(autocvar_g_vehicle_raptor_bomblet_alt)
+    {
+        self.nextthink = time;
+        traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self);
+        if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius))
+        {
+            UpdateCSQCProjectile(self);
+            return;
+        }
+    }
+
+    entity bomblet;
+    float i;
+
+    Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT, 0, self);
+
+    for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i)
+    {
+        bomblet = spawn();
+        setorigin(bomblet, self.origin);
+
+        bomblet.movetype       = MOVETYPE_TOSS;
+        bomblet.touch     = raptor_bomblet_touch;
+        bomblet.think     = raptor_bomblet_boom;
+        bomblet.nextthink   = time + 5;
+        bomblet.owner     = self.owner;
+        bomblet.realowner   = self.realowner;
+        bomblet.velocity       = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity);
+
+        PROJECTILE_MAKETRIGGER(bomblet);
+        CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true);
+    }
+
+    remove(self);
+}
+
+void raptor_bombdrop()
+{SELFPARAM();
+    entity bomb_1, bomb_2;
+
+    bomb_1 = spawn();
+    bomb_2 = spawn();
+
+    setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left")));
+    setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right")));
+
+    bomb_1.movetype     = bomb_2.movetype   = MOVETYPE_BOUNCE;
+    bomb_1.velocity     = bomb_2.velocity   = self.velocity;
+    bomb_1.touch               = bomb_2.touch    = raptor_bomb_burst;
+    bomb_1.think               = bomb_2.think    = raptor_bomb_burst;
+    bomb_1.cnt           = bomb_2.cnt          = time + 10;
+
+    if(autocvar_g_vehicle_raptor_bomblet_alt)
+        bomb_1.nextthink = bomb_2.nextthink  = time;
+    else
+        bomb_1.nextthink = bomb_2.nextthink  = time + autocvar_g_vehicle_raptor_bomblet_time;
+
+    bomb_1.owner        = bomb_2.owner   = self;
+    bomb_1.realowner = bomb_2.realowner  = self.owner;
+    bomb_1.solid        = bomb_2.solid   = SOLID_BBOX;
+    bomb_1.gravity   = bomb_2.gravity  = 1;
+
+    PROJECTILE_MAKETRIGGER(bomb_1);
+    PROJECTILE_MAKETRIGGER(bomb_2);
+
+    CSQCProjectile(bomb_1, true, PROJECTILE_RAPTORBOMB, true);
+    CSQCProjectile(bomb_2, true, PROJECTILE_RAPTORBOMB, true);
+}
+
+void raptor_flare_touch()
+{SELFPARAM();
+    remove(self);
+}
+
+void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{SELFPARAM();
+    self.health -= damage;
+    if(self.health <= 0)
+        remove(self);
+}
+
+void raptor_flare_think()
+{SELFPARAM();
+    self.nextthink = time + 0.1;
+    entity _missile = findchainentity(enemy, self.owner);
+    while(_missile)
+    {
+        if(_missile.flags & FL_PROJECTILE)
+        if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range)
+        if(random() > autocvar_g_vehicle_raptor_flare_chase)
+            _missile.enemy = self;
+        _missile = _missile.chain;
+    }
+
+    if(self.tur_impacttime < time)
+        remove(self);
+}
+
+#endif
+
+#ifdef CSQC
+
+void RaptorCBShellfragDraw(entity this)
+{
+    if(wasfreed(self))
+        return;
+
+    Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
+    self.move_avelocity += randomvec() * 15;
+    self.renderflags = 0;
+
+    if(self.cnt < time)
+        self.alpha = bound(0, self.nextthink - time, 1);
+
+    if(self.alpha < ALPHA_MIN_VISIBLE)
+        remove(self);
+}
+
+void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
+{SELFPARAM();
+    entity sfrag;
+
+    sfrag = spawn();
+    setmodel(sfrag, MDL_VEH_RAPTOR_CB_FRAGMENT);
+    setorigin(sfrag, _org);
+
+    sfrag.move_movetype = MOVETYPE_BOUNCE;
+    sfrag.gravity = 0.15;
+    sfrag.solid = SOLID_CORPSE;
+
+    sfrag.draw = RaptorCBShellfragDraw;
+
+    sfrag.move_origin = sfrag.origin = _org;
+    sfrag.move_velocity = _vel;
+    sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
+    sfrag.angles = self.move_angles = _ang;
+
+    sfrag.move_time = time;
+    sfrag.damageforcescale = 4;
+
+    sfrag.nextthink = time + 3;
+    sfrag.cnt = time + 2;
+    sfrag.alpha = 1;
+    sfrag.drawmask = MASK_NORMAL;
+}
+
+#endif
+
+#endif
diff --git a/qcsrc/common/vehicles/vehicle/spiderbot.qc b/qcsrc/common/vehicles/vehicle/spiderbot.qc
new file mode 100644 (file)
index 0000000..ee79966
--- /dev/null
@@ -0,0 +1,671 @@
+#ifndef VEHICLE_SPIDERBOT
+#define VEHICLE_SPIDERBOT
+
+#include "spiderbot_weapons.qc"
+
+CLASS(Spiderbot, Vehicle)
+/* spawnflags */ ATTRIB(Spiderbot, spawnflags, int, VHF_DMGSHAKE);
+/* mins       */ ATTRIB(Spiderbot, mins, vector, '-75 -75 10');
+/* maxs       */ ATTRIB(Spiderbot, maxs, vector, '75 75 125');
+/* model         */ ATTRIB(Spiderbot, mdl, string, "models/vehicles/spiderbot.dpm");
+/* model         */ ATTRIB(Spiderbot, model, string, "models/vehicles/spiderbot.dpm");
+/* head_model */ ATTRIB(Spiderbot, head_model, string, "models/vehicles/spiderbot_top.dpm");
+/* hud_model  */ ATTRIB(Spiderbot, hud_model, string, "models/vehicles/spiderbot_cockpit.dpm");
+/* tags       */ ATTRIB(Spiderbot, tag_head, string, "tag_head");
+/* tags       */ ATTRIB(Spiderbot, tag_hud, string, "tag_hud");
+/* tags       */ ATTRIB(Spiderbot, tag_view, string, "");
+/* netname    */ ATTRIB(Spiderbot, netname, string, "spiderbot");
+/* fullname   */ ATTRIB(Spiderbot, vehicle_name, string, _("Spiderbot"));
+/* icon       */ ATTRIB(Spiderbot, m_icon, string, "vehicle_spider");
+ENDCLASS(Spiderbot)
+
+REGISTER_VEHICLE(SPIDERBOT, NEW(Spiderbot));
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+const int SBRM_FIRST = 1;
+const int SBRM_VOLLY = 1;
+const int SBRM_GUIDE = 2;
+const int SBRM_ARTILLERY = 3;
+const int SBRM_LAST = 3;
+
+#include "spiderbot_weapons.qc"
+
+#ifdef SVQC
+bool autocvar_g_vehicle_spiderbot;
+
+float autocvar_g_vehicle_spiderbot_respawntime;
+
+float autocvar_g_vehicle_spiderbot_speed_stop;
+float autocvar_g_vehicle_spiderbot_speed_strafe;
+float autocvar_g_vehicle_spiderbot_speed_walk;
+float autocvar_g_vehicle_spiderbot_speed_run = 700;
+float autocvar_g_vehicle_spiderbot_turnspeed;
+float autocvar_g_vehicle_spiderbot_turnspeed_strafe;
+float autocvar_g_vehicle_spiderbot_movement_inertia;
+
+float autocvar_g_vehicle_spiderbot_springlength;
+float autocvar_g_vehicle_spiderbot_springup;
+float autocvar_g_vehicle_spiderbot_springblend;
+float autocvar_g_vehicle_spiderbot_tiltlimit;
+
+float autocvar_g_vehicle_spiderbot_head_pitchlimit_down;
+float autocvar_g_vehicle_spiderbot_head_pitchlimit_up;
+float autocvar_g_vehicle_spiderbot_head_turnlimit;
+float autocvar_g_vehicle_spiderbot_head_turnspeed;
+
+int autocvar_g_vehicle_spiderbot_health;
+float autocvar_g_vehicle_spiderbot_health_regen;
+float autocvar_g_vehicle_spiderbot_health_regen_pause;
+
+int autocvar_g_vehicle_spiderbot_shield;
+float autocvar_g_vehicle_spiderbot_shield_regen;
+float autocvar_g_vehicle_spiderbot_shield_regen_pause;
+
+vector autocvar_g_vehicle_spiderbot_bouncepain;
+
+.float jump_delay;
+float spiderbot_frame()
+{SELFPARAM();
+       vector ad, vf;
+       entity player, spider;
+       float ftmp;
+
+       if(intermission_running)
+       {
+               self.vehicle.velocity = '0 0 0';
+               self.vehicle.avelocity = '0 0 0';
+               return 1;
+       }
+
+       player = self;
+       spider = self.vehicle;
+       setself(spider);
+
+       vehicles_painframe();
+
+       player.BUTTON_ZOOM        = 0;
+       player.BUTTON_CROUCH    = 0;
+       player.switchweapon      = 0;
+       player.vehicle_weapon2mode = spider.vehicle_weapon2mode;
+
+
+#if 1 // 0 to enable per-gun impact aux crosshairs
+       // Avarage gun impact point's -> aux cross
+       ad = gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint01"));
+       vf = v_forward;
+       ad += gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint02"));
+       vf += v_forward;
+       ad = ad * 0.5;
+       v_forward = vf * 0.5;
+       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
+       UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
+#else
+       ad = gettaginfo(spider.gun1, gettagindex(spider.gun1, "barrels"));
+       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
+       UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
+       vf = ad;
+       ad = gettaginfo(spider.gun2, gettagindex(spider.gun2, "barrels"));
+       traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
+       UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 1);
+       ad = 0.5 * (ad + vf);
+#endif
+
+       crosshair_trace(player);
+       ad = vectoangles(normalize(trace_endpos - ad));
+       ad = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(spider.angles), AnglesTransform_FromAngles(ad))) - spider.tur_head.angles;
+       ad = AnglesTransform_Normalize(ad, true);
+       //UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload2) + ('0 1 0' * (1 - player.vehicle_reload2)), 2);
+
+       // Rotate head
+       ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime;
+       ad_y = bound(-ftmp, ad_y, ftmp);
+       spider.tur_head.angles_y = bound(autocvar_g_vehicle_spiderbot_head_turnlimit * -1, spider.tur_head.angles_y + ad_y, autocvar_g_vehicle_spiderbot_head_turnlimit);
+
+       // Pitch head
+       ad_x = bound(ftmp * -1, ad_x, ftmp);
+       spider.tur_head.angles_x = bound(autocvar_g_vehicle_spiderbot_head_pitchlimit_down, spider.tur_head.angles_x + ad_x, autocvar_g_vehicle_spiderbot_head_pitchlimit_up);
+
+
+       //fixedmakevectors(spider.angles);
+       makevectors(spider.angles + '-2 0 0' * spider.angles_x);
+
+       movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend, autocvar_g_vehicle_spiderbot_tiltlimit);
+
+       if(spider.flags & FL_ONGROUND)
+               spider.jump_delay = time; // reset now so movement can begin
+
+       //if(spider.flags & FL_ONGROUND)
+       {
+               if(spider.flags & FL_ONGROUND)
+               if(spider.frame == 4 && self.tur_head.wait != 0)
+               {
+                       sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_LAND, VOL_VEHICLEENGINE, ATTEN_NORM);
+                       spider.frame = 5;
+               }
+
+               if(!player.BUTTON_JUMP)
+                       spider.BUTTON_JUMP = 0;
+
+               if((spider.flags & FL_ONGROUND) && player.BUTTON_JUMP && !spider.BUTTON_JUMP && self.tur_head.wait < time)
+               {
+                       sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_JUMP, VOL_VEHICLEENGINE, ATTEN_NORM);
+                       //dprint("spiderbot_jump:", ftos(soundlength("vehicles/spiderbot_jump.wav")), "\n");
+                       self.delay = 0;
+
+                       self.tur_head.wait = time + 2;
+                       spider.jump_delay = time + 2;
+                       spider.BUTTON_JUMP = 1; // set spider's jump
+                       //player.BUTTON_JUMP = 0;
+
+                       vector movefix = '0 0 0';
+                       if(player.movement_x > 0) movefix_x = 1;
+                       if(player.movement_x < 0) movefix_x = -1;
+                       if(player.movement_y > 0) movefix_y = 1;
+                       if(player.movement_y < 0) movefix_y = -1;
+
+                       vector rt = movefix_y * v_right;
+                       vector sd = movefix_x * v_forward;
+                       if(movefix_y == 0 && movefix_x == 0)
+                               sd = v_forward; // always do forward
+
+                       spider.flags &= ~FL_ONGROUND;
+
+                       spider.velocity = sd * 700 + rt * 600 + v_up * 600;
+                       spider.frame = 4;
+               }
+               else if(time >= spider.jump_delay)
+               {
+                       if(vlen(player.movement) == 0)
+                       {
+                               if(spider.flags & FL_ONGROUND)
+                               {
+                                       if(self.sound_nexttime < time || self.delay != 3)
+                                       {
+                                               self.delay = 3;
+                                               self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_idle.wav");
+                                               //dprint("spiderbot_idle:", ftos(soundlength("vehicles/spiderbot_idle.wav")), "\n");
+                                               sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_IDLE, VOL_VEHICLEENGINE, ATTEN_NORM);
+                                       }
+                                       movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
+                                       spider.frame = 5;
+                               }
+                       }
+                       else
+                       {
+                               // Turn Body
+                               if(player.movement_x == 0 && player.movement_y != 0)
+                                       ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * sys_frametime;
+                               else
+                                       ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime;
+
+                               ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp);
+                               spider.angles_y = anglemods(spider.angles_y + ftmp);
+                               spider.tur_head.angles_y -= ftmp;
+
+                               if(player.movement_x != 0)
+                               {
+                                       if(player.movement_x > 0)
+                                       {
+                                               player.movement_x = 1;
+                                               if(spider.flags & FL_ONGROUND)
+                                                       spider.frame = 0;
+                                       }
+                                       else if(player.movement_x < 0)
+                                       {
+                                               player.movement_x = -1;
+                                               if(spider.flags & FL_ONGROUND)
+                                                       spider.frame = 1;
+                                       }
+                                       player.movement_y = 0;
+                                       float oldvelz = spider.velocity_z;
+                                       movelib_move_simple(normalize(v_forward * player.movement_x),((player.BUTTON_JUMP) ? autocvar_g_vehicle_spiderbot_speed_run : autocvar_g_vehicle_spiderbot_speed_walk),autocvar_g_vehicle_spiderbot_movement_inertia);
+                                       spider.velocity_z = oldvelz;
+                                       float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
+                                       if(spider.velocity_z <= 20) // not while jumping
+                                               spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
+                                       if(spider.flags & FL_ONGROUND)
+                                       if(self.sound_nexttime < time || self.delay != 1)
+                                       {
+                                               self.delay = 1;
+                                               self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_walk.wav");
+                                               sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_WALK, VOL_VEHICLEENGINE, ATTEN_NORM);
+                                               //dprint("spiderbot_walk:", ftos(soundlength("vehicles/spiderbot_walk.wav")), "\n");
+                                       }
+                               }
+                               else if(player.movement_y != 0)
+                               {
+                                       if(player.movement_y < 0)
+                                       {
+                                               player.movement_y = -1;
+                                               if(spider.flags & FL_ONGROUND)
+                                                       spider.frame = 2;
+                                       }
+                                       else if(player.movement_y > 0)
+                                       {
+                                               player.movement_y = 1;
+                                               if(spider.flags & FL_ONGROUND)
+                                                       spider.frame = 3;
+                                       }
+
+                                       float oldvelz = spider.velocity_z;
+                                       movelib_move_simple(normalize(v_right * player.movement_y),autocvar_g_vehicle_spiderbot_speed_strafe,autocvar_g_vehicle_spiderbot_movement_inertia);
+                                       spider.velocity_z = oldvelz;
+                                       float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
+                                       if(spider.velocity_z <= 20) // not while jumping
+                                               spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
+                                       if(spider.flags & FL_ONGROUND)
+                                       if(self.sound_nexttime < time || self.delay != 2)
+                                       {
+                                               self.delay = 2;
+                                               self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_strafe.wav");
+                                               sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_STRAFE, VOL_VEHICLEENGINE, ATTEN_NORM);
+                                               //dprint("spiderbot_strafe:", ftos(soundlength("vehicles/spiderbot_strafe.wav")), "\n");
+                                       }
+                               }
+                       }
+               }
+       }
+
+       self.angles_x = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_x, autocvar_g_vehicle_spiderbot_tiltlimit);
+       self.angles_z = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_z, autocvar_g_vehicle_spiderbot_tiltlimit);
+
+       if(!forbidWeaponUse(player))
+       if(player.BUTTON_ATCK)
+       {
+               spider.cnt = time;
+               if(spider.vehicle_ammo1 >= autocvar_g_vehicle_spiderbot_minigun_ammo_cost && spider.tur_head.attack_finished_single <= time)
+               {
+                       entity gun;
+                       vector v;
+                       spider.misc_bulletcounter += 1;
+
+                       setself(player);
+
+                       gun = (spider.misc_bulletcounter % 2) ? spider.gun1 : spider.gun2;
+
+                       v = gettaginfo(gun, gettagindex(gun, "barrels"));
+                       v_forward = normalize(v_forward);
+                       v += v_forward * 50;
+
+                       fireBullet(v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration,
+                                autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN, 0);
+
+                       sound (gun, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
+                       //trailparticles(self, _particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
+                       pointparticles(particleeffectnum(EFFECT_SPIDERBOT_MINIGUN_MUZZLEFLASH), v, v_forward * 2500, 1);
+
+                       setself(spider);
+
+                       spider.vehicle_ammo1 -= autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
+                       spider.tur_head.attack_finished_single = time + autocvar_g_vehicle_spiderbot_minigun_refire;
+                       player.vehicle_ammo1 = (spider.vehicle_ammo1 / autocvar_g_vehicle_spiderbot_minigun_ammo_max) * 100;
+                       spider.gun1.angles_z += 45;
+                       spider.gun2.angles_z -= 45;
+                       if(spider.gun1.angles_z >= 360)
+                       {
+                               spider.gun1.angles_z = 0;
+                               spider.gun2.angles_z = 0;
+                       }
+               }
+       }
+       else
+               vehicles_regen(spider.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);
+
+
+       spiderbot_rocket_do();
+
+       if(self.vehicle_flags  & VHF_SHIELDREGEN)
+               vehicles_regen(spider.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime, true);
+
+       if(self.vehicle_flags  & VHF_HEALTHREGEN)
+               vehicles_regen(spider.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime, false);
+
+       player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+       //player.vehicle_ammo2 = spider.tur_head.frame;
+       player.vehicle_ammo2 = (9 - spider.tur_head.frame) / 8 * 100; // Percentage, like ammo1
+
+       if(spider.gun2.cnt <= time)
+               player.vehicle_reload2 = 100;
+       else
+               player.vehicle_reload2 = 100 - ((spider.gun2.cnt - time) / spider.attack_finished_single) * 100;
+
+       setorigin(player, spider.origin + '0 0 1' * spider.maxs_z);
+       player.velocity = spider.velocity;
+
+       VEHICLE_UPDATE_PLAYER(player, health, spiderbot);
+
+       if(self.vehicle_flags & VHF_HASSHIELD)
+               VEHICLE_UPDATE_PLAYER(player, shield, spiderbot);
+
+       setself(player);
+       return 1;
+}
+
+void spiderbot_exit(float eject)
+{SELFPARAM();
+       entity e;
+       vector spot;
+
+       e = findchain(classname,"spiderbot_rocket");
+       while(e)
+       {
+               if(e.owner == self.owner)
+               {
+                       e.realowner = self.owner;
+                       e.owner = world;
+               }
+               e = e.chain;
+       }
+
+       self.think = vehicles_think;
+       self.nextthink = time;
+       self.frame = 5;
+       self.movetype = MOVETYPE_WALK;
+
+       if(!self.owner)
+               return;
+
+       makevectors(self.angles);
+       if(eject)
+       {
+               spot = self.origin + v_forward * 100 + '0 0 64';
+               spot = vehicles_findgoodexit(spot);
+               setorigin(self.owner , spot);
+               self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+               self.owner.oldvelocity = self.owner.velocity;
+       }
+       else
+       {
+               if(vlen(self.velocity) > autocvar_g_vehicle_spiderbot_speed_strafe)
+               {
+                       self.owner.velocity = normalize(self.velocity) * vlen(self.velocity);
+                       self.owner.velocity_z += 200;
+                       spot = self.origin + v_forward * 128 + '0 0 64';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               else
+               {
+                       self.owner.velocity = self.velocity * 0.5;
+                       self.owner.velocity_z += 10;
+                       spot = self.origin + v_forward * 256 + '0 0 64';
+                       spot = vehicles_findgoodexit(spot);
+               }
+               self.owner.oldvelocity = self.owner.velocity;
+               setorigin(self.owner , spot);
+       }
+
+       antilag_clear(self.owner);
+       self.owner = world;
+}
+
+void spiderbot_headfade()
+{SELFPARAM();
+       self.think = spiderbot_headfade;
+       self.nextthink = self.fade_time;
+       self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
+
+       if(self.cnt < time || self.alpha < 0.1)
+       {
+               if(self.alpha > 0.1)
+               {
+                       sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+                       Send_Effect(EFFECT_EXPLOSION_BIG, self.origin + '0 0 100', '0 0 0', 1);
+               }
+               remove(self);
+       }
+}
+
+void spiderbot_blowup()
+{SELFPARAM();
+       if(self.cnt > time)
+       {
+               if(random() < 0.1)
+               {
+                       sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
+                       Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
+               }
+               self.nextthink = time + 0.1;
+               return;
+       }
+
+       entity h, g1, g2, b;
+       b = spawn();
+       h = spawn();
+       g1 = spawn();
+       g2 = spawn();
+
+       setmodel(b, MDL_VEH_SPIDERBOT_BODY);
+       setmodel(h, MDL_VEH_SPIDERBOT_TOP);
+       setmodel(g1, MDL_VEH_SPIDERBOT_GUN);
+       setmodel(g2, MDL_VEH_SPIDERBOT_GUN);
+
+       setorigin(b, self.origin);
+       b.frame = 11;
+       b.angles = self.angles;
+       setsize(b, self.mins, self.maxs);
+
+       setorigin(h, gettaginfo(self, gettagindex(self, "tag_head")));
+       h.movetype = MOVETYPE_BOUNCE;
+       h.solid = SOLID_BBOX;
+       h.velocity = v_up * (500 + random() * 500) + randomvec() * 128;
+       h.modelflags = MF_ROCKET;
+       h.effects = EF_FLAME | EF_LOWPRECISION;
+       h.avelocity = randomvec() * 360;
+
+       h.alpha = 1;
+       h.cnt = time + (3.5 * random());
+       h.fade_rate = 1 / min(self.respawntime, 10);
+       h.fade_time = time;
+       h.think = spiderbot_headfade;
+       h.nextthink = time;
+
+       setorigin(g1, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint01")));
+       g1.movetype = MOVETYPE_TOSS;
+       g1.solid = SOLID_CORPSE;
+       g1.velocity = v_forward * 700 + (randomvec() * 32);
+       g1.avelocity = randomvec() * 180;
+
+       setorigin(g2, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint02")));
+       g2.movetype = MOVETYPE_TOSS;
+       g2.solid = SOLID_CORPSE;
+       g2.velocity = v_forward * 700 + (randomvec() * 32);
+       g2.avelocity = randomvec() * 180;
+
+       h.colormod = b.colormod = g1.colormod = g2.colormod = '-2 -2 -2';
+
+       SUB_SetFade(b,  time + 5, min(self.respawntime, 1));
+       //SUB_SetFade(h,  time, min(self.respawntime, 10));
+       SUB_SetFade(g1, time, min(self.respawntime, 10));
+       SUB_SetFade(g2, time, min(self.respawntime, 10));
+
+       RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_SPID_DEATH, world);
+
+       self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
+       self.movetype = MOVETYPE_NONE;
+       self.deadflag = DEAD_DEAD;
+       self.solid = SOLID_NOT;
+       self.tur_head.effects &= ~EF_FLAME;
+       self.vehicle_hudmodel.viewmodelforclient = self;
+}
+
+bool spiderbot_impulse(int _imp)
+{SELFPARAM();
+       switch(_imp)
+       {
+               case 1:
+                       self.vehicle.vehicle_weapon2mode = SBRM_VOLLY;
+                       CSQCVehicleSetup(self, 0);
+                       return true;
+               case 2:
+                       self.vehicle.vehicle_weapon2mode = SBRM_GUIDE;
+                       CSQCVehicleSetup(self, 0);
+                       return true;
+               case 3:
+                       self.vehicle.vehicle_weapon2mode = SBRM_ARTILLERY;
+                       CSQCVehicleSetup(self, 0);
+                       return true;
+
+               case 10:
+               case 15:
+               case 18:
+                       self.vehicle.vehicle_weapon2mode += 1;
+                       if(self.vehicle.vehicle_weapon2mode > SBRM_LAST)
+                               self.vehicle.vehicle_weapon2mode = SBRM_FIRST;
+
+                       //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
+                       CSQCVehicleSetup(self, 0);
+                       return true;
+               case 11:
+               case 12:
+               case 16:
+               case 19:
+                       self.vehicle.vehicle_weapon2mode -= 1;
+                       if(self.vehicle.vehicle_weapon2mode < SBRM_FIRST)
+                               self.vehicle.vehicle_weapon2mode = SBRM_LAST;
+
+                       //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
+                       CSQCVehicleSetup(self, 0);
+                       return true;
+
+               /*
+               case 17: // toss gun, could be used to exit?
+                       break;
+               case 20: // Manual minigun reload?
+                       break;
+               */
+       }
+       return false;
+}
+
+spawnfunc(vehicle_spiderbot)
+{
+       if(!autocvar_g_vehicle_spiderbot) { remove(self); return; }
+       if(!vehicle_initialize(VEH_SPIDERBOT, false)) { remove(self); return; }
+}
+
+               METHOD(Spiderbot, vr_impact, void(Spiderbot thisveh))
+               {
+                       if(autocvar_g_vehicle_spiderbot_bouncepain)
+                               vehicles_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z);
+               }
+               METHOD(Spiderbot, vr_enter, void(Spiderbot thisveh))
+               {
+                       self.vehicle_weapon2mode = SBRM_GUIDE;
+                       self.movetype = MOVETYPE_WALK;
+                       CSQCVehicleSetup(self.owner, 0);
+                       self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100;
+                       self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100;
+
+                       if(self.owner.flagcarried)
+                       {
+                               setattachment(self.owner.flagcarried, self.tur_head, "");
+                               setorigin(self.owner.flagcarried, '-20 0 120');
+                       }
+               }
+               METHOD(Spiderbot, vr_think, void(Spiderbot thisveh))
+               {
+                       if(self.flags & FL_ONGROUND)
+                               movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
+               }
+               METHOD(Spiderbot, vr_death, void(Spiderbot thisveh))
+               {
+                       self.health                             = 0;
+                       self.event_damage               = func_null;
+                       self.takedamage                 = DAMAGE_NO;
+                       self.touch                              = func_null;
+                       self.cnt                                = 3.4 + time + random() * 2;
+                       self.think                              = spiderbot_blowup;
+                       self.nextthink                  = time;
+                       self.deadflag                   = DEAD_DYING;
+                       self.frame                              = 5;
+                       self.tur_head.effects  |= EF_FLAME;
+                       self.colormod                   = self.tur_head.colormod = '-1 -1 -1';
+                       self.frame                              = 10;
+                       self.movetype                   = MOVETYPE_TOSS;
+
+                       CSQCModel_UnlinkEntity(self); // networking the death scene would be a nightmare
+               }
+               METHOD(Spiderbot, vr_spawn, void(Spiderbot thisveh))
+               {
+                       if(!self.gun1)
+                       {
+                               self.vehicles_impulse = spiderbot_impulse;
+                               self.gun1 = spawn();
+                               self.gun2 = spawn();
+                               setmodel(self.gun1, MDL_VEH_SPIDERBOT_GUN);
+                               setmodel(self.gun2, MDL_VEH_SPIDERBOT_GUN);
+                               setattachment(self.gun1, self.tur_head, "tag_hardpoint01");
+                               setattachment(self.gun2, self.tur_head, "tag_hardpoint02");
+                               self.gravity = 2;
+                               self.mass = 5000;
+                       }
+
+                       self.frame = 5;
+                       self.tur_head.frame = 1;
+                       self.movetype = MOVETYPE_WALK;
+                       self.solid = SOLID_SLIDEBOX;
+                       self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
+                       self.tur_head.angles = '0 0 0';
+                       self.vehicle_exit = spiderbot_exit;
+
+                       setorigin(self, self.pos1 + '0 0 128');
+                       self.angles = self.pos2;
+                       self.damageforcescale = 0.03;
+                       self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
+                       self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
+
+                       self.PlayerPhysplug = spiderbot_frame;
+               }
+               METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh))
+               {
+                       if(autocvar_g_vehicle_spiderbot_shield)
+                               self.vehicle_flags |= VHF_HASSHIELD;
+
+                       if(autocvar_g_vehicle_spiderbot_shield_regen)
+                               self.vehicle_flags |= VHF_SHIELDREGEN;
+
+                       if(autocvar_g_vehicle_spiderbot_health_regen)
+                               self.vehicle_flags |= VHF_HEALTHREGEN;
+
+                       self.respawntime = autocvar_g_vehicle_spiderbot_respawntime;
+                       self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
+                       self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
+                       self.max_health = self.vehicle_health;
+                       self.pushable = true; // spiderbot can use jumppads
+               }
+
+#endif // SVQC
+#ifdef CSQC
+float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
+float autocvar_cl_vehicle_spiderbot_cross_size = 1;
+
+               METHOD(Spiderbot, vr_hud, void(Spiderbot thisveh))
+               {
+                       string crosshair;
+
+                       switch(weapon2mode)
+                       {
+                               case SBRM_VOLLY:     crosshair = vCROSS_BURST; break;
+                               case SBRM_GUIDE:     crosshair = vCROSS_GUIDE; break;
+                               case SBRM_ARTILLERY: crosshair = vCROSS_RAIN;  break;
+                               default:             crosshair = vCROSS_BURST;
+                       }
+
+                       Vehicles_drawHUD(VEH_SPIDERBOT.m_icon, "vehicle_spider_weapon1", "vehicle_spider_weapon2",
+                                                        "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
+                                                        "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
+                                                        crosshair);
+               }
+               METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh))
+               {
+                       AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1
+                       AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2
+               }
+
+#endif
+#endif
diff --git a/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc b/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc
new file mode 100644 (file)
index 0000000..0960fca
--- /dev/null
@@ -0,0 +1,283 @@
+#ifndef VEHICLE_SPIDERBOT_WEAPONS_H
+#define VEHICLE_SPIDERBOT_WEAPONS_H
+
+#include "../../weapons/all.qh"
+
+#endif
+
+#ifdef IMPLEMENTATION
+
+#ifdef SVQC
+
+float autocvar_g_vehicle_spiderbot_minigun_damage;
+float autocvar_g_vehicle_spiderbot_minigun_refire;
+float autocvar_g_vehicle_spiderbot_minigun_spread;
+int autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
+int autocvar_g_vehicle_spiderbot_minigun_ammo_max;
+int autocvar_g_vehicle_spiderbot_minigun_ammo_regen;
+float autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause;
+float autocvar_g_vehicle_spiderbot_minigun_force;
+float autocvar_g_vehicle_spiderbot_minigun_solidpenetration;
+
+float autocvar_g_vehicle_spiderbot_rocket_damage;
+float autocvar_g_vehicle_spiderbot_rocket_force;
+float autocvar_g_vehicle_spiderbot_rocket_radius;
+float autocvar_g_vehicle_spiderbot_rocket_speed;
+float autocvar_g_vehicle_spiderbot_rocket_spread;
+float autocvar_g_vehicle_spiderbot_rocket_refire;
+float autocvar_g_vehicle_spiderbot_rocket_refire2;
+float autocvar_g_vehicle_spiderbot_rocket_reload;
+float autocvar_g_vehicle_spiderbot_rocket_health;
+float autocvar_g_vehicle_spiderbot_rocket_noise;
+float autocvar_g_vehicle_spiderbot_rocket_turnrate;
+float autocvar_g_vehicle_spiderbot_rocket_lifetime;
+
+void spiderbot_rocket_artillery()
+{SELFPARAM();
+    self.nextthink = time;
+    UpdateCSQCProjectile(self);
+}
+
+void spiderbot_rocket_unguided()
+{SELFPARAM();
+    vector newdir, olddir;
+
+    self.nextthink  = time;
+
+    olddir = normalize(self.velocity);
+    newdir = normalize(self.pos1 - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
+    self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
+
+    UpdateCSQCProjectile(self);
+
+    if (self.owner.deadflag != DEAD_NO || self.cnt < time || vlen(self.pos1 - self.origin) < 16)
+        self.use();
+}
+
+void spiderbot_rocket_guided()
+{SELFPARAM();
+    vector newdir, olddir;
+
+    self.nextthink  = time;
+
+    if(!self.realowner.vehicle)
+        self.think = spiderbot_rocket_unguided;
+
+    crosshair_trace(self.realowner);
+    olddir = normalize(self.velocity);
+    newdir = normalize(trace_endpos - self.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
+    self.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
+
+    UpdateCSQCProjectile(self);
+
+    if (self.owner.deadflag != DEAD_NO || self.cnt < time)
+        self.use();
+}
+
+void spiderbot_guide_release()
+{SELFPARAM();
+    entity rkt;
+    rkt = findchainentity(realowner, self.owner);
+    if(!rkt)
+        return;
+
+    crosshair_trace(self.owner);
+    while(rkt)
+    {
+        if(rkt.think == spiderbot_rocket_guided)
+        {
+            rkt.pos1 = trace_endpos;
+            rkt.think = spiderbot_rocket_unguided;
+        }
+        rkt = rkt.chain;
+    }
+}
+
+float spiberbot_calcartillery_flighttime;
+vector spiberbot_calcartillery(vector org, vector tgt, float ht)
+{
+    float grav, sdist, zdist, vs, vz, jumpheight;
+    vector sdir;
+
+    grav  = autocvar_sv_gravity;
+    zdist = tgt_z - org_z;
+    sdist = vlen(tgt - org - zdist * '0 0 1');
+    sdir  = normalize(tgt - org - zdist * '0 0 1');
+
+    // how high do we need to go?
+    jumpheight = fabs(ht);
+    if(zdist > 0)
+        jumpheight = jumpheight + zdist;
+
+    // push so high...
+    vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
+
+    // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
+    if(ht < 0)
+        if(zdist < 0)
+            vz = -vz;
+
+    vector solution;
+    solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
+    // ALWAYS solvable because jumpheight >= zdist
+    if(!solution_z)
+        solution_y = solution_x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0)
+    if(zdist == 0)
+        solution_x = solution_y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually)
+
+    if(zdist < 0)
+    {
+        // down-jump
+        if(ht < 0)
+        {
+            // almost straight line type
+            // jump apex is before the jump
+            // we must take the larger one
+            spiberbot_calcartillery_flighttime = solution_y;
+        }
+        else
+        {
+            // regular jump
+            // jump apex is during the jump
+            // we must take the larger one too
+            spiberbot_calcartillery_flighttime = solution_y;
+        }
+    }
+    else
+    {
+        // up-jump
+        if(ht < 0)
+        {
+            // almost straight line type
+            // jump apex is after the jump
+            // we must take the smaller one
+            spiberbot_calcartillery_flighttime = solution_x;
+        }
+        else
+        {
+            // regular jump
+            // jump apex is during the jump
+            // we must take the larger one
+            spiberbot_calcartillery_flighttime = solution_y;
+        }
+    }
+    vs = sdist / spiberbot_calcartillery_flighttime;
+
+    // finally calculate the velocity
+    return sdir * vs + '0 0 1' * vz;
+}
+
+void spiderbot_rocket_do()
+{SELFPARAM();
+    vector v;
+    entity rocket = world;
+
+    if (self.wait != -10)
+    {
+        if (self.owner.BUTTON_ATCK2 && self.vehicle_weapon2mode == SBRM_GUIDE)
+        {
+            if (self.wait == 1)
+            if (self.tur_head.frame == 9 || self.tur_head.frame == 1)
+            {
+                if(self.gun2.cnt < time && self.tur_head.frame == 9)
+                    self.tur_head.frame = 1;
+
+                return;
+            }
+            self.wait = 1;
+        }
+        else
+        {
+            if(self.wait)
+                spiderbot_guide_release();
+
+            self.wait = 0;
+        }
+    }
+
+    if(self.gun2.cnt > time)
+        return;
+
+    if (self.tur_head.frame >= 9)
+    {
+        self.tur_head.frame = 1;
+        self.wait = 0;
+    }
+
+    if(self.wait != -10)
+    if(!self.owner.BUTTON_ATCK2)
+        return;
+
+    if(forbidWeaponUse(self.owner))
+        return;
+
+    v = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
+
+    switch(self.vehicle_weapon2mode)
+    {
+        case SBRM_VOLLY:
+            rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
+                                   v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
+                                   autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
+                                   DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
+            crosshair_trace(self.owner);
+            float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
+            _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
+            rocket.nextthink  = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed);
+            rocket.think        = vehicles_projectile_explode;
+
+            if(self.owner.BUTTON_ATCK2 && self.tur_head.frame == 1)
+                self.wait = -10;
+            break;
+        case SBRM_GUIDE:
+            rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
+                                   v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
+                                   autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
+                                   DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, self.owner);
+            crosshair_trace(self.owner);
+            rocket.pos1           = trace_endpos;
+            rocket.nextthink  = time;
+            rocket.think         = spiderbot_rocket_guided;
+
+
+        break;
+        case SBRM_ARTILLERY:
+            rocket = vehicles_projectile(EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND(ROCKET_FIRE),
+                                   v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
+                                   autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
+                                   DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, self.owner);
+
+            crosshair_trace(self.owner);
+
+            rocket.pos1           = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
+            rocket.pos1_z         = trace_endpos_z;
+
+            traceline(v, v + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
+            float h1 = 0.75 * vlen(v - trace_endpos);
+
+            //v = trace_endpos;
+            traceline(v , rocket.pos1 + '0 0 1' * MAX_SHOT_DISTANCE, MOVE_WORLDONLY, self);
+            float h2 = 0.75 * vlen(rocket.pos1 - v);
+
+            rocket.velocity  = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
+            rocket.movetype  = MOVETYPE_TOSS;
+            rocket.gravity   = 1;
+            //rocket.think      = spiderbot_rocket_artillery;
+        break;
+    }
+    rocket.classname  = "spiderbot_rocket";
+
+    rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
+
+    self.tur_head.frame += 1;
+    if (self.tur_head.frame == 9)
+        self.attack_finished_single = autocvar_g_vehicle_spiderbot_rocket_reload;
+    else
+        self.attack_finished_single = ((self.vehicle_weapon2mode ==  SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
+
+    self.gun2.cnt = time + self.attack_finished_single;
+}
+
+#endif
+
+#endif
index 125e6f8e12f0cfa0d27ed2af62eabe33219ab890..ce89bde34e453d392be294d5cf7814db4e622cf4 100644 (file)
@@ -11,7 +11,7 @@
 
 // client movement
 void viewloc_PlayerPhysics()
-{
+{SELFPARAM();
        if(self.viewloc)
        {
                vector oldmovement = self.movement;
@@ -58,7 +58,7 @@ void viewloc_PlayerPhysics()
 #ifdef CSQC
 
 void viewloc_SetTags()
-{
+{SELFPARAM();
        if(self.viewloc && wasfreed(self.viewloc))
                self.viewloc = world;
 
index fc89a0cd20360dc8f447542253a57c3e886d61d6..3257215a9fef5b84ef4c073b87774689f496f7c3 100644 (file)
@@ -27,3 +27,5 @@
 #include "weapon/arc.qc"
 #include "weapon/hmg.qc"
 #include "weapon/rpc.qc"
+
+#include "../../server/mutators/gamemode_nexball_weapon.qc"
index 046298a4c4f97c7bd2111a74503b2ac7483d46c6..2c72d380fcc8db9274203062ce8685de3882fad6 100644 (file)
@@ -12,7 +12,7 @@
        #include "../../warpzonelib/common.qh"
        #include "../../warpzonelib/client.qh"
        #include "../util.qh"
-       #include "../buffs.qh"
+       #include "../buffs/all.qh"
        #include "../../client/autocvars.qh"
        #include "../deathtypes.qh"
        #include "../../csqcmodellib/interpolate.qh"
@@ -31,7 +31,7 @@
     #include "../stats.qh"
     #include "../teams.qh"
     #include "../util.qh"
-    #include "../buffs.qh"
+    #include "../buffs/all.qh"
     #include "../monsters/all.qh"
     #include "config.qh"
     #include "../../server/weapons/csqcprojectile.qh"
 
 // WEAPON PLUGIN SYSTEM
 
-#if WEP_MAXCOUNT > 72
-# error Kein Weltraum links auf dem Gerät
-#endif
-
 WepSet WepSet_FromWeapon(int a) {
        a -= WEP_FIRST;
-#if WEP_MAXCOUNT > 24
-       if(a >= 24) {
+       if (Weapons_MAX > 24)
+       if (a >= 24) {
                a -= 24;
-#if WEP_MAXCOUNT > 48
-               if(a >= 24) {
+               if (Weapons_MAX > 48)
+               if (a >= 24) {
                        a -= 24;
                        return '0 0 1' * power2of(a);
                }
-#endif
                return '0 1 0' * power2of(a);
        }
-#endif
        return '1 0 0' * power2of(a);
 }
 #ifdef SVQC
 void WepSet_AddStat()
 {
        addstat(STAT_WEAPONS, AS_INT, weapons_x);
-#if WEP_MAXCOUNT > 24
+       if (Weapons_MAX > 24)
        addstat(STAT_WEAPONS2, AS_INT, weapons_y);
-#if WEP_MAXCOUNT > 48
+       if (Weapons_MAX > 48)
        addstat(STAT_WEAPONS3, AS_INT, weapons_z);
-#endif
-#endif
 }
 void WepSet_AddStat_InMap()
 {
        addstat(STAT_WEAPONSINMAP, AS_INT, weaponsinmap_x);
-#if WEP_MAXCOUNT > 24
+       if (Weapons_MAX > 24)
        addstat(STAT_WEAPONSINMAP2, AS_INT, weaponsinmap_y);
-#if WEP_MAXCOUNT > 48
+       if (Weapons_MAX > 48)
        addstat(STAT_WEAPONSINMAP3, AS_INT, weaponsinmap_z);
-#endif
-#endif
 }
 void WriteWepSet(float dst, WepSet w)
 {
-#if WEP_MAXCOUNT > 48
+       if (Weapons_MAX > 48)
        WriteInt72_t(dst, w);
-#elif WEP_MAXCOUNT > 24
+       else if (Weapons_MAX > 24)
        WriteInt48_t(dst, w);
-#else
+       else
        WriteInt24_t(dst, w.x);
-#endif
 }
 #endif
 #ifdef CSQC
@@ -115,61 +104,35 @@ WepSet WepSet_GetFromStat()
 {
        WepSet w = '0 0 0';
        w.x = getstati(STAT_WEAPONS);
-#if WEP_MAXCOUNT > 24
+       if (Weapons_MAX > 24)
        w.y = getstati(STAT_WEAPONS2);
-#if WEP_MAXCOUNT > 48
+       if (Weapons_MAX > 48)
        w.z = getstati(STAT_WEAPONS3);
-#endif
-#endif
        return w;
 }
 WepSet WepSet_GetFromStat_InMap()
 {
        WepSet w = '0 0 0';
        w_x = getstati(STAT_WEAPONSINMAP);
-#if WEP_MAXCOUNT > 24
+       if (Weapons_MAX > 24)
        w_y = getstati(STAT_WEAPONSINMAP2);
-#if WEP_MAXCOUNT > 48
+       if (Weapons_MAX > 48)
        w_z = getstati(STAT_WEAPONSINMAP3);
-#endif
-#endif
        return w;
 }
 WepSet ReadWepSet()
 {
-#if WEP_MAXCOUNT > 48
+       if (Weapons_MAX > 48)
        return ReadInt72_t();
-#elif WEP_MAXCOUNT > 24
+       if (Weapons_MAX > 24)
        return ReadInt48_t();
-#else
        return ReadInt24_t() * '1 0 0';
-#endif
 }
 #endif
 
-void register_weapons_done()
-{
-       dummy_weapon_info = NEW(Weapon);
-
-       weaponorder_byid = "";
-       for (int i = WEP_MAXCOUNT - 1; i >= 0; --i)
-               if (weapon_info[i])
-                       weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
-       weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
-}
-entity get_weaponinfo(int id)
-{
-       entity w;
-       if(id < WEP_FIRST || id > WEP_LAST)
-               return dummy_weapon_info;
-       w = weapon_info[id - 1];
-       if(w)
-               return w;
-       return dummy_weapon_info;
-}
 string W_FixWeaponOrder(string order, float complete)
 {
-       return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
+       return fixPriorityList(order, WEP_FIRST, WEP_LAST, WEP_IMPULSE_BEGIN - WEP_FIRST, complete);
 }
 string W_NameWeaponOrder_MapFunc(string s)
 {
@@ -177,7 +140,7 @@ string W_NameWeaponOrder_MapFunc(string s)
        if(s == "0" || stof(s))
        {
                wi = get_weaponinfo(stof(s));
-               if(wi != dummy_weapon_info)
+               if(wi != WEP_Null)
                        return wi.netname;
        }
        return s;
@@ -216,7 +179,7 @@ string W_NumberWeaponOrder(string order)
        return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
 }
 
-float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
+float W_FixWeaponOrder_BuildImpulseList_buf[Weapons_MAX];
 string W_FixWeaponOrder_BuildImpulseList_order;
 void W_FixWeaponOrder_BuildImpulseList_swap(int i, int j, entity pass)
 {
@@ -331,7 +294,16 @@ int GetAmmoStat(.int ammotype)
 
 string W_Sound(string w_snd)
 {
-       string output = strcat("weapons/", w_snd, ".wav");
+       #define extensions(X) X(wav) X(ogg)
+       #define tryext(ext) { if (fexists(strcat("sound/", output = strcat("weapons/", w_snd, "."#ext)))) break; }
+       string output;
+       do {
+               extensions(tryext);
+               #undef tryext
+               #undef extensions
+               output = strcat("weapons/", w_snd);
+       } while (0);
+
 #ifdef SVQC
        MUTATOR_CALLHOOK(WeaponSound, w_snd, output);
        return weapon_sound_output;
index 081e13a7e58e64f4c5205d047b58fa8f3f7ea0d0..c96061fe615c00833f0d0524d2f6868bda021d9f 100644 (file)
 #ifndef WEAPONS_ALL_H
 #define WEAPONS_ALL_H
 
-#ifndef MENUQC
-#include "calculations.qh"
-#endif
-
-#include "../util.qh"
-#ifdef SVQC
-#include "../../server/bot/aim.qh"
-#endif
-const int MAX_SHOT_DISTANCE = 32768;
-
-// weapon pickup ratings for bot logic
-const int BOT_PICKUP_RATING_LOW  =  2500;
-const int BOT_PICKUP_RATING_MID  =  5000;
-const int BOT_PICKUP_RATING_HIGH = 10000;
-
-// weapon flags
-const int WEP_TYPE_OTHER          =  0x00; // not for damaging people
-const int WEP_TYPE_SPLASH         =  0x01; // splash damage
-const int WEP_TYPE_HITSCAN        =  0x02; // hitscan
-const int WEP_TYPEMASK            =  0x0F;
-const int WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
-const int WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
-const int WEP_FLAG_HIDDEN         =  0x40; // hides from menu
-const int WEP_FLAG_RELOADABLE     =  0x80; // can has reload
-const int WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
-const int WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
-
-// weapon requests
-const int WR_SETUP          =  1; // (SERVER) setup weapon data
-const int WR_THINK          =  2; // (SERVER) logic to run every frame
-const int WR_CHECKAMMO1     =  3; // (SERVER) checks ammo for weapon primary
-const int WR_CHECKAMMO2     =  4; // (SERVER) checks ammo for weapon second
-const int WR_AIM            =  5; // (SERVER) runs bot aiming code for this weapon
-const int WR_INIT           =  6; // (BOTH)   precaches models/sounds used by this weapon, also sets up weapon properties
-const int WR_SUICIDEMESSAGE =  7; // (SERVER) notification number for suicide message (may inspect w_deathtype for details)
-const int WR_KILLMESSAGE    =  8; // (SERVER) notification number for kill message (may inspect w_deathtype for details)
-const int WR_RELOAD         =  9; // (SERVER) handles reloading for weapon
-const int WR_RESETPLAYER    = 10; // (SERVER) clears fields that the weapon may use
-const int WR_IMPACTEFFECT   = 11; // (CLIENT) impact effect for weapon explosion
-const int WR_PLAYERDEATH    = 12; // (SERVER) called whenever a player dies
-const int WR_GONETHINK      = 13; // (SERVER) logic to run when weapon is lost
-const int WR_CONFIG         = 14; // (ALL)    dump weapon cvars to config in data directory (see: sv_cmd dumpweapons)
-const int WR_ZOOMRETICLE    = 15; // (CLIENT) weapon specific zoom reticle
-const int WR_DROP           = 16; // (SERVER) the weapon is dropped
-const int WR_PICKUP         = 17; // (SERVER) a weapon is picked up
-
-// variables:
-string weaponorder_byid;
-
 // weapon sets
 typedef vector WepSet;
+#define WEPSET(id) WepSet_FromWeapon(WEP_##id.m_id)
 WepSet WepSet_FromWeapon(int a);
 #ifdef SVQC
 void WepSet_AddStat();
 void WepSet_AddStat_InMap();
 void WriteWepSet(float dest, WepSet w);
 #endif
+
 #ifdef CSQC
 WepSet WepSet_GetFromStat();
 WepSet WepSet_GetFromStat_InMap();
 WepSet ReadWepSet();
 #endif
 
-// weapon name macros
-const int WEP_FIRST = 1;
-#define WEP_MAXCOUNT 24 // Increase as needed. Can be up to three times as much.
-int WEP_COUNT;
-#define WEP_LAST (WEP_FIRST + WEP_COUNT - 1)
-WepSet WEPSET_ALL;
-WepSet WEPSET_SUPERWEAPONS;
+#include "weapon.qh"
 
-// functions:
-entity get_weaponinfo(int id);
-string W_FixWeaponOrder(string order, float complete);
-string W_UndeprecateName(string s);
-string W_NameWeaponOrder(string order);
-string W_NumberWeaponOrder(string order);
-string W_FixWeaponOrder_BuildImpulseList(string o);
-string W_FixWeaponOrder_AllowIncomplete(string order);
-string W_FixWeaponOrder_ForceComplete(string order);
-void W_RandomWeapons(entity e, float n);
-
-string GetAmmoPicture(.int ammotype);
-
-#ifdef CSQC
-.int GetAmmoFieldFromNum(int i);
-int GetAmmoStat(.int ammotype);
+#ifndef MENUQC
+#include "calculations.qh"
+#include "../models/all.qh"
 #endif
 
-string W_Sound(string w_snd);
-string W_Model(string w_mdl);
-
-// ammo types
-.int ammo_shells;
-.int ammo_nails;
-.int ammo_rockets;
-.int ammo_cells;
-.int ammo_plasma;
-.int ammo_fuel;
-.int ammo_none;
+#include "../util.qh"
 
-// other useful macros
-#define WEP_ACTION(wpn,wrequest) (get_weaponinfo(wpn)).weapon_func(wrequest)
-#define WEP_AMMO(wpn) (WEP_##wpn.ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
-#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).message)
+#ifdef SVQC
+#include "../../server/bot/aim.qh"
+#endif
 
+REGISTRY(Weapons, 72) // Increase as needed. Can be up to 72.
+REGISTER_REGISTRY(RegisterWeapons)
+entity get_weaponinfo(int id);
 
-// ======================
-//  Configuration Macros
-// ======================
+#define REGISTER_WEAPON(id, inst) \
+       /* WepSet WEPSET_##id; */ \
+       REGISTER(RegisterWeapons, WEP, Weapons, id, m_id, inst)
 
 // create cvars for weapon settings
 #define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name;
@@ -138,134 +64,57 @@ string W_Model(string w_mdl);
 #define WEP_SKIP_CVAR(unuseda,unusedb,unusedc,unusedd) /* skip cvars */
 #define WEP_SET_PROP(wepid,wepname,type,prop,name) WEP_##wepid.prop = autocvar_g_balance_##wepname##_##name;
 
+const int WEP_FIRST = 1;
+#define WEP_LAST (Weapons_COUNT - 1)
+WepSet WEPSET_ALL;
+WepSet WEPSET_SUPERWEAPONS;
 
-// =====================
-//  Weapon Registration
-// =====================
-
-bool w_null(int) { return false; }
-
-/** 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)
-    /**
-     * M: WEP_id    : WEP_...
-     * you can recognize dummies when this == 0
-     */
-    ATTRIB(Weapon, weapon, int, 0);
-    /** A: WEPSET_id : WEPSET_... */
-    ATTRIB(Weapon, weapons, WepSet, '0 0 0');
-    /** M: function  : w_... */
-    ATTRIB(Weapon, weapon_func, bool(int), w_null);
-    /** M: ammotype  : main ammo field */
-    ATTRIB(Weapon, ammo_field, .int, ammo_none);
-    /** M: impulse   : weapon impulse */
-    ATTRIB(Weapon, impulse, int, -1);
-    /** M: flags     : WEPSPAWNFLAG_... combined */
-    ATTRIB(Weapon, spawnflags, int, 0);
-    /** M: rating    : bot weapon priority */
-    ATTRIB(Weapon, bot_pickupbasevalue, float, 0);
-    /** M: color     : waypointsprite color */
-    ATTRIB(Weapon, wpcolor, vector, '0 0 0');
-    /** A: wpn-id    : wpn- sprite name */
-    ATTRIB(Weapon, wpmodel, string, "");
-    /** M: modelname : name of model (without g_ v_ or h_ prefixes) */
-    ATTRIB(Weapon, mdl, string, "");
-    /** A: modelname : full path to g_ model */
-    ATTRIB(Weapon, model, string, "");
-    /** M: simplemdl : simpleitems weapon model/image */
-    ATTRIB(Weapon, w_simplemdl, string, "foobar");
-    /** 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) */
-    ATTRIB(Weapon, w_crosshair_size, float, 1);
-    /** M: wepimg    : "weaponfoobar" side view image file of weapon. WEAPONTODO: Move out of skin files, move to common files */
-    ATTRIB(Weapon, model2, string, "");
-    /** M: refname   : reference name name */
-    ATTRIB(Weapon, netname, string, "");
-    /** M: wepname   : human readable name */
-    ATTRIB(Weapon, message, string, "AOL CD Thrower");
+REGISTER_WEAPON(Null, NEW(Weapon));
 
-       METHOD(Weapon, display, void(entity this, void(string name, string icon) returns)) {
-               returns(this.message, this.model2 ? sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.model2) : string_null);
-       }
+#include "all.inc"
 
-       CONSTRUCTOR(Weapon,
-               bool(int) function,
-               .int ammotype,
-               int i,
-               int weapontype,
-               float pickupbasevalue,
-               vector clr,
-               string modelname,
-               string simplemdl,
-               string crosshair,
-               string wepimg,
-               string refname,
-               string wepname
-       ) {
-               CONSTRUCT(Weapon);
-               this.weapon_func = function;
-               this.ammo_field = ammotype;
-               this.impulse = i;
-               this.spawnflags = weapontype;
-               this.bot_pickupbasevalue = pickupbasevalue;
-               this.wpcolor = clr;
-               this.mdl = modelname;
-               this.model = strzone(W_Model(strcat("g_", modelname, ".md3")));
-               this.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image
-               this.w_crosshair = strzone(car(crosshair));
-               string s = cdr(crosshair);
-               this.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
-               this.model2 = strzone(wepimg);
-               this.netname = refname;
-               this.message = wepname;
+entity get_weaponinfo(int id)
+{
+       if (id >= WEP_FIRST && id <= WEP_LAST) {
+               Weapon w = Weapons[id];
+               if (w) return w;
        }
-       void register_weapon(entity this, int id, WepSet bit)
-       {
-               this.classname = "weapon_info";
-               this.weapon = id;
-               this.weapons = bit;
-               this.wpmodel = strzone(strcat("wpn-", ftos(id)));
+       return WEP_Null;
+}
+
+// TODO: remove after 0.8.2. Retains impulse number compatibility because 0.8.1 clients don't reload the weapons.cfg
+#define WEP_HARDCODED_IMPULSES 22
+
+// TODO: invert after 0.8.2. Will require moving 'best weapon' impulses
+#define WEP_IMPULSE_BEGIN 230
+#define WEP_IMPULSE_END bound(WEP_IMPULSE_BEGIN, WEP_IMPULSE_BEGIN + (Weapons_COUNT - 1) - 1, 253)
+
+REGISTRY_SORT(Weapons, netname, WEP_HARDCODED_IMPULSES + 1)
+
+STATIC_INIT(register_weapons_done)
+{
+       for (int i = 0; i < Weapons_COUNT; ++i) {
+               Weapon it = Weapons[i];
+               it.m_id = i;
+               WepSet set = WepSet_FromWeapon(it.m_id);
+               WEPSET_ALL |= set;
+               if ((it.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
+               it.weapon = it.m_id;
+               it.weapons = set;
                #ifdef CSQC
-               this.weapon_func(WR_INIT);
+               it.wr_init(it);
                #endif
+               int imp = WEP_IMPULSE_BEGIN + it.m_id - 1;
+               if (imp <= WEP_IMPULSE_END)
+                       localcmd(sprintf("alias weapon_%s \"impulse %d\"\n", it.netname, imp));
+               else
+                       LOG_TRACEF(_("Impulse limit exceeded, weapon will not be directly accessible: %s\n"), it.netname);
        }
-ENDCLASS(Weapon)
-
-void RegisterWeapons();
-REGISTER_REGISTRY(RegisterWeapons)
-entity weapon_info[WEP_MAXCOUNT], weapon_info_first, weapon_info_last;
-entity dummy_weapon_info;
-
-#define _REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
-       WepSet WEPSET_##id; \
-       REGISTER(RegisterWeapons, WEP, weapon_info, WEP_COUNT, id, m_id, \
-               NEW(Weapon, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
-       ) { \
-               this.m_id++; \
-               WEPSET_ALL |= (WEPSET_##id = WepSet_FromWeapon(this.m_id)); \
-               if ((flags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= WEPSET_##id; \
-               register_weapon(this, this.m_id, WEPSET_##id); \
-       }
-
-#ifndef MENUQC
-       #define REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
-       bool function(int); \
-       _REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname)
-#else
-       #define REGISTER_WEAPON(id, function, ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname) \
-               _REGISTER_WEAPON(id, w_null,   ammotype, impulse, flags, rating, color, modelname, simplemdl, crosshair, wepimg, refname, wepname)
-#endif
-
-#include "all.inc"
+       weaponorder_byid = "";
+       for (int i = Weapons_MAX - 1; i >= 1; --i)
+               if (Weapons[i])
+                       weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
+       weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
+}
 
-#undef WEP_ADD_CVAR_MO_PRI
-#undef WEP_ADD_CVAR_MO_SEC
-#undef WEP_ADD_CVAR_MO_BOTH
-#undef WEP_ADD_CVAR_MO_NONE
-#undef WEP_ADD_CVAR
-#undef WEP_ADD_PROP
-void register_weapons_done();
-ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done);
 #endif
index b90c01f4a65abd6e300485335c03fa2bd74e32ed..d932224e3a8bae0e990604ec19ed47410e05b517 100644 (file)
@@ -35,7 +35,8 @@ void Dump_Weapon_Settings(void)
                        { wep_config_queue[x] = string_null; }
 
                // step 2: build new queue
-               WEP_ACTION(i, WR_CONFIG);
+               Weapon w = get_weaponinfo(i);
+               w.wr_config(w);
 
                // step 3: sort queue
                heapsort(WEP_CONFIG_COUNT, W_Config_Queue_Swap, W_Config_Queue_Compare, world);
diff --git a/qcsrc/common/weapons/weapon.qh b/qcsrc/common/weapons/weapon.qh
new file mode 100644 (file)
index 0000000..a4eb7b7
--- /dev/null
@@ -0,0 +1,145 @@
+#ifndef WEAPON_H
+#define WEAPON_H
+
+.int ammo_shells;
+.int ammo_nails;
+.int ammo_rockets;
+.int ammo_cells;
+.int ammo_plasma;
+.int ammo_fuel;
+.int ammo_none;
+
+/** 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)
+    /**
+     * M: WEP_id    : WEP_...
+     * you can recognize dummies when this == 0
+     */
+    ATTRIB(Weapon, weapon, int, 0);
+    /** A: WEPSET_id : WEPSET_... */
+    ATTRIB(Weapon, weapons, WepSet, '0 0 0');
+    /** M: ammotype  : main ammo field */
+    ATTRIB(Weapon, ammo_field, .int, ammo_none);
+    /** M: impulse   : weapon impulse */
+    ATTRIB(Weapon, impulse, int, -1);
+    /** M: flags     : WEPSPAWNFLAG_... combined */
+    ATTRIB(Weapon, spawnflags, int, 0);
+    /** M: rating    : bot weapon priority */
+    ATTRIB(Weapon, bot_pickupbasevalue, float, 0);
+    /** M: color     : waypointsprite color */
+    ATTRIB(Weapon, wpcolor, vector, '0 0 0');
+    /** 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);
+    /** 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) */
+    ATTRIB(Weapon, w_crosshair_size, float, 1);
+    /** M: wepimg    : "weaponfoobar" side view image file of weapon. WEAPONTODO: Move out of skin files, move to common files */
+    ATTRIB(Weapon, model2, string, "");
+    /** M: refname   : reference name name */
+    ATTRIB(Weapon, netname, string, "");
+    /** M: wepname   : human readable name */
+    ATTRIB(Weapon, message, string, "AOL CD Thrower");
+
+    /** (SERVER) setup weapon data */
+    METHOD(Weapon, wr_setup, void(Weapon this)) {}
+    /** (SERVER) logic to run every frame */
+    METHOD(Weapon, wr_think, void(Weapon this, entity actor, bool fire1, bool fire2)) {}
+    /** (SERVER) checks ammo for weapon primary */
+    METHOD(Weapon, wr_checkammo1, bool(Weapon this)) {return false;}
+    /** (SERVER) checks ammo for weapon second */
+    METHOD(Weapon, wr_checkammo2, bool(Weapon this)) {return false;}
+    /** (SERVER) runs bot aiming code for this weapon */
+    METHOD(Weapon, wr_aim, void(Weapon this)) {}
+    /** (BOTH)   precaches models/sounds used by this weapon, also sets up weapon properties */
+    METHOD(Weapon, wr_init, void(Weapon this)) {}
+    /** (SERVER) notification number for suicide message (may inspect w_deathtype for details) */
+    METHOD(Weapon, wr_suicidemessage, int(Weapon this)) {return 0;}
+    /** (SERVER) notification number for kill message (may inspect w_deathtype for details) */
+    METHOD(Weapon, wr_killmessage, int(Weapon this)) {return 0;}
+    /** (SERVER) handles reloading for weapon */
+    METHOD(Weapon, wr_reload, void(Weapon this)) {}
+    /** (SERVER) clears fields that the weapon may use */
+    METHOD(Weapon, wr_resetplayer, void(Weapon this)) {}
+    /** (CLIENT) impact effect for weapon explosion */
+    METHOD(Weapon, wr_impacteffect, void(Weapon this)) {}
+    /** (SERVER) called whenever a player dies */
+    METHOD(Weapon, wr_playerdeath, void(Weapon this)) {}
+    /** (SERVER) logic to run when weapon is lost */
+    METHOD(Weapon, wr_gonethink, void(Weapon this)) {}
+    /** (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 */
+    METHOD(Weapon, wr_zoomreticle, bool(Weapon this)) {
+        // no weapon specific image for this weapon
+        return false;
+    }
+    /** (SERVER) the weapon is dropped */
+    METHOD(Weapon, wr_drop, void(Weapon this)) {}
+    /** (SERVER) a weapon is picked up */
+    METHOD(Weapon, wr_pickup, void(Weapon this)) {}
+
+       METHOD(Weapon, display, void(entity this, void(string name, string icon) returns)) {
+               returns(this.message, this.model2 ? sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.model2) : string_null);
+       }
+ENDCLASS(Weapon)
+
+CLASS(OffhandWeapon, Object)
+    METHOD(OffhandWeapon, offhand_think, void(OffhandWeapon this, entity player, bool key_pressed)) {}
+ENDCLASS(OffhandWeapon)
+
+#ifdef SVQC
+.OffhandWeapon offhand;
+#endif
+
+const int MAX_SHOT_DISTANCE = 32768;
+
+// weapon pickup ratings for bot logic
+const int BOT_PICKUP_RATING_LOW  =  2500;
+const int BOT_PICKUP_RATING_MID  =  5000;
+const int BOT_PICKUP_RATING_HIGH = 10000;
+
+// weapon flags
+const int WEP_TYPE_OTHER          =  0x00; // not for damaging people
+const int WEP_TYPE_SPLASH         =  0x01; // splash damage
+const int WEP_TYPE_HITSCAN        =  0x02; // hitscan
+const int WEP_TYPEMASK            =  0x0F;
+const int WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
+const int WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
+const int WEP_FLAG_HIDDEN         =  0x40; // hides from menu
+const int WEP_FLAG_RELOADABLE     =  0x80; // can has reload
+const int WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
+const int WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
+
+// variables:
+string weaponorder_byid;
+
+// functions:
+string W_FixWeaponOrder(string order, float complete);
+string W_UndeprecateName(string s);
+string W_NameWeaponOrder(string order);
+string W_NumberWeaponOrder(string order);
+string W_FixWeaponOrder_BuildImpulseList(string o);
+string W_FixWeaponOrder_AllowIncomplete(string order);
+string W_FixWeaponOrder_ForceComplete(string order);
+void W_RandomWeapons(entity e, float n);
+
+string GetAmmoPicture(.int ammotype);
+
+#ifdef CSQC
+.int GetAmmoFieldFromNum(int i);
+int GetAmmoStat(.int ammotype);
+#endif
+
+string W_Sound(string w_snd);
+string W_Model(string w_mdl);
+
+
+// other useful macros
+#define WEP_AMMO(wpn) (WEP_##wpn.ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
+#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).message)
+
+#endif
index c101a8c8ab326f79fd8d0e72972d00d30b0fc2b5..99eb17d031b89453a0d2da13ec56fd7fedb83702 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ ARC,
-/* function  */ W_Arc,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 3,
-/* flags     */ WEP_FLAG_NORMAL,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '1 1 1',
-/* modelname */ "arc",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhlac 0.7",
-/* wepimg    */ "weaponarc",
-/* refname   */ "arc",
-/* wepname   */ _("Arc")
-);
+CLASS(Arc, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Arc, mdl, string, "arc");
+#ifndef MENUQC
+/* model     */ ATTRIB(Arc, m_model, Model, MDL_ARC_ITEM);
+#endif
+/* crosshair */ ATTRIB(Arc, w_crosshair, string, "gfx/crosshairhlac");
+/* crosshair */ ATTRIB(Arc, w_crosshair_size, float, 0.7);
+/* wepimg    */ ATTRIB(Arc, model2, string, "weaponarc");
+/* refname   */ ATTRIB(Arc, netname, string, "arc");
+/* wepname   */ ATTRIB(Arc, message, string, _("Arc"));
+ENDCLASS(Arc)
+REGISTER_WEAPON(ARC, NEW(Arc));
 
 #define ARC_SETTINGS(w_cvar,w_prop) ARC_SETTINGS_LIST(w_cvar, w_prop, ARC, arc)
 #define ARC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -82,7 +84,7 @@ const int ARC_SF_LOCALMASK =   14;
 #ifdef SVQC
 ARC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 .entity arc_beam;
-.float arc_BUTTON_ATCK_prev; // for better animation control
+.bool arc_BUTTON_ATCK_prev; // for better animation control
 .float beam_prev;
 .float beam_initialized;
 .float beam_bursting;
@@ -126,9 +128,9 @@ vector Draw_ArcBeam_callback_last_bottom; // NOTE: in same coordinate system as
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_arc(void) { weapon_defaultspawnfunc(WEP_ARC.m_id); }
+spawnfunc(weapon_arc) { weapon_defaultspawnfunc(WEP_ARC.m_id); }
 
-float W_Arc_Beam_Send(entity to, int sf)
+bool W_Arc_Beam_Send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_ARC_BEAM);
 
@@ -213,7 +215,7 @@ void Arc_Player_SetHeat(entity player)
 }
 
 void W_Arc_Beam_Think(void)
-{
+{SELFPARAM();
        if(self != self.owner.arc_beam)
        {
                remove(self);
@@ -267,20 +269,20 @@ void W_Arc_Beam_Think(void)
                        {
                                Send_Effect_("arc_overheat",
                                        self.beam_start, self.beam_wantdir, 1 );
-                               sound(self, CH_WEAPON_A, W_Sound("arc_stop"), VOL_BASE, ATTN_NORM);
+                               sound(self, CH_WEAPON_A, SND_ARC_STOP, VOL_BASE, ATTN_NORM);
                        }
                }
 
                if(self == self.owner.arc_beam) { self.owner.arc_beam = world; }
-               entity oldself = self;
-               self = self.owner;
-               if(!WEP_ACTION(WEP_ARC.m_id, WR_CHECKAMMO1) && !WEP_ACTION(WEP_ARC.m_id, WR_CHECKAMMO2))
+               setself(self.owner);
+               Weapon w = WEP_ARC;
+               if(!w.wr_checkammo1(w) && !w.wr_checkammo2(w))
                if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
                        W_SwitchToOtherWeapon(self);
                }
-               self = oldself;
+               setself(this);
                remove(self);
                return;
        }
@@ -576,11 +578,11 @@ void W_Arc_Beam_Think(void)
 }
 
 void W_Arc_Beam(float burst)
-{
+{SELFPARAM();
 
        // only play fire sound if 1 sec has passed since player let go the fire button
        if(time - self.beam_prev > 1)
-               sound(self, CH_WEAPON_A, W_Sound("arc_fire"), VOL_BASE, ATTN_NORM);
+               sound(self, CH_WEAPON_A, SND_ARC_FIRE, VOL_BASE, ATTN_NORM);
 
        entity beam = self.arc_beam = spawn();
        beam.classname = "W_Arc_Beam";
@@ -593,14 +595,11 @@ void W_Arc_Beam(float burst)
        beam.beam_bursting = burst;
        Net_LinkEntity(beam, false, 0, W_Arc_Beam_Send);
 
-       entity oldself = self;
-       self = beam;
-       self.think();
-       self = oldself;
+       WITH(entity, self, beam, beam.think());
 }
 
 void Arc_Smoke()
-{
+{SELFPARAM();
        makevectors(self.v_angle);
        W_SetupShot_Range(self,true,0,"",0,0,0);
 
@@ -615,7 +614,7 @@ void Arc_Smoke()
                        if ( !self.arc_smoke_sound )
                        {
                                self.arc_smoke_sound = 1;
-                               sound(self, CH_SHOTS_SINGLE, W_Sound("arc_loop_overheat"), VOL_BASE, ATTN_NORM);
+                               sound(self, CH_SHOTS_SINGLE, SND_ARC_LOOP_OVERHEAT, VOL_BASE, ATTN_NORM);
                        }
                }
        }
@@ -631,16 +630,13 @@ void Arc_Smoke()
                !( self.BUTTON_ATCK || self.BUTTON_ATCK2 ) ) || self.switchweapon != WEP_ARC.m_id )
        {
                self.arc_smoke_sound = 0;
-               sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
+               sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
        }
 }
 
-bool W_Arc(int req)
-{
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Arc, wr_aim, void(entity thiswep))
                {
+                       SELFPARAM();
                        if(WEP_CVAR(arc, beam_botaimspeed))
                        {
                                self.BUTTON_ATCK = bot_aim(
@@ -659,74 +655,64 @@ bool W_Arc(int req)
                                        false
                                );
                        }
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Arc, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       Arc_Player_SetHeat(self);
+                       Arc_Player_SetHeat(actor);
                        Arc_Smoke();
 
-                       if ( self.arc_overheat <= time )
-                       if(self.BUTTON_ATCK || self.BUTTON_ATCK2 || self.arc_beam.beam_bursting )
+                       if (time >= actor.arc_overheat)
+                       if (fire1 || fire2 || actor.arc_beam.beam_bursting)
                        {
 
-                               if(self.arc_BUTTON_ATCK_prev)
+                               if(actor.arc_BUTTON_ATCK_prev)
                                {
                                        #if 0
-                                       if(self.animstate_startframe == self.anim_shoot.x && self.animstate_numframes == self.anim_shoot.y)
-                                               weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
+                                       if(actor.animstate_startframe == actor.anim_shoot.x && actor.animstate_numframes == actor.anim_shoot.y)
+                                               weapon_thinkf(actor, WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
                                        else
                                        #endif
-                                               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+                                               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
                                }
 
-                               if((!self.arc_beam) || wasfreed(self.arc_beam))
+                               if((!actor.arc_beam) || wasfreed(actor.arc_beam))
                                {
-                                       if(weapon_prepareattack(!!self.BUTTON_ATCK2, 0))
+                                       if(weapon_prepareattack(thiswep, actor, fire2, 0))
                                        {
-                                               W_Arc_Beam(!!self.BUTTON_ATCK2);
+                                               W_Arc_Beam(fire2);
 
-                                               if(!self.arc_BUTTON_ATCK_prev)
+                                               if(!actor.arc_BUTTON_ATCK_prev)
                                                {
-                                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
-                                                       self.arc_BUTTON_ATCK_prev = 1;
+                                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+                                                       actor.arc_BUTTON_ATCK_prev = true;
                                                }
                                        }
                                }
 
-                               return true;
+                               return;
                        }
 
-                       if(self.arc_BUTTON_ATCK_prev != 0)
+                       if(actor.arc_BUTTON_ATCK_prev)
                        {
-                               sound(self, CH_WEAPON_A, W_Sound("arc_stop"), VOL_BASE, ATTN_NORM);
-                               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
-                               ATTACK_FINISHED(self) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor();
+                               sound(actor, CH_WEAPON_A, SND_ARC_STOP, VOL_BASE, ATTN_NORM);
+                               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+                               ATTACK_FINISHED(actor) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor();
                        }
-                       self.arc_BUTTON_ATCK_prev = 0;
+                       actor.arc_BUTTON_ATCK_prev = false;
 
                        #if 0
-                       if(self.BUTTON_ATCK2)
-                       if(weapon_prepareattack(1, autocvar_g_balance_arc_secondary_refire))
+                       if(fire2)
+                       if(weapon_prepareattack(thiswep, actor, true, autocvar_g_balance_arc_secondary_refire))
                        {
                                W_Arc_Attack2();
-                               self.arc_count = autocvar_g_balance_arc_secondary_count;
-                               weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_arc_secondary_animtime, w_arc_checkattack);
-                               self.arc_secondarytime = time + autocvar_g_balance_arc_secondary_refire2 * W_WeaponRateFactor();
+                               actor.arc_count = autocvar_g_balance_arc_secondary_count;
+                               weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_balance_arc_secondary_animtime, w_arc_checkattack);
+                               actor.arc_secondarytime = time + autocvar_g_balance_arc_secondary_refire2 * W_WeaponRateFactor();
                        }
                        #endif
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Arc, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_arc.md3"));
-                       precache_model(W_Model("v_arc.md3"));
-                       precache_model(W_Model("h_arc.iqm"));
-                       precache_sound(W_Sound("arc_fire"));
-                       precache_sound(W_Sound("arc_loop"));
-                       precache_sound(W_Sound("arc_stop"));
-                       precache_sound(W_Sound("arc_loop_overheat"));
                        if(!arc_shotorigin[0])
                        {
                                arc_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC.m_id), false, false, 1);
@@ -735,35 +721,34 @@ bool W_Arc(int req)
                                arc_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC.m_id), false, false, 4);
                        }
                        ARC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Arc, wr_checkammo1, bool(entity thiswep))
                {
+                       SELFPARAM();
                        return ((!WEP_CVAR(arc, beam_ammo)) || (self.WEP_AMMO(ARC) > 0));
                }
-               case WR_CHECKAMMO2:
+               METHOD(Arc, wr_checkammo2, bool(entity thiswep))
                {
+                       SELFPARAM();
                        return WEP_CVAR(arc, overheat_max) > 0 &&
                                ((!WEP_CVAR(arc, burst_ammo)) || (self.WEP_AMMO(ARC) > 0));
                }
-               case WR_CONFIG:
+               METHOD(Arc, wr_config, void(entity thiswep))
                {
                        ARC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Arc, wr_killmessage, int(entity thiswep))
                {
                        return WEAPON_ARC_MURDER;
                }
-               case WR_DROP:
+               METHOD(Arc, wr_drop, void(entity thiswep))
                {
                        weapon_dropevent_item.arc_overheat = self.arc_overheat;
                        weapon_dropevent_item.arc_cooldown = self.arc_cooldown;
                        self.arc_overheat = 0;
                        self.arc_cooldown = 0;
-                       return true;
                }
-               case WR_PICKUP:
+               METHOD(Arc, wr_pickup, void(entity thiswep))
                {
                        if ( !client_hasweapon(self, WEP_ARC.m_id, false, false) &&
                                weapon_dropevent_item.arc_overheat > time )
@@ -771,11 +756,7 @@ bool W_Arc(int req)
                                self.arc_overheat = weapon_dropevent_item.arc_overheat;
                                self.arc_cooldown = weapon_dropevent_item.arc_cooldown;
                        }
-                       return true;
                }
-       }
-       return false;
-}
 #endif
 #ifdef CSQC
 void Draw_ArcBeam_callback(vector start, vector hit, vector end)
@@ -869,7 +850,7 @@ void Reset_ArcBeam(void)
        }
 }
 
-void Draw_ArcBeam(void)
+void Draw_ArcBeam(entity this)
 {
        float dt = time - self.move_time;
        self.move_time = time;
@@ -1163,13 +1144,13 @@ void Draw_ArcBeam(void)
 }
 
 void Remove_ArcBeam(void)
-{
+{SELFPARAM();
        remove(self.beam_muzzleentity);
-       sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
+       sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
 }
 
 void Ent_ReadArcBeam(float isnew)
-{
+{SELFPARAM();
        int sf = ReadByte();
        entity flash;
 
@@ -1187,7 +1168,7 @@ void Ent_ReadArcBeam(float isnew)
                self.draw = Draw_ArcBeam;
                self.entremove = Remove_ArcBeam;
                self.move_time = time;
-               loopsound(self, CH_SHOTS_SINGLE, W_Sound("arc_loop"), VOL_BASE, ATTEN_NORM);
+               loopsound(self, CH_SHOTS_SINGLE, SND(ARC_LOOP), VOL_BASE, ATTEN_NORM);
 
                flash = spawn();
                flash.owner = self;
@@ -1294,7 +1275,7 @@ void Ent_ReadArcBeam(float isnew)
                                self.beam_muzzlelight[3] = 1;
                                if(self.beam_muzzleeffect >= 0)
                                {
-                                       setmodel(flash, "models/flash.md3");
+                                       setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                        flash.colormod = self.beam_color;
                                        flash.scale = 0.5;
@@ -1320,7 +1301,7 @@ void Ent_ReadArcBeam(float isnew)
                                self.beam_image = "particles/lgbeam";
                                if(self.beam_muzzleeffect >= 0)
                                {
-                                       setmodel(flash, "models/flash.md3");
+                                       setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                        flash.colormod = self.beam_color;
                                        flash.scale = 0.5;
@@ -1346,7 +1327,7 @@ void Ent_ReadArcBeam(float isnew)
                                self.beam_image = "particles/lgbeam";
                                if(self.beam_muzzleeffect >= 0)
                                {
-                                       setmodel(flash, "models/flash.md3");
+                                       setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                        flash.colormod = self.beam_color;
                                        flash.scale = 0.5;
@@ -1372,7 +1353,7 @@ void Ent_ReadArcBeam(float isnew)
                                self.beam_image = "particles/lgbeam";
                                if(self.beam_muzzleeffect >= 0)
                                {
-                                       setmodel(flash, "models/flash.md3");
+                                       setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                        flash.colormod = self.beam_color;
                                        flash.scale = 0.5;
@@ -1398,7 +1379,7 @@ void Ent_ReadArcBeam(float isnew)
                                self.beam_image = "particles/lgbeam";
                                if(self.beam_muzzleeffect >= 0)
                                {
-                                       setmodel(flash, "models/flash.md3");
+                                       setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                        flash.colormod = self.beam_color;
                                        flash.scale = 0.5;
@@ -1424,7 +1405,7 @@ void Ent_ReadArcBeam(float isnew)
                                self.beam_image = "particles/lgbeam";
                                if(self.beam_muzzleeffect >= 0)
                                {
-                                       setmodel(flash, "models/flash.md3");
+                                       setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                        flash.colormod = self.beam_color;
                                        flash.scale = 0.5;
@@ -1450,7 +1431,7 @@ void Ent_ReadArcBeam(float isnew)
                                self.beam_image = "particles/lgbeam";
                                if(self.beam_muzzleeffect >= 0)
                                {
-                                       setmodel(flash, "models/flash.md3");
+                                       setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                        flash.colormod = self.beam_color;
                                        flash.scale = 0.5;
@@ -1476,7 +1457,7 @@ void Ent_ReadArcBeam(float isnew)
                                self.beam_image = "particles/lgbeam";
                                if(self.beam_muzzleeffect >= 0)
                                {
-                                       setmodel(flash, "models/flash.md3");
+                                       setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                        flash.colormod = self.beam_color;
                                        flash.scale = 0.5;
@@ -1504,7 +1485,7 @@ void Ent_ReadArcBeam(float isnew)
                                self.beam_image = "particles/lgbeam";
                                if(self.beam_muzzleeffect >= 0)
                                {
-                                       setmodel(flash, "models/flash.md3");
+                                       setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                        flash.colormod = self.beam_color;
                                        flash.scale = 0.5;
@@ -1520,27 +1501,5 @@ void Ent_ReadArcBeam(float isnew)
        }
 }
 
-bool W_Arc(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
-               {
-                       // todo
-                       return true;
-               }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("arc_loop"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
 #endif
 #endif
index 6234f4a3e1154b1233afa9ee52ad5fd1b0d7f06d..d7792fac4aef157ea91a93f6a8b72a54c0facb8b 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ BLASTER,
-/* function  */ W_Blaster,
-/* ammotype  */ ammo_none,
-/* impulse   */ 1,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ 0,
-/* color     */ '1 0.5 0.5',
-/* modelname */ "laser",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairlaser 0.5",
-/* wepimg    */ "weaponlaser",
-/* refname   */ "blaster",
-/* wepname   */ _("Blaster")
-);
+CLASS(Blaster, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Blaster, mdl, string, "laser");
+#ifndef MENUQC
+/* model     */ ATTRIB(Blaster, m_model, Model, MDL_BLASTER_ITEM);
+#endif
+/* crosshair */ ATTRIB(Blaster, w_crosshair, string, "gfx/crosshairlaser");
+/* crosshair */ ATTRIB(Blaster, w_crosshair_size, float, 0.5);
+/* wepimg    */ ATTRIB(Blaster, model2, string, "weaponlaser");
+/* refname   */ ATTRIB(Blaster, netname, string, "blaster");
+/* wepname   */ ATTRIB(Blaster, message, string, _("Blaster"));
+ENDCLASS(Blaster)
+REGISTER_WEAPON(BLASTER, NEW(Blaster));
 
 #define BLASTER_SETTINGS(w_cvar,w_prop) BLASTER_SETTINGS_LIST(w_cvar, w_prop, BLASTER, blaster)
 #define BLASTER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -48,11 +50,11 @@ BLASTER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_blaster(void) { weapon_defaultspawnfunc(WEP_BLASTER.m_id); }
-void spawnfunc_weapon_laser(void) { spawnfunc_weapon_blaster(); }
+spawnfunc(weapon_blaster) { weapon_defaultspawnfunc(WEP_BLASTER.m_id); }
+spawnfunc(weapon_laser) { spawnfunc_weapon_blaster(this); }
 
 void W_Blaster_Touch(void)
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
 
        self.event_damage = func_null;
@@ -74,7 +76,7 @@ void W_Blaster_Touch(void)
 }
 
 void W_Blaster_Think(void)
-{
+{SELFPARAM();
        self.movetype = MOVETYPE_FLY;
        self.think = SUB_Remove;
        self.nextthink = time + self.blaster_lifetime;
@@ -82,6 +84,7 @@ void W_Blaster_Think(void)
 }
 
 void W_Blaster_Attack(
+       entity actor,
        float atk_deathtype,
        float atk_shotangle,
        float atk_damage,
@@ -92,14 +95,14 @@ void W_Blaster_Attack(
        float atk_spread,
        float atk_delay,
        float atk_lifetime)
-{
+{SELFPARAM();
        vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD);
 
-       W_SetupShot_Dir(self, s_forward, false, 3, W_Sound("lasergun_fire"), CH_WEAPON_B, atk_damage);
+       W_SetupShot_Dir(actor, 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 = spawn();
-       missile.owner = missile.realowner = self;
+       missile.owner = missile.realowner = actor;
        missile.classname = "blasterbolt";
        missile.bot_dodge = true;
        missile.bot_dodgerating = atk_damage;
@@ -137,22 +140,15 @@ void W_Blaster_Attack(
        missile.think = W_Blaster_Think;
        missile.nextthink = time + atk_delay;
 
-       MUTATOR_CALLHOOK(EditProjectile, self, missile);
+       MUTATOR_CALLHOOK(EditProjectile, actor, missile);
 
-       if(time >= missile.nextthink)
+       if (time >= missile.nextthink)
        {
-               entity oldself;
-               oldself = self;
-               self = missile;
-               self.think();
-               self = oldself;
+               WITH(entity, self, missile, missile.think());
        }
 }
-bool W_Blaster(int request)
-{
-       switch(request)
-       {
-               case WR_AIM:
+
+               METHOD(Blaster, wr_aim, void(entity thiswep))
                {
                        if(WEP_CVAR(blaster, secondary))
                        {
@@ -163,17 +159,16 @@ bool W_Blaster(int request)
                        }
                        else
                                { self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
-
-                       return true;
                }
 
-               case WR_THINK:
+               METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(self.BUTTON_ATCK)
+                       if(fire1)
                        {
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(blaster, refire)))
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(blaster, refire)))
                                {
                                        W_Blaster_Attack(
+                                               actor,
                                                WEP_BLASTER.m_id,
                                                WEP_CVAR_PRI(blaster, shotangle),
                                                WEP_CVAR_PRI(blaster, damage),
@@ -185,25 +180,26 @@ bool W_Blaster(int request)
                                                WEP_CVAR_PRI(blaster, delay),
                                                WEP_CVAR_PRI(blaster, lifetime)
                                        );
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(blaster, animtime), w_ready);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(blaster, animtime), w_ready);
                                }
                        }
-                       else if(self.BUTTON_ATCK2)
+                       else if(fire2)
                        {
                                switch(WEP_CVAR(blaster, secondary))
                                {
                                        case 0: // switch to last used weapon
                                        {
-                                               if(self.switchweapon == WEP_BLASTER.m_id) // don't do this if already switching
+                                               if(actor.switchweapon == WEP_BLASTER.m_id) // don't do this if already switching
                                                        W_LastWeapon();
                                                break;
                                        }
 
                                        case 1: // normal projectile secondary
                                        {
-                                               if(weapon_prepareattack(1, WEP_CVAR_SEC(blaster, refire)))
+                                               if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(blaster, refire)))
                                                {
                                                        W_Blaster_Attack(
+                                                               actor,
                                                                WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                                                                WEP_CVAR_SEC(blaster, shotangle),
                                                                WEP_CVAR_SEC(blaster, damage),
@@ -215,83 +211,60 @@ bool W_Blaster(int request)
                                                                WEP_CVAR_SEC(blaster, delay),
                                                                WEP_CVAR_SEC(blaster, lifetime)
                                                        );
-                                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(blaster, animtime), w_ready);
+                                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(blaster, animtime), w_ready);
                                                }
 
                                                break;
                                        }
                                }
                        }
-                       return true;
                }
 
-               case WR_INIT:
+               METHOD(Blaster, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_laser.md3"));
-                       precache_model(W_Model("v_laser.md3"));
-                       precache_model(W_Model("h_laser.iqm"));
-                       precache_sound(W_Sound("lasergun_fire"));
                        BLASTER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
 
-               case WR_SETUP:
+               METHOD(Blaster, wr_setup, void(entity thiswep))
                {
                        self.ammo_field = ammo_none;
-                       return true;
                }
 
-               case WR_CHECKAMMO1:
-               case WR_CHECKAMMO2:
+               METHOD(Blaster, wr_checkammo1, bool(entity thiswep))
                {
-                       return true; // laser has infinite ammo
+                       return true; // infinite ammo
                }
 
-               case WR_CONFIG:
+               METHOD(Blaster, wr_checkammo2, bool(entity thiswep))
+               {
+                       return true; // blaster has infinite ammo
+               }
+
+               METHOD(Blaster, wr_config, void(entity thiswep))
                {
                        BLASTER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
 
-               case WR_SUICIDEMESSAGE:
+               METHOD(Blaster, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_BLASTER_SUICIDE;
                }
 
-               case WR_KILLMESSAGE:
+               METHOD(Blaster, wr_killmessage, int(entity thiswep))
                {
                        return WEAPON_BLASTER_MURDER;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_Blaster(int request)
-{
-       switch(request)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Blaster, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 6;
                        pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
-                       if(!w_issilent) { sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTN_NORM); }
-                       return true;
+                       if(!w_issilent) { sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
                }
 
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("laserimpact"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
 #endif
 #endif
index 08deaf78c4a81e5ade345c1e9fd8590e5fb194bf..75d8146de4eb67b1d4fcf18b3241dc7632eaea41 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ CRYLINK,
-/* function  */ W_Crylink,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 6,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 0.5 1',
-/* modelname */ "crylink",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshaircrylink 0.5",
-/* wepimg    */ "weaponcrylink",
-/* refname   */ "crylink",
-/* wepname   */ _("Crylink")
-);
+CLASS(Crylink, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Crylink, mdl, string, "crylink");
+#ifndef MENUQC
+/* model     */ ATTRIB(Crylink, m_model, Model, MDL_CRYLINK_ITEM);
+#endif
+/* crosshair */ ATTRIB(Crylink, w_crosshair, string, "gfx/crosshaircrylink");
+/* crosshair */ ATTRIB(Crylink, w_crosshair_size, float, 0.5);
+/* wepimg    */ ATTRIB(Crylink, model2, string, "weaponcrylink");
+/* refname   */ ATTRIB(Crylink, netname, string, "crylink");
+/* wepname   */ ATTRIB(Crylink, message, string, _("Crylink"));
+ENDCLASS(Crylink)
+REGISTER_WEAPON(CRYLINK, NEW(Crylink));
 
 #define CRYLINK_SETTINGS(w_cvar,w_prop) CRYLINK_SETTINGS_LIST(w_cvar, w_prop, CRYLINK, crylink)
 #define CRYLINK_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -64,7 +66,7 @@ CRYLINK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_crylink(void) { weapon_defaultspawnfunc(WEP_CRYLINK.m_id); }
+spawnfunc(weapon_crylink) { weapon_defaultspawnfunc(WEP_CRYLINK.m_id); }
 
 void W_Crylink_CheckLinks(entity e)
 {
@@ -107,7 +109,7 @@ void W_Crylink_Dequeue(entity e)
 }
 
 void W_Crylink_Reset(void)
-{
+{SELFPARAM();
        W_Crylink_Dequeue(self);
        remove(self);
 }
@@ -224,7 +226,7 @@ vector W_Crylink_LinkJoin(entity e, float jspeed)
 }
 
 void W_Crylink_LinkJoinEffect_Think(void)
-{
+{SELFPARAM();
        // is there at least 2 projectiles very close?
        entity e, p;
        float n;
@@ -289,7 +291,7 @@ float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad)
 
 // NO bounce protection, as bounces are limited!
 void W_Crylink_Touch(void)
-{
+{SELFPARAM();
        float finalhit;
        float f;
        float isprimary = !(self.projectiledeathtype & HITTYPE_SECONDARY);
@@ -334,27 +336,27 @@ void W_Crylink_Touch(void)
 }
 
 void W_Crylink_Fadethink(void)
-{
+{SELFPARAM();
        W_Crylink_Dequeue(self);
        remove(self);
 }
 
-void W_Crylink_Attack(void)
-{
+void W_Crylink_Attack(Weapon thiswep)
+{SELFPARAM();
        float counter, shots;
        entity proj, prevproj, firstproj;
        vector s;
        vector forward, right, up;
        float maxdmg;
 
-       W_DecreaseAmmo(WEP_CVAR_PRI(crylink, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(crylink, ammo));
 
        maxdmg = WEP_CVAR_PRI(crylink, damage) * WEP_CVAR_PRI(crylink, shots);
        maxdmg *= 1 + WEP_CVAR_PRI(crylink, bouncedamagefactor) * WEP_CVAR_PRI(crylink, bounces);
        if(WEP_CVAR_PRI(crylink, joinexplode))
                maxdmg += WEP_CVAR_PRI(crylink, joinexplode_damage);
 
-       W_SetupShot(self, false, 2, W_Sound("crylink_fire"), CH_WEAPON_A, maxdmg);
+       W_SetupShot(self, false, 2, SND(CRYLINK_FIRE), CH_WEAPON_A, maxdmg);
        forward = v_forward;
        right = v_right;
        up = v_up;
@@ -448,22 +450,22 @@ void W_Crylink_Attack(void)
        }
 }
 
-void W_Crylink_Attack2(void)
-{
+void W_Crylink_Attack2(Weapon thiswep)
+{SELFPARAM();
        float counter, shots;
        entity proj, prevproj, firstproj;
        vector s;
        vector forward, right, up;
        float maxdmg;
 
-       W_DecreaseAmmo(WEP_CVAR_SEC(crylink, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(crylink, ammo));
 
        maxdmg = WEP_CVAR_SEC(crylink, damage) * WEP_CVAR_SEC(crylink, shots);
        maxdmg *= 1 + WEP_CVAR_SEC(crylink, bouncedamagefactor) * WEP_CVAR_SEC(crylink, bounces);
        if(WEP_CVAR_SEC(crylink, joinexplode))
                maxdmg += WEP_CVAR_SEC(crylink, joinexplode_damage);
 
-       W_SetupShot(self, false, 2, W_Sound("crylink_fire2"), CH_WEAPON_A, maxdmg);
+       W_SetupShot(self, false, 2, SND(CRYLINK_FIRE2), CH_WEAPON_A, maxdmg);
        forward = v_forward;
        right = v_right;
        up = v_up;
@@ -564,168 +566,133 @@ void W_Crylink_Attack2(void)
        }
 }
 
-bool W_Crylink(int req)
-{
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Crylink, wr_aim, void(entity thiswep))
                {
+                       SELFPARAM();
                        if(random() < 0.10)
                                self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(crylink, speed), 0, WEP_CVAR_PRI(crylink, middle_lifetime), false);
                        else
                                self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(crylink, speed), 0, WEP_CVAR_SEC(crylink, middle_lifetime), false);
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Crylink, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
+                       if(autocvar_g_balance_crylink_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       }
 
-                       if(self.BUTTON_ATCK)
+                       if(fire1)
                        {
-                               if(self.crylink_waitrelease != 1)
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(crylink, refire)))
+                               if(actor.crylink_waitrelease != 1)
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(crylink, refire)))
                                {
-                                       W_Crylink_Attack();
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(crylink, animtime), w_ready);
+                                       W_Crylink_Attack(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(crylink, animtime), w_ready);
                                }
                        }
 
-                       if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary)
+                       if(fire2 && autocvar_g_balance_crylink_secondary)
                        {
-                               if(self.crylink_waitrelease != 2)
-                               if(weapon_prepareattack(1, WEP_CVAR_SEC(crylink, refire)))
+                               if(actor.crylink_waitrelease != 2)
+                               if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(crylink, refire)))
                                {
-                                       W_Crylink_Attack2();
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(crylink, animtime), w_ready);
+                                       W_Crylink_Attack2(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(crylink, animtime), w_ready);
                                }
                        }
 
-                       if((self.crylink_waitrelease == 1 && !self.BUTTON_ATCK) || (self.crylink_waitrelease == 2 && !self.BUTTON_ATCK2))
+                       if((actor.crylink_waitrelease == 1 && !fire1) || (actor.crylink_waitrelease == 2 && !fire2))
                        {
-                               if(!self.crylink_lastgroup || time > self.crylink_lastgroup.teleport_time)
+                               if(!actor.crylink_lastgroup || time > actor.crylink_lastgroup.teleport_time)
                                {
                                        // fired and released now!
-                                       if(self.crylink_lastgroup)
+                                       if(actor.crylink_lastgroup)
                                        {
                                                vector pos;
                                                entity linkjoineffect;
-                                               float isprimary = (self.crylink_waitrelease == 1);
+                                               float isprimary = (actor.crylink_waitrelease == 1);
 
-                                               pos = W_Crylink_LinkJoin(self.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
+                                               pos = W_Crylink_LinkJoin(actor.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
 
                                                linkjoineffect = spawn();
                                                linkjoineffect.think = W_Crylink_LinkJoinEffect_Think;
                                                linkjoineffect.classname = "linkjoineffect";
                                                linkjoineffect.nextthink = time + w_crylink_linkjoin_time;
-                                               linkjoineffect.owner = self;
+                                               linkjoineffect.owner = actor;
                                                setorigin(linkjoineffect, pos);
                                        }
-                                       self.crylink_waitrelease = 0;
-                                       if(!W_Crylink(WR_CHECKAMMO1) && !W_Crylink(WR_CHECKAMMO2))
-                                       if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+                                       actor.crylink_waitrelease = 0;
+                                       if(!thiswep.wr_checkammo1(thiswep) && !thiswep.wr_checkammo2(thiswep))
+                                       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                                        {
                                                // ran out of ammo!
-                                               self.cnt = WEP_CRYLINK.m_id;
-                                               self.switchweapon = w_getbestweapon(self);
+                                               actor.cnt = WEP_CRYLINK.m_id;
+                                               actor.switchweapon = w_getbestweapon(actor);
                                        }
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Crylink, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_crylink.md3"));
-                       precache_model(W_Model("v_crylink.md3"));
-                       precache_model(W_Model("h_crylink.iqm"));
-                       precache_sound(W_Sound("crylink_fire"));
-                       precache_sound(W_Sound("crylink_fire2"));
-                       precache_sound(W_Sound("crylink_linkjoin"));
                        CRYLINK_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Crylink, wr_checkammo1, bool(entity thiswep))
                {
+                       SELFPARAM();
                        // don't "run out of ammo" and switch weapons while waiting for release
                        if(self.crylink_lastgroup && self.crylink_waitrelease)
                                return true;
 
-                       ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_PRI(crylink, ammo);
+                       float ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_PRI(crylink, ammo);
                        ammo_amount += self.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(Crylink, wr_checkammo2, bool(entity thiswep))
                {
+                       SELFPARAM();
                        // don't "run out of ammo" and switch weapons while waiting for release
                        if(self.crylink_lastgroup && self.crylink_waitrelease)
                                return true;
 
-                       ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_SEC(crylink, ammo);
+                       float ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_SEC(crylink, ammo);
                        ammo_amount += self.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(Crylink, wr_config, void(entity thiswep))
                {
                        CRYLINK_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Crylink, wr_reload, void(entity thiswep))
                {
-                       W_Reload(min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Crylink, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_CRYLINK_SUICIDE;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Crylink, wr_killmessage, int(entity thiswep))
                {
                        return WEAPON_CRYLINK_MURDER;
                }
-       }
-       return false;
-}
 #endif
 #ifdef CSQC
-bool W_Crylink(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+               METHOD(Crylink, wr_impacteffect, void(entity thiswep))
                {
+                       SELFPARAM();
                        vector org2;
                        org2 = w_org + w_backoff * 2;
                        if(w_deathtype & HITTYPE_SECONDARY)
                        {
                                pointparticles(particleeffectnum(EFFECT_CRYLINK_IMPACT2), org2, '0 0 0', 1);
                                if(!w_issilent)
-                                       sound(self, CH_SHOTS, W_Sound("crylink_impact2"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_CRYLINK_IMPACT2, VOL_BASE, ATTN_NORM);
                        }
                        else
                        {
                                pointparticles(particleeffectnum(EFFECT_CRYLINK_IMPACT), org2, '0 0 0', 1);
                                if(!w_issilent)
-                                       sound(self, CH_SHOTS, W_Sound("crylink_impact"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_CRYLINK_IMPACT, VOL_BASE, ATTN_NORM);
                        }
-
-                       return true;
                }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("crylink_impact2"));
-                       precache_sound(W_Sound("crylink_impact"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
 #endif
 #endif
index 9a235bf35d5206b4d5d8fe049aa355d85ad5a50c..8c080862db500649b02d61508b1c1ae90b0c4a8d 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ DEVASTATOR,
-/* function  */ W_Devastator,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 9,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '1 1 0',
-/* modelname */ "rl",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairrocketlauncher 0.7",
-/* wepimg    */ "weaponrocketlauncher",
-/* refname   */ "devastator",
-/* wepname   */ _("Devastator")
-);
+CLASS(Devastator, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Devastator, mdl, string, "rl");
+#ifndef MENUQC
+/* model     */ ATTRIB(Devastator, m_model, Model, MDL_DEVASTATOR_ITEM);
+#endif
+/* crosshair */ ATTRIB(Devastator, w_crosshair, string, "gfx/crosshairrocketlauncher");
+/* crosshair */ ATTRIB(Devastator, w_crosshair_size, float, 0.7);
+/* wepimg    */ ATTRIB(Devastator, model2, string, "weaponrocketlauncher");
+/* refname   */ ATTRIB(Devastator, netname, string, "devastator");
+/* wepname   */ ATTRIB(Devastator, message, string, _("Devastator"));
+ENDCLASS(Devastator)
+REGISTER_WEAPON(DEVASTATOR, NEW(Devastator));
 
 #define DEVASTATOR_SETTINGS(w_cvar,w_prop) DEVASTATOR_SETTINGS_LIST(w_cvar, w_prop, DEVASTATOR, devastator)
 #define DEVASTATOR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -62,11 +64,11 @@ DEVASTATOR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_devastator(void) { weapon_defaultspawnfunc(WEP_DEVASTATOR.m_id); }
-void spawnfunc_weapon_rocketlauncher(void) { spawnfunc_weapon_devastator(); }
+spawnfunc(weapon_devastator) { weapon_defaultspawnfunc(WEP_DEVASTATOR.m_id); }
+spawnfunc(weapon_rocketlauncher) { spawnfunc_weapon_devastator(this); }
 
 void W_Devastator_Unregister(void)
-{
+{SELFPARAM();
        if(self.realowner && self.realowner.lastrocket == self)
        {
                self.realowner.lastrocket = world;
@@ -75,7 +77,7 @@ void W_Devastator_Unregister(void)
 }
 
 void W_Devastator_Explode(void)
-{
+{SELFPARAM();
        W_Devastator_Unregister();
 
        if(other.takedamage == DAMAGE_AIM)
@@ -115,7 +117,7 @@ void W_Devastator_Explode(void)
 }
 
 void W_Devastator_DoRemoteExplode(void)
-{
+{SELFPARAM();
        W_Devastator_Unregister();
 
        self.event_damage = func_null;
@@ -194,7 +196,7 @@ void W_Devastator_DoRemoteExplode(void)
 }
 
 void W_Devastator_RemoteExplode(void)
-{
+{SELFPARAM();
        if(self.realowner.deadflag == DEAD_NO)
        if(self.realowner.lastrocket)
        {
@@ -242,7 +244,7 @@ vector W_Devastator_SteerTo(vector thisdir, vector goaldir, float maxturn_cos)
 //   normalize(0)
 
 void W_Devastator_Think(void)
-{
+{SELFPARAM();
        vector desireddir, olddir, newdir, desiredorigin, goal;
        float velspeed, f;
        self.nextthink = time;
@@ -295,7 +297,7 @@ void W_Devastator_Think(void)
                        {
                                Send_Effect(EFFECT_ROCKET_GUIDE, self.origin, self.velocity, 1);
                                // TODO add a better sound here
-                               sound(self.realowner, CH_WEAPON_B, W_Sound("rocket_mode"), VOL_BASE, ATTN_NORM);
+                               sound(self.realowner, CH_WEAPON_B, SND_ROCKET_MODE, VOL_BASE, ATTN_NORM);
                                self.count = 1;
                        }
                }
@@ -309,7 +311,7 @@ void W_Devastator_Think(void)
 }
 
 void W_Devastator_Touch(void)
-{
+{SELFPARAM();
        if(WarpZone_Projectile_Touch())
        {
                if(wasfreed(self))
@@ -321,7 +323,7 @@ void W_Devastator_Touch(void)
 }
 
 void W_Devastator_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -335,14 +337,14 @@ void W_Devastator_Damage(entity inflictor, entity attacker, float damage, int de
                W_PrepareExplosionByDamage(attacker, W_Devastator_Explode);
 }
 
-void W_Devastator_Attack(void)
-{
+void W_Devastator_Attack(Weapon thiswep)
+{SELFPARAM();
        entity missile;
        entity flash;
 
-       W_DecreaseAmmo(WEP_CVAR(devastator, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR(devastator, ammo));
 
-       W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 5, W_Sound("rocket_fire"), CH_WEAPON_A, WEP_CVAR(devastator, damage));
+       W_SetupShot_ProjectileSize(self, '-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);
 
        missile = WarpZone_RefSys_SpawnSameRefSys(self);
@@ -383,24 +385,17 @@ void W_Devastator_Attack(void)
 
        // muzzle flash for 1st person view
        flash = spawn();
-       setmodel(flash, "models/flash.md3"); // precision set below
+       setmodel(flash, MDL_DEVASTATOR_MUZZLEFLASH); // precision set below
        SUB_SetFade(flash, time, 0.1);
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-       W_AttachToShotorg(flash, '5 0 0');
+       W_AttachToShotorg(self, flash, '5 0 0');
 
        // common properties
        MUTATOR_CALLHOOK(EditProjectile, self, missile);
 }
 
-bool W_Devastator(int req)
-{
-       entity rock;
-       float rockfound;
-       float ammo_amount;
-       switch(req)
-       {
                #if 0
-               case WR_AIM:
+               METHOD(Devastator, wr_aim, void(entity thiswep))
                {
                        // aim and decide to fire if appropriate
                        self.BUTTON_ATCK = bot_aim(WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false);
@@ -425,11 +420,9 @@ bool W_Devastator(int req)
 
                                if(self.BUTTON_ATCK2) self.BUTTON_ATCK = false;
                        }
-
-                       return true;
                }
                #else
-               case WR_AIM:
+               METHOD(Devastator, wr_aim, void(entity thiswep))
                {
                        // aim and decide to fire if appropriate
                        self.BUTTON_ATCK = bot_aim(WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false);
@@ -523,69 +516,54 @@ bool W_Devastator(int req)
                                //      dprint(ftos(desirabledamage),"\n");
                                if(self.BUTTON_ATCK2 == true) self.BUTTON_ATCK = false;
                        }
-
-                       return true;
                }
                #endif
-               case WR_THINK:
+               METHOD(Devastator, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(WEP_CVAR(devastator, reload_ammo) && self.clip_load < WEP_CVAR(devastator, ammo)) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else
-                       {
-                               if(self.BUTTON_ATCK)
+                       if(WEP_CVAR(devastator, reload_ammo) && actor.clip_load < WEP_CVAR(devastator, ammo)) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else {
+                               if(fire1)
                                {
-                                       if(self.rl_release || WEP_CVAR(devastator, guidestop))
-                                       if(weapon_prepareattack(0, WEP_CVAR(devastator, refire)))
+                                       if(actor.rl_release || WEP_CVAR(devastator, guidestop))
+                                       if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(devastator, refire)))
                                        {
-                                               W_Devastator_Attack();
-                                               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(devastator, animtime), w_ready);
-                                               self.rl_release = 0;
+                                               W_Devastator_Attack(thiswep);
+                                               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(devastator, animtime), w_ready);
+                                               actor.rl_release = 0;
                                        }
                                }
                                else
-                                       self.rl_release = 1;
+                                       actor.rl_release = 1;
 
-                               if(self.BUTTON_ATCK2)
-                               if(self.switchweapon == WEP_DEVASTATOR.m_id)
+                               if(fire2)
+                               if(actor.switchweapon == WEP_DEVASTATOR.m_id)
                                {
-                                       rockfound = 0;
-                                       for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self)
+                                       entity rock;
+                                       bool rockfound = false;
+                                       for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == actor)
                                        {
                                                if(!rock.rl_detonate_later)
                                                {
                                                        rock.rl_detonate_later = true;
-                                                       rockfound = 1;
+                                                       rockfound = true;
                                                }
                                        }
                                        if(rockfound)
-                                               sound(self, CH_WEAPON_B, W_Sound("rocket_det"), VOL_BASE, ATTN_NORM);
+                                               sound(actor, CH_WEAPON_B, SND_ROCKET_DET, VOL_BASE, ATTN_NORM);
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Devastator, wr_init, void(entity thiswep))
                {
-                       //if(autocvar_sv_precacheweapons)
-                       //{
-                               precache_model("models/flash.md3");
-                               precache_model(W_Model("g_rl.md3"));
-                               precache_model(W_Model("v_rl.md3"));
-                               precache_model(W_Model("h_rl.iqm"));
-                               precache_sound(W_Sound("rocket_det"));
-                               precache_sound(W_Sound("rocket_fire"));
-                               precache_sound(W_Sound("rocket_mode"));
-                       //}
                        DEVASTATOR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_SETUP:
+               METHOD(Devastator, wr_setup, void(entity thiswep))
                {
                        self.rl_release = 1;
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Devastator, wr_checkammo1, bool(entity thiswep))
                {
                        #if 0
                        // don't switch while guiding a missile
@@ -616,72 +594,50 @@ bool W_Devastator(int req)
                                return ammo_amount;
                        }
                        #else
-                       ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo);
+                       float ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo);
                        ammo_amount += self.(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
                        return ammo_amount;
                        #endif
                }
-               case WR_CHECKAMMO2:
+               METHOD(Devastator, wr_checkammo2, bool(entity thiswep))
                {
                        return false;
                }
-               case WR_CONFIG:
+               METHOD(Devastator, wr_config, void(entity thiswep))
                {
                        DEVASTATOR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(Devastator, wr_resetplayer, void(entity thiswep))
                {
                        self.rl_release = 0;
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Devastator, wr_reload, void(entity thiswep))
                {
-                       W_Reload(WEP_CVAR(devastator, ammo), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, WEP_CVAR(devastator, ammo), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Devastator, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_DEVASTATOR_SUICIDE;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Devastator, wr_killmessage, int(entity thiswep))
                {
                        if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
                                return WEAPON_DEVASTATOR_MURDER_SPLASH;
                        else
                                return WEAPON_DEVASTATOR_MURDER_DIRECT;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_Devastator(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Devastator, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 12;
                        pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), org2, '0 0 0', 1);
                        if(!w_issilent)
-                               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTN_NORM);
-
-                       return true;
+                               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTN_NORM);
                }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("rocket_impact"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 0f60fd29d3568b6b430ba864ed9c23882e60f9e1..7321d38f2aed1fcd60b90b1552783013e8e59a27 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ ELECTRO,
-/* function  */ W_Electro,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 5,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0 0.5 1',
-/* modelname */ "electro",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairelectro 0.6",
-/* wepimg    */ "weaponelectro",
-/* refname   */ "electro",
-/* wepname   */ _("Electro")
-);
+CLASS(Electro, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Electro, mdl, string, "electro");
+#ifndef MENUQC
+/* model     */ ATTRIB(Electro, m_model, Model, MDL_ELECTRO_ITEM);
+#endif
+/* crosshair */ ATTRIB(Electro, w_crosshair, string, "gfx/crosshairelectro");
+/* crosshair */ ATTRIB(Electro, w_crosshair_size, float, 0.6);
+/* wepimg    */ ATTRIB(Electro, model2, string, "weaponelectro");
+/* refname   */ ATTRIB(Electro, netname, string, "electro");
+/* wepname   */ ATTRIB(Electro, message, string, _("Electro"));
+ENDCLASS(Electro)
+REGISTER_WEAPON(ELECTRO, NEW(Electro));
 
 #define ELECTRO_SETTINGS(w_cvar,w_prop) ELECTRO_SETTINGS_LIST(w_cvar, w_prop, ELECTRO, electro)
 #define ELECTRO_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -67,7 +69,7 @@ void W_Electro_ExplodeCombo(void);
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_electro(void) { weapon_defaultspawnfunc(WEP_ELECTRO.m_id); }
+spawnfunc(weapon_electro) { weapon_defaultspawnfunc(WEP_ELECTRO.m_id); }
 
 void W_Electro_TriggerCombo(vector org, float rad, entity own)
 {
@@ -117,7 +119,7 @@ void W_Electro_TriggerCombo(vector org, float rad, entity own)
 }
 
 void W_Electro_ExplodeCombo(void)
-{
+{SELFPARAM();
        W_Electro_TriggerCombo(self.origin, WEP_CVAR(electro, combo_comboradius), self.realowner);
 
        self.event_damage = func_null;
@@ -139,7 +141,7 @@ void W_Electro_ExplodeCombo(void)
 }
 
 void W_Electro_Explode(void)
-{
+{SELFPARAM();
        if(other.takedamage == DAMAGE_AIM)
                if(IS_PLAYER(other))
                        if(DIFF_TEAM(self.realowner, other))
@@ -192,7 +194,7 @@ void W_Electro_TouchExplode(void)
 }
 
 void W_Electro_Bolt_Think(void)
-{
+{SELFPARAM();
        if(time >= self.ltime)
        {
                self.use();
@@ -243,11 +245,11 @@ void W_Electro_Bolt_Think(void)
        else { self.nextthink = self.ltime; }
 }
 
-void W_Electro_Attack_Bolt(void)
-{
+void W_Electro_Attack_Bolt(Weapon thiswep)
+{SELFPARAM();
        entity proj;
 
-       W_DecreaseAmmo(WEP_CVAR_PRI(electro, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(electro, ammo));
 
        W_SetupShot_ProjectileSize(
                self,
@@ -255,7 +257,7 @@ void W_Electro_Attack_Bolt(void)
                '0 0 -3',
                false,
                2,
-               W_Sound("electro_fire"),
+               SND(ELECTRO_FIRE),
                CH_WEAPON_A,
                WEP_CVAR_PRI(electro, damage)
        );
@@ -289,20 +291,20 @@ void W_Electro_Attack_Bolt(void)
 }
 
 void W_Electro_Orb_Touch(void)
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
        if(other.takedamage == DAMAGE_AIM)
                { if(WEP_CVAR_SEC(electro, touchexplode)) { W_Electro_Explode(); } }
        else
        {
                //UpdateCSQCProjectile(self);
-               spamsound(self, CH_SHOTS, W_Sound("electro_bounce"), VOL_BASE, ATTEN_NORM);
+               spamsound(self, CH_SHOTS, SND(ELECTRO_BOUNCE), VOL_BASE, ATTEN_NORM);
                self.projectiledeathtype |= HITTYPE_BOUNCE;
        }
 }
 
 void W_Electro_Orb_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -343,9 +345,9 @@ void W_Electro_Orb_Damage(entity inflictor, entity attacker, float damage, int d
        }
 }
 
-void W_Electro_Attack_Orb(void)
-{
-       W_DecreaseAmmo(WEP_CVAR_SEC(electro, ammo));
+void W_Electro_Attack_Orb(Weapon thiswep)
+{SELFPARAM();
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(electro, ammo));
 
        W_SetupShot_ProjectileSize(
                self,
@@ -353,7 +355,7 @@ void W_Electro_Attack_Orb(void)
                '0 0 -4',
                false,
                2,
-               W_Sound("electro_fire2"),
+               SND(ELECTRO_FIRE2),
                CH_WEAPON_A,
                WEP_CVAR_SEC(electro, damage)
        );
@@ -395,7 +397,7 @@ void W_Electro_Attack_Orb(void)
        entity p2;
        p2 = spawn();
        copyentity(proj, p2);
-       setmodel(p2, "models/ebomb.mdl");
+       setmodel(p2, MDL_PROJECTILE_ELECTRO);
        setsize(p2, proj.mins, proj.maxs);
 #endif
 
@@ -404,28 +406,24 @@ void W_Electro_Attack_Orb(void)
        MUTATOR_CALLHOOK(EditProjectile, self, proj);
 }
 
-void W_Electro_CheckAttack(void)
-{
+void W_Electro_CheckAttack(Weapon thiswep, entity actor, bool fire1, bool fire2)
+{SELFPARAM();
        if(self.electro_count > 1)
        if(self.BUTTON_ATCK2)
-       if(weapon_prepareattack(1, -1))
+       if(weapon_prepareattack(thiswep, actor, true, -1))
        {
-               W_Electro_Attack_Orb();
+               W_Electro_Attack_Orb(WEP_ELECTRO);
                self.electro_count -= 1;
-               weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
+               weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
                return;
        }
        // WEAPONTODO: when the player releases the button, cut down the length of refire2?
-       w_ready();
+       w_ready(thiswep, actor, fire1, fire2);
 }
 
 .float bot_secondary_electromooth;
-bool W_Electro(int req)
-{
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+
+               METHOD(Electro, wr_aim, void(entity thiswep))
                {
                        self.BUTTON_ATCK = self.BUTTON_ATCK2 = false;
                        if(vlen(self.origin-self.enemy.origin) > 1000) { self.bot_secondary_electromooth = 0; }
@@ -452,71 +450,58 @@ bool W_Electro(int req)
                                        if(random() < 0.03) self.bot_secondary_electromooth = 0;
                                }
                        }
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Electro, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
                        if(autocvar_g_balance_electro_reload_ammo) // forced reload // WEAPONTODO
                        {
-                               ammo_amount = 0;
-                               if(self.clip_load >= WEP_CVAR_PRI(electro, ammo))
+                               float ammo_amount = 0;
+                               if(actor.clip_load >= WEP_CVAR_PRI(electro, ammo))
                                        ammo_amount = 1;
-                               if(self.clip_load >= WEP_CVAR_SEC(electro, ammo))
+                               if(actor.clip_load >= WEP_CVAR_SEC(electro, ammo))
                                        ammo_amount += 1;
 
                                if(!ammo_amount)
                                {
-                                       WEP_ACTION(self.weapon, WR_RELOAD);
-                                       return false;
+                                       Weapon w = get_weaponinfo(actor.weapon);
+                                       w.wr_reload(w);
+                                       return;
                                }
-
-                               return true;
                        }
 
-                       if(self.BUTTON_ATCK)
+                       if(fire1)
                        {
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(electro, refire)))
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(electro, refire)))
                                {
-                                               W_Electro_Attack_Bolt();
-                                               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
+                                               W_Electro_Attack_Bolt(thiswep);
+                                               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
                                }
                        }
-                       else if(self.BUTTON_ATCK2)
+                       else if(fire2)
                        {
-                               if(time >= self.electro_secondarytime)
-                               if(weapon_prepareattack(1, WEP_CVAR_SEC(electro, refire)))
+                               if(time >= actor.electro_secondarytime)
+                               if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(electro, refire)))
                                {
-                                       W_Electro_Attack_Orb();
-                                       self.electro_count = WEP_CVAR_SEC(electro, count);
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
-                                       self.electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor();
+                                       W_Electro_Attack_Orb(thiswep);
+                                       actor.electro_count = WEP_CVAR_SEC(electro, count);
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
+                                       actor.electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor();
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Electro, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_electro.md3"));
-                       precache_model(W_Model("v_electro.md3"));
-                       precache_model(W_Model("h_electro.iqm"));
-                       precache_sound(W_Sound("electro_bounce"));
-                       precache_sound(W_Sound("electro_fire"));
-                       precache_sound(W_Sound("electro_fire2"));
-                       precache_sound(W_Sound("electro_impact"));
-                       precache_sound(W_Sound("electro_impact_combo"));
                        ELECTRO_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Electro, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_PRI(electro, ammo);
+                       float ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_PRI(electro, ammo);
                        ammo_amount += self.(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_PRI(electro, ammo);
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(Electro, wr_checkammo2, bool(entity thiswep))
                {
+                       float ammo_amount;
                        if(WEP_CVAR(electro, combo_safeammocheck)) // true if you can fire at least one secondary blob AND one primary shot after it, otherwise false.
                        {
                                ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
@@ -529,29 +514,26 @@ bool W_Electro(int req)
                        }
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(Electro, wr_config, void(entity thiswep))
                {
                        ELECTRO_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(Electro, wr_resetplayer, void(entity thiswep))
                {
                        self.electro_secondarytime = time;
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Electro, wr_reload, void(entity thiswep))
                {
-                       W_Reload(min(WEP_CVAR_PRI(electro, ammo), WEP_CVAR_SEC(electro, ammo)), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, min(WEP_CVAR_PRI(electro, ammo), WEP_CVAR_SEC(electro, ammo)), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Electro, wr_suicidemessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_ELECTRO_SUICIDE_ORBS;
                        else
                                return WEAPON_ELECTRO_SUICIDE_BOLT;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Electro, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                        {
@@ -565,16 +547,11 @@ bool W_Electro(int req)
                                        return WEAPON_ELECTRO_MURDER_BOLT;
                        }
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_Electro(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Electro, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 6;
@@ -582,7 +559,7 @@ bool W_Electro(int req)
                        {
                                pointparticles(particleeffectnum(EFFECT_ELECTRO_BALLEXPLODE), org2, '0 0 0', 1);
                                if(!w_issilent)
-                                       sound(self, CH_SHOTS, W_Sound("electro_impact"), VOL_BASE, ATTEN_NORM);
+                                       sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_NORM);
                        }
                        else
                        {
@@ -591,31 +568,16 @@ bool W_Electro(int req)
                                        // this is sent as "primary (w_deathtype & HITTYPE_BOUNCE)" to distinguish it from (w_deathtype & HITTYPE_SECONDARY) bounced balls
                                        pointparticles(particleeffectnum(EFFECT_ELECTRO_COMBO), org2, '0 0 0', 1);
                                        if(!w_issilent)
-                                               sound(self, CH_SHOTS, W_Sound("electro_impact_combo"), VOL_BASE, ATTEN_NORM);
+                                               sound(self, CH_SHOTS, SND_ELECTRO_IMPACT_COMBO, VOL_BASE, ATTEN_NORM);
                                }
                                else
                                {
                                        pointparticles(particleeffectnum(EFFECT_ELECTRO_IMPACT), org2, '0 0 0', 1);
                                        if(!w_issilent)
-                                               sound(self, CH_SHOTS, W_Sound("electro_impact"), VOL_BASE, ATTEN_NORM);
+                                               sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_NORM);
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("electro_impact"));
-                       precache_sound(W_Sound("electro_impact_combo"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 4f8f3787c3443335c0d91ca11aa72c5648d5b484..b0761b2c2ad1006623ab473ca9b7cbe912476c99 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ FIREBALL,
-/* function  */ W_Fireball,
-/* ammotype  */ ammo_none,
-/* impulse   */ 9,
-/* flags     */ WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 0.5 0',
-/* modelname */ "fireball",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairfireball",
-/* wepimg    */ "weaponfireball",
-/* refname   */ "fireball",
-/* wepname   */ _("Fireball")
-);
+CLASS(Fireball, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Fireball, mdl, string, "fireball");
+#ifndef MENUQC
+/* model     */ ATTRIB(Fireball, m_model, Model, MDL_FIREBALL_ITEM);
+#endif
+/* crosshair */ ATTRIB(Fireball, w_crosshair, string, "gfx/crosshairfireball");
+/* crosshair */ //ATTRIB(Fireball, w_crosshair_size, float, 0.65);
+/* wepimg    */ ATTRIB(Fireball, model2, string, "weaponfireball");
+/* refname   */ ATTRIB(Fireball, netname, string, "fireball");
+/* wepname   */ ATTRIB(Fireball, message, string, _("Fireball"));
+ENDCLASS(Fireball)
+REGISTER_WEAPON(FIREBALL, NEW(Fireball));
 
 #define FIREBALL_SETTINGS(w_cvar,w_prop) FIREBALL_SETTINGS_LIST(w_cvar, w_prop, FIREBALL, fireball)
 #define FIREBALL_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -55,10 +57,10 @@ FIREBALL_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_fireball(void) { weapon_defaultspawnfunc(WEP_FIREBALL.m_id); }
+spawnfunc(weapon_fireball) { weapon_defaultspawnfunc(WEP_FIREBALL.m_id); }
 
 void W_Fireball_Explode(void)
-{
+{SELFPARAM();
        entity e;
        float dist;
        float points;
@@ -114,7 +116,7 @@ void W_Fireball_TouchExplode(void)
 }
 
 void W_Fireball_LaserPlay(float dt, float dist, float damage, float edgedamage, float burntime)
-{
+{SELFPARAM();
        entity e;
        float d;
        vector p;
@@ -148,7 +150,7 @@ void W_Fireball_LaserPlay(float dt, float dist, float damage, float edgedamage,
 }
 
 void W_Fireball_Think(void)
-{
+{SELFPARAM();
        if(time > self.pushltime)
        {
                self.cnt = 1;
@@ -163,7 +165,7 @@ void W_Fireball_Think(void)
 }
 
 void W_Fireball_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -179,10 +181,10 @@ void W_Fireball_Damage(entity inflictor, entity attacker, float damage, int deat
 }
 
 void W_Fireball_Attack1(void)
-{
+{SELFPARAM();
        entity proj;
 
-       W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', false, 2, W_Sound("fireball_fire2"), CH_WEAPON_A, WEP_CVAR_PRI(fireball, damage) + WEP_CVAR_PRI(fireball, bfgdamage));
+       W_SetupShot_ProjectileSize(self, '-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);
 
@@ -218,45 +220,45 @@ void W_Fireball_Attack1(void)
 }
 
 void W_Fireball_AttackEffect(float i, vector f_diff)
-{
+{SELFPARAM();
        W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', false, 0, "", 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(void)
+void W_Fireball_Attack1_Frame4(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
        W_Fireball_Attack1();
-       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), w_ready);
+       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), w_ready);
 }
 
-void W_Fireball_Attack1_Frame3(void)
+void W_Fireball_Attack1_Frame3(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
        W_Fireball_AttackEffect(0, '+1.25 +3.75 0');
-       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame4);
+       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame4);
 }
 
-void W_Fireball_Attack1_Frame2(void)
+void W_Fireball_Attack1_Frame2(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
        W_Fireball_AttackEffect(0, '-1.25 +3.75 0');
-       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame3);
+       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame3);
 }
 
-void W_Fireball_Attack1_Frame1(void)
+void W_Fireball_Attack1_Frame1(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
        W_Fireball_AttackEffect(1, '+1.25 -3.75 0');
-       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame2);
+       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame2);
 }
 
-void W_Fireball_Attack1_Frame0(void)
-{
+void W_Fireball_Attack1_Frame0(Weapon thiswep, entity actor, bool fire1, bool fire2)
+{SELFPARAM();
        W_Fireball_AttackEffect(0, '-1.25 -3.75 0');
-       sound(self, CH_WEAPON_SINGLE, W_Sound("fireball_prefire2"), VOL_BASE, ATTEN_NORM);
-       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame1);
+       sound(self, CH_WEAPON_SINGLE, SND_FIREBALL_PREFIRE2, VOL_BASE, ATTEN_NORM);
+       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame1);
 }
 
 void W_Fireball_Firemine_Think(void)
-{
+{SELFPARAM();
        if(time > self.pushltime)
        {
                remove(self);
@@ -282,7 +284,7 @@ void W_Fireball_Firemine_Think(void)
 }
 
 void W_Fireball_Firemine_Touch(void)
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
        if(other.takedamage == DAMAGE_AIM)
        if(Fire_AddDamage(other, self.realowner, WEP_CVAR_SEC(fireball, damage), WEP_CVAR_SEC(fireball, damagetime), self.projectiledeathtype) >= 0)
@@ -294,7 +296,7 @@ void W_Fireball_Firemine_Touch(void)
 }
 
 void W_Fireball_Attack2(void)
-{
+{SELFPARAM();
        entity proj;
        vector f_diff;
        float c;
@@ -316,7 +318,7 @@ void W_Fireball_Attack2(void)
                        f_diff = '+1.25 +3.75 0';
                        break;
        }
-       W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', false, 2, W_Sound("fireball_fire"), CH_WEAPON_A, WEP_CVAR_SEC(fireball, damage));
+       W_SetupShot_ProjectileSize(self, '-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, self);
        w_shotorg = trace_endpos;
 
@@ -348,11 +350,7 @@ void W_Fireball_Attack2(void)
        MUTATOR_CALLHOOK(EditProjectile, self, proj);
 }
 
-bool W_Fireball(int req)
-{
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Fireball, wr_aim, void(entity thiswep))
                {
                        self.BUTTON_ATCK = false;
                        self.BUTTON_ATCK2 = false;
@@ -372,87 +370,70 @@ bool W_Fireball(int req)
                                        if(random() < 0.01) self.bot_primary_fireballmooth = 1;
                                }
                        }
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Fireball, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(self.BUTTON_ATCK)
+                       if(fire1)
                        {
-                               if(time >= self.fireball_primarytime)
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(fireball, refire)))
+                               if(time >= actor.fireball_primarytime)
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(fireball, refire)))
                                {
-                                       W_Fireball_Attack1_Frame0();
-                                       self.fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor();
+                                       W_Fireball_Attack1_Frame0(thiswep, actor, fire1, fire2);
+                                       actor.fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor();
                                }
                        }
-                       else if(self.BUTTON_ATCK2)
+                       else if(fire2)
                        {
-                               if(weapon_prepareattack(1, WEP_CVAR_SEC(fireball, refire)))
+                               if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(fireball, refire)))
                                {
                                        W_Fireball_Attack2();
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(fireball, animtime), w_ready);
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(fireball, animtime), w_ready);
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Fireball, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_fireball.md3"));
-                       precache_model(W_Model("v_fireball.md3"));
-                       precache_model(W_Model("h_fireball.iqm"));
-                       precache_model("models/sphere/sphere.md3");
-                       precache_sound(W_Sound("fireball_fire"));
-                       precache_sound(W_Sound("fireball_fire2"));
-                       precache_sound(W_Sound("fireball_prefire2"));
                        FIREBALL_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_SETUP:
+               METHOD(Fireball, wr_setup, void(entity thiswep))
                {
                        self.ammo_field = ammo_none;
-                       return true;
                }
-               case WR_CHECKAMMO1:
-               case WR_CHECKAMMO2:
+               METHOD(Fireball, wr_checkammo1, bool(entity thiswep))
+               {
+                       return true; // infinite ammo
+               }
+               METHOD(Fireball, wr_checkammo2, bool(entity thiswep))
                {
                        return true; // fireball has infinite ammo
                }
-               case WR_CONFIG:
+               METHOD(Fireball, wr_config, void(entity thiswep))
                {
                        FIREBALL_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(Fireball, wr_resetplayer, void(entity thiswep))
                {
                        self.fireball_primarytime = time;
-                       return true;
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Fireball, wr_suicidemessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_FIREBALL_SUICIDE_FIREMINE;
                        else
                                return WEAPON_FIREBALL_SUICIDE_BLAST;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Fireball, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_FIREBALL_MURDER_FIREMINE;
                        else
                                return WEAPON_FIREBALL_MURDER_BLAST;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_Fireball(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Fireball, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        if(w_deathtype & HITTYPE_SECONDARY)
@@ -464,23 +445,9 @@ bool W_Fireball(int req)
                                org2 = w_org + w_backoff * 16;
                                pointparticles(particleeffectnum(EFFECT_FIREBALL_EXPLODE), org2, '0 0 0', 1);
                                if(!w_issilent)
-                                       sound(self, CH_SHOTS, W_Sound("fireball_impact2"), VOL_BASE, ATTEN_NORM * 0.25); // long range boom
+                                       sound(self, CH_SHOTS, SND_FIREBALL_IMPACT2, VOL_BASE, ATTEN_NORM * 0.25); // long range boom
                        }
-
-                       return true;
                }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("fireball_impact2"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 4f1b9058474596b1f1fc148090ed02cfe5488166..37f6875b5595118009cace956d568318439194b8 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ HAGAR,
-/* function  */ W_Hagar,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 8,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 1 0.5',
-/* modelname */ "hagar",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhagar 0.8",
-/* wepimg    */ "weaponhagar",
-/* refname   */ "hagar",
-/* wepname   */ _("Hagar")
-);
+CLASS(Hagar, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Hagar, mdl, string, "hagar");
+#ifndef MENUQC
+/* model     */ ATTRIB(Hagar, m_model, Model, MDL_HAGAR_ITEM);
+#endif
+/* crosshair */ ATTRIB(Hagar, w_crosshair, string, "gfx/crosshairhagar");
+/* crosshair */ ATTRIB(Hagar, w_crosshair_size, float, 0.8);
+/* wepimg    */ ATTRIB(Hagar, model2, string, "weaponhagar");
+/* refname   */ ATTRIB(Hagar, netname, string, "hagar");
+/* wepname   */ ATTRIB(Hagar, message, string, _("Hagar"));
+ENDCLASS(Hagar)
+REGISTER_WEAPON(HAGAR, NEW(Hagar));
 
 #define HAGAR_SETTINGS(w_cvar,w_prop) HAGAR_SETTINGS_LIST(w_cvar, w_prop, HAGAR, hagar)
 #define HAGAR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -56,12 +58,12 @@ HAGAR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_hagar(void) { weapon_defaultspawnfunc(WEP_HAGAR.m_id); }
+spawnfunc(weapon_hagar) { weapon_defaultspawnfunc(WEP_HAGAR.m_id); }
 
 // NO bounce protection, as bounces are limited!
 
 void W_Hagar_Explode(void)
-{
+{SELFPARAM();
        self.event_damage = func_null;
        RadiusDamage(self, self.realowner, WEP_CVAR_PRI(hagar, damage), WEP_CVAR_PRI(hagar, edgedamage), WEP_CVAR_PRI(hagar, radius), world, world, WEP_CVAR_PRI(hagar, force), self.projectiledeathtype, other);
 
@@ -69,7 +71,7 @@ void W_Hagar_Explode(void)
 }
 
 void W_Hagar_Explode2(void)
-{
+{SELFPARAM();
        self.event_damage = func_null;
        RadiusDamage(self, self.realowner, WEP_CVAR_SEC(hagar, damage), WEP_CVAR_SEC(hagar, edgedamage), WEP_CVAR_SEC(hagar, radius), world, world, WEP_CVAR_SEC(hagar, force), self.projectiledeathtype, other);
 
@@ -77,7 +79,7 @@ void W_Hagar_Explode2(void)
 }
 
 void W_Hagar_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -101,13 +103,13 @@ void W_Hagar_Damage(entity inflictor, entity attacker, float damage, int deathty
 }
 
 void W_Hagar_Touch(void)
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
        self.use();
 }
 
 void W_Hagar_Touch2(void)
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
 
        if(self.cnt > 0 || other.takedamage == DAMAGE_AIM) {
@@ -121,13 +123,13 @@ void W_Hagar_Touch2(void)
        }
 }
 
-void W_Hagar_Attack(void)
-{
+void W_Hagar_Attack(Weapon thiswep)
+{SELFPARAM();
        entity missile;
 
-       W_DecreaseAmmo(WEP_CVAR_PRI(hagar, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(hagar, ammo));
 
-       W_SetupShot(self, false, 2, W_Sound("hagar_fire"), CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
+       W_SetupShot(self, false, 2, SND(HAGAR_FIRE), CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
 
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -164,13 +166,13 @@ void W_Hagar_Attack(void)
        MUTATOR_CALLHOOK(EditProjectile, self, missile);
 }
 
-void W_Hagar_Attack2(void)
-{
+void W_Hagar_Attack2(Weapon thiswep)
+{SELFPARAM();
        entity missile;
 
-       W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo));
 
-       W_SetupShot(self, false, 2, W_Sound("hagar_fire"), CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
+       W_SetupShot(self, false, 2, SND(HAGAR_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
 
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -210,7 +212,7 @@ void W_Hagar_Attack2(void)
 
 .float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning;
 void W_Hagar_Attack2_Load_Release(void)
-{
+{SELFPARAM();
        // time to release the rockets we've loaded
 
        entity missile;
@@ -221,9 +223,9 @@ void W_Hagar_Attack2_Load_Release(void)
        if(!self.hagar_load)
                return;
 
-       weapon_prepareattack_do(1, WEP_CVAR_SEC(hagar, refire));
+       weapon_prepareattack_do(self, true, WEP_CVAR_SEC(hagar, refire));
 
-       W_SetupShot(self, false, 2, W_Sound("hagar_fire"), CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
+       W_SetupShot(self, 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;
@@ -284,13 +286,13 @@ void W_Hagar_Attack2_Load_Release(void)
                MUTATOR_CALLHOOK(EditProjectile, self, missile);
        }
 
-       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready);
+       weapon_thinkf(self, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready);
        self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, refire) * W_WeaponRateFactor();
        self.hagar_load = 0;
 }
 
-void W_Hagar_Attack2_Load(void)
-{
+void W_Hagar_Attack2_Load(Weapon thiswep)
+{SELFPARAM();
        // loadable hagar secondary attack, must always run each frame
 
        if(time < game_starttime)
@@ -317,9 +319,9 @@ void W_Hagar_Attack2_Load(void)
                        {
                                // if we pressed primary fire while loading, unload all rockets and abort
                                self.weaponentity.state = WS_READY;
-                               W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo
+                               W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo
                                self.hagar_load = 0;
-                               sound(self, CH_WEAPON_A, W_Sound("hagar_beep"), VOL_BASE, ATTN_NORM);
+                               sound(self, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
 
                                // pause until we can load rockets again, once we re-press the alt fire button
                                self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor();
@@ -335,10 +337,10 @@ void W_Hagar_Attack2_Load(void)
                        {
                                if(!self.hagar_loadblock && self.hagar_loadstep < time)
                                {
-                                       W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo));
+                                       W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo));
                                        self.weaponentity.state = WS_INUSE;
                                        self.hagar_load += 1;
-                                       sound(self, CH_WEAPON_B, W_Sound("hagar_load"), VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
+                                       sound(self, CH_WEAPON_B, SND_HAGAR_LOAD, VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
 
                                        if(self.hagar_load >= WEP_CVAR_SEC(hagar, load_max))
                                                stopped = true;
@@ -349,7 +351,7 @@ void W_Hagar_Attack2_Load(void)
                        if(stopped && !self.hagar_loadbeep && self.hagar_load) // prevents the beep from playing each frame
                        {
                                // if this is the last rocket we can load, play a beep sound to notify the player
-                               sound(self, CH_WEAPON_A, W_Sound("hagar_beep"), VOL_BASE, ATTN_NORM);
+                               sound(self, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
                                self.hagar_loadbeep = true;
                                self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_hold) * W_WeaponRateFactor();
                        }
@@ -369,7 +371,7 @@ void W_Hagar_Attack2_Load(void)
                        if(!self.hagar_warning) // prevents the beep from playing each frame
                        {
                                // we're about to automatically release after holding time, play a beep sound to notify the player
-                               sound(self, CH_WEAPON_A, W_Sound("hagar_beep"), VOL_BASE, ATTN_NORM);
+                               sound(self, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
                                self.hagar_warning = true;
                        }
                }
@@ -387,7 +389,8 @@ void W_Hagar_Attack2_Load(void)
                self.hagar_warning = false;
 
                // we aren't checking ammo during an attack, so we must do it here
-               if(!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2)))
+               Weapon w = get_weaponinfo(self.weapon);
+               if(!(w.wr_checkammo1(w) + w.wr_checkammo2(w)))
                if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
@@ -397,48 +400,41 @@ void W_Hagar_Attack2_Load(void)
        }
 }
 
-bool W_Hagar(int req)
-{
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Hagar, wr_aim, void(entity thiswep))
                {
                        if(random()>0.15)
                                self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
                        else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
                                self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Hagar, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
                        float loadable_secondary;
                        loadable_secondary = (WEP_CVAR_SEC(hagar, load) && WEP_CVAR(hagar, secondary));
 
                        if(loadable_secondary)
-                               W_Hagar_Attack2_Load(); // must always run each frame
-                       if(autocvar_g_balance_hagar_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else if(self.BUTTON_ATCK && !self.hagar_load && !self.hagar_loadblock) // not while secondary is loaded or awaiting reset
+                               W_Hagar_Attack2_Load(thiswep); // must always run each frame
+                       if(autocvar_g_balance_hagar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else if(fire1 && !actor.hagar_load && !actor.hagar_loadblock) // not while secondary is loaded or awaiting reset
                        {
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(hagar, refire)))
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(hagar, refire)))
                                {
-                                       W_Hagar_Attack();
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hagar, refire), w_ready);
+                                       W_Hagar_Attack(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hagar, refire), w_ready);
                                }
                        }
-                       else if(self.BUTTON_ATCK2 && !loadable_secondary && WEP_CVAR(hagar, secondary))
+                       else if(fire2 && !loadable_secondary && WEP_CVAR(hagar, secondary))
                        {
-                               if(weapon_prepareattack(1, WEP_CVAR_SEC(hagar, refire)))
+                               if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(hagar, refire)))
                                {
-                                       W_Hagar_Attack2();
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready);
+                                       W_Hagar_Attack2(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready);
                                }
                        }
-                       return true;
                }
-               case WR_GONETHINK:
+               METHOD(Hagar, wr_gonethink, void(entity thiswep))
                {
                        // we lost the weapon and want to prepare switching away
                        if(self.hagar_load)
@@ -446,90 +442,68 @@ bool W_Hagar(int req)
                                self.weaponentity.state = WS_READY;
                                W_Hagar_Attack2_Load_Release();
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Hagar, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_hagar.md3"));
-                       precache_model(W_Model("v_hagar.md3"));
-                       precache_model(W_Model("h_hagar.iqm"));
-                       precache_sound(W_Sound("hagar_fire"));
-                       precache_sound(W_Sound("hagar_load"));
-                       precache_sound(W_Sound("hagar_beep"));
                        HAGAR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_SETUP:
+               METHOD(Hagar, wr_setup, void(entity thiswep))
                {
                        self.hagar_loadblock = false;
 
                        if(self.hagar_load)
                        {
-                               W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo if necessary
+                               W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo if necessary
                                self.hagar_load = 0;
                        }
-
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Hagar, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_PRI(hagar, ammo);
+                       float ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_PRI(hagar, ammo);
                        ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(Hagar, wr_checkammo2, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo);
+                       float ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo);
                        ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(Hagar, wr_config, void(entity thiswep))
                {
                        HAGAR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(Hagar, wr_resetplayer, void(entity thiswep))
                {
                        self.hagar_load = 0;
-                       return true;
                }
-               case WR_PLAYERDEATH:
+               METHOD(Hagar, wr_playerdeath, void(entity thiswep))
                {
                        // if we have any rockets loaded when we die, release them
                        if(self.hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
                                W_Hagar_Attack2_Load_Release();
-
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Hagar, wr_reload, void(entity thiswep))
                {
                        if(!self.hagar_load) // require releasing loaded rockets first
-                               W_Reload(min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), W_Sound("reload"));
-
-                       return true;
+                               W_Reload(self, min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Hagar, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_HAGAR_SUICIDE;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Hagar, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_HAGAR_MURDER_BURST;
                        else
                                return WEAPON_HAGAR_MURDER_SPRAY;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_Hagar(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Hagar, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 6;
@@ -537,29 +511,13 @@ bool W_Hagar(int req)
                        if(!w_issilent)
                        {
                                if(w_random<0.15)
-                                       sound(self, CH_SHOTS, W_Sound("hagexp1"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_HAGEXP1, VOL_BASE, ATTN_NORM);
                                else if(w_random<0.7)
-                                       sound(self, CH_SHOTS, W_Sound("hagexp2"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_HAGEXP2, VOL_BASE, ATTN_NORM);
                                else
-                                       sound(self, CH_SHOTS, W_Sound("hagexp3"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_HAGEXP3, VOL_BASE, ATTN_NORM);
                        }
-
-                       return true;
-               }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("hagexp1"));
-                       precache_sound(W_Sound("hagexp2"));
-                       precache_sound(W_Sound("hagexp3"));
-                       return true;
                }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 49685296a86385f6ffad495fff76356406be238f..616939d1e80abd1a83c259d626f91d699ff931ed 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ HLAC,
-/* function  */ W_HLAC,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 6,
-/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0 1 0',
-/* modelname */ "hlac",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhlac 0.6",
-/* wepimg    */ "weaponhlac",
-/* refname   */ "hlac",
-/* wepname   */ _("Heavy Laser Assault Cannon")
-);
+CLASS(HLAC, Weapon)
+/* 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');
+/* modelname */ ATTRIB(HLAC, mdl, string, "hlac");
+#ifndef MENUQC
+/* model     */ ATTRIB(HLAC, m_model, Model, MDL_HLAC_ITEM);
+#endif
+/* crosshair */ ATTRIB(HLAC, w_crosshair, string, "gfx/crosshairhlac");
+/* crosshair */ ATTRIB(HLAC, w_crosshair_size, float, 0.6);
+/* wepimg    */ ATTRIB(HLAC, model2, string, "weaponhlac");
+/* refname   */ ATTRIB(HLAC, netname, string, "hlac");
+/* wepname   */ ATTRIB(HLAC, message, string, _("Heavy Laser Assault Cannon"));
+ENDCLASS(HLAC)
+REGISTER_WEAPON(HLAC, NEW(HLAC));
 
 #define HLAC_SETTINGS(w_cvar,w_prop) HLAC_SETTINGS_LIST(w_cvar, w_prop, HLAC, hlac)
 #define HLAC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -48,10 +50,10 @@ HLAC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_hlac(void) { weapon_defaultspawnfunc(WEP_HLAC.m_id); }
+spawnfunc(weapon_hlac) { weapon_defaultspawnfunc(WEP_HLAC.m_id); }
 
 void W_HLAC_Touch(void)
-{
+{SELFPARAM();
        float isprimary;
 
        PROJECTILE_TOUCH;
@@ -65,19 +67,19 @@ void W_HLAC_Touch(void)
        remove(self);
 }
 
-void W_HLAC_Attack(void)
-{
+void W_HLAC_Attack(Weapon thiswep)
+{SELFPARAM();
        entity missile;
     float spread;
 
-       W_DecreaseAmmo(WEP_CVAR_PRI(hlac, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(hlac, ammo));
 
     spread = WEP_CVAR_PRI(hlac, spread_min) + (WEP_CVAR_PRI(hlac, spread_add) * self.misc_bulletcounter);
     spread = min(spread,WEP_CVAR_PRI(hlac, spread_max));
     if(self.crouch)
         spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
 
-       W_SetupShot(self, false, 3, W_Sound("lasergun_fire"), CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage));
+       W_SetupShot(self, 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)
        {
@@ -115,7 +117,7 @@ void W_HLAC_Attack(void)
 }
 
 void W_HLAC_Attack2(void)
-{
+{SELFPARAM();
        entity missile;
     float spread;
 
@@ -125,7 +127,7 @@ void W_HLAC_Attack2(void)
     if(self.crouch)
         spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod);
 
-       W_SetupShot(self, false, 3, W_Sound("lasergun_fire"), CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage));
+       W_SetupShot(self, 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 = spawn();
@@ -159,40 +161,41 @@ void W_HLAC_Attack2(void)
 }
 
 // weapon frames
-void W_HLAC_Attack_Frame(void)
+void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       if(self.weapon != self.switchweapon) // abort immediately if switching
+       if(actor.weapon != actor.switchweapon) // abort immediately if switching
        {
-               w_ready();
+               w_ready(thiswep, actor, fire1, fire2);
                return;
        }
 
-       if(self.BUTTON_ATCK)
+       if(actor.BUTTON_ATCK)
        {
-               if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1))
-               if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+               Weapon w = get_weaponinfo(actor.weapon);
+               if(!w.wr_checkammo1(w))
+               if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
-                       W_SwitchWeapon_Force(self, w_getbestweapon(self));
-                       w_ready();
+                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                       w_ready(thiswep, actor, fire1, fire2);
                        return;
                }
 
-               ATTACK_FINISHED(self) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor();
-               W_HLAC_Attack();
-               self.misc_bulletcounter = self.misc_bulletcounter + 1;
-        weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
+               ATTACK_FINISHED(actor) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor();
+               W_HLAC_Attack(WEP_HLAC);
+               actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
+        weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
        }
        else
        {
-               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, animtime), w_ready);
+               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, animtime), w_ready);
        }
 }
 
-void W_HLAC_Attack2_Frame(void)
-{
+void W_HLAC_Attack2_Frame(Weapon thiswep)
+{SELFPARAM();
     float i;
 
-       W_DecreaseAmmo(WEP_CVAR_SEC(hlac, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(hlac, ammo));
 
     for(i=WEP_CVAR_SEC(hlac, shots);i>0;--i)
         W_HLAC_Attack2();
@@ -204,111 +207,78 @@ void W_HLAC_Attack2_Frame(void)
        }
 }
 
-bool W_HLAC(int req)
-{
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(HLAC, wr_aim, void(entity thiswep))
                {
                        self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(hlac, speed), 0, WEP_CVAR_PRI(hlac, lifetime), false);
-                       return true;
                }
-               case WR_THINK:
+               METHOD(HLAC, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(autocvar_g_balance_hlac_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else if(self.BUTTON_ATCK)
+                       if(autocvar_g_balance_hlac_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else if(fire1)
                        {
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(hlac, refire)))
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(hlac, refire)))
                                {
-                                       self.misc_bulletcounter = 0;
-                                       W_HLAC_Attack();
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
+                                       actor.misc_bulletcounter = 0;
+                                       W_HLAC_Attack(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
                                }
                        }
 
-                       else if(self.BUTTON_ATCK2 && WEP_CVAR(hlac, secondary))
+                       else if(fire2 && WEP_CVAR(hlac, secondary))
                        {
-                               if(weapon_prepareattack(1, WEP_CVAR_SEC(hlac, refire)))
+                               if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(hlac, refire)))
                                {
-                                       W_HLAC_Attack2_Frame();
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hlac, animtime), w_ready);
+                                       W_HLAC_Attack2_Frame(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(hlac, animtime), w_ready);
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(HLAC, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_hlac.md3"));
-                       precache_model(W_Model("v_hlac.md3"));
-                       precache_model(W_Model("h_hlac.iqm"));
-                       precache_sound(W_Sound("lasergun_fire"));
                        HLAC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(HLAC, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_PRI(hlac, ammo);
+                       float ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_PRI(hlac, ammo);
                        ammo_amount += self.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(HLAC, wr_checkammo2, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_SEC(hlac, ammo);
+                       float ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_SEC(hlac, ammo);
                        ammo_amount += self.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(HLAC, wr_config, void(entity thiswep))
                {
                        HLAC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(HLAC, wr_reload, void(entity thiswep))
                {
-                       W_Reload(min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(HLAC, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_HLAC_SUICIDE;
                }
-               case WR_KILLMESSAGE:
+               METHOD(HLAC, wr_killmessage, int(entity thiswep))
                {
                        return WEAPON_HLAC_MURDER;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_HLAC(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(HLAC, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 6;
                        pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
                        if(!w_issilent)
-                               sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTN_NORM);
-
-                       return true;
-               }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("laserimpact"));
-                       return true;
+                               sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM);
                }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 52b60e83bbf2549b5771f482efe3d64baa25de9c..6707a7c32e960cc0eac5c9a01c68eb8bc42f0dd7 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id     */ HMG,
-/* function     */ W_HeavyMachineGun,
-/* ammotype     */ ammo_nails,
-/* impulse      */ 3,
-/* flags        */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_SUPERWEAPON,
-/* rating       */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '0.5 0.5 0',
-/* modelname */ "ok_hmg",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairuzi 0.6",
-/* wepimg    */ "weaponhmg",
-/* refname   */ "hmg",
-/* wepname   */ _("Heavy Machine Gun")
-);
+CLASS(HeavyMachineGun, Weapon)
+/* 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');
+/* modelname */ ATTRIB(HeavyMachineGun, mdl, string, "ok_hmg");
+#ifndef MENUQC
+/* model     */ ATTRIB(HeavyMachineGun, m_model, Model, MDL_HMG_ITEM);
+#endif
+/* crosshair */ ATTRIB(HeavyMachineGun, w_crosshair, string, "gfx/crosshairuzi");
+/* crosshair */ ATTRIB(HeavyMachineGun, w_crosshair_size, float, 0.6);
+/* wepimg    */ ATTRIB(HeavyMachineGun, model2, string, "weaponhmg");
+/* refname   */ ATTRIB(HeavyMachineGun, netname, string, "hmg");
+/* wepname   */ ATTRIB(HeavyMachineGun, message, string, _("Heavy Machine Gun"));
+ENDCLASS(HeavyMachineGun)
+REGISTER_WEAPON(HMG, NEW(HeavyMachineGun));
 
 #define HMG_SETTINGS(w_cvar,w_prop) HMG_SETTINGS_LIST(w_cvar, w_prop, HMG, hmg)
 #define HMG_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -41,168 +43,132 @@ HMG_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #ifdef IMPLEMENTATION
 #ifdef SVQC
 
-void spawnfunc_weapon_hmg() { weapon_defaultspawnfunc(WEP_HMG.m_id); }
+spawnfunc(weapon_hmg) { weapon_defaultspawnfunc(WEP_HMG.m_id); }
 
-void W_HeavyMachineGun_Attack_Auto()
+void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       if (!self.BUTTON_ATCK)
+       if (!actor.BUTTON_ATCK)
        {
-               w_ready();
+               w_ready(thiswep, actor, fire1, fire2);
                return;
        }
 
-       if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1))
-       if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+       Weapon w = get_weaponinfo(actor.weapon);
+       if(!w.wr_checkammo1(w))
+       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(self, w_getbestweapon(self));
-               w_ready();
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               w_ready(thiswep, actor, fire1, fire2);
                return;
        }
 
-       W_DecreaseAmmo(WEP_CVAR(hmg, ammo));
+       W_DecreaseAmmo(WEP_HMG, self, WEP_CVAR(hmg, ammo));
 
-       W_SetupShot (self, true, 0, W_Sound("uzi_fire"), CH_WEAPON_A, WEP_CVAR(hmg, damage));
+       W_SetupShot (actor, true, 0, SND(UZI_FIRE), CH_WEAPON_A, WEP_CVAR(hmg, damage));
 
        if(!autocvar_g_norecoil)
        {
-               self.punchangle_x = random () - 0.5;
-               self.punchangle_y = random () - 0.5;
+               actor.punchangle_x = random () - 0.5;
+               actor.punchangle_y = random () - 0.5;
        }
 
-       float hmg_spread = bound(WEP_CVAR(hmg, spread_min), WEP_CVAR(hmg, spread_min) + (WEP_CVAR(hmg, spread_add) * self.misc_bulletcounter), WEP_CVAR(hmg, spread_max));
+       float hmg_spread = bound(WEP_CVAR(hmg, spread_min), WEP_CVAR(hmg, spread_min) + (WEP_CVAR(hmg, spread_add) * actor.misc_bulletcounter), WEP_CVAR(hmg, spread_max));
        fireBullet(w_shotorg, w_shotdir, hmg_spread, WEP_CVAR(hmg, solidpenetration), WEP_CVAR(hmg, damage), WEP_CVAR(hmg, force), WEP_HMG.m_id, 0);
 
-       self.misc_bulletcounter = self.misc_bulletcounter + 1;
+       actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        W_MachineGun_MuzzleFlash();
-       W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+       W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
 
        if (autocvar_g_casings >= 2) // casing code
-               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, self);
+               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);
 
-       ATTACK_FINISHED(self) = time + WEP_CVAR(hmg, refire) * W_WeaponRateFactor();
-       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(hmg, refire), W_HeavyMachineGun_Attack_Auto);
+       ATTACK_FINISHED(actor) = time + WEP_CVAR(hmg, refire) * W_WeaponRateFactor();
+       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(hmg, refire), W_HeavyMachineGun_Attack_Auto);
 }
 
-bool W_HeavyMachineGun(int req)
-{
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(HeavyMachineGun, wr_aim, void(entity thiswep))
                {
                        if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200)
                                self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, false);
                        else
                                self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, false);
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(HeavyMachineGun, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(WEP_CVAR(hmg, reload_ammo) && self.clip_load < WEP_CVAR(hmg, ammo)) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else
+                       if(WEP_CVAR(hmg, reload_ammo) && actor.clip_load < WEP_CVAR(hmg, ammo)) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else
                        {
-                               if (self.BUTTON_ATCK)
-                               if (weapon_prepareattack(0, 0))
+                               if (fire1)
+                               if (weapon_prepareattack(thiswep, actor, false, 0))
                                {
-                                       self.misc_bulletcounter = 0;
-                                       W_HeavyMachineGun_Attack_Auto();
+                                       actor.misc_bulletcounter = 0;
+                                       W_HeavyMachineGun_Attack_Auto(thiswep, actor, fire1, fire2);
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(HeavyMachineGun, wr_init, void(entity thiswep))
                {
-                       precache_model ("models/uziflash.md3");
-                       precache_model(W_Model("g_ok_hmg.md3"));
-                       precache_model(W_Model("v_ok_hmg.md3"));
-                       precache_model(W_Model("h_ok_hmg.iqm"));
-                       precache_sound (W_Sound("uzi_fire"));
                        HMG_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(HeavyMachineGun, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
+                       float ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
 
                        if(autocvar_g_balance_hmg_reload_ammo)
                                ammo_amount += self.(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
 
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(HeavyMachineGun, wr_checkammo2, bool(entity thiswep))
                {
-                       ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
+                       float ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
 
                        if(autocvar_g_balance_hmg_reload_ammo)
                                ammo_amount += self.(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
 
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(HeavyMachineGun, wr_config, void(entity thiswep))
                {
                        HMG_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(HeavyMachineGun, wr_reload, void(entity thiswep))
                {
-                       W_Reload(WEP_CVAR(hmg, ammo), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, WEP_CVAR(hmg, ammo), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(HeavyMachineGun, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_THINKING_WITH_PORTALS;
                }
-               case WR_KILLMESSAGE:
+               METHOD(HeavyMachineGun, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_HMG_MURDER_SNIPE;
                        else
                                return WEAPON_HMG_MURDER_SPRAY;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_HeavyMachineGun(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(HeavyMachineGun, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 2;
                        pointparticles(particleeffectnum(EFFECT_MACHINEGUN_IMPACT), org2, w_backoff * 1000, 1);
                        if(!w_issilent)
                                if(w_random < 0.05)
-                                       sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTEN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTEN_NORM);
                                else if(w_random < 0.1)
-                                       sound(self, CH_SHOTS, W_Sound("ric2"), VOL_BASE, ATTEN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC2, VOL_BASE, ATTEN_NORM);
                                else if(w_random < 0.2)
-                                       sound(self, CH_SHOTS, W_Sound("ric3"), VOL_BASE, ATTEN_NORM);
-
-                       return true;
-               }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("ric1"));
-                       precache_sound(W_Sound("ric2"));
-                       precache_sound(W_Sound("ric3"));
-                       return true;
+                                       sound(self, CH_SHOTS, SND_RIC3, VOL_BASE, ATTEN_NORM);
                }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 6c5519e60b5c8e5eab3768ed900426440c5e5deb..bc79a88a313db91961d254bbb1765966ce384f31 100644 (file)
@@ -1,19 +1,31 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ HOOK,
-/* function  */ W_Hook,
-/* ammotype  */ ammo_fuel,
-/* impulse   */ 0,
-/* flags     */ WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ 0,
-/* color     */ '0 0.5 0',
-/* modelname */ "hookgun",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhook 0.5",
-/* wepimg    */ "weaponhook",
-/* refname   */ "hook",
-/* wepname   */ _("Grappling Hook")
-);
+CLASS(Hook, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Hook, mdl, string, "hookgun");
+#ifndef MENUQC
+/* model     */ ATTRIB(Hook, m_model, Model, MDL_HOOK_ITEM);
+#endif
+/* crosshair */ ATTRIB(Hook, w_crosshair, string, "gfx/crosshairhook");
+/* crosshair */ ATTRIB(Hook, w_crosshair_size, float, 0.5);
+/* wepimg    */ ATTRIB(Hook, model2, string, "weaponhook");
+/* refname   */ ATTRIB(Hook, netname, string, "hook");
+/* wepname   */ ATTRIB(Hook, message, string, _("Grappling Hook"));
+       ATTRIB(Hook, ammo_factor, float, 1)
+ENDCLASS(Hook)
+REGISTER_WEAPON(HOOK, NEW(Hook));
+
+CLASS(OffhandHook, OffhandWeapon)
+    METHOD(OffhandHook, offhand_think, void(OffhandHook this, entity actor, bool key_pressed))
+    {
+       Weapon wep = WEP_HOOK;
+       wep.wr_think(wep, actor, key_pressed, false);
+    }
+ENDCLASS(OffhandHook)
+OffhandHook OFFHAND_HOOK; STATIC_INIT(OFFHAND_HOOK) { OFFHAND_HOOK = NEW(OffhandHook); }
 
 #define HOOK_SETTINGS(w_cvar,w_prop) HOOK_SETTINGS_LIST(w_cvar, w_prop, HOOK, hook)
 #define HOOK_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -59,19 +71,10 @@ HOOK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #ifdef IMPLEMENTATION
 #ifdef SVQC
 
-void spawnfunc_weapon_hook(void)
-{
-       if(g_grappling_hook) // offhand hook
-       {
-               startitem_failed = true;
-               remove(self);
-               return;
-       }
-       weapon_defaultspawnfunc(WEP_HOOK.m_id);
-}
+spawnfunc(weapon_hook) { weapon_defaultspawnfunc(WEP_HOOK.m_id); }
 
 void W_Hook_ExplodeThink(void)
-{
+{SELFPARAM();
        float dt, dmg_remaining_next, f;
 
        dt = time - self.teleport_time;
@@ -91,7 +94,7 @@ void W_Hook_ExplodeThink(void)
 }
 
 void W_Hook_Explode2(void)
-{
+{SELFPARAM();
        self.event_damage = func_null;
        self.touch = func_null;
        self.effects |= EF_NODRAW;
@@ -110,7 +113,7 @@ void W_Hook_Explode2(void)
 }
 
 void W_Hook_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -124,21 +127,18 @@ void W_Hook_Damage(entity inflictor, entity attacker, float damage, int deathtyp
 }
 
 void W_Hook_Touch2(void)
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
        self.use();
 }
 
-void W_Hook_Attack2(void)
+void W_Hook_Attack2(Weapon thiswep, entity actor)
 {
-       entity gren;
+       //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_DecreaseAmmo(WEP_CVAR_SEC(hook, ammo)); // WEAPONTODO: Figure out how to handle ammo with hook secondary (gravitybomb)
-       W_SetupShot(self, false, 4, W_Sound("hookbomb_fire"), CH_WEAPON_A, WEP_CVAR_SEC(hook, damage));
-
-       gren = spawn();
-       gren.owner = gren.realowner = self;
-       gren.classname = "hookbomb";
+       entity gren = new(hookbomb);
+       gren.owner = gren.realowner = actor;
        gren.bot_dodge = true;
        gren.bot_dodgerating = WEP_CVAR_SEC(hook, damage);
        gren.movetype = MOVETYPE_TOSS;
@@ -160,8 +160,8 @@ void W_Hook_Attack2(void)
        gren.missile_flags = MIF_SPLASH | MIF_ARC;
 
        gren.velocity = '0 0 1' * WEP_CVAR_SEC(hook, speed);
-       if(autocvar_g_projectiles_newton_style)
-               gren.velocity = gren.velocity + self.velocity;
+       if (autocvar_g_projectiles_newton_style)
+               gren.velocity = gren.velocity + actor.velocity;
 
        gren.gravity = WEP_CVAR_SEC(hook, gravity);
        //W_SetupProjVelocity_Basic(gren); // just falling down!
@@ -171,82 +171,73 @@ void W_Hook_Attack2(void)
 
        CSQCProjectile(gren, true, PROJECTILE_HOOKBOMB, true);
 
-       MUTATOR_CALLHOOK(EditProjectile, self, gren);
+       MUTATOR_CALLHOOK(EditProjectile, actor, gren);
 }
 
-bool W_Hook(int req)
-{
-       float hooked_time_max, hooked_fuel;
-
-       switch(req)
-       {
-               case WR_AIM:
-               {
-                       // no bot AI for hook (yet?)
-                       return true;
-               }
-               case WR_THINK:
+               METHOD(Hook, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(self.BUTTON_ATCK || self.BUTTON_HOOK)
-                       {
-                               if(!self.hook)
-                               if(!(self.hook_state & HOOK_WAITING_FOR_RELEASE))
-                               if(!(self.hook_state & HOOK_FIRING))
-                               if(time > self.hook_refire)
-                               if(weapon_prepareattack(0, -1))
+                       if (fire1) {
+                               if(!actor.hook)
+                               if(!(actor.hook_state & HOOK_WAITING_FOR_RELEASE))
+                               if(time > actor.hook_refire)
+                               if(weapon_prepareattack(thiswep, actor, false, -1))
                                {
-                                       W_DecreaseAmmo(WEP_CVAR_PRI(hook, ammo));
-                                       self.hook_state |= HOOK_FIRING;
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready);
+                                       W_DecreaseAmmo(thiswep, actor, thiswep.ammo_factor * WEP_CVAR_PRI(hook, ammo));
+                                       actor.hook_state |= HOOK_FIRING;
+                                       actor.hook_state |= HOOK_WAITING_FOR_RELEASE;
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready);
                                }
+                       } else {
+                               actor.hook_state |= HOOK_REMOVING;
+                               actor.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
                        }
 
-                       if(self.BUTTON_ATCK2)
+                       if(fire2)
                        {
-                               if(weapon_prepareattack(1, WEP_CVAR_SEC(hook, refire)))
+                               if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(hook, refire)))
                                {
-                                       W_Hook_Attack2();
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hook, animtime), w_ready);
+                                       W_Hook_Attack2(thiswep, actor);
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(hook, animtime), w_ready);
                                }
                        }
 
-                       if(self.hook)
+                       if(actor.hook)
                        {
                                // if hooked, no bombs, and increase the timer
-                               self.hook_refire = max(self.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor());
+                               actor.hook_refire = max(actor.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor());
 
                                // hook also inhibits health regeneration, but only for 1 second
-                               if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-                                       self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
+                               if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+                                       actor.pauseregen_finished = max(actor.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
                        }
 
-                       if(self.hook && self.hook.state == 1)
+                       if(actor.hook && actor.hook.state == 1)
                        {
-                               hooked_time_max = WEP_CVAR_PRI(hook, hooked_time_max);
+                               float hooked_time_max = WEP_CVAR_PRI(hook, hooked_time_max);
                                if(hooked_time_max > 0)
                                {
-                                       if( time > self.hook_time_hooked + hooked_time_max )
-                                               self.hook_state |= HOOK_REMOVING;
+                                       if( time > actor.hook_time_hooked + hooked_time_max )
+                                               actor.hook_state |= HOOK_REMOVING;
                                }
 
-                               hooked_fuel = WEP_CVAR_PRI(hook, hooked_ammo);
+                               float hooked_fuel = thiswep.ammo_factor * WEP_CVAR_PRI(hook, hooked_ammo);
                                if(hooked_fuel > 0)
                                {
-                                       if( time > self.hook_time_fueldecrease )
+                                       if( time > actor.hook_time_fueldecrease )
                                        {
-                                               if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+                                               if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                                                {
-                                                       if( self.ammo_fuel >= (time - self.hook_time_fueldecrease) * hooked_fuel )
+                                                       if( actor.ammo_fuel >= (time - actor.hook_time_fueldecrease) * hooked_fuel )
                                                        {
-                                                               W_DecreaseAmmo((time - self.hook_time_fueldecrease) * hooked_fuel);
-                                                               self.hook_time_fueldecrease = time;
+                                                               W_DecreaseAmmo(thiswep, actor, (time - actor.hook_time_fueldecrease) * hooked_fuel);
+                                                               actor.hook_time_fueldecrease = time;
                                                                // decrease next frame again
                                                        }
                                                        else
                                                        {
-                                                               self.ammo_fuel = 0;
-                                                               self.hook_state |= HOOK_REMOVING;
-                                                               W_SwitchWeapon_Force(self, w_getbestweapon(self));
+                                                               actor.ammo_fuel = 0;
+                                                               actor.hook_state |= HOOK_REMOVING;
+                                                               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
                                                        }
                                                }
                                        }
@@ -254,115 +245,76 @@ bool W_Hook(int req)
                        }
                        else
                        {
-                               self.hook_time_hooked = time;
-                               self.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
+                               actor.hook_time_hooked = time;
+                               actor.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
                        }
 
-                       if(self.BUTTON_CROUCH)
+                       actor.hook_state = BITSET(actor.hook_state, HOOK_PULLING, (!actor.BUTTON_CROUCH || !autocvar_g_balance_grapplehook_crouchslide));
+
+                       if (actor.hook_state & HOOK_FIRING)
                        {
-                               self.hook_state &= ~HOOK_PULLING;
-                               if(self.BUTTON_ATCK || self.BUTTON_HOOK)
-                                       self.hook_state &= ~HOOK_RELEASING;
-                               else
-                                       self.hook_state |= HOOK_RELEASING;
+                               if (actor.hook)
+                                       RemoveGrapplingHook(actor);
+                               WITH(entity, self, actor, FireGrapplingHook());
+                               actor.hook_state &= ~HOOK_FIRING;
+                               actor.hook_refire = max(actor.hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor());
                        }
-                       else
+                       else if (actor.hook_state & HOOK_REMOVING)
                        {
-                               self.hook_state |= HOOK_PULLING;
-                               self.hook_state &= ~HOOK_RELEASING;
-
-                               if(self.BUTTON_ATCK || self.BUTTON_HOOK)
-                               {
-                                       // already fired
-                                       if(self.hook)
-                                               self.hook_state |= HOOK_WAITING_FOR_RELEASE;
-                               }
-                               else
-                               {
-                                       self.hook_state |= HOOK_REMOVING;
-                                       self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
-                               }
+                               if (actor.hook)
+                                       RemoveGrapplingHook(actor);
+                               actor.hook_state &= ~HOOK_REMOVING;
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Hook, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_hookgun.md3"));
-                       precache_model(W_Model("v_hookgun.md3"));
-                       precache_model(W_Model("h_hookgun.iqm"));
-                       precache_sound(W_Sound("hook_impact")); // done by g_hook.qc
-                       precache_sound(W_Sound("hook_fire"));
-                       precache_sound(W_Sound("hookbomb_fire"));
                        HOOK_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_SETUP:
+               METHOD(Hook, wr_setup, void(entity thiswep))
                {
                        self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Hook, wr_checkammo1, bool(Hook thiswep))
                {
+                       if (!thiswep.ammo_factor) return true;
                        if(self.hook)
                                return self.ammo_fuel > 0;
                        else
                                return self.ammo_fuel >= WEP_CVAR_PRI(hook, ammo);
                }
-               case WR_CHECKAMMO2:
+               METHOD(Hook, wr_checkammo2, bool(Hook thiswep))
                {
                        // infinite ammo for now
                        return true; // self.ammo_cells >= WEP_CVAR_SEC(hook, ammo); // WEAPONTODO: see above
                }
-               case WR_CONFIG:
+               METHOD(Hook, wr_config, void(entity thiswep))
                {
                        HOOK_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(Hook, wr_resetplayer, void(entity thiswep))
                {
                        self.hook_refire = time;
-                       return true;
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Hook, wr_suicidemessage, int(entity thiswep))
                {
                        return false;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Hook, wr_killmessage, int(entity thiswep))
                {
                        return WEAPON_HOOK_MURDER;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_Hook(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Hook, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 2;
                        pointparticles(particleeffectnum(EFFECT_HOOK_EXPLODE), org2, '0 0 0', 1);
                        if(!w_issilent)
-                               sound(self, CH_SHOTS, W_Sound("hookbomb_impact"), VOL_BASE, ATTN_NORM);
-
-                       return true;
+                               sound(self, CH_SHOTS, SND_HOOKBOMB_IMPACT, VOL_BASE, ATTN_NORM);
                }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("hookbomb_impact"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index da1eb33a6046cf30fdda57a2a1d7d1de698ba60a..90a4471f17bbf6110bca905b19da7b0883821c20 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ MACHINEGUN,
-/* function  */ W_MachineGun,
-/* ammotype  */ ammo_nails,
-/* impulse   */ 3,
-/* flags     */ WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 1 0',
-/* modelname */ "uzi",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairuzi 0.6",
-/* wepimg    */ "weaponuzi",
-/* refname   */ "machinegun",
-/* wepname   */ _("Machine Gun")
-);
+CLASS(MachineGun, Weapon)
+/* 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');
+/* modelname */ ATTRIB(MachineGun, mdl, string, "uzi");
+#ifndef MENUQC
+/* model     */ ATTRIB(MachineGun, m_model, Model, MDL_MACHINEGUN_ITEM);
+#endif
+/* crosshair */ ATTRIB(MachineGun, w_crosshair, string, "gfx/crosshairuzi");
+/* crosshair */ ATTRIB(MachineGun, w_crosshair_size, float, 0.6);
+/* wepimg    */ ATTRIB(MachineGun, model2, string, "weaponuzi");
+/* refname   */ ATTRIB(MachineGun, netname, string, "machinegun");
+/* wepname   */ ATTRIB(MachineGun, message, string, _("MachineGun"));
+ENDCLASS(MachineGun)
+REGISTER_WEAPON(MACHINEGUN, NEW(MachineGun));
 
 #define MACHINEGUN_SETTINGS(w_cvar,w_prop) MACHINEGUN_SETTINGS_LIST(w_cvar, w_prop, MACHINEGUN, machinegun)
 #define MACHINEGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -55,7 +57,7 @@ MACHINEGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #ifdef IMPLEMENTATION
 #ifdef SVQC
 
-void spawnfunc_weapon_machinegun(void)
+spawnfunc(weapon_machinegun)
 {
        if(autocvar_sv_q3acompat_machineshotgunswap)
        if(self.classname != "droppedweapon")
@@ -65,10 +67,10 @@ void spawnfunc_weapon_machinegun(void)
        }
        weapon_defaultspawnfunc(WEP_MACHINEGUN.m_id);
 }
-void spawnfunc_weapon_uzi(void) { spawnfunc_weapon_machinegun(); }
+spawnfunc(weapon_uzi) { spawnfunc_weapon_machinegun(this); }
 
 void W_MachineGun_MuzzleFlash_Think(void)
-{
+{SELFPARAM();
        self.frame = self.frame + 2;
        self.scale = self.scale * 0.5;
        self.alpha = self.alpha - 0.25;
@@ -85,12 +87,12 @@ void W_MachineGun_MuzzleFlash_Think(void)
 }
 
 void W_MachineGun_MuzzleFlash(void)
-{
+{SELFPARAM();
        if(self.muzzle_flash == world)
                self.muzzle_flash = spawn();
 
        // muzzle flash for 1st person view
-       setmodel(self.muzzle_flash, "models/uziflash.md3"); // precision set below
+       setmodel(self.muzzle_flash, MDL_MACHINEGUN_MUZZLEFLASH); // precision set below
 
        self.muzzle_flash.scale = 0.75;
        self.muzzle_flash.think = W_MachineGun_MuzzleFlash_Think;
@@ -102,9 +104,9 @@ void W_MachineGun_MuzzleFlash(void)
        self.muzzle_flash.owner = self.muzzle_flash.realowner = self;
 }
 
-void W_MachineGun_Attack(int deathtype)
-{
-       W_SetupShot(self, true, 0, W_Sound("uzi_fire"), CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
+void W_MachineGun_Attack(Weapon thiswep, int deathtype)
+{SELFPARAM();
+       W_SetupShot(self, true, 0, SND(UZI_FIRE), CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
        if(!autocvar_g_norecoil)
        {
                self.punchangle_x = random() - 0.5;
@@ -122,95 +124,97 @@ void W_MachineGun_Attack(int deathtype)
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        W_MachineGun_MuzzleFlash();
-       W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+       W_AttachToShotorg(self, self.muzzle_flash, '5 0 0');
 
        // casing code
        if(autocvar_g_casings >= 2)
                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, self);
 
        if(self.misc_bulletcounter == 1)
-               W_DecreaseAmmo(WEP_CVAR(machinegun, first_ammo));
+               W_DecreaseAmmo(thiswep, self, WEP_CVAR(machinegun, first_ammo));
        else
-               W_DecreaseAmmo(WEP_CVAR(machinegun, sustained_ammo));
+               W_DecreaseAmmo(thiswep, self, WEP_CVAR(machinegun, sustained_ammo));
 }
 
 // weapon frames
-void W_MachineGun_Attack_Frame(void)
+void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       if(self.weapon != self.switchweapon) // abort immediately if switching
+       if(actor.weapon != actor.switchweapon) // abort immediately if switching
        {
-               w_ready();
+               w_ready(thiswep, actor, fire1, fire2);
                return;
        }
-       if(self.BUTTON_ATCK)
+       if(actor.BUTTON_ATCK)
        {
-               if(!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
-               if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+               Weapon w = get_weaponinfo(actor.weapon);
+               if(!w.wr_checkammo2(w))
+               if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
-                       W_SwitchWeapon_Force(self, w_getbestweapon(self));
-                       w_ready();
+                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                       w_ready(thiswep, actor, fire1, fire2);
                        return;
                }
-               self.misc_bulletcounter = self.misc_bulletcounter + 1;
-               W_MachineGun_Attack(WEP_MACHINEGUN.m_id);
-               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
+               actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
+               W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id);
+               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
        }
        else
-               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), w_ready);
+               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), w_ready);
 }
 
 
-void W_MachineGun_Attack_Auto(void)
+void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
        float machinegun_spread;
 
-       if(!self.BUTTON_ATCK)
+       if(!fire1)
        {
-               w_ready();
+               w_ready(thiswep, actor, fire1, fire2);
                return;
        }
 
-       if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1))
-       if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+       Weapon w = get_weaponinfo(actor.weapon);
+       if(!w.wr_checkammo1(w))
+       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(self, w_getbestweapon(self));
-               w_ready();
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               w_ready(thiswep, actor, fire1, fire2);
                return;
        }
 
-       W_DecreaseAmmo(WEP_CVAR(machinegun, sustained_ammo));
+       W_DecreaseAmmo(WEP_MACHINEGUN, actor, WEP_CVAR(machinegun, sustained_ammo));
 
-       W_SetupShot(self, true, 0, W_Sound("uzi_fire"), CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
+       W_SetupShot(actor, true, 0, SND(UZI_FIRE), CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
        if(!autocvar_g_norecoil)
        {
-               self.punchangle_x = random() - 0.5;
-               self.punchangle_y = random() - 0.5;
+               actor.punchangle_x = random() - 0.5;
+               actor.punchangle_y = random() - 0.5;
        }
 
-       machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * self.misc_bulletcounter), WEP_CVAR(machinegun, spread_max));
+       machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * actor.misc_bulletcounter), WEP_CVAR(machinegun, spread_max));
        fireBullet(w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
 
-       self.misc_bulletcounter = self.misc_bulletcounter + 1;
+       actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        W_MachineGun_MuzzleFlash();
-       W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+       W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
 
        if(autocvar_g_casings >= 2) // casing code
-               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, self);
+               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);
 
-       ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor();
-       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Auto);
+       ATTACK_FINISHED(actor) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor();
+       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Auto);
 }
 
-void W_MachineGun_Attack_Burst(void)
+void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       W_SetupShot(self, true, 0, W_Sound("uzi_fire"), CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
+       W_SetupShot(actor, true, 0, SND(UZI_FIRE), CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
        if(!autocvar_g_norecoil)
        {
-               self.punchangle_x = random() - 0.5;
-               self.punchangle_y = random() - 0.5;
+               actor.punchangle_x = random() - 0.5;
+               actor.punchangle_y = random() - 0.5;
        }
 
        fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
@@ -218,102 +222,91 @@ void W_MachineGun_Attack_Burst(void)
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        W_MachineGun_MuzzleFlash();
-       W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+       W_AttachToShotorg(actor, actor.muzzle_flash, '5 0 0');
 
        if(autocvar_g_casings >= 2) // casing code
-               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, self);
+               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);
 
-       self.misc_bulletcounter = self.misc_bulletcounter + 1;
-       if(self.misc_bulletcounter == 0)
+       actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
+       if(actor.misc_bulletcounter == 0)
        {
-               ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, burst_refire2) * W_WeaponRateFactor();
-               weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, burst_animtime), w_ready);
+               ATTACK_FINISHED(actor) = time + WEP_CVAR(machinegun, burst_refire2) * W_WeaponRateFactor();
+               weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(machinegun, burst_animtime), w_ready);
        }
        else
        {
-               weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, burst_refire), W_MachineGun_Attack_Burst);
+               weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(machinegun, burst_refire), W_MachineGun_Attack_Burst);
        }
 
 }
 
-bool W_MachineGun(int req)
-{
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(MachineGun, wr_aim, void(entity thiswep))
                {
                        if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200)
                                self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, false);
                        else
                                self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, false);
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(WEP_CVAR(machinegun, reload_ammo) && self.clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else if(WEP_CVAR(machinegun, mode) == 1)
+                       if(WEP_CVAR(machinegun, reload_ammo) && actor.clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else
+                       if(WEP_CVAR(machinegun, mode) == 1)
                        {
-                               if(self.BUTTON_ATCK)
-                               if(weapon_prepareattack(0, 0))
+                               if(fire1)
+                               if(weapon_prepareattack(thiswep, actor, false, 0))
                                {
-                                       self.misc_bulletcounter = 0;
-                                       W_MachineGun_Attack_Auto();
+                                       actor.misc_bulletcounter = 0;
+                                       W_MachineGun_Attack_Auto(thiswep, actor, fire1, fire2);
                                }
 
-                               if(self.BUTTON_ATCK2)
-                               if(weapon_prepareattack(1, 0))
+                               if(fire2)
+                               if(weapon_prepareattack(thiswep, actor, true, 0))
                                {
-                                       if(!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
-                                       if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+                                       Weapon w = get_weaponinfo(actor.weapon);
+                                       if(!w.wr_checkammo2(w))
+                                       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                                        {
-                                               W_SwitchWeapon_Force(self, w_getbestweapon(self));
-                                               w_ready();
-                                               return false;
+                                               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                                               w_ready(thiswep, actor, fire1, fire2);
+                                               return;
                                        }
 
-                                       W_DecreaseAmmo(WEP_CVAR(machinegun, burst_ammo));
+                                       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, burst_ammo));
 
-                                       self.misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1;
-                                       W_MachineGun_Attack_Burst();
+                                       actor.misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1;
+                                       W_MachineGun_Attack_Burst(thiswep, actor, fire1, fire2);
                                }
                        }
                        else
                        {
 
-                               if(self.BUTTON_ATCK)
-                               if(weapon_prepareattack(0, 0))
+                               if(fire1)
+                               if(weapon_prepareattack(thiswep, actor, false, 0))
                                {
-                                       self.misc_bulletcounter = 1;
-                                       W_MachineGun_Attack(WEP_MACHINEGUN.m_id); // sets attack_finished
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
+                                       actor.misc_bulletcounter = 1;
+                                       W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id); // sets attack_finished
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
                                }
 
-                               if(self.BUTTON_ATCK2 && WEP_CVAR(machinegun, first))
-                               if(weapon_prepareattack(1, 0))
+                               if(fire2 && WEP_CVAR(machinegun, first))
+                               if(weapon_prepareattack(thiswep, actor, true, 0))
                                {
-                                       self.misc_bulletcounter = 1;
-                                       W_MachineGun_Attack(WEP_MACHINEGUN.m_id | HITTYPE_SECONDARY); // sets attack_finished
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, first_refire), w_ready);
+                                       actor.misc_bulletcounter = 1;
+                                       W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id | HITTYPE_SECONDARY); // sets attack_finished
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(machinegun, first_refire), w_ready);
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(MachineGun, wr_init, void(entity thiswep))
                {
-                       precache_model("models/uziflash.md3");
-                       precache_model(W_Model("g_uzi.md3"));
-                       precache_model(W_Model("v_uzi.md3"));
-                       precache_model(W_Model("h_uzi.iqm"));
-                       precache_sound(W_Sound("uzi_fire"));
                        MACHINEGUN_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(MachineGun, wr_checkammo1, bool(entity thiswep))
                {
+                       float ammo_amount;
                        if(WEP_CVAR(machinegun, mode) == 1)
                                ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, sustained_ammo);
                        else
@@ -328,8 +321,9 @@ bool W_MachineGun(int req)
                        }
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(MachineGun, wr_checkammo2, bool(entity thiswep))
                {
+                       float ammo_amount;
                        if(WEP_CVAR(machinegun, mode) == 1)
                                ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, burst_ammo);
                        else
@@ -344,65 +338,42 @@ bool W_MachineGun(int req)
                        }
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(MachineGun, wr_config, void(entity thiswep))
                {
                        MACHINEGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(MachineGun, wr_reload, void(entity thiswep))
                {
-                       W_Reload(min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(MachineGun, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_THINKING_WITH_PORTALS;
                }
-               case WR_KILLMESSAGE:
+               METHOD(MachineGun, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_MACHINEGUN_MURDER_SNIPE;
                        else
                                return WEAPON_MACHINEGUN_MURDER_SPRAY;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_MachineGun(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(MachineGun, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 2;
                        pointparticles(particleeffectnum(EFFECT_MACHINEGUN_IMPACT), org2, w_backoff * 1000, 1);
                        if(!w_issilent)
                                if(w_random < 0.05)
-                                       sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTN_NORM);
                                else if(w_random < 0.1)
-                                       sound(self, CH_SHOTS, W_Sound("ric2"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC2, VOL_BASE, ATTN_NORM);
                                else if(w_random < 0.2)
-                                       sound(self, CH_SHOTS, W_Sound("ric3"), VOL_BASE, ATTN_NORM);
-
-                       return true;
+                                       sound(self, CH_SHOTS, SND_RIC3, VOL_BASE, ATTN_NORM);
                }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("ric1"));
-                       precache_sound(W_Sound("ric2"));
-                       precache_sound(W_Sound("ric3"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 8048957bce8ab958dab25b557a0c55128b8daf86..548ede96606e08d786ca252624c4d0353e89e737 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ MINE_LAYER,
-/* function  */ W_MineLayer,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 4,
-/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '0.75 1 0',
-/* modelname */ "minelayer",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairminelayer 0.9",
-/* wepimg    */ "weaponminelayer",
-/* refname   */ "minelayer",
-/* wepname   */ _("Mine Layer")
-);
+CLASS(MineLayer, Weapon)
+/* 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');
+/* modelname */ ATTRIB(MineLayer, mdl, string, "minelayer");
+#ifndef MENUQC
+/* model     */ ATTRIB(MineLayer, m_model, Model, MDL_MINELAYER_ITEM);
+#endif
+/* crosshair */ ATTRIB(MineLayer, w_crosshair, string, "gfx/crosshairminelayer");
+/* crosshair */ ATTRIB(MineLayer, w_crosshair_size, float, 0.9);
+/* wepimg    */ ATTRIB(MineLayer, model2, string, "weaponminelayer");
+/* refname   */ ATTRIB(MineLayer, netname, string, "minelayer");
+/* wepname   */ ATTRIB(MineLayer, message, string, _("Mine Layer"));
+ENDCLASS(MineLayer)
+REGISTER_WEAPON(MINE_LAYER, NEW(MineLayer));
 
 #define MINELAYER_SETTINGS(w_cvar,w_prop) MINELAYER_SETTINGS_LIST(w_cvar, w_prop, MINE_LAYER, minelayer)
 #define MINELAYER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -57,11 +59,11 @@ void W_MineLayer_Think(void);
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_minelayer(void) { weapon_defaultspawnfunc(WEP_MINE_LAYER.m_id); }
+spawnfunc(weapon_minelayer) { weapon_defaultspawnfunc(WEP_MINE_LAYER.m_id); }
 
 void W_MineLayer_Stick(entity to)
-{
-       spamsound(self, CH_SHOTS, W_Sound("mine_stick"), VOL_BASE, ATTN_NORM);
+{SELFPARAM();
+       spamsound(self, CH_SHOTS, SND(MINE_STICK), VOL_BASE, ATTN_NORM);
 
        // in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
 
@@ -76,7 +78,7 @@ void W_MineLayer_Stick(entity to)
        newmine.realowner = self.realowner;
        setsize(newmine, '-4 -4 -4', '4 4 4');
        setorigin(newmine, self.origin);
-       setmodel(newmine, "models/mine.md3");
+       setmodel(newmine, MDL_MINELAYER_MINE);
        newmine.angles = vectoangles(-trace_plane_normal); // face against the surface
 
        newmine.mine_orientation = -trace_plane_normal;
@@ -100,14 +102,14 @@ void W_MineLayer_Stick(entity to)
        newmine.flags = self.flags;
 
        remove(self);
-       self = newmine;
+       setself(newmine);
 
        if(to)
                SetMovetypeFollow(self, to);
 }
 
 void W_MineLayer_Explode(void)
-{
+{SELFPARAM();
        if(other.takedamage == DAMAGE_AIM)
                if(IS_PLAYER(other))
                        if(DIFF_TEAM(self.realowner, other))
@@ -122,23 +124,22 @@ void W_MineLayer_Explode(void)
 
        if(self.realowner.weapon == WEP_MINE_LAYER.m_id)
        {
-               entity oldself;
-               oldself = self;
-               self = self.realowner;
-               if(!WEP_ACTION(WEP_MINE_LAYER.m_id, WR_CHECKAMMO1))
+               setself(self.realowner);
+               Weapon w = WEP_MINE_LAYER;
+               if(!w.wr_checkammo1(w))
                {
                        self.cnt = WEP_MINE_LAYER.m_id;
                        ATTACK_FINISHED(self) = time;
                        self.switchweapon = w_getbestweapon(self);
                }
-               self = oldself;
+               setself(this);
        }
        self.realowner.minelayer_mines -= 1;
        remove(self);
 }
 
 void W_MineLayer_DoRemoteExplode(void)
-{
+{SELFPARAM();
        self.event_damage = func_null;
        self.takedamage = DAMAGE_NO;
 
@@ -149,23 +150,22 @@ void W_MineLayer_DoRemoteExplode(void)
 
        if(self.realowner.weapon == WEP_MINE_LAYER.m_id)
        {
-               entity oldself;
-               oldself = self;
-               self = self.realowner;
-               if(!WEP_ACTION(WEP_MINE_LAYER.m_id, WR_CHECKAMMO1))
+               setself(self.realowner);
+               Weapon w = WEP_MINE_LAYER;
+               if(!w.wr_checkammo1(w))
                {
                        self.cnt = WEP_MINE_LAYER.m_id;
                        ATTACK_FINISHED(self) = time;
                        self.switchweapon = w_getbestweapon(self);
                }
-               self = oldself;
+               setself(this);
        }
        self.realowner.minelayer_mines -= 1;
        remove(self);
 }
 
 void W_MineLayer_RemoteExplode(void)
-{
+{SELFPARAM();
        if(self.realowner.deadflag == DEAD_NO)
                if((self.spawnshieldtime >= 0)
                        ? (time >= self.spawnshieldtime) // timer
@@ -177,7 +177,7 @@ void W_MineLayer_RemoteExplode(void)
 }
 
 void W_MineLayer_ProximityExplode(void)
-{
+{SELFPARAM();
        // make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance
        if(WEP_CVAR(minelayer, protection) && self.mine_explodeanyway == 0)
        {
@@ -206,7 +206,7 @@ int W_MineLayer_Count(entity e)
 }
 
 void W_MineLayer_Think(void)
-{
+{SELFPARAM();
        entity head;
 
        self.nextthink = time;
@@ -225,7 +225,7 @@ void W_MineLayer_Think(void)
        if((time > self.cnt) && (!self.mine_time) && (self.cnt > 0))
        {
                if(WEP_CVAR(minelayer, lifetime_countdown) > 0)
-                       spamsound(self, CH_SHOTS, W_Sound("mine_trigger"), VOL_BASE, ATTN_NORM);
+                       spamsound(self, CH_SHOTS, SND(MINE_TRIGGER), VOL_BASE, ATTN_NORM);
                self.mine_time = time + WEP_CVAR(minelayer, lifetime_countdown);
                self.mine_explodeanyway = 1; // make the mine super aggressive -- Samual: Rather, make it not care if a team mate is near.
        }
@@ -248,7 +248,7 @@ void W_MineLayer_Think(void)
                if(head != self.realowner && DIFF_TEAM(head, self.realowner)) // don't trigger for team mates
                if(!self.mine_time)
                {
-                       spamsound(self, CH_SHOTS, W_Sound("mine_trigger"), VOL_BASE, ATTN_NORM);
+                       spamsound(self, CH_SHOTS, SND(MINE_TRIGGER), VOL_BASE, ATTN_NORM);
                        self.mine_time = time + WEP_CVAR(minelayer, time);
                }
                head = head.chain;
@@ -269,7 +269,7 @@ void W_MineLayer_Think(void)
 }
 
 void W_MineLayer_Touch(void)
-{
+{SELFPARAM();
        if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
                return; // we're already a stuck mine, why do we get called? TODO does this even happen?
 
@@ -292,7 +292,7 @@ void W_MineLayer_Touch(void)
 }
 
 void W_MineLayer_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -308,8 +308,8 @@ void W_MineLayer_Damage(entity inflictor, entity attacker, float damage, int dea
                W_PrepareExplosionByDamage(attacker, W_MineLayer_Explode);
 }
 
-void W_MineLayer_Attack(void)
-{
+void W_MineLayer_Attack(Weapon thiswep)
+{SELFPARAM();
        entity mine;
        entity flash;
 
@@ -320,14 +320,14 @@ void W_MineLayer_Attack(void)
                {
                        // the refire delay keeps this message from being spammed
                        Send_Notification(NOTIF_ONE, self, MSG_MULTI, WEAPON_MINELAYER_LIMIT, WEP_CVAR(minelayer, limit));
-                       play2(self, W_Sound("unavailable"));
+                       play2(self, SND(UNAVAILABLE));
                        return;
                }
        }
 
-       W_DecreaseAmmo(WEP_CVAR(minelayer, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR(minelayer, ammo));
 
-       W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', false, 5, W_Sound("mine_fire"), CH_WEAPON_A, WEP_CVAR(minelayer, damage));
+       W_SetupShot_ProjectileSize(self, '-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(self);
@@ -368,10 +368,10 @@ void W_MineLayer_Attack(void)
 
        // muzzle flash for 1st person view
        flash = spawn();
-       setmodel(flash, "models/flash.md3"); // precision set below
+       setmodel(flash, MDL_MINELAYER_MUZZLEFLASH); // precision set below
        SUB_SetFade(flash, time, 0.1);
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-       W_AttachToShotorg(flash, '5 0 0');
+       W_AttachToShotorg(self, flash, '5 0 0');
 
        // common properties
 
@@ -381,7 +381,7 @@ void W_MineLayer_Attack(void)
 }
 
 float W_MineLayer_PlacedMines(float detonate)
-{
+{SELFPARAM();
        entity mine;
        float minfound = 0;
 
@@ -401,13 +401,7 @@ float W_MineLayer_PlacedMines(float detonate)
        return minfound;
 }
 
-bool W_MineLayer(int req)
-{
-       entity mine;
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(MineLayer, wr_aim, void(entity thiswep))
                {
                        // aim and decide to fire if appropriate
                        if(self.minelayer_mines >= WEP_CVAR(minelayer, limit))
@@ -428,7 +422,7 @@ bool W_MineLayer(int req)
                                teamdamage = 0;
                                enemydamage = 0;
                                targetlist = findchainfloat(bot_attack, true);
-                               mine = find(world, classname, "mine");
+                               entity mine = find(world, classname, "mine");
                                while(mine)
                                {
                                        if(mine.realowner != self)
@@ -504,120 +498,86 @@ bool W_MineLayer(int req)
                                //      dprint(ftos(desirabledamage),"\n");
                                if(self.BUTTON_ATCK2 == true) self.BUTTON_ATCK = false;
                        }
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(MineLayer, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(autocvar_g_balance_minelayer_reload_ammo && self.clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
+                       if(autocvar_g_balance_minelayer_reload_ammo && actor.clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
                        {
                                // not if we're holding the minelayer without enough ammo, but can detonate existing mines
-                               if(!(W_MineLayer_PlacedMines(false) && self.WEP_AMMO(MINE_LAYER) < WEP_CVAR(minelayer, ammo)))
-                                       WEP_ACTION(self.weapon, WR_RELOAD);
+                               if(!(W_MineLayer_PlacedMines(false) && actor.WEP_AMMO(MINE_LAYER) < WEP_CVAR(minelayer, ammo))) {
+                                       Weapon w = get_weaponinfo(actor.weapon);
+                                       w.wr_reload(w);
+                               }
                        }
-                       else if(self.BUTTON_ATCK)
+                       else if(fire1)
                        {
-                               if(weapon_prepareattack(0, WEP_CVAR(minelayer, refire)))
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(minelayer, refire)))
                                {
-                                       W_MineLayer_Attack();
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(minelayer, animtime), w_ready);
+                                       W_MineLayer_Attack(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(minelayer, animtime), w_ready);
                                }
                        }
 
-                       if(self.BUTTON_ATCK2)
+                       if(fire2)
                        {
                                if(W_MineLayer_PlacedMines(true))
-                                       sound(self, CH_WEAPON_B, W_Sound("mine_det"), VOL_BASE, ATTN_NORM);
+                                       sound(actor, CH_WEAPON_B, SND_MINE_DET, VOL_BASE, ATTN_NORM);
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(MineLayer, wr_init, void(entity thiswep))
                {
-                       precache_model("models/flash.md3");
-                       precache_model("models/mine.md3");
-                       precache_model(W_Model("g_minelayer.md3"));
-                       precache_model(W_Model("v_minelayer.md3"));
-                       precache_model(W_Model("h_minelayer.iqm"));
-                       precache_sound(W_Sound("mine_det"));
-                       precache_sound(W_Sound("mine_fire"));
-                       precache_sound(W_Sound("mine_stick"));
-                       precache_sound(W_Sound("mine_trigger"));
                        MINELAYER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(MineLayer, wr_checkammo1, bool(entity thiswep))
                {
                        // don't switch while placing a mine
                        if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER.m_id)
                        {
-                               ammo_amount = self.WEP_AMMO(MINE_LAYER) >= WEP_CVAR(minelayer, ammo);
+                               float ammo_amount = self.WEP_AMMO(MINE_LAYER) >= WEP_CVAR(minelayer, ammo);
                                ammo_amount += self.(weapon_load[WEP_MINE_LAYER.m_id]) >= WEP_CVAR(minelayer, ammo);
                                return ammo_amount;
                        }
                        return true;
                }
-               case WR_CHECKAMMO2:
+               METHOD(MineLayer, wr_checkammo2, bool(entity thiswep))
                {
                        if(W_MineLayer_PlacedMines(false))
                                return true;
                        else
                                return false;
                }
-               case WR_CONFIG:
+               METHOD(MineLayer, wr_config, void(entity thiswep))
                {
                        MINELAYER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(MineLayer, wr_resetplayers, void(entity thiswep))
                {
                        self.minelayer_mines = 0;
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(MineLayer, wr_reload, void(entity thiswep))
                {
-                       W_Reload(WEP_CVAR(minelayer, ammo), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, WEP_CVAR(minelayer, ammo), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(MineLayer, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_MINELAYER_SUICIDE;
                }
-               case WR_KILLMESSAGE:
+               METHOD(MineLayer, wr_killmessage, int(entity thiswep))
                {
                        return WEAPON_MINELAYER_MURDER;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_MineLayer(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(MineLayer, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 12;
                        pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), org2, '0 0 0', 1);
                        if(!w_issilent)
-                               sound(self, CH_SHOTS, W_Sound("mine_exp"), VOL_BASE, ATTN_NORM);
-
-                       return true;
-               }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("mine_exp"));
-                       return true;
+                               sound(self, CH_SHOTS, SND_MINE_EXP, VOL_BASE, ATTN_NORM);
                }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 850a6c342fb4e2a6d0a4d47d552ab611e473bc9b..c1995745816ba1d7059743728ab81244d8f06309 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ MORTAR,
-/* function  */ W_Mortar,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 4,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 0 0',
-/* modelname */ "gl",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairgrenadelauncher 0.7",
-/* wepimg    */ "weapongrenadelauncher",
-/* refname   */ "mortar",
-/* wepname   */ _("Mortar")
-);
+CLASS(Mortar, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Mortar, mdl, string, "gl");
+#ifndef MENUQC
+/* model     */ ATTRIB(Mortar, m_model, Model, MDL_MORTAR_ITEM);
+#endif
+/* crosshair */ ATTRIB(Mortar, w_crosshair, string, "gfx/crosshairgrenadelauncher");
+/* crosshair */ ATTRIB(Mortar, w_crosshair_size, float, 0.7);
+/* wepimg    */ ATTRIB(Mortar, model2, string, "weapongrenadelauncher");
+/* refname   */ ATTRIB(Mortar, netname, string, "mortar");
+/* wepname   */ ATTRIB(Mortar, message, string, _("Mortar"));
+ENDCLASS(Mortar)
+REGISTER_WEAPON(MORTAR, NEW(Mortar));
 
 #define MORTAR_SETTINGS(w_cvar,w_prop) MORTAR_SETTINGS_LIST(w_cvar, w_prop, MORTAR, mortar)
 #define MORTAR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -56,11 +58,11 @@ MORTAR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #ifdef IMPLEMENTATION
 #ifdef SVQC
 
-void spawnfunc_weapon_mortar(void) { weapon_defaultspawnfunc(WEP_MORTAR.m_id); }
-void spawnfunc_weapon_grenadelauncher(void) { spawnfunc_weapon_mortar(); }
+spawnfunc(weapon_mortar) { weapon_defaultspawnfunc(WEP_MORTAR.m_id); }
+spawnfunc(weapon_grenadelauncher) { spawnfunc_weapon_mortar(this); }
 
 void W_Mortar_Grenade_Explode(void)
-{
+{SELFPARAM();
        if(other.takedamage == DAMAGE_AIM)
                if(IS_PLAYER(other))
                        if(DIFF_TEAM(self.realowner, other))
@@ -80,7 +82,7 @@ void W_Mortar_Grenade_Explode(void)
 }
 
 void W_Mortar_Grenade_Explode2(void)
-{
+{SELFPARAM();
        if(other.takedamage == DAMAGE_AIM)
                if(IS_PLAYER(other))
                        if(DIFF_TEAM(self.realowner, other))
@@ -101,7 +103,7 @@ void W_Mortar_Grenade_Explode2(void)
 
 
 void W_Mortar_Grenade_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -115,7 +117,7 @@ void W_Mortar_Grenade_Damage(entity inflictor, entity attacker, float damage, in
 }
 
 void W_Mortar_Grenade_Think1(void)
-{
+{SELFPARAM();
        self.nextthink = time;
        if(time > self.cnt)
        {
@@ -129,7 +131,7 @@ void W_Mortar_Grenade_Think1(void)
 }
 
 void W_Mortar_Grenade_Touch1(void)
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
        if(other.takedamage == DAMAGE_AIM || WEP_CVAR_PRI(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
        {
@@ -137,27 +139,14 @@ void W_Mortar_Grenade_Touch1(void)
        }
        else if(WEP_CVAR_PRI(mortar, type) == 1) // bounce
        {
-               float r;
-               r = random() * 6;
-               if(r < 1)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce1"), VOL_BASE, ATTN_NORM);
-               else if(r < 2)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce2"), VOL_BASE, ATTN_NORM);
-               else if(r < 3)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce3"), VOL_BASE, ATTN_NORM);
-               else if(r < 4)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce4"), VOL_BASE, ATTN_NORM);
-               else if(r < 5)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce5"), VOL_BASE, ATTN_NORM);
-               else
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce6"), VOL_BASE, ATTN_NORM);
+               spamsound(self, CH_SHOTS, SND(GRENADE_BOUNCE_RANDOM()), VOL_BASE, ATTN_NORM);
                Send_Effect(EFFECT_HAGAR_BOUNCE, self.origin, self.velocity, 1);
                self.projectiledeathtype |= HITTYPE_BOUNCE;
                self.gl_bouncecnt += 1;
        }
        else if(WEP_CVAR_PRI(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
        {
-               spamsound(self, CH_SHOTS, W_Sound("grenade_stick"), VOL_BASE, ATTN_NORM);
+               spamsound(self, CH_SHOTS, SND(GRENADE_STICK), VOL_BASE, ATTN_NORM);
 
                // let it stick whereever it is
                self.oldvelocity = self.velocity;
@@ -174,7 +163,7 @@ void W_Mortar_Grenade_Touch1(void)
 }
 
 void W_Mortar_Grenade_Touch2(void)
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
        if(other.takedamage == DAMAGE_AIM || WEP_CVAR_SEC(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
        {
@@ -182,20 +171,7 @@ void W_Mortar_Grenade_Touch2(void)
        }
        else if(WEP_CVAR_SEC(mortar, type) == 1) // bounce
        {
-               float r;
-               r = random() * 6;
-               if(r < 1)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce1"), VOL_BASE, ATTN_NORM);
-               else if(r < 2)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce2"), VOL_BASE, ATTN_NORM);
-               else if(r < 3)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce3"), VOL_BASE, ATTN_NORM);
-               else if(r < 4)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce4"), VOL_BASE, ATTN_NORM);
-               else if(r < 5)
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce5"), VOL_BASE, ATTN_NORM);
-               else
-                       spamsound(self, CH_SHOTS, W_Sound("grenade_bounce6"), VOL_BASE, ATTN_NORM);
+               spamsound(self, CH_SHOTS, SND(GRENADE_BOUNCE_RANDOM()), VOL_BASE, ATTN_NORM);
                Send_Effect(EFFECT_HAGAR_BOUNCE, self.origin, self.velocity, 1);
                self.projectiledeathtype |= HITTYPE_BOUNCE;
                self.gl_bouncecnt += 1;
@@ -206,7 +182,7 @@ void W_Mortar_Grenade_Touch2(void)
        }
        else if(WEP_CVAR_SEC(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
        {
-               spamsound(self, CH_SHOTS, W_Sound("grenade_stick"), VOL_BASE, ATTN_NORM);
+               spamsound(self, CH_SHOTS, SND(GRENADE_STICK), VOL_BASE, ATTN_NORM);
 
                // let it stick whereever it is
                self.oldvelocity = self.velocity;
@@ -222,13 +198,13 @@ void W_Mortar_Grenade_Touch2(void)
        }
 }
 
-void W_Mortar_Attack(void)
-{
+void W_Mortar_Attack(Weapon thiswep)
+{SELFPARAM();
        entity gren;
 
-       W_DecreaseAmmo(WEP_CVAR_PRI(mortar, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(mortar, ammo));
 
-       W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 4, W_Sound("grenade_fire"), CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage));
+       W_SetupShot_ProjectileSize(self, '-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);
@@ -271,13 +247,13 @@ void W_Mortar_Attack(void)
        MUTATOR_CALLHOOK(EditProjectile, self, gren);
 }
 
-void W_Mortar_Attack2(void)
-{
+void W_Mortar_Attack2(Weapon thiswep)
+{SELFPARAM();
        entity gren;
 
-       W_DecreaseAmmo(WEP_CVAR_SEC(mortar, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_SEC(mortar, ammo));
 
-       W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 4, W_Sound("grenade_fire"), CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage));
+       W_SetupShot_ProjectileSize(self, '-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);
@@ -320,14 +296,8 @@ void W_Mortar_Attack2(void)
 }
 
 .float bot_secondary_grenademooth;
-bool W_Mortar(int req)
-{
-       entity nade;
-       float nadefound;
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+
+               METHOD(Mortar, wr_aim, void(entity thiswep))
                {
                        self.BUTTON_ATCK = false;
                        self.BUTTON_ATCK2 = false;
@@ -347,8 +317,6 @@ bool W_Mortar(int req)
                                        if(random() < 0.02) self.bot_secondary_grenademooth = 0;
                                }
                        }
-
-                       return true;
                }
                /*case WR_CALCINFO:
                {
@@ -366,126 +334,93 @@ bool W_Mortar(int req)
                        wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime))));
                        wepinfo_ter_dps = 0;
                        */
-               case WR_THINK:
+               METHOD(Mortar, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(autocvar_g_balance_mortar_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else if(self.BUTTON_ATCK)
+                       if(autocvar_g_balance_mortar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else if(fire1)
                        {
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(mortar, refire)))
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(mortar, refire)))
                                {
-                                       W_Mortar_Attack();
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(mortar, animtime), w_ready);
+                                       W_Mortar_Attack(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(mortar, animtime), w_ready);
                                }
                        }
-                       else if(self.BUTTON_ATCK2)
+                       else if(fire2)
                        {
                                if(WEP_CVAR_SEC(mortar, remote_detonateprimary))
                                {
-                                       nadefound = 0;
-                                       for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self)
+                                       bool nadefound = false;
+                                       entity nade;
+                                       for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == actor)
                                        {
                                                if(!nade.gl_detonate_later)
                                                {
                                                        nade.gl_detonate_later = true;
-                                                       nadefound = 1;
+                                                       nadefound = true;
                                                }
                                        }
                                        if(nadefound)
-                                               sound(self, CH_WEAPON_B, W_Sound("rocket_det"), VOL_BASE, ATTN_NORM);
+                                               sound(actor, CH_WEAPON_B, SND_ROCKET_DET, VOL_BASE, ATTN_NORM);
                                }
-                               else if(weapon_prepareattack(1, WEP_CVAR_SEC(mortar, refire)))
+                               else if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(mortar, refire)))
                                {
-                                       W_Mortar_Attack2();
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(mortar, animtime), w_ready);
+                                       W_Mortar_Attack2(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(mortar, animtime), w_ready);
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Mortar, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_gl.md3"));
-                       precache_model(W_Model("v_gl.md3"));
-                       precache_model(W_Model("h_gl.iqm"));
-                       precache_sound(W_Sound("grenade_bounce1"));
-                       precache_sound(W_Sound("grenade_bounce2"));
-                       precache_sound(W_Sound("grenade_bounce3"));
-                       precache_sound(W_Sound("grenade_bounce4"));
-                       precache_sound(W_Sound("grenade_bounce5"));
-                       precache_sound(W_Sound("grenade_bounce6"));
-                       precache_sound(W_Sound("grenade_stick"));
-                       precache_sound(W_Sound("grenade_fire"));
                        MORTAR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Mortar, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_PRI(mortar, ammo);
+                       float ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_PRI(mortar, ammo);
                        ammo_amount += self.(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_PRI(mortar, ammo);
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(Mortar, wr_checkammo2, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_SEC(mortar, ammo);
+                       float ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_SEC(mortar, ammo);
                        ammo_amount += self.(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_SEC(mortar, ammo);
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(Mortar, wr_config, void(entity thiswep))
                {
                        MORTAR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Mortar, wr_reload, void(entity thiswep))
                {
-                       W_Reload(min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), W_Sound("reload")); // WEAPONTODO
-                       return true;
+                       W_Reload(self, min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), SND(RELOAD)); // WEAPONTODO
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Mortar, wr_suicidemessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_MORTAR_SUICIDE_BOUNCE;
                        else
                                return WEAPON_MORTAR_SUICIDE_EXPLODE;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Mortar, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_MORTAR_MURDER_BOUNCE;
                        else
                                return WEAPON_MORTAR_MURDER_EXPLODE;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_Mortar(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Mortar, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 12;
                        pointparticles(particleeffectnum(EFFECT_GRENADE_EXPLODE), org2, '0 0 0', 1);
                        if(!w_issilent)
-                               sound(self, CH_SHOTS, W_Sound("grenade_impact"), VOL_BASE, ATTN_NORM);
-
-                       return true;
+                               sound(self, CH_SHOTS, SND_GRENADE_IMPACT, VOL_BASE, ATTN_NORM);
                }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("grenade_impact"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 2d08c0fcfd2e553de3db16996b6eb07feb353ded..b17476632b9681f5c0cc0bc6ed229d4d3a60bbd0 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ PORTO,
-/* function  */ W_Porto,
-/* ammotype  */ ammo_none,
-/* impulse   */ 0,
-/* flags     */ WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON,
-/* rating    */ 0,
-/* color     */ '0.5 0.5 0.5',
-/* modelname */ "porto",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairporto 0.6",
-/* wepimg    */ "weaponporto",
-/* refname   */ "porto",
-/* wepname   */ _("Port-O-Launch")
-);
+CLASS(PortoLaunch, Weapon)
+/* 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');
+/* modelname */ ATTRIB(PortoLaunch, mdl, string, "porto");
+#ifndef MENUQC
+/* model     */ ATTRIB(PortoLaunch, m_model, Model, MDL_PORTO_ITEM);
+#endif
+/* crosshair */ ATTRIB(PortoLaunch, w_crosshair, string, "gfx/crosshairporto");
+/* crosshair */ ATTRIB(PortoLaunch, w_crosshair_size, float, 0.6);
+/* wepimg    */ ATTRIB(PortoLaunch, model2, string, "weaponporto");
+/* refname   */ ATTRIB(PortoLaunch, netname, string, "porto");
+/* wepname   */ ATTRIB(PortoLaunch, message, string, _("Port-O-Launch"));
+ENDCLASS(PortoLaunch)
+REGISTER_WEAPON(PORTO, NEW(PortoLaunch));
 
 #define PORTO_SETTINGS(w_cvar,w_prop) PORTO_SETTINGS_LIST(w_cvar, w_prop, PORTO, porto)
 #define PORTO_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -39,12 +41,12 @@ PORTO_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-#include "../triggers/trigger/jumppads.qh"
+#include "../../triggers/trigger/jumppads.qh"
 
-void spawnfunc_weapon_porto(void) { weapon_defaultspawnfunc(WEP_PORTO.m_id); }
+spawnfunc(weapon_porto) { weapon_defaultspawnfunc(WEP_PORTO.m_id); }
 
 void W_Porto_Success(void)
-{
+{SELFPARAM();
        if(self.realowner == world)
        {
                objerror("Cannot succeed successfully: no owner\n");
@@ -57,7 +59,7 @@ void W_Porto_Success(void)
 
 string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
 void W_Porto_Fail(float failhard)
-{
+{SELFPARAM();
        if(self.realowner == world)
        {
                objerror("Cannot fail successfully: no owner\n");
@@ -72,7 +74,7 @@ void W_Porto_Fail(float failhard)
 
        self.realowner.porto_current = world;
 
-       if(self.cnt < 0 && !failhard && self.realowner.playerid == self.playerid && self.realowner.deadflag == DEAD_NO && !(self.realowner.weapons & WEPSET_PORTO))
+       if(self.cnt < 0 && !failhard && self.realowner.playerid == self.playerid && self.realowner.deadflag == DEAD_NO && !(self.realowner.weapons & WEPSET(PORTO)))
        {
                setsize(self, '-16 -16 0', '16 16 32');
                setorigin(self, self.origin + trace_plane_normal);
@@ -92,19 +94,15 @@ void W_Porto_Fail(float failhard)
 }
 
 void W_Porto_Remove(entity p)
-{
+{SELFPARAM();
        if(p.porto_current.realowner == p && p.porto_current.classname == "porto")
        {
-               entity oldself;
-               oldself = self;
-               self = p.porto_current;
-               W_Porto_Fail(1);
-               self = oldself;
+               WITH(entity, self, p.porto_current, W_Porto_Fail(1));
        }
 }
 
 void W_Porto_Think(void)
-{
+{SELFPARAM();
        trace_plane_normal = '0 0 0';
        if(self.realowner.playerid != self.playerid)
                remove(self);
@@ -113,7 +111,7 @@ void W_Porto_Think(void)
 }
 
 void W_Porto_Touch(void)
-{
+{SELFPARAM();
        vector norm;
 
        // do not use PROJECTILE_TOUCH here
@@ -136,19 +134,19 @@ void W_Porto_Touch(void)
 
        if(self.realowner.playerid != self.playerid)
        {
-               sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+               sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
                remove(self);
        }
        else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
        {
-               spamsound(self, CH_SHOTS, "porto/bounce.wav", VOL_BASE, ATTEN_NORM);
+               spamsound(self, CH_SHOTS, SND(PORTO_BOUNCE), VOL_BASE, ATTEN_NORM);
                // just reflect
                self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * trace_plane_normal);
                self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * trace_plane_normal));
        }
        else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
        {
-               sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+               sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
                W_Porto_Fail(0);
                if(self.cnt < 0)
                        Portal_ClearAll_PortalsOnly(self.realowner);
@@ -158,14 +156,14 @@ void W_Porto_Touch(void)
                // in-portal only
                if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
                {
-                       sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_SHOTS, SND_PORTO_CREATE, VOL_BASE, ATTEN_NORM);
                        trace_plane_normal = norm;
                        Send_Notification(NOTIF_ONE, self.realowner, MSG_CENTER, CENTER_PORTO_CREATED_IN);
                        W_Porto_Success();
                }
                else
                {
-                       sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
                        trace_plane_normal = norm;
                        W_Porto_Fail(0);
                }
@@ -175,14 +173,14 @@ void W_Porto_Touch(void)
                // out-portal only
                if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
                {
-                       sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_SHOTS, SND_PORTO_CREATE, VOL_BASE, ATTEN_NORM);
                        trace_plane_normal = norm;
                        Send_Notification(NOTIF_ONE, self.realowner, MSG_CENTER, CENTER_PORTO_CREATED_OUT);
                        W_Porto_Success();
                }
                else
                {
-                       sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
                        trace_plane_normal = norm;
                        W_Porto_Fail(0);
                }
@@ -192,7 +190,7 @@ void W_Porto_Touch(void)
                self.effects += EF_BLUE - EF_RED;
                if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
                {
-                       sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_SHOTS, SND_PORTO_CREATE, VOL_BASE, ATTEN_NORM);
                        trace_plane_normal = norm;
                        Send_Notification(NOTIF_ONE, self.realowner, MSG_CENTER, CENTER_PORTO_CREATED_IN);
                        self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * norm);
@@ -201,7 +199,7 @@ void W_Porto_Touch(void)
                }
                else
                {
-                       sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
                        trace_plane_normal = norm;
                        Portal_ClearAll_PortalsOnly(self.realowner);
                        W_Porto_Fail(0);
@@ -213,21 +211,21 @@ void W_Porto_Touch(void)
                {
                        if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
                        {
-                               sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_PORTO_CREATE, VOL_BASE, ATTEN_NORM);
                                trace_plane_normal = norm;
                                Send_Notification(NOTIF_ONE, self.realowner, MSG_CENTER, CENTER_PORTO_CREATED_OUT);
                                W_Porto_Success();
                        }
                        else
                        {
-                               sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+                               sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
                                Portal_ClearAll_PortalsOnly(self.realowner);
                                W_Porto_Fail(0);
                        }
                }
                else
                {
-                       sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
                        Portal_ClearAll_PortalsOnly(self.realowner);
                        W_Porto_Fail(0);
                }
@@ -235,10 +233,10 @@ void W_Porto_Touch(void)
 }
 
 void W_Porto_Attack(float type)
-{
+{SELFPARAM();
        entity gren;
 
-       W_SetupShot(self, false, 4, "porto/fire.wav", CH_WEAPON_A, 0);
+       W_SetupShot(self, false, 4, SND(PORTO_FIRE), CH_WEAPON_A, 0);
        // always shoot from the eye
        w_shotdir = v_forward;
        w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
@@ -287,145 +285,103 @@ void W_Porto_Attack(float type)
        MUTATOR_CALLHOOK(EditProjectile, self, gren);
 }
 
-bool w_nexball_weapon(int req); // WEAPONTODO
-bool W_Porto(int req)
-{
-       //vector v_angle_save;
-
-       if(g_nexball) { return w_nexball_weapon(req); }
-
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(PortoLaunch, wr_aim, void(entity thiswep))
                {
+                       SELFPARAM();
                        self.BUTTON_ATCK = false;
                        self.BUTTON_ATCK2 = false;
                        if(!WEP_CVAR(porto, secondary))
                                if(bot_aim(WEP_CVAR_PRI(porto, speed), 0, WEP_CVAR_PRI(porto, lifetime), false))
                                        self.BUTTON_ATCK = true;
-
-                       return true;
                }
-               case WR_CONFIG:
+               METHOD(PortoLaunch, wr_config, void(entity this))
                {
                        PORTO_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_THINK:
+               METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
                        if(WEP_CVAR(porto, secondary))
                        {
-                               if(self.BUTTON_ATCK)
-                               if(!self.porto_current)
-                               if(!self.porto_forbidden)
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(porto, refire)))
+                               if(fire1)
+                               if(!actor.porto_current)
+                               if(!actor.porto_forbidden)
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(porto, refire)))
                                {
                                        W_Porto_Attack(0);
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
                                }
 
-                               if(self.BUTTON_ATCK2)
-                               if(!self.porto_current)
-                               if(!self.porto_forbidden)
-                               if(weapon_prepareattack(1, WEP_CVAR_SEC(porto, refire)))
+                               if(fire2)
+                               if(!actor.porto_current)
+                               if(!actor.porto_forbidden)
+                               if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(porto, refire)))
                                {
                                        W_Porto_Attack(1);
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(porto, animtime), w_ready);
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(porto, animtime), w_ready);
                                }
                        }
                        else
                        {
-                               if(self.porto_v_angle_held)
+                               if(actor.porto_v_angle_held)
                                {
-                                       if(!self.BUTTON_ATCK2)
+                                       if(!fire2)
                                        {
-                                               self.porto_v_angle_held = 0;
+                                               actor.porto_v_angle_held = 0;
 
-                                               ClientData_Touch(self);
+                                               ClientData_Touch(actor);
                                        }
                                }
                                else
                                {
-                                       if(self.BUTTON_ATCK2)
+                                       if(fire2)
                                        {
-                                               self.porto_v_angle = self.v_angle;
-                                               self.porto_v_angle_held = 1;
+                                               actor.porto_v_angle = actor.v_angle;
+                                               actor.porto_v_angle_held = 1;
 
-                                               ClientData_Touch(self);
+                                               ClientData_Touch(actor);
                                        }
                                }
-                               if(self.porto_v_angle_held)
-                                       makevectors(self.porto_v_angle); // override the previously set angles
+                               if(actor.porto_v_angle_held)
+                                       makevectors(actor.porto_v_angle); // override the previously set angles
 
-                               if(self.BUTTON_ATCK)
-                               if(!self.porto_current)
-                               if(!self.porto_forbidden)
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(porto, refire)))
+                               if(fire1)
+                               if(!actor.porto_current)
+                               if(!actor.porto_forbidden)
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(porto, refire)))
                                {
                                        W_Porto_Attack(-1);
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
                                }
                        }
-
+               }
+               METHOD(PortoLaunch, wr_checkammo1, bool(entity this))
+               {
+                       // always allow infinite ammo
                        return true;
                }
-               case WR_CHECKAMMO1:
-               case WR_CHECKAMMO2:
+               METHOD(PortoLaunch, wr_checkammo2, bool(entity this))
                {
                        // always allow infinite ammo
                        return true;
                }
-               case WR_INIT:
+               METHOD(PortoLaunch, wr_init, void(entity this))
                {
-                       precache_model(W_Model("g_porto.md3"));
-                       precache_model(W_Model("v_porto.md3"));
-                       precache_model(W_Model("h_porto.iqm"));
-                       precache_model("models/portal.md3");
-                       precache_sound("porto/bounce.wav");
-                       precache_sound("porto/create.wav");
-                       precache_sound("porto/expire.wav");
-                       precache_sound("porto/explode.wav");
-                       precache_sound("porto/fire.wav");
-                       precache_sound("porto/unsupported.wav");
                        PORTO_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_SETUP:
+               METHOD(PortoLaunch, wr_setup, void(entity thiswep))
                {
+                       SELFPARAM();
                        self.ammo_field = ammo_none;
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(PortoLaunch, wr_resetplayer, void(entity thiswep))
                {
+                       SELFPARAM();
                        self.porto_current = world;
-                       return true;
                }
-       }
-       return false;
-}
 #endif
 #ifdef CSQC
-bool W_Porto(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
-               {
-                       LOG_INFO("Since when does Porto send DamageInfo?\n");
-                       return true;
+               METHOD(PortoLaunch, wr_impacteffect, void(entity this)) {
+                       LOG_WARNING("Since when does Porto send DamageInfo?\n");
                }
-               case WR_INIT:
-               {
-                       // nothing to do
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
 #endif
 #endif
index ef3babd8723c24128b30f9a6ff813fb676c0c1b9..49b3931566fd829e61e31a77253d5f5a8bfa2f25 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ RIFLE,
-/* function  */ W_Rifle,
-/* ammotype  */ ammo_nails,
-/* impulse   */ 7,
-/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0.5 1 0',
-/* modelname */ "campingrifle",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairrifle 0.6",
-/* wepimg    */ "weaponrifle",
-/* refname   */ "rifle",
-/* wepname   */ _("Rifle")
-);
+CLASS(Rifle, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Rifle, mdl, string, "campingrifle");
+#ifndef MENUQC
+/* model     */ ATTRIB(Rifle, m_model, Model, MDL_RIFLE_ITEM);
+#endif
+/* crosshair */ ATTRIB(Rifle, w_crosshair, string, "gfx/crosshairrifle");
+/* crosshair */ ATTRIB(Rifle, w_crosshair_size, float, 0.6);
+/* wepimg    */ ATTRIB(Rifle, model2, string, "weaponrifle");
+/* refname   */ ATTRIB(Rifle, netname, string, "rifle");
+/* wepname   */ ATTRIB(Rifle, message, string, _("Rifle"));
+ENDCLASS(Rifle)
+REGISTER_WEAPON(RIFLE, NEW(Rifle));
 
 #define RIFLE_SETTINGS(w_cvar,w_prop) RIFLE_SETTINGS_LIST(w_cvar, w_prop, RIFLE, rifle)
 #define RIFLE_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -47,15 +49,15 @@ RIFLE_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_rifle(void) { weapon_defaultspawnfunc(WEP_RIFLE.m_id); }
-void spawnfunc_weapon_campingrifle(void) { spawnfunc_weapon_rifle(); }
-void spawnfunc_weapon_sniperrifle(void) { spawnfunc_weapon_rifle(); }
+spawnfunc(weapon_rifle) { weapon_defaultspawnfunc(WEP_RIFLE.m_id); }
+spawnfunc(weapon_campingrifle) { spawnfunc_weapon_rifle(this); }
+spawnfunc(weapon_sniperrifle) { spawnfunc_weapon_rifle(this); }
 
-void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, string pSound)
-{
+void W_Rifle_FireBullet(Weapon thiswep, float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, string pSound)
+{SELFPARAM();
        float i;
 
-       W_DecreaseAmmo(pAmmo);
+       W_DecreaseAmmo(thiswep, self, pAmmo);
 
        W_SetupShot(self, true, 2, pSound, CH_WEAPON_A, pDamage * pShots);
 
@@ -76,45 +78,45 @@ void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolid
 
 void W_Rifle_Attack(void)
 {
-       W_Rifle_FireBullet(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), W_Sound("campingrifle_fire"));
+       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));
 }
 
 void W_Rifle_Attack2(void)
 {
-       W_Rifle_FireBullet(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), W_Sound("campingrifle_fire2"));
+       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));
 }
 
 .void(void) rifle_bullethail_attackfunc;
 .float rifle_bullethail_frame;
 .float rifle_bullethail_animtime;
 .float rifle_bullethail_refire;
-void W_Rifle_BulletHail_Continue(void)
+void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
        float r, sw, af;
 
-       sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing
-       af = ATTACK_FINISHED(self);
-       self.switchweapon = self.weapon;
-       ATTACK_FINISHED(self) = time;
-       LOG_INFO(ftos(self.WEP_AMMO(RIFLE)), "\n");
-       r = weapon_prepareattack(self.rifle_bullethail_frame == WFRAME_FIRE2, self.rifle_bullethail_refire);
-       if(self.switchweapon == self.weapon)
-               self.switchweapon = sw;
+       sw = actor.switchweapon; // make it not detect weapon changes as reason to abort firing
+       af = ATTACK_FINISHED(actor);
+       actor.switchweapon = actor.weapon;
+       ATTACK_FINISHED(actor) = time;
+       LOG_INFO(ftos(actor.WEP_AMMO(RIFLE)), "\n");
+       r = weapon_prepareattack(thiswep, actor, actor.rifle_bullethail_frame == WFRAME_FIRE2, actor.rifle_bullethail_refire);
+       if(actor.switchweapon == actor.weapon)
+               actor.switchweapon = sw;
        if(r)
        {
-               self.rifle_bullethail_attackfunc();
-               weapon_thinkf(self.rifle_bullethail_frame, self.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue);
+               actor.rifle_bullethail_attackfunc();
+               weapon_thinkf(actor, actor.rifle_bullethail_frame, actor.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue);
                LOG_INFO("thinkf set\n");
        }
        else
        {
-               ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
-               LOG_INFO("out of ammo... ", ftos(self.weaponentity.state), "\n");
+               ATTACK_FINISHED(actor) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
+               LOG_INFO("out of ammo... ", ftos(actor.weaponentity.state), "\n");
        }
 }
 
 void W_Rifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire)
-{
+{SELFPARAM();
        // if we get here, we have at least one bullet to fire
        AttackFunc();
        if(mode)
@@ -124,23 +126,18 @@ void W_Rifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animt
                self.rifle_bullethail_frame = fr;
                self.rifle_bullethail_animtime = animtime;
                self.rifle_bullethail_refire = refire;
-               weapon_thinkf(fr, animtime, W_Rifle_BulletHail_Continue);
+               weapon_thinkf(self, fr, animtime, W_Rifle_BulletHail_Continue);
        }
        else
        {
                // just one shot
-               weapon_thinkf(fr, animtime, w_ready);
+               weapon_thinkf(self, fr, animtime, w_ready);
        }
 }
 
 .float bot_secondary_riflemooth;
-bool W_Rifle(int req)
-{
-       float ammo_amount;
 
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Rifle, wr_aim, void(entity thiswep))
                {
                        self.BUTTON_ATCK=false;
                        self.BUTTON_ATCK2=false;
@@ -162,88 +159,77 @@ bool W_Rifle(int req)
                                        if(random() < 0.03) self.bot_secondary_riflemooth = 0;
                                }
                        }
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Rifle, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(autocvar_g_balance_rifle_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else
+                       if(autocvar_g_balance_rifle_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else
                        {
-                               self.rifle_accumulator = bound(time - WEP_CVAR(rifle, bursttime), self.rifle_accumulator, time);
-                               if(self.BUTTON_ATCK)
-                               if(weapon_prepareattack_check(0, WEP_CVAR_PRI(rifle, refire)))
-                               if(time >= self.rifle_accumulator + WEP_CVAR_PRI(rifle, burstcost))
+                               actor.rifle_accumulator = bound(time - WEP_CVAR(rifle, bursttime), actor.rifle_accumulator, time);
+                               if(fire1)
+                               if(weapon_prepareattack_check(thiswep, actor, false, WEP_CVAR_PRI(rifle, refire)))
+                               if(time >= actor.rifle_accumulator + WEP_CVAR_PRI(rifle, burstcost))
                                {
-                                       weapon_prepareattack_do(0, WEP_CVAR_PRI(rifle, refire));
+                                       weapon_prepareattack_do(actor, false, WEP_CVAR_PRI(rifle, refire));
                                        W_Rifle_BulletHail(WEP_CVAR_PRI(rifle, bullethail), W_Rifle_Attack, WFRAME_FIRE1, WEP_CVAR_PRI(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
-                                       self.rifle_accumulator += WEP_CVAR_PRI(rifle, burstcost);
+                                       actor.rifle_accumulator += WEP_CVAR_PRI(rifle, burstcost);
                                }
-                               if(self.BUTTON_ATCK2)
+                               if(fire2)
                                {
                                        if(WEP_CVAR(rifle, secondary))
                                        {
-                                               if(WEP_CVAR_SEC(rifle, reload))
-                                                       WEP_ACTION(self.weapon, WR_RELOAD);
-                                               else
+                                               if(WEP_CVAR_SEC(rifle, reload)) {
+                                                       Weapon w = get_weaponinfo(actor.weapon);
+                                                       w.wr_reload(w);
+                                               } else
                                                {
-                                                       if(weapon_prepareattack_check(1, WEP_CVAR_SEC(rifle, refire)))
-                                                       if(time >= self.rifle_accumulator + WEP_CVAR_SEC(rifle, burstcost))
+                                                       if(weapon_prepareattack_check(thiswep, actor, true, WEP_CVAR_SEC(rifle, refire)))
+                                                       if(time >= actor.rifle_accumulator + WEP_CVAR_SEC(rifle, burstcost))
                                                        {
-                                                               weapon_prepareattack_do(1, WEP_CVAR_SEC(rifle, refire));
+                                                               weapon_prepareattack_do(actor, true, WEP_CVAR_SEC(rifle, refire));
                                                                W_Rifle_BulletHail(WEP_CVAR_SEC(rifle, bullethail), W_Rifle_Attack2, WFRAME_FIRE2, WEP_CVAR_SEC(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
-                                                               self.rifle_accumulator += WEP_CVAR_SEC(rifle, burstcost);
+                                                               actor.rifle_accumulator += WEP_CVAR_SEC(rifle, burstcost);
                                                        }
                                                }
                                        }
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Rifle, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_sniperrifle.md3"));
-                       precache_model(W_Model("v_sniperrifle.md3"));
-                       precache_model(W_Model("h_sniperrifle.iqm"));
-                       precache_sound(W_Sound("campingrifle_fire"));
-                       precache_sound(W_Sound("campingrifle_fire2"));
                        RIFLE_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Rifle, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_PRI(rifle, ammo);
+                       float ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_PRI(rifle, ammo);
                        ammo_amount += self.(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_PRI(rifle, ammo);
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(Rifle, wr_checkammo2, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_SEC(rifle, ammo);
+                       float ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_SEC(rifle, ammo);
                        ammo_amount += self.(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_SEC(rifle, ammo);
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(Rifle, wr_config, void(entity thiswep))
                {
                        RIFLE_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(Rifle, wr_resetplayer, void(entity thiswep))
                {
                        self.rifle_accumulator = time - WEP_CVAR(rifle, bursttime);
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Rifle, wr_reload, void(entity thiswep))
                {
-                       W_Reload(min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo)), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo)), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Rifle, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_THINKING_WITH_PORTALS;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Rifle, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                        {
@@ -260,16 +246,11 @@ bool W_Rifle(int req)
                                        return WEAPON_RIFLE_MURDER;
                        }
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_Rifle(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Rifle, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 2;
@@ -277,27 +258,21 @@ bool W_Rifle(int req)
                        if(!w_issilent)
                        {
                                if(w_random < 0.2)
-                                       sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTN_NORM);
                                else if(w_random < 0.4)
-                                       sound(self, CH_SHOTS, W_Sound("ric2"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC2, VOL_BASE, ATTN_NORM);
                                else if(w_random < 0.5)
-                                       sound(self, CH_SHOTS, W_Sound("ric3"), VOL_BASE, ATTN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC3, VOL_BASE, ATTN_NORM);
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Rifle, wr_init, void(entity thiswep))
                {
-                       precache_sound(W_Sound("ric1"));
-                       precache_sound(W_Sound("ric2"));
-                       precache_sound(W_Sound("ric3"));
                        if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
                        {
                                precache_pic("gfx/reticle_nex");
                        }
-                       return true;
                }
-               case WR_ZOOMRETICLE:
+               METHOD(Rifle, wr_zoomreticle, bool(entity thiswep))
                {
                        if(button_zoom || zoomscript_caught)
                        {
@@ -310,8 +285,6 @@ bool W_Rifle(int req)
                                return false;
                        }
                }
-       }
-       return false;
-}
+
 #endif
 #endif
index 8a34490e28c0760b91f07994c7dcde7907fb823a..71ddaa6b58acd7f77bde45fbca2cb917c70123bf 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id     */ RPC,
-/* function     */ W_RocketPropelledChainsaw,
-/* ammotype     */ ammo_rockets,
-/* impulse      */ 7,
-/* flags        */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON,
-/* rating       */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '0.5 0.5 0',
-/* modelname */ "ok_rl",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairrocketlauncher 0.7",
-/* wepimg    */ "weaponrpc",
-/* refname   */ "rpc",
-/* wepname      */ _("Rocket Propelled Chainsaw")
-);
+CLASS(RocketPropelledChainsaw, Weapon)
+/* 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');
+/* modelname */ ATTRIB(RocketPropelledChainsaw, mdl, string, "ok_rl");
+#ifndef MENUQC
+/* model     */ ATTRIB(RocketPropelledChainsaw, m_model, Model, MDL_RPC_ITEM);
+#endif
+/* crosshair */ ATTRIB(RocketPropelledChainsaw, w_crosshair, string, "gfx/crosshairrocketlauncher");
+/* crosshair */ ATTRIB(RocketPropelledChainsaw, w_crosshair_size, float, 0.6);
+/* wepimg    */ ATTRIB(RocketPropelledChainsaw, model2, string, "weaponrpc");
+/* refname   */ ATTRIB(RocketPropelledChainsaw, netname, string, "rpc");
+/* wepname   */ ATTRIB(RocketPropelledChainsaw, message, string, _("Rocket Propelled Chainsaw"));
+ENDCLASS(RocketPropelledChainsaw)
+REGISTER_WEAPON(RPC, NEW(RocketPropelledChainsaw));
 
 #define RPC_SETTINGS(w_cvar,w_prop) RPC_SETTINGS_LIST(w_cvar, w_prop, RPC, rpc)
 #define RPC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -45,10 +47,10 @@ RPC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_rpc() { weapon_defaultspawnfunc(WEP_RPC.m_id); }
+spawnfunc(weapon_rpc) { weapon_defaultspawnfunc(WEP_RPC.m_id); }
 
 void W_RocketPropelledChainsaw_Explode()
-{
+{SELFPARAM();
        self.event_damage = func_null;
        self.takedamage = DAMAGE_NO;
 
@@ -58,7 +60,7 @@ void W_RocketPropelledChainsaw_Explode()
 }
 
 void W_RocketPropelledChainsaw_Touch (void)
-{
+{SELFPARAM();
        if(WarpZone_Projectile_Touch())
                if(wasfreed(self))
                        return;
@@ -67,7 +69,7 @@ void W_RocketPropelledChainsaw_Touch (void)
 }
 
 void W_RocketPropelledChainsaw_Damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if (self.health <= 0)
                return;
 
@@ -81,7 +83,7 @@ void W_RocketPropelledChainsaw_Damage (entity inflictor, entity attacker, float
 }
 
 void W_RocketPropelledChainsaw_Think()
-{
+{SELFPARAM();
        if(self.cnt <= time)
        {
                remove(self);
@@ -102,13 +104,13 @@ void W_RocketPropelledChainsaw_Think()
        self.nextthink = time;
 }
 
-void W_RocketPropelledChainsaw_Attack (void)
-{
+void W_RocketPropelledChainsaw_Attack (Weapon thiswep)
+{SELFPARAM();
        entity missile = spawn(); //WarpZone_RefSys_SpawnSameRefSys(self);
        entity flash = spawn ();
 
-       W_DecreaseAmmo(WEP_CVAR(rpc, ammo));
-       W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', false, 5, W_Sound("rocket_fire"), CH_WEAPON_A, WEP_CVAR(rpc, damage));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR(rpc, ammo));
+       W_SetupShot_ProjectileSize (self, '-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);
 
@@ -138,86 +140,71 @@ void W_RocketPropelledChainsaw_Attack (void)
 
        CSQCProjectile(missile, true, PROJECTILE_RPC, false);
 
-       setmodel(flash, "models/flash.md3"); // precision set below
+       setmodel(flash, MDL_RPC_MUZZLEFLASH); // precision set below
        SUB_SetFade (flash, time, 0.1);
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-       W_AttachToShotorg(flash, '5 0 0');
+       W_AttachToShotorg(self, flash, '5 0 0');
        missile.pos1 = missile.velocity;
 
        MUTATOR_CALLHOOK(EditProjectile, self, missile);
 }
 
-bool W_RocketPropelledChainsaw(int req)
-{
-       float ammo_amount = false;
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(RocketPropelledChainsaw, wr_aim, void(entity thiswep))
                {
                        self.BUTTON_ATCK = bot_aim(WEP_CVAR(rpc, speed), 0, WEP_CVAR(rpc, lifetime), false);
-                       return true;
                }
-               case WR_THINK:
+               METHOD(RocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(WEP_CVAR(rpc, reload_ammo) && self.clip_load < WEP_CVAR(rpc, ammo))
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else
+                       if(WEP_CVAR(rpc, reload_ammo) && actor.clip_load < WEP_CVAR(rpc, ammo)) {
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else
                        {
-                               if (self.BUTTON_ATCK)
+                               if (fire1)
                                {
-                                       if(weapon_prepareattack(0, WEP_CVAR(rpc, refire)))
+                                       if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(rpc, refire)))
                                        {
-                                               W_RocketPropelledChainsaw_Attack();
-                                               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(rpc, animtime), w_ready);
+                                               W_RocketPropelledChainsaw_Attack(thiswep);
+                                               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(rpc, animtime), w_ready);
                                        }
                                }
 
-                               if (self.BUTTON_ATCK2)
+                               if (fire2)
                                {
                                        // to-do
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(RocketPropelledChainsaw, wr_init, void(entity thiswep))
                {
-                       precache_model ("models/flash.md3");
-                       precache_model(W_Model("g_ok_rl.md3"));
-                       precache_model(W_Model("v_ok_rl.md3"));
-                       precache_model(W_Model("h_ok_rl.iqm"));
-                       precache_sound (W_Sound("rocket_fire"));
                        RPC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(RocketPropelledChainsaw, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(RPC) >= WEP_CVAR(rpc, ammo);
+                       float ammo_amount = self.WEP_AMMO(RPC) >= WEP_CVAR(rpc, ammo);
                        ammo_amount += self.(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR(rpc, ammo);
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(RocketPropelledChainsaw, wr_checkammo2, bool(entity thiswep))
                {
                        return false;
                }
-               case WR_CONFIG:
+               METHOD(RocketPropelledChainsaw, wr_config, void(entity thiswep))
                {
                        RPC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(RocketPropelledChainsaw, wr_reload, void(entity thiswep))
                {
-                       W_Reload(WEP_CVAR(rpc, ammo), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, WEP_CVAR(rpc, ammo), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(RocketPropelledChainsaw, wr_suicidemessage, int(entity thiswep))
                {
                        if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
                                return WEAPON_RPC_SUICIDE_SPLASH;
                        else
                                return WEAPON_RPC_SUICIDE_DIRECT;
                }
-               case WR_KILLMESSAGE:
+               METHOD(RocketPropelledChainsaw, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_BLASTER_MURDER;
@@ -226,40 +213,19 @@ bool W_RocketPropelledChainsaw(int req)
                        else
                                return WEAPON_RPC_MURDER_DIRECT;
                }
-       }
 
-       return false;
-}
 #endif
 
 #ifdef CSQC
-bool W_RocketPropelledChainsaw(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(RocketPropelledChainsaw, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 12;
                        pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), org2, '0 0 0', 1);
                        if(!w_issilent)
-                               sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
-
-                       return true;
-               }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("rocket_impact"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
+                               sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
                }
-       }
 
-       return false;
-}
 #endif
 #endif
index 69c4974de666df4ac72f24dd5a759c4be0457f5a..645bd9eb9b4475ec31156c64cf358614ec59cf13 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ SEEKER,
-/* function  */ W_Seeker,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 8,
-/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0.5 1 0',
-/* modelname */ "seeker",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairseeker 0.8",
-/* wepimg    */ "weaponseeker",
-/* refname   */ "seeker",
-/* wepname   */ _("T.A.G. Seeker")
-);
+CLASS(Seeker, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Seeker, mdl, string, "seeker");
+#ifndef MENUQC
+/* model     */ ATTRIB(Seeker, m_model, Model, MDL_SEEKER_ITEM);
+#endif
+/* crosshair */ ATTRIB(Seeker, w_crosshair, string, "gfx/crosshairseeker");
+/* crosshair */ ATTRIB(Seeker, w_crosshair_size, float, 0.8);
+/* wepimg    */ ATTRIB(Seeker, model2, string, "weaponseeker");
+/* refname   */ ATTRIB(Seeker, netname, string, "seeker");
+/* wepname   */ ATTRIB(Seeker, message, string, _("T.A.G. Seeker"));
+ENDCLASS(Seeker)
+REGISTER_WEAPON(SEEKER, NEW(Seeker));
 
 #define SEEKER_SETTINGS(w_cvar,w_prop) SEEKER_SETTINGS_LIST(w_cvar, w_prop, SEEKER, seeker)
 #define SEEKER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -84,13 +86,13 @@ SEEKER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_seeker(void) { weapon_defaultspawnfunc(WEP_SEEKER.m_id); }
+spawnfunc(weapon_seeker) { weapon_defaultspawnfunc(WEP_SEEKER.m_id); }
 
 // ============================
 // Begin: Missile functions, these are general functions to be manipulated by other code
 // ============================
 void W_Seeker_Missile_Explode(void)
-{
+{SELFPARAM();
        self.event_damage = func_null;
        RadiusDamage(self, self.realowner, WEP_CVAR(seeker, missile_damage), WEP_CVAR(seeker, missile_edgedamage), WEP_CVAR(seeker, missile_radius), world, world, WEP_CVAR(seeker, missile_force), self.projectiledeathtype, other);
 
@@ -105,7 +107,7 @@ void W_Seeker_Missile_Touch(void)
 }
 
 void W_Seeker_Missile_Think(void)
-{
+{SELFPARAM();
        entity e;
        vector desireddir, olddir, newdir, eorg;
        float turnrate;
@@ -202,7 +204,7 @@ void W_Seeker_Missile_Think(void)
 
 
 void W_Seeker_Missile_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -243,14 +245,14 @@ void W_Seeker_Missile_Animate(void)
 }
 */
 
-void W_Seeker_Fire_Missile(vector f_diff, entity m_target)
-{
+void W_Seeker_Fire_Missile(Weapon thiswep, vector f_diff, entity m_target)
+{SELFPARAM();
        entity missile;
 
-       W_DecreaseAmmo(WEP_CVAR(seeker, missile_ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR(seeker, missile_ammo));
 
        makevectors(self.v_angle);
-       W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, W_Sound("seeker_fire"), CH_WEAPON_A, 0);
+       W_SetupShot_ProjectileSize(self, '-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);
 
@@ -301,7 +303,7 @@ void W_Seeker_Fire_Missile(vector f_diff, entity m_target)
 // Begin: FLAC, close range attack meant for defeating rockets which are coming at you.
 // ============================
 void W_Seeker_Flac_Explode(void)
-{
+{SELFPARAM();
        self.event_damage = func_null;
 
        RadiusDamage(self, self.realowner, WEP_CVAR(seeker, flac_damage), WEP_CVAR(seeker, flac_edgedamage), WEP_CVAR(seeker, flac_radius), world, world, WEP_CVAR(seeker, flac_force), self.projectiledeathtype, other);
@@ -316,13 +318,13 @@ void W_Seeker_Flac_Touch(void)
        W_Seeker_Flac_Explode();
 }
 
-void W_Seeker_Fire_Flac(void)
-{
+void W_Seeker_Fire_Flac(Weapon thiswep)
+{SELFPARAM();
        entity missile;
        vector f_diff;
        float c;
 
-       W_DecreaseAmmo(WEP_CVAR(seeker, flac_ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR(seeker, flac_ammo));
 
        c = self.bulletcounter % 4;
        switch(c)
@@ -341,7 +343,7 @@ void W_Seeker_Fire_Flac(void)
                        f_diff = '+1.25 +3.75 0';
                        break;
        }
-       W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, W_Sound("flac_fire"), CH_WEAPON_A, WEP_CVAR(seeker, flac_damage));
+       W_SetupShot_ProjectileSize(self, '-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);
@@ -389,7 +391,7 @@ entity W_Seeker_Tagged_Info(entity isowner, entity istarget)
 }
 
 void W_Seeker_Attack(void)
-{
+{SELFPARAM();
        entity tracker, closest_target;
 
        closest_target = world;
@@ -408,13 +410,13 @@ void W_Seeker_Attack(void)
        if((!closest_target) || ((trace_fraction < 1) && (trace_ent != closest_target)))
                closest_target = world;
 
-       W_Seeker_Fire_Missile('0 0 0', closest_target);
+       W_Seeker_Fire_Missile(WEP_SEEKER, '0 0 0', closest_target);
 }
 
 void W_Seeker_Vollycontroller_Think(void) // TODO: Merge this with W_Seeker_Attack
-{
+{SELFPARAM();
        float c;
-       entity oldself,oldenemy;
+       entity oldenemy;
        self.cnt = self.cnt - 1;
 
        if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.WEP_AMMO(SEEKER) < WEP_CVAR(seeker, missile_ammo)) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER.m_id))
@@ -425,36 +427,35 @@ void W_Seeker_Vollycontroller_Think(void) // TODO: Merge this with W_Seeker_Atta
 
        self.nextthink = time + WEP_CVAR(seeker, missile_delay) * W_WeaponRateFactor();
 
-       oldself = self;
-       self = self.realowner;
+       setself(self.realowner);
 
        oldenemy = self.enemy;
-       self.enemy = oldself.enemy;
+       self.enemy = this.enemy;
 
        c = self.cnt % 4;
        switch(c)
        {
                case 0:
-                       W_Seeker_Fire_Missile('-1.25 -3.75 0', self.enemy);
+                       W_Seeker_Fire_Missile(WEP_SEEKER, '-1.25 -3.75 0', self.enemy);
                        break;
                case 1:
-                       W_Seeker_Fire_Missile('+1.25 -3.75 0', self.enemy);
+                       W_Seeker_Fire_Missile(WEP_SEEKER, '+1.25 -3.75 0', self.enemy);
                        break;
                case 2:
-                       W_Seeker_Fire_Missile('-1.25 +3.75 0', self.enemy);
+                       W_Seeker_Fire_Missile(WEP_SEEKER, '-1.25 +3.75 0', self.enemy);
                        break;
                case 3:
                default:
-                       W_Seeker_Fire_Missile('+1.25 +3.75 0', self.enemy);
+                       W_Seeker_Fire_Missile(WEP_SEEKER, '+1.25 +3.75 0', self.enemy);
                        break;
        }
 
        self.enemy = oldenemy;
-       self = oldself;
+       setself(this);
 }
 
 void W_Seeker_Tracker_Think(void)
-{
+{SELFPARAM();
        // commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up
        if((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER.m_id)
        || (time > self.tag_time + WEP_CVAR(seeker, tag_tracker_lifetime)))
@@ -475,7 +476,7 @@ void W_Seeker_Tracker_Think(void)
 // Begin: Tag projectile
 // ============================
 void W_Seeker_Tag_Explode(void)
-{
+{SELFPARAM();
        //if(other==self.realowner)
        //    return;
        Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE, other.species, self);
@@ -484,7 +485,7 @@ void W_Seeker_Tag_Explode(void)
 }
 
 void W_Seeker_Tag_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
        self.health = self.health - damage;
@@ -493,7 +494,7 @@ void W_Seeker_Tag_Damage(entity inflictor, entity attacker, float damage, int de
 }
 
 void W_Seeker_Tag_Touch(void)
-{
+{SELFPARAM();
        vector dir;
        vector org2;
        entity e;
@@ -555,12 +556,12 @@ void W_Seeker_Tag_Touch(void)
        return;
 }
 
-void W_Seeker_Fire_Tag(void)
-{
+void W_Seeker_Fire_Tag(Weapon thiswep)
+{SELFPARAM();
        entity missile;
-       W_DecreaseAmmo(WEP_CVAR(seeker, tag_ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR(seeker, tag_ammo));
 
-       W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, W_Sound("tag_fire"), CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count));
+       W_SetupShot_ProjectileSize(self, '-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                 = spawn();
        missile.owner           = missile.realowner = self;
@@ -597,13 +598,7 @@ void W_Seeker_Fire_Tag(void)
 // Begin: Genereal weapon functions
 // ============================
 
-bool W_Seeker(int req)
-{
-       float ammo_amount;
-
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Seeker, wr_aim, void(entity thiswep))
                {
                        if(WEP_CVAR(seeker, type) == 1)
                                if(W_Seeker_Tagged_Info(self, self.enemy) != world)
@@ -612,68 +607,59 @@ bool W_Seeker(int req)
                                        self.BUTTON_ATCK2 = bot_aim(WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), false);
                        else
                                self.BUTTON_ATCK = bot_aim(WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), false);
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Seeker, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(autocvar_g_balance_seeker_reload_ammo && self.clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-
-                       else if(self.BUTTON_ATCK)
+                       if(autocvar_g_balance_seeker_reload_ammo && actor.clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else if(fire1)
                        {
                                if(WEP_CVAR(seeker, type) == 1)
                                {
-                                       if(weapon_prepareattack(0, WEP_CVAR(seeker, missile_refire)))
+                                       if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(seeker, missile_refire)))
                                        {
                                                W_Seeker_Attack();
-                                               weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, missile_animtime), w_ready);
+                                               weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(seeker, missile_animtime), w_ready);
                                        }
                                }
                                else
                                {
-                                       if(weapon_prepareattack(0, WEP_CVAR(seeker, tag_refire)))
+                                       if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(seeker, tag_refire)))
                                        {
-                                               W_Seeker_Fire_Tag();
-                                               weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
+                                               W_Seeker_Fire_Tag(thiswep);
+                                               weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
                                        }
                                }
                        }
 
-                       else if(self.BUTTON_ATCK2)
+                       else if(fire2)
                        {
                                if(WEP_CVAR(seeker, type) == 1)
                                {
-                                       if(weapon_prepareattack(0, WEP_CVAR(seeker, tag_refire)))
+                                       if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(seeker, tag_refire)))
                                        {
-                                               W_Seeker_Fire_Tag();
-                                               weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
+                                               W_Seeker_Fire_Tag(thiswep);
+                                               weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
                                        }
                                }
                                else
                                {
-                                       if(weapon_prepareattack(0, WEP_CVAR(seeker, flac_refire)))
+                                       if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(seeker, flac_refire)))
                                        {
-                                               W_Seeker_Fire_Flac();
-                                               weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, flac_animtime), w_ready);
+                                               W_Seeker_Fire_Flac(thiswep);
+                                               weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(seeker, flac_animtime), w_ready);
                                        }
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Seeker, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_seeker.md3"));
-                       precache_model(W_Model("v_seeker.md3"));
-                       precache_model(W_Model("h_seeker.iqm"));
-                       precache_sound(W_Sound("tag_fire"));
-                       precache_sound(W_Sound("flac_fire"));
-                       precache_sound(W_Sound("seeker_fire"));
                        SEEKER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Seeker, wr_checkammo1, bool(entity thiswep))
                {
+                       float ammo_amount;
                        if(WEP_CVAR(seeker, type) == 1)
                        {
                                ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, missile_ammo);
@@ -686,8 +672,9 @@ bool W_Seeker(int req)
                        }
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(Seeker, wr_checkammo2, bool(entity thiswep))
                {
+                       float ammo_amount;
                        if(WEP_CVAR(seeker, type) == 1)
                        {
                                ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, tag_ammo);
@@ -700,37 +687,30 @@ bool W_Seeker(int req)
                        }
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(Seeker, wr_config, void(entity thiswep))
                {
                        SEEKER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Seeker, wr_reload, void(entity thiswep))
                {
-                       W_Reload(min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo)), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo)), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Seeker, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_SEEKER_SUICIDE;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Seeker, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_SEEKER_MURDER_TAG;
                        else
                                return WEAPON_SEEKER_MURDER_SPRAY;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-bool W_Seeker(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Seeker, wr_impacteffect, void(entity thiswep))
                {
                        vector org2;
                        org2 = w_org + w_backoff * 6;
@@ -739,7 +719,7 @@ bool W_Seeker(int req)
                                if(w_deathtype & HITTYPE_SECONDARY)
                                {
                                        if(!w_issilent)
-                                               sound(self, CH_SHOTS, W_Sound("tag_impact"), 1, ATTEN_NORM);
+                                               sound(self, CH_SHOTS, SND_TAG_IMPACT, 1, ATTEN_NORM);
                                }
                                else
                                {
@@ -747,11 +727,11 @@ bool W_Seeker(int req)
                                        if(!w_issilent)
                                        {
                                                if(w_random<0.15)
-                                                       sound(self, CH_SHOTS, W_Sound("tagexp1"), 1, ATTEN_NORM);
+                                                       sound(self, CH_SHOTS, SND_TAGEXP1, 1, ATTEN_NORM);
                                                else if(w_random<0.7)
-                                                       sound(self, CH_SHOTS, W_Sound("tagexp2"), 1, ATTEN_NORM);
+                                                       sound(self, CH_SHOTS, SND_TAGEXP2, 1, ATTEN_NORM);
                                                else
-                                                       sound(self, CH_SHOTS, W_Sound("tagexp3"), 1, ATTEN_NORM);
+                                                       sound(self, CH_SHOTS, SND_TAGEXP3, 1, ATTEN_NORM);
                                        }
                                }
                        }
@@ -761,33 +741,14 @@ bool W_Seeker(int req)
                                if(!w_issilent)
                                {
                                        if(w_random<0.15)
-                                               sound(self, CH_SHOTS, W_Sound("seekerexp1"), 1, ATTEN_NORM);
+                                               sound(self, CH_SHOTS, SND_SEEKEREXP1, 1, ATTEN_NORM);
                                        else if(w_random<0.7)
-                                               sound(self, CH_SHOTS, W_Sound("seekerexp2"), 1, ATTEN_NORM);
+                                               sound(self, CH_SHOTS, SND_SEEKEREXP2, 1, ATTEN_NORM);
                                        else
-                                               sound(self, CH_SHOTS, W_Sound("seekerexp3"), 1, ATTEN_NORM);
+                                               sound(self, CH_SHOTS, SND_SEEKEREXP3, 1, ATTEN_NORM);
                                }
                        }
-                       return true;
-               }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("seekerexp1"));
-                       precache_sound(W_Sound("seekerexp2"));
-                       precache_sound(W_Sound("seekerexp3"));
-                       precache_sound(W_Sound("tagexp1"));
-                       precache_sound(W_Sound("tagexp2"));
-                       precache_sound(W_Sound("tagexp3"));
-                       precache_sound(W_Sound("tag_impact"));
-                       return true;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
                }
-       }
-       return false;
-}
+
 #endif
 #endif
index 3287ea3cb366e88a61cf9cca8d1a96fc67b81971..cc4daf0486732f99be82c67237c5eb1aba086496 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ SHOCKWAVE,
-/* function  */ W_Shockwave,
-/* ammotype  */ ammo_none,
-/* impulse   */ 2,
-/* flags     */ WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_FLAG_MUTATORBLOCKED,
-/* rating    */ BOT_PICKUP_RATING_LOW,
-/* color     */ '0.5 0.25 0',
-/* modelname */ "shotgun",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairshotgun 0.7",
-/* wepimg    */ "weaponshotgun",
-/* refname   */ "shockwave",
-/* wepname   */ _("Shockwave")
-);
+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_FLAG_MUTATORBLOCKED);
+/* 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");
+#ifndef MENUQC
+/* model     */ ATTRIB(Shockwave, m_model, Model, MDL_SHOCKWAVE_ITEM);
+#endif
+/* crosshair */ ATTRIB(Shockwave, w_crosshair, string, "gfx/crosshairshotgun");
+/* crosshair */ ATTRIB(Shockwave, w_crosshair_size, float, 0.7);
+/* wepimg    */ ATTRIB(Shockwave, model2, string, "weaponshotgun");
+/* refname   */ ATTRIB(Shockwave, netname, string, "shockwave");
+/* wepname   */ ATTRIB(Shockwave, message, string, _("Shockwave"));
+ENDCLASS(Shockwave)
+REGISTER_WEAPON(SHOCKWAVE, NEW(Shockwave));
 
 #define SHOCKWAVE_SETTINGS(w_cvar,w_prop) SHOCKWAVE_SETTINGS_LIST(w_cvar, w_prop, SHOCKWAVE, shockwave)
 #define SHOCKWAVE_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -82,7 +84,7 @@ void Net_ReadShockwaveParticle(void);
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_shockwave(void)
+spawnfunc(weapon_shockwave)
 {
        //if(autocvar_sv_q3acompat_machineshockwaveswap) // WEAPONTODO
        if(autocvar_sv_q3acompat_machineshotgunswap)
@@ -106,7 +108,7 @@ vector shockwave_hit_force[MAX_SHOCKWAVE_HITS];
 
 // MELEE ATTACK MODE
 void W_Shockwave_Melee_Think(void)
-{
+{SELFPARAM();
        // declarations
        float i, f, swing, swing_factor, swing_damage, meleetime, is_player;
        entity target_victim;
@@ -227,17 +229,17 @@ void W_Shockwave_Melee_Think(void)
        }
 }
 
-void W_Shockwave_Melee(void)
+void W_Shockwave_Melee(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       sound(self, CH_WEAPON_A, W_Sound("shotgun_melee"), VOL_BASE, ATTN_NORM);
-       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(shockwave, melee_animtime), w_ready);
+       sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTN_NORM);
+       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR(shockwave, melee_animtime), w_ready);
 
        entity meleetemp;
        meleetemp = spawn();
-       meleetemp.owner = meleetemp.realowner = self;
+       meleetemp.owner = meleetemp.realowner = actor;
        meleetemp.think = W_Shockwave_Melee_Think;
        meleetemp.nextthink = time + WEP_CVAR(shockwave, melee_delay) * W_WeaponRateFactor();
-       W_SetupShot_Range(self, true, 0, "", 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range));
+       W_SetupShot_Range(actor, true, 0, "", 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range));
 }
 
 // SHOCKWAVE ATTACK MODE
@@ -274,7 +276,7 @@ float W_Shockwave_Attack_IsVisible(
        vector nearest_on_line,
        vector sw_shotorg,
        vector attack_endpos)
-{
+{SELFPARAM();
        vector nearest_to_attacker = head.WarpZone_findradius_nearest;
        vector center = (head.origin + (head.mins + head.maxs) * 0.5);
        vector corner;
@@ -334,7 +336,7 @@ float W_Shockwave_Attack_CheckHit(
 }
 
 void W_Shockwave_Send(void)
-{
+{SELFPARAM();
        WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
        WriteByte(MSG_BROADCAST, TE_CSQC_SHOCKWAVEPARTICLE);
        WriteCoord(MSG_BROADCAST, w_shotorg.x);
@@ -350,7 +352,7 @@ void W_Shockwave_Send(void)
 }
 
 void W_Shockwave_Attack(void)
-{
+{SELFPARAM();
        // declarations
        float multiplier, multiplier_from_accuracy, multiplier_from_distance;
        float final_damage;
@@ -360,7 +362,7 @@ void W_Shockwave_Attack(void)
        float i, queue = 0;
 
        // set up the shot direction
-       W_SetupShot(self, false, 3, W_Sound("lasergun_fire"), CH_WEAPON_B, WEP_CVAR(shockwave, blast_damage));
+       W_SetupShot(self, false, 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, self);
        vector attack_hitpos = trace_endpos;
@@ -437,7 +439,7 @@ void W_Shockwave_Attack(void)
                                        );
 
                                // figure out the direction of force
-                               vel = normalize(combine_to_vector(head.velocity.x, head.velocity.y, 0));
+                               vel = normalize(vec3(head.velocity.x, head.velocity.y, 0));
                                vel *=
                                        (
                                                bound(0, (vlen(vel) / autocvar_sv_maxspeed), 1)
@@ -666,90 +668,74 @@ void W_Shockwave_Attack(void)
        }
 }
 
-bool W_Shockwave(int req)
-{
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Shockwave, wr_aim, void(entity thiswep))
                {
                        if(vlen(self.origin - self.enemy.origin) <= WEP_CVAR(shockwave, melee_range))
                                { self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, false); }
                        else
                                { self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, false); }
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Shockwave, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(self.BUTTON_ATCK)
+                       if(fire1)
                        {
-                               if(time >= self.shockwave_blasttime) // handle refire separately so the secondary can be fired straight after a primary
+                               if(time >= actor.shockwave_blasttime) // handle refire separately so the secondary can be fired straight after a primary
                                {
-                                       if(weapon_prepareattack(0, WEP_CVAR(shockwave, blast_animtime)))
+                                       if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(shockwave, blast_animtime)))
                                        {
                                                W_Shockwave_Attack();
-                                               self.shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor();
-                                               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready);
+                                               actor.shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor();
+                                               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready);
                                        }
                                }
                        }
-                       else if(self.BUTTON_ATCK2)
+                       else if(fire2)
                        {
-                               //if(self.clip_load >= 0) // we are not currently reloading
-                               if(!self.crouch) // no crouchmelee please
-                               if(weapon_prepareattack(1, WEP_CVAR(shockwave, melee_refire)))
+                               //if(actor.clip_load >= 0) // we are not currently reloading
+                               if(!actor.crouch) // no crouchmelee please
+                               if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR(shockwave, melee_refire)))
                                {
                                        // attempt forcing playback of the anim by switching to another anim (that we never play) here...
-                                       weapon_thinkf(WFRAME_FIRE1, 0, W_Shockwave_Melee);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, 0, W_Shockwave_Melee);
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Shockwave, wr_init, void(entity thiswep))
                {
-                       precache_model("models/uziflash.md3");
-                       precache_model(W_Model("g_shotgun.md3"));
-                       precache_model(W_Model("v_shotgun.md3"));
-                       precache_model(W_Model("h_shotgun.iqm"));
-                       precache_sound("misc/itempickup.wav");
-                       precache_sound(W_Sound("lasergun_fire"));
-                       precache_sound(W_Sound("shotgun_melee"));
                        SHOCKWAVE_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_CHECKAMMO1:
-               case WR_CHECKAMMO2:
+               METHOD(Shockwave, wr_checkammo1, bool(entity thiswep))
+               {
+                       return true; // infinite ammo
+               }
+               METHOD(Shockwave, wr_checkammo2, bool(entity thiswep))
                {
                        // shockwave has infinite ammo
                        return true;
                }
-               case WR_CONFIG:
+               METHOD(Shockwave, wr_config, void(entity thiswep))
                {
                        SHOCKWAVE_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Shockwave, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_THINKING_WITH_PORTALS;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Shockwave, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_SHOCKWAVE_MURDER_SLAP;
                        else
                                return WEAPON_SHOCKWAVE_MURDER;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
 // WEAPONTODO: add client side settings for these
 const float SW_MAXALPHA = 0.5;
 const float SW_FADETIME = 0.4;
 const float SW_DISTTOMIN = 200;
-void Draw_Shockwave()
+void Draw_Shockwave(entity this)
 {
        // fading/removal control
        float a = bound(0, (SW_MAXALPHA - ((time - self.sw_time) / SW_FADETIME)), SW_MAXALPHA);
@@ -865,32 +851,13 @@ void Net_ReadShockwaveParticle(void)
        shockwave.sw_time = time;
 }
 
-bool W_Shockwave(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+               METHOD(Shockwave, wr_impacteffect, void(entity thiswep))
                {
                        // handled by Net_ReadShockwaveParticle
                        //vector org2;
                        //org2 = w_org + w_backoff * 2;
                        //pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
-                       return false;
-               }
-               case WR_INIT:
-               {
-                       //precache_sound(W_Sound("ric1"));
-                       //precache_sound(W_Sound("ric2"));
-                       //precache_sound(W_Sound("ric3"));
-                       return false;
-               }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
                }
-       }
-       return false;
-}
+
 #endif
 #endif
index 9024bbfa1f70e36b57db17674bf6498f7c5e6d0a..a5cb397737267127c620db7a4e7269fb31a7f7d1 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ SHOTGUN,
-/* function  */ W_Shotgun,
-/* ammotype  */ ammo_shells,
-/* impulse   */ 2,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_LOW,
-/* color     */ '0.5 0.25 0',
-/* modelname */ "shotgun",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairshotgun 0.65",
-/* wepimg    */ "weaponshotgun",
-/* refname   */ "shotgun",
-/* wepname   */ _("Shotgun")
-);
+CLASS(Shotgun, Weapon)
+/* 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);
+/* rating    */ ATTRIB(Shotgun, bot_pickupbasevalue, float, BOT_PICKUP_RATING_LOW);
+/* color     */ ATTRIB(Shotgun, wpcolor, vector, '0.5 0.25 0');
+/* modelname */ ATTRIB(Shotgun, mdl, string, "shotgun");
+#ifndef MENUQC
+/* model     */ ATTRIB(Shotgun, m_model, Model, MDL_SHOTGUN_ITEM);
+#endif
+/* crosshair */ ATTRIB(Shotgun, w_crosshair, string, "gfx/crosshairshotgun");
+/* crosshair */ ATTRIB(Shotgun, w_crosshair_size, float, 0.65);
+/* wepimg    */ ATTRIB(Shotgun, model2, string, "weaponshotgun");
+/* refname   */ ATTRIB(Shotgun, netname, string, "shotgun");
+/* wepname   */ ATTRIB(Shotgun, message, string, _("Shotgun"));
+ENDCLASS(Shotgun)
+REGISTER_WEAPON(SHOTGUN, NEW(Shotgun));
 
 #define SHOTGUN_SETTINGS(w_cvar,w_prop) SHOTGUN_SETTINGS_LIST(w_cvar, w_prop, SHOTGUN, shotgun)
 #define SHOTGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -52,16 +54,16 @@ SHOTGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_shotgun(void) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); }
+spawnfunc(weapon_shotgun) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); }
 
-void W_Shotgun_Attack(float isprimary)
-{
+void W_Shotgun_Attack(Weapon thiswep, float isprimary)
+{SELFPARAM();
        float   sc;
        entity flash;
 
-       W_DecreaseAmmo(WEP_CVAR_PRI(shotgun, ammo));
+       W_DecreaseAmmo(thiswep, self, WEP_CVAR_PRI(shotgun, ammo));
 
-       W_SetupShot(self, true, 5, W_Sound("shotgun_fire"), ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
+       W_SetupShot(self, 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)
                fireBullet(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);
 
@@ -74,17 +76,17 @@ void W_Shotgun_Attack(float isprimary)
 
        // muzzle flash for 1st person view
        flash = spawn();
-       setmodel(flash, "models/uziflash.md3"); // precision set below
+       setmodel(flash, MDL_SHOTGUN_MUZZLEFLASH); // precision set below
        flash.think = SUB_Remove;
        flash.nextthink = time + 0.06;
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-       W_AttachToShotorg(flash, '5 0 0');
+       W_AttachToShotorg(self, flash, '5 0 0');
 }
 
 .float swing_prev;
 .entity swing_alreadyhit;
 void W_Shotgun_Melee_Think(void)
-{
+{SELFPARAM();
        // declarations
        float i, f, swing, swing_factor, swing_damage, meleetime, is_player;
        entity target_victim;
@@ -179,135 +181,121 @@ void W_Shotgun_Melee_Think(void)
        }
 }
 
-void W_Shotgun_Attack2(void)
+void W_Shotgun_Attack2(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       sound(self, CH_WEAPON_A, W_Sound("shotgun_melee"), VOL_BASE, ATTEN_NORM);
-       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready);
+       sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTEN_NORM);
+       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready);
 
        entity meleetemp;
        meleetemp = spawn();
-       meleetemp.realowner = self;
+       meleetemp.realowner = actor;
        meleetemp.think = W_Shotgun_Melee_Think;
        meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor();
-       W_SetupShot_Range(self, true, 0, "", 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range));
+       W_SetupShot_Range(actor, true, 0, "", 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range));
 }
 
 // alternate secondary weapon frames
-void W_Shotgun_Attack3_Frame2()
+void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       if (!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
-       if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+       Weapon w = get_weaponinfo(actor.weapon);
+       if (!w.wr_checkammo2(w))
+       if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(self, w_getbestweapon(self));
-               w_ready();
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               w_ready(thiswep, actor, fire1, fire2);
                return;
        }
 
-       sound(self, CH_WEAPON_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM); // kill previous sound
-       W_Shotgun_Attack(true); // actually is secondary, but we trick the last shot into playing full reload sound
-       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready);
+       sound(actor, CH_WEAPON_SINGLE, SND_Null, VOL_BASE, ATTN_NORM); // kill previous sound
+       W_Shotgun_Attack(WEP_SHOTGUN, true); // actually is secondary, but we trick the last shot into playing full reload sound
+       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready);
 }
-void W_Shotgun_Attack3_Frame1()
+void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       if (!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
-       if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+       Weapon w = get_weaponinfo(actor.weapon);
+       if (!w.wr_checkammo2(w))
+       if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(self, w_getbestweapon(self));
-               w_ready();
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               w_ready(thiswep, actor, fire1, fire2);
                return;
        }
 
-       W_Shotgun_Attack(false);
-       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2);
+       W_Shotgun_Attack(WEP_SHOTGUN, false);
+       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2);
 }
 
 .float shotgun_primarytime;
 
-float W_Shotgun(float req)
-{
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Shotgun, wr_aim, void(entity thiswep))
                {
                        if(vlen(self.origin-self.enemy.origin) <= WEP_CVAR_SEC(shotgun, melee_range))
                                self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, false);
                        else
                                self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, false);
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(WEP_CVAR(shotgun, reload_ammo) && self.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
+                       if(WEP_CVAR(shotgun, reload_ammo) && actor.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
                        {
                                // don't force reload an empty shotgun if its melee attack is active
-                               if(WEP_CVAR(shotgun, secondary) < 2)
-                                       WEP_ACTION(self.weapon, WR_RELOAD);
+                               if(WEP_CVAR(shotgun, secondary) < 2) {
+                                       Weapon w = get_weaponinfo(actor.weapon);
+                                       w.wr_reload(w);
+                               }
                        }
                        else
                        {
-                               if(self.BUTTON_ATCK)
+                               if(fire1)
                                {
-                                       if(time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
+                                       if(time >= actor.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
                                        {
-                                               if(weapon_prepareattack(0, WEP_CVAR_PRI(shotgun, animtime)))
+                                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(shotgun, animtime)))
                                                {
-                                                       W_Shotgun_Attack(true);
-                                                       self.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor();
-                                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
+                                                       W_Shotgun_Attack(thiswep, true);
+                                                       actor.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor();
+                                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
                                                }
                                        }
                                }
-                               else if(self.BUTTON_ATCK2 && WEP_CVAR(shotgun, secondary) == 2)
+                               else if(fire2 && WEP_CVAR(shotgun, secondary) == 2)
                                {
-                                       if(time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
+                                       if(time >= actor.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
                                        {
-                                               if(weapon_prepareattack(0, WEP_CVAR_SEC(shotgun, alt_animtime)))
+                                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_SEC(shotgun, alt_animtime)))
                                                {
-                                                       W_Shotgun_Attack(false);
-                                                       self.shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor();
-                                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1);
+                                                       W_Shotgun_Attack(thiswep, false);
+                                                       actor.shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor();
+                                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1);
                                                }
                                        }
                                }
                        }
-                       if(self.clip_load >= 0) // we are not currently reloading
-                       if(!self.crouch) // no crouchmelee please
+                       if(actor.clip_load >= 0) // we are not currently reloading
+                       if(!actor.crouch) // no crouchmelee please
                        if(WEP_CVAR(shotgun, secondary) == 1)
-                       if((self.BUTTON_ATCK && self.WEP_AMMO(SHOTGUN) <= 0 && !(self.items & IT_UNLIMITED_WEAPON_AMMO)) || self.BUTTON_ATCK2)
-                       if(weapon_prepareattack(1, WEP_CVAR_SEC(shotgun, refire)))
+                       if((fire1 && actor.WEP_AMMO(SHOTGUN) <= 0 && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || fire2)
+                       if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR_SEC(shotgun, refire)))
                        {
                                // attempt forcing playback of the anim by switching to another anim (that we never play) here...
-                               weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2);
+                               weapon_thinkf(actor, WFRAME_FIRE1, 0, W_Shotgun_Attack2);
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Shotgun, wr_init, void(entity thiswep))
                {
-                       precache_model("models/uziflash.md3");
-                       precache_model(W_Model("g_shotgun.md3"));
-                       precache_model(W_Model("v_shotgun.md3"));
-                       precache_model(W_Model("h_shotgun.iqm"));
-                       precache_sound("misc/itempickup.wav");
-                       precache_sound(W_Sound("shotgun_fire"));
-                       precache_sound(W_Sound("shotgun_melee"));
                        SHOTGUN_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_SETUP:
+               METHOD(Shotgun, wr_setup, void(entity thiswep))
                {
                        self.ammo_field = ammo_none;
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Shotgun, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
+                       float ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
                        ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(Shotgun, wr_checkammo2, bool(entity thiswep))
                {
                        if(IS_BOT_CLIENT(self))
                        if(vlen(self.origin-self.enemy.origin) > WEP_CVAR_SEC(shotgun, melee_range))
@@ -317,76 +305,52 @@ float W_Shotgun(float req)
                                case 1: return true; // melee does not use ammo
                                case 2: // secondary triple shot
                                {
-                                       ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
+                                       float ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
                                        ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
                                        return ammo_amount;
                                }
                                default: return false; // secondary unavailable
                        }
                }
-               case WR_CONFIG:
+               METHOD(Shotgun, wr_config, void(entity thiswep))
                {
                        SHOTGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Shotgun, wr_reload, void(entity thiswep))
                {
-                       W_Reload(WEP_CVAR_PRI(shotgun, ammo), W_Sound("reload")); // WEAPONTODO
-                       return true;
+                       W_Reload(self, WEP_CVAR_PRI(shotgun, ammo), SND(RELOAD)); // WEAPONTODO
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Shotgun, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_THINKING_WITH_PORTALS;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Shotgun, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_SECONDARY)
                                return WEAPON_SHOTGUN_MURDER_SLAP;
                        else
                                return WEAPON_SHOTGUN_MURDER;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
 .float prevric;
-float W_Shotgun(float req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Shotgun, wr_impacteffect, void(entity thiswep))
                {
-                       vector org2;
-                       org2 = w_org + w_backoff * 2;
+                       vector org2 = w_org + w_backoff * 2;
                        pointparticles(particleeffectnum(EFFECT_SHOTGUN_IMPACT), org2, w_backoff * 1000, 1);
                        if(!w_issilent && time - self.prevric > 0.25)
                        {
                                if(w_random < 0.0165)
-                                       sound(self, CH_SHOTS, W_Sound("ric1"), VOL_BASE, ATTEN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTEN_NORM);
                                else if(w_random < 0.033)
-                                       sound(self, CH_SHOTS, W_Sound("ric2"), VOL_BASE, ATTEN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC2, VOL_BASE, ATTEN_NORM);
                                else if(w_random < 0.05)
-                                       sound(self, CH_SHOTS, W_Sound("ric3"), VOL_BASE, ATTEN_NORM);
+                                       sound(self, CH_SHOTS, SND_RIC3, VOL_BASE, ATTEN_NORM);
                                self.prevric = time;
                        }
-
-                       return true;
-               }
-               case WR_INIT:
-               {
-                       precache_sound(W_Sound("ric1"));
-                       precache_sound(W_Sound("ric2"));
-                       precache_sound(W_Sound("ric3"));
-                       return true;
                }
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-       return false;
-}
+
 #endif
 #endif
index 686c89ec3a7f6f0dae6a0fe3ed8c0761735b6555..66ea8f7b5165151bdb4040bb01883068dd452bf1 100644 (file)
@@ -1,20 +1,22 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ TUBA,
-/* function  */ W_Tuba,
-/* ammotype  */ ammo_none,
-/* impulse   */ 1,
-/* flags     */ WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0 1 0',
-/* modelname */ "tuba",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairtuba",
-/* wepimg    */ "weapontuba",
-/* refname   */ "tuba",
+CLASS(Tuba, Weapon)
+/* ammotype  */ //ATTRIB(Tuba, ammo_field, .int, ammo_none)
+/* 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');
+/* modelname */ ATTRIB(Tuba, mdl, string, "tuba");
+#ifndef MENUQC
+/* model     */ ATTRIB(Tuba, m_model, Model, MDL_TUBA_ITEM);
+#endif
+/* crosshair */ ATTRIB(Tuba, w_crosshair, string, "gfx/crosshairtuba");
+/* crosshair */ //ATTRIB(Tuba, w_crosshair_size, float, 0.65);
+/* wepimg    */ ATTRIB(Tuba, model2, string, "weapontuba");
+/* refname   */ ATTRIB(Tuba, netname, string, "tuba");
 /* xgettext:no-c-format */
-/* wepname   */ _("@!#%'n Tuba")
-);
+/* wepname   */ ATTRIB(Tuba, message, string, _("@!#%'n Tuba"));
+ENDCLASS(Tuba)
+REGISTER_WEAPON(TUBA, NEW(Tuba));
 
 #define TUBA_SETTINGS(w_cvar,w_prop) TUBA_SETTINGS_LIST(w_cvar, w_prop, TUBA, tuba)
 #define TUBA_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -54,7 +56,7 @@ float W_Tuba_MarkClientOnlyFieldsAsUsed() {
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_tuba(void) { weapon_defaultspawnfunc(WEP_TUBA.m_id); }
+spawnfunc(weapon_tuba) { weapon_defaultspawnfunc(WEP_TUBA.m_id); }
 
 bool W_Tuba_HasPlayed(entity pl, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo)
 {
@@ -148,7 +150,7 @@ bool W_Tuba_HasPlayed(entity pl, string melody, int instrument, bool ignorepitch
 }
 
 void W_Tuba_NoteOff(void)
-{
+{SELFPARAM();
        // we have a note:
        //   on: self.spawnshieldtime
        //   off: time
@@ -251,7 +253,7 @@ int W_Tuba_GetNote(entity pl, int hittype)
        return note;
 }
 
-bool W_Tuba_NoteSendEntity(entity to, int sf)
+bool W_Tuba_NoteSendEntity(entity this, entity to, int sf)
 {
        int f;
 
@@ -280,7 +282,7 @@ bool W_Tuba_NoteSendEntity(entity to, int sf)
 }
 
 void W_Tuba_NoteThink(void)
-{
+{SELFPARAM();
        float dist_mult;
        float vol0, vol1;
        vector dir0, dir1;
@@ -318,7 +320,7 @@ void W_Tuba_NoteThink(void)
 }
 
 void W_Tuba_NoteOn(float hittype)
-{
+{SELFPARAM();
        vector o;
        float n;
 
@@ -336,10 +338,7 @@ void W_Tuba_NoteOn(float hittype)
        {
                if(self.tuba_note.cnt != n || self.tuba_note.tuba_instrument != self.tuba_instrument)
                {
-                       entity oldself = self;
-                       self = self.tuba_note;
-                       W_Tuba_NoteOff();
-                       self = oldself;
+                       WITH(entity, self, self.tuba_note, W_Tuba_NoteOff());
                }
        }
 
@@ -368,11 +367,7 @@ void W_Tuba_NoteOn(float hittype)
        }
 }
 
-bool W_Tuba(int req)
-{
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Tuba, wr_aim, void(entity thiswep))
                {
                        // bots cannot play the Tuba well yet
                        // I think they should start with the recorder first
@@ -383,57 +378,41 @@ bool W_Tuba(int req)
                                else
                                        self.BUTTON_ATCK2 = 1;
                        }
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Tuba, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(self.BUTTON_ATCK)
-                       if(weapon_prepareattack(0, WEP_CVAR(tuba, refire)))
+                       if(fire1)
+                       if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR(tuba, refire)))
                        {
                                W_Tuba_NoteOn(0);
-                               //weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_tuba_animtime, w_ready);
-                               weapon_thinkf(WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
+                               //weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_tuba_animtime, w_ready);
+                               weapon_thinkf(actor, WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
                        }
-                       if(self.BUTTON_ATCK2)
-                       if(weapon_prepareattack(1, WEP_CVAR(tuba, refire)))
+                       if(fire2)
+                       if(weapon_prepareattack(thiswep, actor, true, WEP_CVAR(tuba, refire)))
                        {
                                W_Tuba_NoteOn(HITTYPE_SECONDARY);
-                               //weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_tuba_animtime, w_ready);
-                               weapon_thinkf(WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
+                               //weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_balance_tuba_animtime, w_ready);
+                               weapon_thinkf(actor, WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
                        }
-                       if(self.tuba_note)
+                       if(actor.tuba_note)
                        {
-                               if(!self.BUTTON_ATCK && !self.BUTTON_ATCK2)
+                               if(!fire1 && !fire2)
                                {
-                                       entity oldself = self;
-                                       self = self.tuba_note;
-                                       W_Tuba_NoteOff();
-                                       self = oldself;
+                                       WITH(entity, self, actor.tuba_note, W_Tuba_NoteOff());
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Tuba, wr_init, void(entity thiswep))
                {
-                       precache_model(W_Model("g_tuba.md3"));
-                       precache_model(W_Model("v_tuba.md3"));
-                       precache_model(W_Model("h_tuba.iqm"));
-                       precache_model(W_Model("v_akordeon.md3"));
-                       precache_model(W_Model("h_akordeon.iqm"));
-                       precache_model(W_Model("v_kleinbottle.md3"));
-                       precache_model(W_Model("h_kleinbottle.iqm"));
                        TUBA_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_SETUP:
+               METHOD(Tuba, wr_setup, void(entity thiswep))
                {
                        self.ammo_field = ammo_none;
                        self.tuba_instrument = 0;
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Tuba, wr_reload, void(entity thiswep))
                {
                        // switch to alternate instruments :)
                        if(self.weaponentity.state == WS_READY)
@@ -456,22 +435,22 @@ bool W_Tuba(int req)
                                W_SetupShot(self, false, 0, "", 0, 0);
                                Send_Effect(EFFECT_TELEPORT, w_shotorg, '0 0 0', 1);
                                self.weaponentity.state = WS_INUSE;
-                               weapon_thinkf(WFRAME_RELOAD, 0.5, w_ready);
+                               weapon_thinkf(self, WFRAME_RELOAD, 0.5, w_ready);
                        }
-
-                       return true;
                }
-               case WR_CHECKAMMO1:
-               case WR_CHECKAMMO2:
+               METHOD(Tuba, wr_checkammo1, bool(entity thiswep))
+               {
+                       return true; // infinite ammo
+               }
+               METHOD(Tuba, wr_checkammo2, bool(entity thiswep))
                {
                        return true; // tuba has infinite ammo
                }
-               case WR_CONFIG:
+               METHOD(Tuba, wr_config, void(entity thiswep))
                {
                        TUBA_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Tuba, wr_suicidemessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_BOUNCE)
                                return WEAPON_KLEINBOTTLE_SUICIDE;
@@ -480,7 +459,7 @@ bool W_Tuba(int req)
                        else
                                return WEAPON_TUBA_SUICIDE;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Tuba, wr_killmessage, int(entity thiswep))
                {
                        if(w_deathtype & HITTYPE_BOUNCE)
                                return WEAPON_KLEINBOTTLE_MURDER;
@@ -489,26 +468,6 @@ bool W_Tuba(int req)
                        else
                                return WEAPON_TUBA_MURDER;
                }
-       }
-       return false;
-}
-#endif
-#ifdef CSQC
-bool W_Tuba(int req)
-{
-       // nothing to do here; particles of tuba are handled differently
-       // WEAPONTODO
 
-       switch(req)
-       {
-               case WR_ZOOMRETICLE:
-               {
-                       // no weapon specific image for this weapon
-                       return false;
-               }
-       }
-
-       return false;
-}
 #endif
 #endif
index 256019d69de67b91a12084a981a4e96e9b5b8b8d..f7aceee20f3f531f0519610d3a1de5e511ad2b17 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ VAPORIZER,
-/* function  */ W_Vaporizer,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 7,
-/* flags     */ WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_FLAG_SUPERWEAPON | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '0.5 1 1',
-/* modelname */ "minstanex",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairminstanex 0.6",
-/* wepimg    */ "weaponminstanex",
-/* refname   */ "vaporizer",
-/* wepname   */ _("Vaporizer")
-);
+CLASS(Vaporizer, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Vaporizer, mdl, string, "minstanex");
+#ifndef MENUQC
+/* model     */ ATTRIB(Vaporizer, m_model, Model, MDL_VAPORIZER_ITEM);
+#endif
+/* crosshair */ ATTRIB(Vaporizer, w_crosshair, string, "gfx/crosshairminstanex");
+/* crosshair */ ATTRIB(Vaporizer, w_crosshair_size, float, 0.6);
+/* wepimg    */ ATTRIB(Vaporizer, model2, string, "weaponminstanex");
+/* refname   */ ATTRIB(Vaporizer, netname, string, "vaporizer");
+/* wepname   */ ATTRIB(Vaporizer, message, string, _("Vaporizer"));
+ENDCLASS(Vaporizer)
+REGISTER_WEAPON(VAPORIZER, NEW(Vaporizer));
 
 #define VAPORIZER_SETTINGS(w_cvar,w_prop) VAPORIZER_SETTINGS_LIST(w_cvar, w_prop, VAPORIZER, vaporizer)
 #define VAPORIZER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -55,11 +57,11 @@ VAPORIZER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_vaporizer(void) { weapon_defaultspawnfunc(WEP_VAPORIZER.m_id); }
-void spawnfunc_weapon_minstanex(void) { spawnfunc_weapon_vaporizer(); }
+spawnfunc(weapon_vaporizer) { weapon_defaultspawnfunc(WEP_VAPORIZER.m_id); }
+spawnfunc(weapon_minstanex) { spawnfunc_weapon_vaporizer(this); }
 
 void W_RocketMinsta_Explosion(vector loc)
-{
+{SELFPARAM();
        if(accuracy_canbegooddamage(self))
                accuracy_add(self, WEP_DEVASTATOR.m_id, autocvar_g_rm_damage, 0);
        entity dmgent = spawn();
@@ -69,15 +71,15 @@ void W_RocketMinsta_Explosion(vector loc)
        remove(dmgent);
 }
 
-void W_Vaporizer_Attack(void)
-{
+void W_Vaporizer_Attack(Weapon thiswep)
+{SELFPARAM();
        bool flying = IsFlying(self); // 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(self, true, 0, "", 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 (self, CH_WEAPON_A, W_Sound("minstanexfire"), VOL_BASE * 0.8, ATTEN_NORM);
+       sound (self, CH_WEAPON_A, SND_MINSTANEXFIRE, VOL_BASE * 0.8, ATTEN_NORM);
 
        yoda = 0;
        damage_goodhits = 0;
@@ -96,51 +98,18 @@ void W_Vaporizer_Attack(void)
        Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        // teamcolor / hit beam effect
-       vector v;
-       v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
-       switch(self.team)
-       {
-               case NUM_TEAM_1:   // Red
-                       if(damage_goodhits)
-                               Send_Effect(EFFECT_VAPORIZER_RED_HIT, w_shotorg, v, 1);
-                       else
-                               Send_Effect(EFFECT_VAPORIZER_RED, w_shotorg, v, 1);
-                       break;
-               case NUM_TEAM_2:   // Blue
-                       if(damage_goodhits)
-                               Send_Effect(EFFECT_VAPORIZER_BLUE_HIT, w_shotorg, v, 1);
-                       else
-                               Send_Effect(EFFECT_VAPORIZER_BLUE, w_shotorg, v, 1);
-                       break;
-               case NUM_TEAM_3:   // Yellow
-                       if(damage_goodhits)
-                               Send_Effect(EFFECT_VAPORIZER_YELLOW_HIT, w_shotorg, v, 1);
-                       else
-                               Send_Effect(EFFECT_VAPORIZER_YELLOW, w_shotorg, v, 1);
-                       break;
-               case NUM_TEAM_4:   // Pink
-                       if(damage_goodhits)
-                               Send_Effect(EFFECT_VAPORIZER_PINK_HIT, w_shotorg, v, 1);
-                       else
-                               Send_Effect(EFFECT_VAPORIZER_PINK, w_shotorg, v, 1);
-                       break;
-               default:
-                       if(damage_goodhits)
-                               Send_Effect_("TE_TEI_G3_HIT", w_shotorg, v, 1);
-                       else
-                               Send_Effect_("TE_TEI_G3", w_shotorg, v, 1);
-                       break;
-       }
+       vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+       Send_Effect((damage_goodhits ? EFFECT_VAPORIZER_HIT(self.team) : EFFECT_VAPORIZER(self.team)), w_shotorg, v, 1);
 
        if(autocvar_g_rm)
        if(!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
                W_RocketMinsta_Explosion(trace_endpos);
 
-       W_DecreaseAmmo(((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)));
+       W_DecreaseAmmo(thiswep, self, ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)));
 }
 
 void W_RocketMinsta_Laser_Explode (void)
-{
+{SELFPARAM();
        if(other.takedamage == DAMAGE_AIM)
                if(IS_PLAYER(other))
                        if(DIFF_TEAM(self.realowner, other))
@@ -155,7 +124,7 @@ void W_RocketMinsta_Laser_Explode (void)
 }
 
 void W_RocketMinsta_Laser_Touch (void)
-{
+{SELFPARAM();
        PROJECTILE_TOUCH;
        //W_RocketMinsta_Laser_Explode ();
        RadiusDamage (self, self.realowner, self.rm_damage, self.rm_edmg, autocvar_g_rm_laser_radius, world, world, self.rm_force, self.projectiledeathtype, other);
@@ -163,9 +132,9 @@ void W_RocketMinsta_Laser_Touch (void)
 }
 
 void W_RocketMinsta_Attack2(void)
-{
+{SELFPARAM();
        makevectors(self.v_angle);
-       
+
        entity proj;
        float counter = 0;
        float total = autocvar_g_rm_laser_count;
@@ -174,7 +143,7 @@ void W_RocketMinsta_Attack2(void)
 
        float w = self.weapon;
        self.weapon = WEP_ELECTRO.m_id;
-       W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', false, 2, W_Sound("crylink_fire"), CH_WEAPON_A, autocvar_g_rm_laser_damage);
+       W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', false, 2, SND(CRYLINK_FIRE), CH_WEAPON_A, autocvar_g_rm_laser_damage);
        self.weapon = w;
 
        Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -192,11 +161,11 @@ void W_RocketMinsta_Attack2(void)
         PROJECTILE_MAKETRIGGER(proj);
         proj.projectiledeathtype = WEP_ELECTRO.m_id;
         setorigin(proj, w_shotorg);
-               
+
                proj.rm_force = autocvar_g_rm_laser_force / total;
                proj.rm_damage = autocvar_g_rm_laser_damage / total;
                proj.rm_edmg = proj.rm_damage;
-        
+
         //W_SetupProjectileVelocity(proj, autocvar_g_rm_laser_speed, spread * (rndspread ? random() : 1) * autocvar_g_rm_laser_speed);
 
         proj.movetype = MOVETYPE_BOUNCEMISSILE;
@@ -218,16 +187,16 @@ void W_RocketMinsta_Attack2(void)
 }
 
 void W_RocketMinsta_Attack3 (void)
-{
+{SELFPARAM();
        makevectors(self.v_angle);
-       
+
        entity proj;
        float counter = 0;
        float total = 1;
 
        int w = self.weapon;
        self.weapon = WEP_ELECTRO.m_id;
-       W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', false, 2, W_Sound("electro_fire2"), CH_WEAPON_A, autocvar_g_rm_laser_damage);
+       W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', false, 2, SND(ELECTRO_FIRE2), CH_WEAPON_A, autocvar_g_rm_laser_damage);
        self.weapon = w;
 
        Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -245,11 +214,11 @@ void W_RocketMinsta_Attack3 (void)
         PROJECTILE_MAKETRIGGER(proj);
         proj.projectiledeathtype = WEP_ELECTRO.m_id;
         setorigin(proj, w_shotorg);
-               
+
                proj.rm_force = autocvar_g_rm_laser_force / total;
                proj.rm_damage = autocvar_g_rm_laser_damage / total;
                proj.rm_edmg = proj.rm_damage;
-        
+
         //W_SetupProjectileVelocity(proj, autocvar_g_rm_laser_speed, spread * (rndspread ? random() : 1) * autocvar_g_rm_laser_speed);
 
         proj.movetype = MOVETYPE_BOUNCEMISSILE;
@@ -268,76 +237,69 @@ void W_RocketMinsta_Attack3 (void)
     }
 }
 
-float W_Vaporizer(float req)
-{
-       float ammo_amount;
-       float vaporizer_ammo;
-       float rapid = autocvar_g_rm_laser_rapid;
-
-       // now multiple WR_s use this
-       vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
-
-       switch(req)
-       {
-               case WR_AIM:
+               METHOD(Vaporizer, wr_aim, void(entity thiswep))
                {
                        if(self.WEP_AMMO(VAPORIZER) > 0)
                                self.BUTTON_ATCK = bot_aim(1000000, 0, 1, false);
                        else
                                self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(vaporizer, speed), 0, WEP_CVAR_SEC(vaporizer, lifetime), false); // WEAPONTODO: replace with proper vaporizer cvars
-
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
+                       float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
                        // if the laser uses load, we also consider its ammo for reloading
-                       if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && self.clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else if(WEP_CVAR(vaporizer, reload_ammo) && self.clip_load < vaporizer_ammo) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       if(self.BUTTON_ATCK && (self.ammo_cells || !autocvar_g_rm) && !forbidWeaponUse(self))
+                       if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && actor.clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else if(WEP_CVAR(vaporizer, reload_ammo) && actor.clip_load < vaporizer_ammo) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       }
+                       if(fire1 && (actor.ammo_cells || !autocvar_g_rm) && !forbidWeaponUse(actor))
                        {
-                               if(weapon_prepareattack(0, WEP_CVAR_PRI(vaporizer, refire)))
+                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(vaporizer, refire)))
                                {
-                                       W_Vaporizer_Attack();
-                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(vaporizer, animtime), w_ready);
+                                       W_Vaporizer_Attack(thiswep);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(vaporizer, animtime), w_ready);
                                }
                        }
-                       if(self.BUTTON_ATCK2 || (self.BUTTON_ATCK && !self.ammo_cells && autocvar_g_rm))
+                       if(fire2 || (fire1 && !actor.ammo_cells && autocvar_g_rm))
                        {
                                if((autocvar_g_rm && autocvar_g_rm_laser) || autocvar_g_rm_laser == 2)
                                {
-                                       if(self.jump_interval <= time && !self.held_down)
+                                       bool rapid = autocvar_g_rm_laser_rapid;
+                                       if(actor.jump_interval <= time && !actor.held_down)
                                        {
                                                if(rapid)
-                                                       self.held_down = true;
-                                               self.jump_interval = time + autocvar_g_rm_laser_refire;
-                                               self.jump_interval2 = time + autocvar_g_rm_laser_rapid_delay;
+                                                       actor.held_down = true;
+                                               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();
                                        }
-                                       else if(rapid && self.jump_interval2 <= time && self.held_down)
+                                       else if(rapid && actor.jump_interval2 <= time && actor.held_down)
                                        {
-                                               self.jump_interval2 = time + autocvar_g_rm_laser_rapid_refire;
+                                               actor.jump_interval2 = time + autocvar_g_rm_laser_rapid_refire;
                                                damage_goodhits = 0;
                                                W_RocketMinsta_Attack3();
-                                               //weapon_thinkf(WFRAME_FIRE2, autocvar_g_rm_laser_rapid_animtime, w_ready);
+                                               //weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_rm_laser_rapid_animtime, w_ready);
                                        }
                                }
-                               else if (self.jump_interval <= time)
+                               else if (actor.jump_interval <= time)
                                {
                                        // handle refire manually, so that primary and secondary can be fired without conflictions (important for instagib)
-                                       self.jump_interval = time + WEP_CVAR_SEC(vaporizer, refire) * W_WeaponRateFactor();
+                                       actor.jump_interval = time + WEP_CVAR_SEC(vaporizer, refire) * W_WeaponRateFactor();
 
                                        // decrease ammo for the laser?
                                        if(WEP_CVAR_SEC(vaporizer, ammo))
-                                               W_DecreaseAmmo(WEP_CVAR_SEC(vaporizer, ammo));
+                                               W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(vaporizer, ammo));
 
                                        // ugly instagib hack to reuse the fire mode of the laser
-                                       makevectors(self.v_angle);
-                                       int oldwep = self.weapon; // we can't avoid this hack
-                                       self.weapon = WEP_BLASTER.m_id;
+                                       makevectors(actor.v_angle);
+                                       int oldwep = actor.weapon; // we can't avoid this hack
+                                       actor.weapon = WEP_BLASTER.m_id;
                                        W_Blaster_Attack(
+                                               actor,
                                                WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                                                WEP_CVAR_SEC(vaporizer, shotangle),
                                                WEP_CVAR_SEC(vaporizer, damage),
@@ -349,115 +311,93 @@ float W_Vaporizer(float req)
                                                WEP_CVAR_SEC(vaporizer, delay),
                                                WEP_CVAR_SEC(vaporizer, lifetime)
                                        );
-                                       self.weapon = oldwep;
+                                       actor.weapon = oldwep;
 
                                        // now do normal refire
-                                       weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(vaporizer, animtime), w_ready);
+                                       weapon_thinkf(actor, WFRAME_FIRE2, WEP_CVAR_SEC(vaporizer, animtime), w_ready);
                                }
                        }
                        else
-                               self.held_down = false;
-                       
-                       return true;
+                               actor.held_down = false;
                }
-               case WR_INIT:
+               METHOD(Vaporizer, wr_init, void(entity thiswep))
                {
-                       precache_model("models/nexflash.md3");
-                       precache_model(W_Model("g_minstanex.md3"));
-                       precache_model(W_Model("v_minstanex.md3"));
-                       precache_model(W_Model("h_minstanex.iqm"));
-                       precache_sound(W_Sound("minstanexfire"));
-                       precache_sound(W_Sound("nexwhoosh1"));
-                       precache_sound(W_Sound("nexwhoosh2"));
-                       precache_sound(W_Sound("nexwhoosh3"));
                        //W_Blaster(WR_INIT); // Samual: Is this really the proper thing to do? Didn't we already run this previously?
                        VAPORIZER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_SETUP:
+               METHOD(Vaporizer, wr_setup, void(entity thiswep))
                {
                        self.ammo_field = WEP_AMMO(VAPORIZER);
                        self.vaporizer_lasthit = 0;
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Vaporizer, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(VAPORIZER) >= vaporizer_ammo;
+                       float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
+                       float ammo_amount = self.WEP_AMMO(VAPORIZER) >= vaporizer_ammo;
                        ammo_amount += self.(weapon_load[WEP_VAPORIZER.m_id]) >= vaporizer_ammo;
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(Vaporizer, wr_checkammo2, bool(entity thiswep))
                {
                        if(!WEP_CVAR_SEC(vaporizer, ammo))
                                return true;
-                       ammo_amount = self.WEP_AMMO(VAPORIZER) >= WEP_CVAR_SEC(vaporizer, ammo);
+                       float ammo_amount = self.WEP_AMMO(VAPORIZER) >= WEP_CVAR_SEC(vaporizer, ammo);
                        ammo_amount += self.(weapon_load[WEP_VAPORIZER.m_id]) >= WEP_CVAR_SEC(vaporizer, ammo);
                        return ammo_amount;
                }
-               case WR_CONFIG:
+               METHOD(Vaporizer, wr_config, void(entity thiswep))
                {
                        VAPORIZER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(Vaporizer, wr_resetplayer, void(entity thiswep))
                {
                        self.vaporizer_lasthit = 0;
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Vaporizer, wr_reload, void(entity thiswep))
                {
+                       float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
                        float used_ammo;
                        if(WEP_CVAR_SEC(vaporizer, ammo))
                                used_ammo = min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo));
                        else
                                used_ammo = vaporizer_ammo;
 
-                       W_Reload(used_ammo, W_Sound("reload"));
-                       return true;
+                       W_Reload(self, used_ammo, SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Vaporizer, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_THINKING_WITH_PORTALS;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Vaporizer, wr_killmessage, int(entity thiswep))
                {
                        return WEAPON_VAPORIZER_MURDER;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
-float W_Vaporizer(float req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Vaporizer, wr_impacteffect, void(entity thiswep))
                {
                        vector org2 = w_org + w_backoff * 6;
                        if(w_deathtype & HITTYPE_SECONDARY)
                        {
                                pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
-                               if(!w_issilent) { sound(self, CH_SHOTS, W_Sound("laserimpact"), VOL_BASE, ATTN_NORM); }
+                               if(!w_issilent) { sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
                        }
                        else
                        {
                                pointparticles(particleeffectnum(EFFECT_VORTEX_IMPACT), org2, '0 0 0', 1);
-                               if(!w_issilent) { sound(self, CH_SHOTS, W_Sound("neximpact"), VOL_BASE, ATTN_NORM); }
+                               if(!w_issilent) { sound(self, CH_SHOTS, SND_NEXIMPACT, VOL_BASE, ATTN_NORM); }
                        }
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Vaporizer, wr_init, void(entity thiswep))
                {
-                       precache_sound(W_Sound("laserimpact"));
-                       precache_sound(W_Sound("neximpact"));
                        if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
                        {
                                precache_pic("gfx/reticle_nex");
                        }
-                       return true;
                }
-               case WR_ZOOMRETICLE:
+               METHOD(Vaporizer, wr_zoomreticle, bool(entity thiswep))
                {
                        if(button_zoom || zoomscript_caught)
                        {
@@ -470,8 +410,6 @@ float W_Vaporizer(float req)
                                return false;
                        }
                }
-       }
-       return false;
-}
+
 #endif
 #endif
index 3aa17e526d566f02734a72dd2d9cb7cbb753a35a..c51028b620b82eafe98006f14786b3662715ba1a 100644 (file)
@@ -1,19 +1,21 @@
 #ifndef IMPLEMENTATION
-REGISTER_WEAPON(
-/* WEP_##id  */ VORTEX,
-/* function  */ W_Vortex,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 7,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '0.5 1 1',
-/* modelname */ "nex",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairnex 0.65",
-/* wepimg    */ "weaponnex",
-/* refname   */ "vortex",
-/* wepname   */ _("Vortex")
-);
+CLASS(Vortex, Weapon)
+/* 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');
+/* modelname */ ATTRIB(Vortex, mdl, string, "nex");
+#ifndef MENUQC
+/* model     */ ATTRIB(Vortex, m_model, Model, MDL_VORTEX_ITEM);
+#endif
+/* crosshair */ ATTRIB(Vortex, w_crosshair, string, "gfx/crosshairnex");
+/* crosshair */ ATTRIB(Vortex, w_crosshair_size, float, 0.65);
+/* wepimg    */ ATTRIB(Vortex, model2, string, "weaponnex");
+/* refname   */ ATTRIB(Vortex, netname, string, "vortex");
+/* wepname   */ ATTRIB(Vortex, message, string, _("Vortex"));
+ENDCLASS(Vortex)
+REGISTER_WEAPON(VORTEX, NEW(Vortex));
 
 #define VORTEX_SETTINGS(w_cvar,w_prop) VORTEX_SETTINGS_LIST(w_cvar, w_prop, VORTEX, vortex)
 #define VORTEX_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
@@ -59,8 +61,8 @@ VORTEX_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
 #endif
 #ifdef IMPLEMENTATION
 #ifdef SVQC
-void spawnfunc_weapon_vortex(void) { weapon_defaultspawnfunc(WEP_VORTEX.m_id); }
-void spawnfunc_weapon_nex(void) { spawnfunc_weapon_vortex(); }
+spawnfunc(weapon_vortex) { weapon_defaultspawnfunc(WEP_VORTEX.m_id); }
+spawnfunc(weapon_nex) { spawnfunc_weapon_vortex(this); }
 
 void SendCSQCVortexBeamParticle(float charge) {
        vector v;
@@ -76,8 +78,8 @@ void SendCSQCVortexBeamParticle(float charge) {
        WriteByte(MSG_BROADCAST, bound(0, 255 * charge, 255));
 }
 
-void W_Vortex_Attack(float issecondary)
-{
+void W_Vortex_Attack(Weapon thiswep, float issecondary)
+{SELFPARAM();
        float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
 
        mydmg = WEP_CVAR_BOTH(vortex, !issecondary, damage);
@@ -103,10 +105,10 @@ void W_Vortex_Attack(float issecondary)
        mydmg *= charge;
        myforce *= charge;
 
-       W_SetupShot(self, true, 5, W_Sound("nexfire"), CH_WEAPON_A, mydmg);
+       W_SetupShot(self, 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(self, CH_WEAPON_B, W_Sound("nexcharge"), VOL_BASE * (charge - 0.5 * WEP_CVAR(vortex, charge_animlimit)) / (1 - 0.5 * WEP_CVAR(vortex, charge_animlimit)), ATTN_NORM);
+               sound(self, 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);
        }
 
        yoda = 0;
@@ -126,19 +128,12 @@ void W_Vortex_Attack(float issecondary)
        //beam and muzzle flash done on client
        SendCSQCVortexBeamParticle(charge);
 
-       W_DecreaseAmmo(myammo);
+       W_DecreaseAmmo(thiswep, self, myammo);
 }
 
-void spawnfunc_weapon_vortex(void); // defined in t_items.qc
-
 .float vortex_chargepool_pauseregen_finished;
-bool W_Vortex(int req)
-{
-       float dt;
-       float ammo_amount;
-       switch(req)
-       {
-               case WR_AIM:
+
+               METHOD(Vortex, wr_aim, void(entity thiswep))
                {
                        if(bot_aim(1000000, 0, 1, false))
                                self.BUTTON_ATCK = true;
@@ -147,141 +142,128 @@ bool W_Vortex(int req)
                                if(WEP_CVAR(vortex, charge))
                                        self.BUTTON_ATCK2 = true;
                        }
-                       return true;
                }
-               case WR_THINK:
+               METHOD(Vortex, wr_think, void(entity thiswep, entity actor, bool fire1, bool fire2))
                {
-                       if(WEP_CVAR(vortex, charge) && self.vortex_charge < WEP_CVAR(vortex, charge_limit))
-                               self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME);
+                       if(WEP_CVAR(vortex, charge) && actor.vortex_charge < WEP_CVAR(vortex, charge_limit))
+                               actor.vortex_charge = min(1, actor.vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME);
 
                        if(WEP_CVAR_SEC(vortex, chargepool))
-                               if(self.vortex_chargepool_ammo < 1)
+                               if(actor.vortex_chargepool_ammo < 1)
                                {
-                                       if(self.vortex_chargepool_pauseregen_finished < time)
-                                               self.vortex_chargepool_ammo = min(1, self.vortex_chargepool_ammo + WEP_CVAR_SEC(vortex, chargepool_regen) * frametime / W_TICSPERFRAME);
-                                       self.pauseregen_finished = max(self.pauseregen_finished, time + WEP_CVAR_SEC(vortex, chargepool_pause_regen));
+                                       if(actor.vortex_chargepool_pauseregen_finished < time)
+                                               actor.vortex_chargepool_ammo = min(1, actor.vortex_chargepool_ammo + WEP_CVAR_SEC(vortex, chargepool_regen) * frametime / W_TICSPERFRAME);
+                                       actor.pauseregen_finished = max(actor.pauseregen_finished, time + WEP_CVAR_SEC(vortex, chargepool_pause_regen));
                                }
 
-                       if(autocvar_g_balance_vortex_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) // forced reload
-                               WEP_ACTION(self.weapon, WR_RELOAD);
-                       else
+                       if(autocvar_g_balance_vortex_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) { // forced reload
+                               Weapon w = get_weaponinfo(actor.weapon);
+                               w.wr_reload(w);
+                       } else
                        {
-                               if(self.BUTTON_ATCK)
+                               if(fire1)
                                {
-                                       if(weapon_prepareattack(0, WEP_CVAR_PRI(vortex, refire)))
+                                       if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_PRI(vortex, refire)))
                                        {
-                                               W_Vortex_Attack(0);
-                                               weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(vortex, animtime), w_ready);
+                                               W_Vortex_Attack(thiswep, 0);
+                                               weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_PRI(vortex, animtime), w_ready);
                                        }
                                }
-                               if((WEP_CVAR(vortex, charge) && !WEP_CVAR(vortex, secondary)) ? (self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) : self.BUTTON_ATCK2)
+                               if((WEP_CVAR(vortex, charge) && !WEP_CVAR(vortex, secondary)) ? (actor.BUTTON_ZOOM | actor.BUTTON_ZOOMSCRIPT) : fire2)
                                {
                                        if(WEP_CVAR(vortex, charge))
                                        {
-                                               self.vortex_charge_rottime = time + WEP_CVAR(vortex, charge_rot_pause);
-                                               dt = frametime / W_TICSPERFRAME;
+                                               actor.vortex_charge_rottime = time + WEP_CVAR(vortex, charge_rot_pause);
+                                               float dt = frametime / W_TICSPERFRAME;
 
-                                               if(self.vortex_charge < 1)
+                                               if(actor.vortex_charge < 1)
                                                {
                                                        if(WEP_CVAR_SEC(vortex, chargepool))
                                                        {
                                                                if(WEP_CVAR_SEC(vortex, ammo))
                                                                {
                                                                        // always deplete if secondary is held
-                                                                       self.vortex_chargepool_ammo = max(0, self.vortex_chargepool_ammo - WEP_CVAR_SEC(vortex, ammo) * dt);
+                                                                       actor.vortex_chargepool_ammo = max(0, actor.vortex_chargepool_ammo - WEP_CVAR_SEC(vortex, ammo) * dt);
 
-                                                                       dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate));
-                                                                       self.vortex_chargepool_pauseregen_finished = time + WEP_CVAR_SEC(vortex, chargepool_pause_regen);
-                                                                       dt = min(dt, self.vortex_chargepool_ammo);
+                                                                       dt = min(dt, (1 - actor.vortex_charge) / WEP_CVAR(vortex, charge_rate));
+                                                                       actor.vortex_chargepool_pauseregen_finished = time + WEP_CVAR_SEC(vortex, chargepool_pause_regen);
+                                                                       dt = min(dt, actor.vortex_chargepool_ammo);
                                                                        dt = max(0, dt);
 
-                                                                       self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
+                                                                       actor.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
                                                                }
                                                        }
 
                                                        else if(WEP_CVAR_SEC(vortex, ammo))
                                                        {
-                                                               if(self.BUTTON_ATCK2) // only eat ammo when the button is pressed
+                                                               if(fire2) // only eat ammo when the button is pressed
                                                                {
-                                                                       dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate));
-                                                                       if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+                                                                       dt = min(dt, (1 - actor.vortex_charge) / WEP_CVAR(vortex, charge_rate));
+                                                                       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                                                                        {
                                                                                // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
                                                                                if(autocvar_g_balance_vortex_reload_ammo)
                                                                                {
-                                                                                       dt = min(dt, (self.clip_load - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
+                                                                                       dt = min(dt, (actor.clip_load - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
                                                                                        dt = max(0, dt);
                                                                                        if(dt > 0)
                                                                                        {
-                                                                                               self.clip_load = max(WEP_CVAR_SEC(vortex, ammo), self.clip_load - WEP_CVAR_SEC(vortex, ammo) * dt);
+                                                                                               actor.clip_load = max(WEP_CVAR_SEC(vortex, ammo), actor.clip_load - WEP_CVAR_SEC(vortex, ammo) * dt);
                                                                                        }
-                                                                                       self.(weapon_load[WEP_VORTEX.m_id]) = self.clip_load;
+                                                                                       actor.(weapon_load[WEP_VORTEX.m_id]) = actor.clip_load;
                                                                                }
                                                                                else
                                                                                {
-                                                                                       dt = min(dt, (self.WEP_AMMO(VORTEX) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
+                                                                                       dt = min(dt, (actor.WEP_AMMO(VORTEX) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
                                                                                        dt = max(0, dt);
                                                                                        if(dt > 0)
                                                                                        {
-                                                                                               self.WEP_AMMO(VORTEX) = max(WEP_CVAR_SEC(vortex, ammo), self.WEP_AMMO(VORTEX) - WEP_CVAR_SEC(vortex, ammo) * dt);
+                                                                                               actor.WEP_AMMO(VORTEX) = max(WEP_CVAR_SEC(vortex, ammo), actor.WEP_AMMO(VORTEX) - WEP_CVAR_SEC(vortex, ammo) * dt);
                                                                                        }
                                                                                }
                                                                        }
-                                                                       self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
+                                                                       actor.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
                                                                }
                                                        }
 
                                                        else
                                                        {
-                                                               dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate));
-                                                               self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
+                                                               dt = min(dt, (1 - actor.vortex_charge) / WEP_CVAR(vortex, charge_rate));
+                                                               actor.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
                                                        }
                                                }
                                        }
                                        else if(WEP_CVAR(vortex, secondary))
                                        {
-                                               if(weapon_prepareattack(0, WEP_CVAR_SEC(vortex, refire)))
+                                               if(weapon_prepareattack(thiswep, actor, false, WEP_CVAR_SEC(vortex, refire)))
                                                {
-                                                       W_Vortex_Attack(1);
-                                                       weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(vortex, animtime), w_ready);
+                                                       W_Vortex_Attack(thiswep, 1);
+                                                       weapon_thinkf(actor, WFRAME_FIRE1, WEP_CVAR_SEC(vortex, animtime), w_ready);
                                                }
                                        }
                                }
                        }
-
-                       return true;
                }
-               case WR_INIT:
+               METHOD(Vortex, wr_init, void(entity thiswep))
                {
-                       precache_model("models/nexflash.md3");
-                       precache_model(W_Model("g_nex.md3"));
-                       precache_model(W_Model("v_nex.md3"));
-                       precache_model(W_Model("h_nex.iqm"));
-                       precache_sound(W_Sound("nexfire"));
-                       precache_sound(W_Sound("nexcharge"));
-                       precache_sound(W_Sound("nexwhoosh1"));
-                       precache_sound(W_Sound("nexwhoosh2"));
-                       precache_sound(W_Sound("nexwhoosh3"));
                        VORTEX_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
-                       return true;
                }
-               case WR_SETUP:
+               METHOD(Vortex, wr_setup, void(entity thiswep))
                {
                        self.vortex_lasthit = 0;
-                       return true;
                }
-               case WR_CHECKAMMO1:
+               METHOD(Vortex, wr_checkammo1, bool(entity thiswep))
                {
-                       ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_PRI(vortex, ammo);
+                       float ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_PRI(vortex, ammo);
                        ammo_amount += (autocvar_g_balance_vortex_reload_ammo && self.(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_PRI(vortex, ammo));
                        return ammo_amount;
                }
-               case WR_CHECKAMMO2:
+               METHOD(Vortex, wr_checkammo2, bool(entity thiswep))
                {
                        if(WEP_CVAR(vortex, secondary))
                        {
                                // don't allow charging if we don't have enough ammo
-                               ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_SEC(vortex, ammo);
+                               float ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_SEC(vortex, ammo);
                                ammo_amount += self.(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_SEC(vortex, ammo);
                                return ammo_amount;
                        }
@@ -290,59 +272,46 @@ bool W_Vortex(int req)
                                return false; // zoom is not a fire mode
                        }
                }
-               case WR_CONFIG:
+               METHOD(Vortex, wr_config, void(entity thiswep))
                {
                        VORTEX_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
-                       return true;
                }
-               case WR_RESETPLAYER:
+               METHOD(Vortex, wr_resetplayer, void(entity thiswep))
                {
                        self.vortex_lasthit = 0;
-                       return true;
                }
-               case WR_RELOAD:
+               METHOD(Vortex, wr_reload, void(entity thiswep))
                {
-                       W_Reload(min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), W_Sound("reload"));
-                       return true;
+                       W_Reload(self, min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), SND(RELOAD));
                }
-               case WR_SUICIDEMESSAGE:
+               METHOD(Vortex, wr_suicidemessage, int(entity thiswep))
                {
                        return WEAPON_THINKING_WITH_PORTALS;
                }
-               case WR_KILLMESSAGE:
+               METHOD(Vortex, wr_killmessage, int(entity thiswep))
                {
                        return WEAPON_VORTEX_MURDER;
                }
-       }
-       return false;
-}
+
 #endif
 #ifdef CSQC
 float autocvar_g_balance_vortex_secondary = 0; // WEAPONTODO
-bool W_Vortex(int req)
-{
-       switch(req)
-       {
-               case WR_IMPACTEFFECT:
+
+               METHOD(Vortex, wr_impacteffect, void(entity thiswep))
                {
-                       vector org2;
-                       org2 = w_org + w_backoff * 6;
+                       vector org2 = w_org + w_backoff * 6;
                        pointparticles(particleeffectnum(EFFECT_VORTEX_IMPACT), org2, '0 0 0', 1);
                        if(!w_issilent)
-                               sound(self, CH_SHOTS, W_Sound("neximpact"), VOL_BASE, ATTN_NORM);
-
-                       return true;
+                               sound(self, CH_SHOTS, SND_NEXIMPACT, VOL_BASE, ATTN_NORM);
                }
-               case WR_INIT:
+               METHOD(Vortex, wr_init, void(entity thiswep))
                {
-                       precache_sound(W_Sound("neximpact"));
                        if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
                        {
                                precache_pic("gfx/reticle_nex");
                        }
-                       return true;
                }
-               case WR_ZOOMRETICLE:
+               METHOD(Vortex, wr_zoomreticle, bool(entity thiswep))
                {
                        if(button_zoom || zoomscript_caught || (!WEP_CVAR(vortex, secondary) && button_attack2))
                        {
@@ -355,8 +324,6 @@ bool W_Vortex(int req)
                                return false;
                        }
                }
-       }
-       return false;
-}
+
 #endif
 #endif
index 95489ad4326de10d9874c5fd29118e1cdd3ba8cc..ab93b0172370f1998d6fde329b8a5b65fad7ea43 100644 (file)
@@ -42,7 +42,7 @@ float autocvar_cl_nolerp = 0;
 .float csqcmodel_lerpfrac2time;
 
 void CSQCModel_InterpolateAnimation_2To4_PreNote(int sf)
-{
+{SELFPARAM();
        if(sf & CSQCMODEL_PROPERTY_FRAME)
        {
                self.frame3 = self.frame;
@@ -61,7 +61,7 @@ void CSQCModel_InterpolateAnimation_2To4_PreNote(int sf)
        }
 }
 void CSQCModel_InterpolateAnimation_1To2_PreNote(int sf)
-{
+{SELFPARAM();
        if(sf & CSQCMODEL_PROPERTY_FRAME)
        {
                self.frame2 = self.frame;
@@ -78,7 +78,7 @@ void CSQCModel_InterpolateAnimation_PreNote(int sf)
 }
 
 void CSQCModel_InterpolateAnimation_2To4_Note(int sf, float set_times)
-{
+{SELFPARAM();
        if(sf & CSQCMODEL_PROPERTY_FRAME)
        {
                if(set_times)
@@ -97,7 +97,7 @@ void CSQCModel_InterpolateAnimation_2To4_Note(int sf, float set_times)
        }
 }
 void CSQCModel_InterpolateAnimation_1To2_Note(int sf, float set_times)
-{
+{SELFPARAM();
        if(sf & CSQCMODEL_PROPERTY_FRAME)
        {
                if(set_times)
@@ -114,7 +114,7 @@ void CSQCModel_InterpolateAnimation_Note(int sf)
 }
 
 void CSQCModel_InterpolateAnimation_2To4_Do()
-{
+{SELFPARAM();
        if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
        {
                self.lerpfrac = self.csqcmodel_lerpfrac;
@@ -161,7 +161,7 @@ void CSQCModel_InterpolateAnimation_2To4_Do()
        }
 }
 void CSQCModel_InterpolateAnimation_1To2_Do()
-{
+{SELFPARAM();
        if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
        {
                self.lerpfrac = 0;
@@ -184,7 +184,7 @@ void CSQCModel_InterpolateAnimation_Do()
 }
 
 void CSQCModel_Draw()
-{
+{SELFPARAM();
        // some nice flags for CSQCMODEL_IF and the hooks
        bool isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
        noref bool islocalplayer = (self.entnum == player_localnum + 1);
@@ -214,7 +214,7 @@ void CSQCModel_Draw()
 }
 
 void CSQCModel_Read(bool isnew)
-{
+{SELFPARAM();
        int sf = ReadInt24_t();
 
        // some nice flags for CSQCMODEL_IF and the hooks
index 3d5f9a00cbc0679eb0cdc0234a87a3c43189e6db..1a96e23dd6d6c0e1fbe77ff4744e541fa3b4ffbf 100644 (file)
@@ -100,7 +100,7 @@ void CSQCPlayer_SetPredictionError(vector o, vector v, float onground_diff)
 }
 
 void CSQCPlayer_Unpredict()
-{
+{SELFPARAM();
        if(csqcplayer_status == CSQCPLAYERSTATUS_UNPREDICTED)
                return;
        if(csqcplayer_status != CSQCPLAYERSTATUS_PREDICTED)
@@ -112,7 +112,7 @@ void CSQCPlayer_Unpredict()
 }
 
 void CSQCPlayer_SetMinsMaxs()
-{
+{SELFPARAM();
        if(self.flags & FL_DUCKED)
        {
                self.mins = PL_CROUCH_MIN;
@@ -128,7 +128,7 @@ void CSQCPlayer_SetMinsMaxs()
 }
 
 void CSQCPlayer_SavePrediction()
-{
+{SELFPARAM();
        player_pmflags = self.flags;
        csqcplayer_origin = self.origin;
        csqcplayer_velocity = self.velocity;
@@ -139,7 +139,7 @@ void CSQCPlayer_SavePrediction()
 void CSQC_ClientMovement_PlayerMove_Frame();
 
 void PM_Movement_Move()
-{
+{SELFPARAM();
        runstandardplayerphysics(self);
 #ifdef CSQC
        self.flags =
@@ -159,7 +159,7 @@ void CSQCPlayer_Physics(void)
 }
 
 void CSQCPlayer_PredictTo(float endframe, float apply_error)
-{
+{SELFPARAM();
        CSQCPlayer_Unpredict();
        if(apply_error)
        {
@@ -204,7 +204,7 @@ void CSQCPlayer_PredictTo(float endframe, float apply_error)
 }
 
 bool CSQCPlayer_IsLocalPlayer()
-{
+{SELFPARAM();
        return (self == csqcplayer);
 }
 
@@ -214,15 +214,13 @@ void CSQCPlayer_SetViewLocation()
 }
 
 void CSQCPlayer_SetCamera()
-{
+{SELFPARAM();
        vector v0;
        v0 = pmove_vel; // TRICK: pmove_vel is set by the engine when we get here. No need to network velocity
 
        if(csqcplayer)
        {
-               entity oldself;
-               oldself = self;
-               self = csqcplayer;
+               setself(csqcplayer);
 
                if(servercommandframe == 0 || clientcommandframe == 0)
                {
@@ -299,19 +297,15 @@ void CSQCPlayer_SetCamera()
                // relink
                setorigin(self, self.origin);
 
-               self = oldself;
+               setself(this);
        }
 
-       entity view;
-       view = CSQCModel_server2csqc(player_localentnum);
+       entity view = CSQCModel_server2csqc(player_localentnum);
 
        if(view && view != csqcplayer)
        {
-               entity oldself = self;
-               self = view;
-               InterpolateOrigin_Do();
-               self.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
-               self = oldself;
+               WITH(entity, self, view, InterpolateOrigin_Do());
+               view.view_ofs = '0 0 1' * getstati(STAT_VIEWHEIGHT);
        }
 
        if(view)
@@ -353,7 +347,7 @@ void CSQCPlayer_Remove()
 }
 
 float CSQCPlayer_PreUpdate()
-{
+{SELFPARAM();
        if(self != csqcplayer)
                return 0;
        if(csqcplayer_status != CSQCPLAYERSTATUS_FROMSERVER)
@@ -362,7 +356,7 @@ float CSQCPlayer_PreUpdate()
 }
 
 float CSQCPlayer_PostUpdate()
-{
+{SELFPARAM();
        if(self.entnum != player_localnum + 1)
                return 0;
        csqcplayer = self;
index 5c8e1e31e62ce7d3af314b5116ce4f02eea24cbf..78fb051f793765d0c9f5d884dead2ef9a5bb8bb1 100644 (file)
 .vector ivup1, ivup2;
 .float itime1, itime2;
 void InterpolateOrigin_Reset()
-{
+{SELFPARAM();
        self.iflags &= ~IFLAG_INTERNALMASK;
        self.itime1 = self.itime2 = 0;
 }
 void InterpolateOrigin_Note()
-{
+{SELFPARAM();
        float dt;
        int f0;
 
@@ -138,7 +138,7 @@ void InterpolateOrigin_Note()
        }
 }
 void InterpolateOrigin_Do()
-{
+{SELFPARAM();
        vector forward, up;
        if(self.itime1 && self.itime2 && self.itime1 != self.itime2)
        {
@@ -165,7 +165,7 @@ void InterpolateOrigin_Do()
        }
 }
 void InterpolateOrigin_Undo()
-{
+{SELFPARAM();
        if(self.iflags & IFLAG_ORIGIN)
                setorigin(self, self.iorigin2);
        if(self.iflags & IFLAG_ANGLES)
index 32c8b870755997168cc9c7a708bcf9ac15f75923..ebe0b6e8765558a76de059fb6eed63f385dfebb3 100644 (file)
@@ -37,7 +37,7 @@
 // generic CSQC model code
 
 bool CSQCModel_Send(entity to, int sf)
-{
+{SELFPARAM();
        // some nice flags for CSQCMODEL_IF
        float isplayer = (IS_CLIENT(self));
        float islocalplayer = (self == to);
@@ -70,10 +70,10 @@ bool CSQCModel_Send(entity to, int sf)
 #ifdef CSQCPLAYER_FORCE_UPDATES
 .float csqcmodel_nextforcedupdate;
 #endif
-void CSQCModel_CheckUpdate()
+void CSQCModel_CheckUpdate(entity e)
 {
        // some nice flags for CSQCMODEL_IF
-       float isplayer = (IS_CLIENT(self));
+       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
 
@@ -82,43 +82,43 @@ void CSQCModel_CheckUpdate()
        unused_float = isnolocalplayer;
 
 #ifdef CSQCPLAYER_FORCE_UPDATES
-       if(isplayer && time > self.csqcmodel_nextforcedupdate)
+       if(isplayer && time > e.csqcmodel_nextforcedupdate)
        {
-               self.SendFlags |= CSQCMODEL_PROPERTY_ORIGIN;
-               self.csqcmodel_nextforcedupdate = time + CSQCPLAYER_FORCE_UPDATES * (0.5 + random()); // ensure about 4 origin sends per sec
+               e.SendFlags |= CSQCMODEL_PROPERTY_ORIGIN;
+               e.csqcmodel_nextforcedupdate = time + CSQCPLAYER_FORCE_UPDATES * (0.5 + random()); // ensure about 4 origin sends per sec
        }
 #endif
 
-       if(self.effects & EF_RESTARTANIM_BIT)
+       if(e.effects & EF_RESTARTANIM_BIT)
        {
-               self.SendFlags |= CSQCMODEL_PROPERTY_FRAME | CSQCMODEL_PROPERTY_FRAME2; // full anim resend please
-               self.effects &= ~EF_RESTARTANIM_BIT;
+               e.SendFlags |= CSQCMODEL_PROPERTY_FRAME | CSQCMODEL_PROPERTY_FRAME2; // full anim resend please
+               e.effects &= ~EF_RESTARTANIM_BIT;
        }
 
-       if(self.effects & EF_TELEPORT_BIT)
+       if(e.effects & EF_TELEPORT_BIT)
        {
-               self.SendFlags |= CSQCMODEL_PROPERTY_TELEPORTED; // no interpolation please
-               self.effects &= ~EF_TELEPORT_BIT;
+               e.SendFlags |= CSQCMODEL_PROPERTY_TELEPORTED; // no interpolation please
+               e.effects &= ~EF_TELEPORT_BIT;
        }
 
 #define CSQCMODEL_IF(cond) if(cond) {
 #define CSQCMODEL_ENDIF }
 #define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
        { \
-               t tmp = self.f; \
-               if(tmp != self.csqcmodel_##f) \
+               t tmp = e.f; \
+               if(tmp != e.csqcmodel_##f) \
                { \
-                       self.csqcmodel_##f = tmp; \
-                       self.SendFlags |= flag; \
+                       e.csqcmodel_##f = tmp; \
+                       e.SendFlags |= flag; \
                } \
        }
 #define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
        { \
-               t tmp = rint(bound(mi, s * self.f, ma) - mi); \
-               if(tmp != self.csqcmodel_##f) \
+               t tmp = rint(bound(mi, s * e.f, ma) - mi); \
+               if(tmp != e.csqcmodel_##f) \
                { \
-                       self.csqcmodel_##f = tmp; \
-                       self.SendFlags |= flag; \
+                       e.csqcmodel_##f = tmp; \
+                       e.SendFlags |= flag; \
                } \
        }
        ALLPROPERTIES
@@ -128,14 +128,14 @@ void CSQCModel_CheckUpdate()
 #undef CSQCMODEL_IF
 }
 
-void CSQCModel_LinkEntity()
+void CSQCModel_LinkEntity(entity e)
 {
-       self.SendEntity = CSQCModel_Send;
-       self.SendFlags = 0xFFFFFF;
-       CSQCModel_CheckUpdate();
+       e.SendEntity = CSQCModel_Send;
+       e.SendFlags = 0xFFFFFF;
+       CSQCModel_CheckUpdate(e);
 }
 
-void CSQCModel_UnlinkEntity()
+void CSQCModel_UnlinkEntity(entity e)
 {
-       self.SendEntity = func_null;
+       e.SendEntity = func_null;
 }
index 73e03e86207e4bdeaf2321a6ef1d31273b64170a..713e8c224c66a083a5f527f141eda2c1125851bb 100644 (file)
@@ -26,9 +26,9 @@
 
 // generic CSQC model code
 
-void CSQCModel_CheckUpdate();
-void CSQCModel_LinkEntity();
-void CSQCModel_UnlinkEntity();
+void CSQCModel_CheckUpdate(entity e);
+void CSQCModel_LinkEntity(entity e);
+void CSQCModel_UnlinkEntity(entity e);
 
 #define CSQCMODEL_IF(cond)
 #define CSQCMODEL_ENDIF
index f48df8e5ccd3c1218334bd1bc825708f8382161c..6ad27242aaf3f6a22161d17db4f4e3bd44d3575a 100644 (file)
@@ -9,8 +9,8 @@
 #define FALSE _FALSE
 
 #define spawn _spawn
-
 #define particleeffectnum _particleeffectnum
+#define setmodel _setmodel
 
 #include "upstream/csprogsdefs.qc"
 
@@ -20,8 +20,8 @@
 #undef FALSE
 
 #undef spawn
-
 #undef particleeffectnum
+#undef setmodel
 
 #pragma noref 0
 
index 3592c7015b53dc37726e7f6e86a35a3c6cb123be..5a93a2444c472d555b643fa18a601b4b0b8e76b4 100644 (file)
@@ -9,6 +9,7 @@
 #define FALSE _FALSE
 
 #define spawn _spawn
+#define setmodel _setmodel
 
 #include "upstream/progsdefs.qc"
 
@@ -18,6 +19,7 @@
 #undef FALSE
 
 #undef spawn
+#undef setmodel
 
 #pragma noref 0
 
diff --git a/qcsrc/lib/Accumulate.qh b/qcsrc/lib/Accumulate.qh
deleted file mode 100644 (file)
index 423f364..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef ACCUMULATE_H
-#define ACCUMULATE_H
-
-#ifdef QCC_SUPPORT_ACCUMULATE
-# define ACCUMULATE_FUNCTION(func, otherfunc) \
-    [[accumulate]] void func() { otherfunc(); }
-# define CALL_ACCUMULATED_FUNCTION(func) \
-    func()
-#else
-#ifdef HAVE_YO_DAWG_CPP
-// TODO make ascii art pic of xzibit
-// YO DAWG!
-// I HERD YO LIEK MACROS
-// SO I PUT A MACRO DEFINITION IN YO MACRO DEFINITION
-// SO YO CAN EXPAND MACROS WHILE YO EXPAND MACROS
-# define ACCUMULATE_FUNCTION(func,otherfunc) \
-    #ifdef func \
-    void __merge__##otherfunc() { func(); otherfunc(); } \
-    #undef func \
-    #define func __merge__##otherfunc \
-    #else \
-    #define func otherfunc \
-    #endif
-# define CALL_ACCUMULATED_FUNCTION(func) \
-    func()
-#else
-# define ACCUMULATE_FUNCTION(func,otherfunc) \
-    .float _ACCUMULATE_##func##__##otherfunc
-void ACCUMULATE_call(string func)
-{
-    float i;
-    float n = numentityfields();
-    string funcprefix = strcat("_ACCUMULATE_", func, "__");
-    float funcprefixlen = strlen(funcprefix);
-    for(i = 0; i < n; ++i)
-    {
-        string name = entityfieldname(i);
-        if(substring(name, 0, funcprefixlen) == funcprefix)
-            callfunction(substring(name, funcprefixlen, -1));
-    }
-}
-# define CALL_ACCUMULATED_FUNCTION(func) \
-    ACCUMULATE_call(#func)
-#endif
-#endif
-
-// used for simplifying ACCUMULATE_FUNCTIONs
-#define SET_FIRST_OR_LAST(input,first,count) if(!input) { input = (first + count); }
-#define SET_FIELD_COUNT(field,first,count) if(!field) { field = (first + count); ++count; }
-#define CHECK_MAX_COUNT(name,max,count,type) if(count > max) { error(strcat("Maximum ", type, " hit: ", #name, ": ", ftos(count), ".\n")); }
-
-#endif
diff --git a/qcsrc/lib/Bool.qh b/qcsrc/lib/Bool.qh
deleted file mode 100644 (file)
index 26169cd..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef BOOL_H
-#define BOOL_H
-
-#ifndef QCC_SUPPORT_BOOL
-    #define bool float
-
-    // Boolean Constants
-    const int true     = 1;
-    const int false = 0;
-#endif
-
-// Transitional aliases
-[[deprecated("use true")]] [[alias("true")]] const bool TRUE;
-[[deprecated("use false")]] [[alias("false")]] const bool FALSE;
-
-// get true/false value of a string with multiple different inputs
-float InterpretBoolean(string input)
-{
-    switch (strtolower(input))
-    {
-        case "yes":
-        case "true":
-        case "on":
-            return true;
-
-        case "no":
-        case "false":
-        case "off":
-            return false;
-
-        default: return stof(input);
-    }
-}
-
-float boolean(float value) { // if value is 0 return false (0), otherwise return true (1)
-    return (value == 0) ? false : true;
-}
-
-#endif
diff --git a/qcsrc/lib/Counting.qh b/qcsrc/lib/Counting.qh
deleted file mode 100644 (file)
index cd0604b..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-#ifndef COUNTING_H
-#define COUNTING_H
-
-#include "I18N.qh"
-
-// ===============================================
-//  Time processing and counting functions/macros
-// ===============================================
-
-#define count_years_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
-#define count_years(time) count_fill(time, \
-               ZCTX(_("CI_ZER^%d years")), /* zeroth */ \
-               ZCTX(_("CI_FIR^%d year")),  /* first */ \
-               ZCTX(_("CI_SEC^%d years")), /* year */ \
-               ZCTX(_("CI_THI^%d years")), /* third */ \
-               ZCTX(_("CI_MUL^%d years"))) /* multi */
-
-#define count_weeks_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
-#define count_weeks(time) count_fill(time, \
-               ZCTX(_("CI_ZER^%d weeks")), /* zeroth */ \
-               ZCTX(_("CI_FIR^%d week")),  /* first */ \
-               ZCTX(_("CI_SEC^%d weeks")), /* week */ \
-               ZCTX(_("CI_THI^%d weeks")), /* third */ \
-               ZCTX(_("CI_MUL^%d weeks"))) /* multi */
-
-#define count_days_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
-#define count_days(time) count_fill(time, \
-               ZCTX(_("CI_ZER^%d days")), /* zeroth */ \
-               ZCTX(_("CI_FIR^%d day")),  /* first */ \
-               ZCTX(_("CI_SEC^%d days")), /* day */ \
-               ZCTX(_("CI_THI^%d days")), /* third */ \
-               ZCTX(_("CI_MUL^%d days"))) /* multi */
-
-#define count_hours_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
-#define count_hours(time) count_fill(time, \
-               ZCTX(_("CI_ZER^%d hours")), /* zeroth */ \
-               ZCTX(_("CI_FIR^%d hour")),  /* first */ \
-               ZCTX(_("CI_SEC^%d hours")), /* hour */ \
-               ZCTX(_("CI_THI^%d hours")), /* third */ \
-               ZCTX(_("CI_MUL^%d hours"))) /* multi */
-
-
-#define count_minutes_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
-#define count_minutes(time) count_fill(time, \
-               ZCTX(_("CI_ZER^%d minutes")), /* zeroth */ \
-               ZCTX(_("CI_FIR^%d minute")),  /* first */ \
-               ZCTX(_("CI_SEC^%d minutes")), /* minute */ \
-               ZCTX(_("CI_THI^%d minutes")), /* third */ \
-               ZCTX(_("CI_MUL^%d minutes"))) /* multi */
-
-#define count_seconds_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
-#define count_seconds(time) count_fill(time, \
-               ZCTX(_("CI_ZER^%d seconds")), /* zeroth */ \
-               ZCTX(_("CI_FIR^%d second")),  /* first */ \
-               ZCTX(_("CI_SEC^%d seconds")), /* second */ \
-               ZCTX(_("CI_THI^%d seconds")), /* third */ \
-               ZCTX(_("CI_MUL^%d seconds"))) /* multi */
-
-string count_ordinal(int interval)
-{
-       // This function is designed primarily for the English language, it's impossible
-       // to accomodate all languages unless we do a specific function for each one...
-       // and since that's not technically feasible/practical, this is all we've got folks.
-
-       // Basically, it just allows you to represent a number or count in different ways
-       // depending on the number... like, with count_ordinal you can provide integers
-       // and retrieve 1st, 2nd, 3rd, nth ordinal numbers in a clean and simple way.
-       if(floor((interval % 100)/10) * 10 != 10) // examples: 12th, 111th, 213th will not execute this block
-       {
-               // otherwise, check normally for 1st,2nd,3rd insertions
-               switch(interval % 10)
-               {
-                       case 1: return sprintf(_("%dst"), interval);
-                       case 2: return sprintf(_("%dnd"), interval);
-                       case 3: return sprintf(_("%drd"), interval);
-                       default: return sprintf(_("%dth"), interval);
-               }
-       }
-       else { return sprintf(_("%dth"), interval); }
-
-       return "";
-}
-
-string count_fill(float interval, string zeroth, string first, string second, string third, string multi)
-{
-       // This function is designed primarily for the English language, it's impossible
-       // to accomodate all languages unless we do a specific function for each one...
-       // and since that's not technically feasible/practical, this is all we've got folks.
-
-       // Here you can insert specific strings based on the interval number, so you could do
-       // i.e. count_seconds which outputs like this:
-       //   0 seconds
-       //   1 second
-       //   2 seconds
-       //   3 seconds
-       //   etc... minutes, hours, days, etc.
-
-       switch(floor(interval))
-       {
-               case 0: return sprintf(zeroth, interval);
-               case 1:
-               {
-                       if(interval == 1) // EXACTLY value of 1
-                               return sprintf(first, interval);
-                       else
-                               return sprintf(multi, interval);
-               }
-               case 2: return sprintf(second, interval);
-               case 3: return sprintf(third, interval);
-               default: return sprintf(multi, interval);
-       }
-       return "";
-}
-
-string process_time(float outputtype, float seconds)
-{
-       float tmp_hours = 0, tmp_minutes = 0, tmp_seconds = 0;
-       float tmp_years = 0, tmp_weeks = 0, tmp_days = 0;
-
-       tmp_seconds = floor(seconds);
-
-       if(tmp_seconds)
-       {
-               tmp_minutes = floor(tmp_seconds / 60);
-
-               if(tmp_minutes)
-               {
-                       tmp_seconds -= (tmp_minutes * 60);
-                       tmp_hours = floor(tmp_minutes / 60);
-
-                       if(tmp_hours)
-                       {
-                               tmp_minutes -= (tmp_hours * 60);
-                               tmp_days = floor(tmp_hours / 24);
-
-                               if(tmp_days)
-                               {
-                                       tmp_hours -= (tmp_days * 24);
-                                       tmp_weeks = floor(tmp_days / 7);
-
-                                       if(tmp_weeks)
-                                       {
-                                               tmp_days -= (tmp_weeks * 7);
-                                               tmp_years = floor(tmp_weeks / 52);
-                                       }
-                               }
-                       }
-               }
-       }
-
-       switch(outputtype)
-       {
-               case 1: return sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds);
-               case 2:
-               {
-                       string output = "";
-
-                       output = count_seconds(tmp_seconds);
-
-                       if(tmp_minutes)
-                       {
-                               output = sprintf(
-                                       "%s%s",
-                                       count_minutes(tmp_minutes),
-                                       ((output != "") ? sprintf(", %s", output) : ""));
-                       }
-
-                       if(tmp_hours)
-                       {
-                               output = sprintf(
-                                       "%s%s",
-                                       count_hours(tmp_hours),
-                                       ((output != "") ? sprintf(", %s", output) : ""));
-                       }
-
-                       if(tmp_days)
-                       {
-                               output = sprintf(
-                                       "%s%s",
-                                       count_days(tmp_days),
-                                       ((output != "") ? sprintf(", %s", output) : ""));
-                       }
-
-                       if(tmp_weeks)
-                       {
-                               output = sprintf(
-                                       "%s%s",
-                                       count_weeks(tmp_weeks),
-                                       ((output != "") ? sprintf(", %s", output) : ""));
-                       }
-
-                       if(tmp_years)
-                       {
-                               output = sprintf(
-                                       "%s%s",
-                                       count_years(tmp_years),
-                                       ((output != "") ? sprintf(", %s", output) : ""));
-                       }
-
-                       return output;
-               }
-               case 3:
-               {
-                       string output = "";
-
-                       output = count_hours(tmp_hours);
-
-                       if(tmp_weeks) { tmp_days += (tmp_weeks * 7); }
-                       if(tmp_years) { tmp_days += (tmp_years * 365); }
-                       if(tmp_days)
-                       {
-                               output = sprintf(
-                                       "%s%s",
-                                       count_days(tmp_days),
-                                       ((output != "") ? sprintf(", %s", output) : ""));
-                       }
-
-                       return output;
-               }
-       }
-       return "";
-}
-#endif
diff --git a/qcsrc/lib/Cvar.qh b/qcsrc/lib/Cvar.qh
deleted file mode 100644 (file)
index 02016a2..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef CVAR_H
-#define CVAR_H
-
-#include "Static.qh"
-
-void RegisterCvars(void(string name, string desc, bool archive, string file) f) { }
-
-void RegisterCvars_Set(string name, string desc, bool archive, string file)
-{
-    localcmd(sprintf("\n%1$s %2$s \"$%2$s\" \"%3$s\"\n", (archive ? "seta" : "set"), name, desc));
-}
-
-STATIC_INIT_LATE(Cvars) { RegisterCvars(RegisterCvars_Set); }
-
-#define AUTOCVAR_5(file, archive, var, type, desc) \
-    [[accumulate]] void RegisterCvars(void(string, string, bool, string) f) { f(#var, desc, archive, file); } \
-    type autocvar_##var
-#define AUTOCVAR_6(file, archive, var, type, default, desc) \
-    AUTOCVAR_5(file, archive, var, type, desc) = default
-#define _AUTOCVAR(...) OVERLOAD(AUTOCVAR, __FILE__, __VA_ARGS__)
-#define AUTOCVAR_SAVE(...) _AUTOCVAR(true, __VA_ARGS__)
-#define AUTOCVAR(...) _AUTOCVAR(false, __VA_ARGS__)
-
-#endif
diff --git a/qcsrc/lib/Defer.qh b/qcsrc/lib/Defer.qh
deleted file mode 100644 (file)
index fd2619d..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef MENUQC
-#ifndef DEFER_H
-#define DEFER_H
-#include "OO.qh"
-
-entityclass(Defer);
-class(Defer) .entity owner;
-class(Defer) .void() think;
-class(Defer) .float nextthink;
-
-/*
-==================
-SUB_Remove
-
-Remove self
-==================
-*/
-void SUB_Remove()
-{
-       remove (self);
-}
-
-void defer_think()
-{
-    entity oself;
-
-    oself           = self;
-    self            = self.owner;
-    oself.think     = SUB_Remove;
-    oself.nextthink = time;
-
-    oself.use();
-}
-
-/*
-    Execute func() after time + fdelay.
-    self when func is executed = self when defer is called
-*/
-void defer(float fdelay, void() func)
-{
-    entity e;
-
-    e           = spawn();
-    e.owner     = self;
-    e.use       = func;
-    e.think     = defer_think;
-    e.nextthink = time + fdelay;
-}
-
-#endif
-#endif
diff --git a/qcsrc/lib/Draw.qh b/qcsrc/lib/Draw.qh
deleted file mode 100644 (file)
index 4ca5369..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifdef CSQC
-#ifndef DRAW_H
-#define DRAW_H
-
-#include "I18N.qh"
-#include "Vector.qh"
-
-#include "../client/defs.qh"
-
-void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
-{
-       // I want to draw a quad...
-       // from and to are MIDPOINTS.
-
-       vector axis, thickdir, A, B, C, D;
-       float length_tex;
-
-       axis = normalize(to - from);
-       length_tex = aspect * vlen(to - from) / thickness;
-
-       // direction is perpendicular to the view normal, and perpendicular to the axis
-       thickdir = normalize(cross(axis, vieworg - from));
-
-       A = from - thickdir * (thickness / 2);
-       B = from + thickdir * (thickness / 2);
-       C = to + thickdir * (thickness / 2);
-       D = to - thickdir * (thickness / 2);
-
-       R_BeginPolygon(texture, drawflag);
-       R_PolygonVertex(A, '0 0 0' + shift * '1 0 0', rgb, theAlpha);
-       R_PolygonVertex(B, '0 1 0' + shift * '1 0 0', rgb, theAlpha);
-       R_PolygonVertex(C, '0 1 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha);
-       R_PolygonVertex(D, '0 0 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha);
-       R_EndPolygon();
-}
-
-// a border picture is a texture containing nine parts:
-//   1/4 width: left part
-//   1/2 width: middle part (stretched)
-//   1/4 width: right part
-// divided into
-//   1/4 height: top part
-//   1/2 height: middle part (stretched)
-//   1/4 height: bottom part
-void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
-{
-    if (theBorderSize.x < 0 && theBorderSize.y < 0) // draw whole image as it is
-    {
-               drawpic(theOrigin, pic, theSize, theColor, theAlpha, 0);
-               return;
-    }
-       if (theBorderSize.x == 0 && theBorderSize.y == 0) // no border
-       {
-               // draw only the central part
-               drawsubpic(theOrigin, theSize, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
-               return;
-       }
-
-       vector dX, dY;
-       vector width, height;
-       vector bW, bH;
-       //pic = draw_UseSkinFor(pic);
-       width = eX * theSize.x;
-       height = eY * theSize.y;
-       if(theSize.x <= theBorderSize.x * 2)
-       {
-               // not wide enough... draw just left and right then
-               bW = eX * (0.25 * theSize.x / (theBorderSize.x * 2));
-               if(theSize.y <= theBorderSize.y * 2)
-               {
-                       // not high enough... draw just corners
-                       bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
-                       drawsubpic(theOrigin,                 width * 0.5 + height * 0.5, pic, '0 0 0',           bW + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width   * 0.5, width * 0.5 + height * 0.5, pic, eX - bW,           bW + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + height  * 0.5, width * 0.5 + height * 0.5, pic, eY - bH,           bW + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
-               }
-               else
-               {
-                       dY = theBorderSize.x * eY;
-                       drawsubpic(theOrigin,                             width * 0.5          +     dY, pic, '0 0    0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width * 0.5,               width * 0.5          +     dY, pic, '0 0    0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin                        + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0',           '0 0.5  0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width * 0.5          + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0' + eX - bW, '0 0.5  0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin               + height - dY, width * 0.5          +     dY, pic, '0 0.75 0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width * 0.5 + height - dY, width * 0.5          +     dY, pic, '0 0.75 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
-               }
-       }
-       else
-       {
-               if(theSize.y <= theBorderSize.y * 2)
-               {
-                       // not high enough... draw just top and bottom then
-                       bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
-                       dX = theBorderSize.x * eX;
-                       drawsubpic(theOrigin,                                         dX + height * 0.5, pic, '0    0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + dX,                        width - 2 * dX + height * 0.5, pic, '0.25 0 0',           '0.5  0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width - dX,                            dX + height * 0.5, pic, '0.75 0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin              + height * 0.5,             dX + height * 0.5, pic, '0    0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + dX         + height * 0.5, width - 2 * dX + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5  0 0' + bH, theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + width - dX + height * 0.5,             dX + height * 0.5, pic, '0.75 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
-               }
-               else
-               {
-                       dX = theBorderSize.x * eX;
-                       dY = theBorderSize.x * eY;
-                       drawsubpic(theOrigin,                                        dX          +     dY, pic, '0    0    0', '0.25 0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin                  + dX,      width - 2 * dX          +     dY, pic, '0.25 0    0', '0.5  0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin          + width - dX,                  dX          +     dY, pic, '0.75 0    0', '0.25 0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin          + dY,                          dX + height - 2 * dY, pic, '0    0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin          + dY         + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin          + dY + width - dX,             dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + height - dY,                          dX          +     dY, pic, '0    0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + height - dY         + dX, width - 2 * dX          +     dY, pic, '0.25 0.75 0', '0.5  0.25 0', theColor, theAlpha, 0);
-                       drawsubpic(theOrigin + height - dY + width - dX,             dX          +     dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
-               }
-       }
-}
-
-void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
-{
-       position.x -= 2 / 3 * strlen(text) * theScale.x;
-       drawstring(position, text, theScale, rgb, theAlpha, flag);
-}
-
-void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
-{
-       position.x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * theScale.x);
-       drawstring(position, text, theScale, rgb, theAlpha, flag);
-}
-
-#endif
-#endif
diff --git a/qcsrc/lib/I18N.qh b/qcsrc/lib/I18N.qh
deleted file mode 100644 (file)
index ab9aa7d..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef I18N_H
-#define I18N_H
-
-// translation helpers
-string prvm_language;
-
-string language_filename(string s)
-{
-    string fn = prvm_language;
-    if (fn == "" || fn == "dump")
-        return s;
-    fn = strcat(s, ".", fn);
-    int fh = fopen(fn, FILE_READ);
-    if (fh >= 0)
-    {
-        fclose(fh);
-        return fn;
-    }
-    return s;
-}
-
-string CTX(string s)
-{
-    int p = strstrofs(s, "^", 0);
-    if (p < 0)
-        return s;
-    return substring(s, p + 1, -1);
-}
-
-#define ZCTX(s) strzone(CTX(s))
-
-#endif
diff --git a/qcsrc/lib/Lazy.qh b/qcsrc/lib/Lazy.qh
deleted file mode 100644 (file)
index fcf0651..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef LAZY_H
-#define LAZY_H
-
-#include "OO.qh"
-
-CLASS(Lazy, Object)
-    ATTRIB(Lazy, m_get, entity(), func_null);
-    CONSTRUCTOR(Lazy, entity() _compute) { this.m_get = _compute; }
-ENDCLASS(Lazy)
-
-#define LAZY(id) __lazy_##id
-#define LAZY_NEW(id, compute) entity LAZY(id)() { \
-    static bool done; \
-    static entity it; \
-    if (!done) { it = compute; done = true; } \
-    return it; \
-}
-#endif
diff --git a/qcsrc/lib/Log.qh b/qcsrc/lib/Log.qh
deleted file mode 100644 (file)
index cd99ebf..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-#ifndef LOG_H
-#define LOG_H
-
-#define _printferr(...)     error(sprintf(__VA_ARGS__))
-#define _printfbt(...)      backtrace(sprintf(__VA_ARGS__))
-#define printf(...)         print(sprintf(__VA_ARGS__))
-#define dprintf(...)        dprint(sprintf(__VA_ARGS__))
-#define _dprintf2(...)      do { if (autocvar_developer > 1) dprintf(__VA_ARGS__); } while (0)
-
-#define _LOG(f, level, s)   f("[::"level"] ["__FILE__":%s:%.0f] %s", __FUNC__, __LINE__, s)
-
-#define  LOG_FATAL(...)     _LOG_FATAL(strcat("", __VA_ARGS__))
-#define  LOG_FATALF(...)    _LOG_FATAL(sprintf(__VA_ARGS__))
-#define _LOG_FATAL(s)       _LOG(_printferr, "FATAL", s)
-
-#define  LOG_SEVERE(...)    _LOG_SEVERE(strcat("", __VA_ARGS__))
-#define  LOG_SEVEREF(...)   _LOG_SEVERE(sprintf(__VA_ARGS__))
-#define _LOG_SEVERE(s)      _LOG(_printfbt, "SEVERE", s)
-
-#define  LOG_WARNING(...)   _LOG_WARNING(strcat("", __VA_ARGS__))
-#define  LOG_WARNINGF(...)  _LOG_WARNING(sprintf(__VA_ARGS__))
-#define _LOG_WARNING(s)     _LOG(printf, "WARNING", s)
-
-#define  LOG_INFO(...)      do { if (autocvar_developer) _LOG_INFO(strcat("", __VA_ARGS__)); else print (__VA_ARGS__); } while (0)
-#define  LOG_INFOF(...)     do { if (autocvar_developer) _LOG_INFO(sprintf(__VA_ARGS__));    else printf(__VA_ARGS__); } while (0)
-#define _LOG_INFO(s)        _LOG(printf, "INFO", s)
-
-#define  LOG_TRACE(...)     _LOG_TRACE(strcat("", __VA_ARGS__))
-#define  LOG_TRACEF(...)    _LOG_TRACE(sprintf(__VA_ARGS__))
-#define _LOG_TRACE(s)       _LOG(dprintf, "TRACE", s)
-
-#define  LOG_DEBUG(...)     _LOG_DEBUG(strcat("", __VA_ARGS__))
-#define  LOG_DEBUGF(...)    _LOG_DEBUG(sprintf(__VA_ARGS__))
-#define _LOG_DEBUG(s)       _LOG(_dprintf2, "DEBUG", s)
-
-// TODO: this sucks, lets find a better way to do backtraces?
-#ifdef SVQC
-void builtin_remove(entity);
-#define _backtrace() builtin_remove(NULL)
-#else
-void remove(entity);
-#define _backtrace() remove(NULL)
-#endif
-
-noref int autocvar_developer;
-noref bool autocvar_prvm_backtraceforwarnings;
-
-#define backtrace(msg) do { \
-    int dev = autocvar_developer; \
-    bool war = autocvar_prvm_backtraceforwarnings; \
-    cvar_set("developer", "1"); \
-    cvar_set("prvm_backtraceforwarnings", "1"); \
-    print("\n--- CUT HERE ---\n", msg, "\n"); \
-    _backtrace(); \
-    print("\n--- CUT UNTIL HERE ---\n"); \
-    cvar_set("developer", ftos(dev)); \
-    cvar_set("prvm_backtraceforwarnings", ftos(war)); \
-} while (0)
-
-#endif
diff --git a/qcsrc/lib/Math.qh b/qcsrc/lib/Math.qh
deleted file mode 100644 (file)
index a8a5290..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-#ifndef MATH_H
-#define MATH_H
-
-void mean_accumulate(entity e, .float a, .float c, float mean, float value, float weight)
-{
-       if (weight == 0)
-               return;
-       if (mean == 0)
-               e.(a) *= pow(value, weight);
-       else
-               e.(a) += pow(value, mean) * weight;
-       e.(c) += weight;
-}
-
-float mean_evaluate(entity e, .float a, .float c, float mean)
-{
-       if (e.(c) == 0)
-               return 0;
-       if (mean == 0)
-               return pow(e.(a), 1.0 / e.(c));
-       else
-               return pow(e.(a) / e.(c), 1.0 / mean);
-}
-
-#define MEAN_ACCUMULATE(prefix,v,w) mean_accumulate(self,prefix##_accumulator,prefix##_count,prefix##_mean,v,w)
-#define MEAN_EVALUATE(prefix) mean_evaluate(self,prefix##_accumulator,prefix##_count,prefix##_mean)
-#define MEAN_DECLARE(prefix,m) float prefix##_mean = m; .float prefix##_count, prefix##_accumulator
-
-/*
-==================
-crandom
-
-Returns a random number between -1.0 and 1.0
-==================
-*/
-float crandom (void)
-{
-       return 2 * (random () - 0.5);
-}
-
-
-/*
-==================
-Angc used for animations
-==================
-*/
-
-
-float angc (float a1, float a2)
-{
-       float   a;
-
-       while (a1 > 180)
-               a1 = a1 - 360;
-       while (a1 < -179)
-               a1 = a1 + 360;
-
-       while (a2 > 180)
-               a2 = a2 - 360;
-       while (a2 < -179)
-               a2 = a2 + 360;
-
-       a = a1 - a2;
-       while (a > 180)
-               a = a - 360;
-       while (a < -179)
-               a = a + 360;
-
-       return a;
-}
-
-float fsnap(float val,float fsize)
-{
-    return rint(val / fsize) * fsize;
-}
-
-vector vsnap(vector point,float fsize)
-{
-    vector vret;
-
-    vret.x = rint(point.x / fsize) * fsize;
-    vret.y = rint(point.y / fsize) * fsize;
-    vret.z = ceil(point.z / fsize) * fsize;
-
-    return vret;
-}
-
-vector lerpv(float t0, vector v0, float t1, vector v1, float t)
-{
-       return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
-}
-
-#endif
diff --git a/qcsrc/lib/Nil.qh b/qcsrc/lib/Nil.qh
deleted file mode 100644 (file)
index 87e3aea..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef NIL_H
-#define NIL_H
-
-#ifdef QCC_SUPPORT_NIL
-#define func_null nil
-#define string_null nil
-#else
-// the NULL function
-var void func_null(void);
-string string_null;
-#endif
-
-#endif
diff --git a/qcsrc/lib/OO.qh b/qcsrc/lib/OO.qh
deleted file mode 100644 (file)
index 63a70f7..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef OO_H
-#define OO_H
-
-#include "Nil.qh"
-#include "Registry.qh"
-
-#ifdef MENUQC
-    #define NULL (null_entity)
-#else
-    #define NULL (world)
-#endif
-
-.string classname;
-/** Location entity was spawned from in source */
-.string sourceLocFile;
-.int sourceLocLine;
-entity _spawn();
-entity __spawn(string _classname, string _sourceFile, int _sourceLine) {
-    entity this = _spawn();
-    this.classname = _classname;
-    this.sourceLocFile = _sourceFile;
-    this.sourceLocLine = _sourceLine;
-    return this;
-}
-
-
-
-#define entityclass(...) OVERLOAD(entityclass, __VA_ARGS__)
-#define entityclass_1(name) entityclass_2(name, Object)
-#ifndef QCC_SUPPORT_ENTITYCLASS
-    #define entityclass_2(name, base) typedef entity name
-    #define class(name)
-    #define new(class) __spawn(#class, __FILE__, __LINE__)
-#else
-    #define entityclass_2(name, base) entityclass name : base {}
-    #define class(name) [[class(name)]]
-    #define new(class) ((class) __spawn(#class, __FILE__, __LINE__))
-#endif
-
-// Classes have a `spawn##cname(entity)` constructor
-// The parameter is used across [[accumulate]] functions
-
-// Macro to hide this implementation detail
-#define NEW(cname, ...) \
-    OVERLOAD(spawn##cname, new(cname), ##__VA_ARGS__)
-
-#define CONSTRUCT(cname, ...) \
-    OVERLOAD(spawn##cname, this, ##__VA_ARGS__)
-
-#define CONSTRUCTOR(cname, ...) \
-    cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) { return = this; } \
-    [[accumulate]] cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__)
-
-.string vtblname;
-.entity vtblbase;
-
-void RegisterClasses() { }
-STATIC_INIT(RegisterClasses) { RegisterClasses(); }
-
-#define VTBL(cname, base) \
-    INIT_STATIC(cname); \
-    entity cname##_vtbl; \
-    void cname##_vtbl_init() { \
-        cname e = new(vtbl); \
-        spawn##cname##_static(e); \
-        e.vtblname = #cname; \
-        /* Top level objects refer to themselves */ \
-        e.vtblbase = base##_vtbl ? base##_vtbl : e; \
-        cname##_vtbl = e; \
-    } \
-    ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init)
-
-#define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this)
-#define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this)
-
-#define CLASS(cname, base)                  \
-    entityclass(cname, base);               \
-    class(cname) .bool instanceOf##cname;   \
-    VTBL(cname, base)                       \
-    INIT_STATIC(cname) {                    \
-        if (cname##_vtbl) {                 \
-            copyentity(cname##_vtbl, this); \
-            return;                         \
-        }                                   \
-        spawn##base##_static(this);         \
-        this.instanceOf##cname = true;      \
-    }                                       \
-    INIT(cname) {                           \
-        /* Only statically initialize the current class, it contains everything it inherits */ \
-        if (cname##_vtbl.vtblname == this.classname) { \
-            spawn##cname##_static(this);    \
-            this.classname = #cname;        \
-            this.vtblname = string_null;    \
-            this.vtblbase = cname##_vtbl;   \
-        }                                   \
-        spawn##base##_1(this);              \
-    }
-
-#define METHOD(cname, name, prototype)      \
-    class(cname) .prototype name;           \
-    prototype cname##_##name;               \
-    INIT_STATIC(cname) { this.name = cname##_##name; } \
-    prototype cname##_##name
-
-#define ATTRIB(cname, name, type, val)      \
-    class(cname) .type name;                \
-    INIT(cname) { this.name = val; }
-
-#define ATTRIBARRAY(cname, name, type, cnt) \
-    class(cname) .type name[cnt];
-
-#define ENDCLASS(cname) \
-    [[last]] INIT(cname) { return this; }
-
-#define SUPER(cname) (cname##_vtbl.vtblbase)
-#define super (this.vtblbase.vtblbase)
-
-#define spawn_static(this)
-#define spawn_1(this)
-#define _vtbl NULL
-CLASS(Object, );
-    METHOD(Object, describe, string(entity this)) {
-        string s = _("No description");
-        if (cvar("developer")) {
-            for (int i = 0, n = numentityfields(); i < n; ++i) {
-                string value = getentityfieldstring(i, this);
-                if (value != "") s = sprintf("%s\n%s = %s", s, entityfieldname(i), value);
-            }
-        }
-        return s;
-    }
-    METHOD(Object, display, void(entity this, void(string name, string icon) returns)) {
-        returns(sprintf("entity %i", this), "nopreview_map");
-    }
-ENDCLASS(Object)
-#undef spawn_static
-#undef spawn_1
-#undef _vtbl
-
-#endif
diff --git a/qcsrc/lib/Player.qh b/qcsrc/lib/Player.qh
deleted file mode 100644 (file)
index 07034a0..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifdef CSQC
-#ifndef PLAYER_H
-#define PLAYER_H
-
-#include "String.qh"
-
-#include "../client/main.qh"
-#include "../common/teams.qh"
-
-int GetPlayerColorForce(int i)
-{
-       if(!teamplay)
-               return 0;
-       else
-               return stof(getplayerkeyvalue(i, "colors")) & 15;
-}
-
-int GetPlayerColor(int i)
-{
-       if(!playerslots[i].gotscores) // unconnected
-               return NUM_SPECTATOR;
-       else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
-               return NUM_SPECTATOR;
-       else
-               return GetPlayerColorForce(i);
-}
-
-string GetPlayerName(int i)
-{
-       return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
-}
-
-#endif
-#endif
diff --git a/qcsrc/lib/Progname.qh b/qcsrc/lib/Progname.qh
deleted file mode 100644 (file)
index ed112a5..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef PROGNAME_H
-#define PROGNAME_H
-
-#if defined(MENUQC)
-    #define PROGNAME "MENUQC"
-#elif defined(SVQC)
-    #define PROGNAME "SVQC"
-#elif defined(CSQC)
-    #define PROGNAME "CSQC"
-#else
-    #error "Unable to detect PROGNAME"
-#endif
-
-#endif
diff --git a/qcsrc/lib/Registry.qh b/qcsrc/lib/Registry.qh
deleted file mode 100644 (file)
index ca0beae..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef REGISTRY_H
-#define REGISTRY_H
-
-#include "OO.qh"
-
-#define REGISTER_INIT(ns, id) [[accumulate]] void Register_##ns##_##id##_init(entity this)
-#define REGISTER_INIT_POST(ns, id) [[accumulate]] void Register_##ns##_##id##_init_post(entity this)
-
-#define REGISTER(initfunc, ns, array, counter, id, fld, inst)   \
-    entity ns##_##id;                                           \
-    REGISTER_INIT(ns, id) { }                                   \
-    REGISTER_INIT_POST(ns, id) { }                              \
-    .entity enemy; /* internal next pointer */                  \
-    void Register_##ns##_##id() {                               \
-        entity this = inst;                                     \
-        ns##_##id = this;                                       \
-        this.fld = counter;                                     \
-        array[counter++] = this;                                \
-        if (!array##_first)    array##_first = this;            \
-        if ( array##_last)     array##_last.enemy = this;       \
-        array##_last = this;                                    \
-        Register_##ns##_##id##_init(this);                      \
-        Register_##ns##_##id##_init_post(this);                 \
-    }                                                           \
-    ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id)         \
-    REGISTER_INIT(ns, id)
-
-#endif
diff --git a/qcsrc/lib/Static.qh b/qcsrc/lib/Static.qh
deleted file mode 100644 (file)
index d51a871..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef STATIC_H
-#define STATIC_H
-
-void __static_init_early() { }
-void __static_init() { CALL_ACCUMULATED_FUNCTION(__static_init_early); }
-#define static_init() CALL_ACCUMULATED_FUNCTION(__static_init)
-#define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init_early, func)
-
-#define _STATIC_INIT(where, func) \
-    void _static_##func(); \
-    ACCUMULATE_FUNCTION(where, _static_##func) \
-    void _static_##func()
-
-#define STATIC_INIT(func)       _STATIC_INIT(__static_init_early,   func##_early)
-#define STATIC_INIT_LATE(func)  _STATIC_INIT(__static_init,         func)
-
-#endif
diff --git a/qcsrc/lib/String.qh b/qcsrc/lib/String.qh
deleted file mode 100644 (file)
index faf81b2..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef STRING_H
-#define STRING_H
-
-#ifndef SVQC
-float stringwidth_colors(string s, vector theSize)
-{
-       return stringwidth(s, true, theSize);
-}
-
-float stringwidth_nocolors(string s, vector theSize)
-{
-       return stringwidth(s, false, theSize);
-}
-#endif
-
-// Timer (#5)
-//
-// TODO: macro
-string seconds_tostring(float sec)
-{
-       float minutes;
-       minutes = floor(sec / 60);
-
-       sec -= minutes * 60;
-       return sprintf("%d:%02d", minutes, sec);
-}
-
-int ColorTranslateMode;
-
-string ColorTranslateRGB(string s)
-{
-       if(ColorTranslateMode & 1)
-               return strdecolorize(s);
-       else
-               return s;
-}
-
-#endif
diff --git a/qcsrc/lib/Struct.qh b/qcsrc/lib/Struct.qh
deleted file mode 100644 (file)
index 507c417..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef STRUCT_H
-#define STRUCT_H
-
-#ifndef QCC_SUPPORT_STRUCT
-    #define _STRUCT_DECLARE(x, id, type, END) noref type x ##_## id ;
-    #define STRUCT_DECLARE(id, s) s(_STRUCT_DECLARE, id)
-
-    #define _STRUCT_PARAM_(x, id, type) type x ##_## id ,
-    #define _STRUCT_PARAM_END(x, id, type) type x ##_## id
-    #define _STRUCT_PARAM(x, id, type, isend) _STRUCT_PARAM_##isend(x, id, type)
-    #define STRUCT_PARAM(id, s) s(_STRUCT_PARAM, id)
-
-    #define _STRUCT_PASS_(x, id, type) x ##_## id ,
-    #define _STRUCT_PASS_END(x, id, type) x ##_## id
-    #define _STRUCT_PASS(x, id, type, END) _STRUCT_PASS_##END(x, id, type)
-    #define STRUCT_PASS(id, s) s(_STRUCT_PASS, id)
-
-    #define _STRUCT_STORE_DST(_, it) it
-    #define _STRUCT_STORE_SRC(it, _) it
-    #define _CONCAT3_(a, b, c) a ## b ## c
-    #define _CONCAT3(a, b, c) _CONCAT3_(a, b, c)
-    #define _STRUCT_STORE(x, id, type, END) _CONCAT3(_STRUCT_STORE_DST x, _, id) = _CONCAT3(_STRUCT_STORE_SRC x, _, id);
-    #define STRUCT_STORE(from, to, s) s(_STRUCT_STORE, (from, to))
-
-    #define STRUCT(id, ...)
-#else
-    #define STRUCT_DECLARE(id, type) type id;
-    #define STRUCT_PARAM(id, type) type id
-    #define STRUCT_PASS(id, type) id
-    #define STRUCT_STORE(from, to, s) to = from
-    #define _STRUCT_MEMBER(my, id, type, END) type id;
-    #define STRUCT(id, s) struct STRUCT_##id { s(_STRUCT_MEMBER, ) };
-#endif
-
-#endif
diff --git a/qcsrc/lib/Vector.qh b/qcsrc/lib/Vector.qh
deleted file mode 100644 (file)
index d81a795..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef VECTOR_H
-#define VECTOR_H
-
-const vector eX = '1 0 0';
-const vector eY = '0 1 0';
-const vector eZ = '0 0 1';
-
-vector randompos(vector m1, vector m2)
-{
-       vector v;
-       m2 = m2 - m1;
-       v_x = m2_x * random() + m1_x;
-       v_y = m2_y * random() + m1_y;
-       v_z = m2_z * random() + m1_z;
-       return  v;
-}
-
-float vlen2d(vector v)
-{
-       return sqrt(v.x * v.x + v.y * v.y);
-}
-
-float vlen_maxnorm2d(vector v)
-{
-       return max(v.x, v.y, -v.x, -v.y);
-}
-
-float vlen_minnorm2d(vector v)
-{
-       return min(max(v.x, -v.x), max(v.y, -v.y));
-}
-
-
-#endif
index 1b7e61e9aa4cb125fd5e20f3b02e4420ee4cb78f..c00c5a12afff460286089191ddc4912ae06c04ea 100644 (file)
@@ -1,28 +1,34 @@
-#include "Bool.qh"
+#include "bool.qh"
 
 #include "../warpzonelib/mathlib.qc"
 
-#include "Accumulate.qh"
-#include "Counting.qh"
-#include "Cvar.qh"
-#include "Defer.qh"
-#include "Draw.qh"
-#include "I18N.qh"
-#include "Lazy.qh"
-#include "Log.qh"
-#include "Math.qh"
-#include "Nil.qh"
+#include "accumulate.qh"
+#include "bits.qh"
+#include "counting.qh"
+#include "cvar.qh"
+#include "defer.qh"
+#include "draw.qh"
+#include "file.qh"
+#include "i18n.qh"
+#include "lazy.qh"
+#include "log.qh"
+#include "math.qh"
+#include "net.qh"
+#include "nil.qh"
 #include "noise.qc"
-#include "OO.qh"
+#include "oo.qh"
 #include "p2mathlib.qc"
-#include "Player.qh"
-#include "prandom.qc"
-#include "Progname.qh"
-#include "Registry.qh"
+#include "player.qh"
+#include "progname.qh"
+#include "random.qc"
+#include "registry.qh"
+#include "replicate.qh"
+#include "sort.qh"
 #include "sortlist.qc"
-#include "Static.qh"
-#include "String.qh"
-#include "Struct.qh"
+#include "spawnfunc.qh"
+#include "static.qh"
+#include "string.qh"
+#include "struct.qh"
 #include "test.qc"
 #include "urllib.qc"
-#include "Vector.qh"
+#include "vector.qh"
diff --git a/qcsrc/lib/accumulate.qh b/qcsrc/lib/accumulate.qh
new file mode 100644 (file)
index 0000000..7e1a1ed
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef ACCUMULATE_H
+#define ACCUMULATE_H
+
+#ifdef QCC_SUPPORT_ACCUMULATE
+# define ACCUMULATE_FUNCTION(func, otherfunc) \
+    [[accumulate]] void func() { otherfunc(); }
+# define CALL_ACCUMULATED_FUNCTION(func) \
+    func()
+#else
+#ifdef HAVE_YO_DAWG_CPP
+// TODO make ascii art pic of xzibit
+// YO DAWG!
+// I HERD YO LIEK MACROS
+// SO I PUT A MACRO DEFINITION IN YO MACRO DEFINITION
+// SO YO CAN EXPAND MACROS WHILE YO EXPAND MACROS
+# define ACCUMULATE_FUNCTION(func,otherfunc) \
+    #ifdef func \
+    void __merge__##otherfunc() { func(); otherfunc(); } \
+    #undef func \
+    #define func __merge__##otherfunc \
+    #else \
+    #define func otherfunc \
+    #endif
+# define CALL_ACCUMULATED_FUNCTION(func) \
+    func()
+#else
+# define ACCUMULATE_FUNCTION(func,otherfunc) \
+    .float _ACCUMULATE_##func##__##otherfunc;
+void ACCUMULATE_call(string func)
+{
+    float i;
+    float n = numentityfields();
+    string funcprefix = strcat("_ACCUMULATE_", func, "__");
+    float funcprefixlen = strlen(funcprefix);
+    for(i = 0; i < n; ++i)
+    {
+        string name = entityfieldname(i);
+        if(substring(name, 0, funcprefixlen) == funcprefix)
+            callfunction(substring(name, funcprefixlen, -1));
+    }
+}
+# define CALL_ACCUMULATED_FUNCTION(func) \
+    ACCUMULATE_call(#func)
+#endif
+#endif
+
+// used for simplifying ACCUMULATE_FUNCTIONs
+#define SET_FIRST_OR_LAST(input,first,count) if(!input) { input = (first + count); }
+#define SET_FIELD_COUNT(field,first,count) if(!field) { field = (first + count); ++count; }
+#define CHECK_MAX_COUNT(name,max,count,type) if(count > max) { error(strcat("Maximum ", type, " hit: ", #name, ": ", ftos(count), ".\n")); }
+
+#endif
diff --git a/qcsrc/lib/bits.qh b/qcsrc/lib/bits.qh
new file mode 100644 (file)
index 0000000..86b5df5
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef BITS_H
+#define BITS_H
+
+#define BIT(n) (1 << (n))
+#define BITS(n) (BIT(n) - 1)
+#ifndef BRANCHLESS_BITSET
+    #define BITSET(var, mask, flag) (flag ? (var) | (mask) : (var) &~ (mask))
+#else
+    #define BITSET(var, mask, flag) ((var) ^ (-(flag) ^ (var)) & (mask))
+#endif
+
+int lowestbit(int f)
+{
+    f &= ~(f << 1);
+    f &= ~(f << 2);
+    f &= ~(f << 4);
+    f &= ~(f << 8);
+    f &= ~(f << 16);
+    return f;
+}
+
+#endif
diff --git a/qcsrc/lib/bool.qh b/qcsrc/lib/bool.qh
new file mode 100644 (file)
index 0000000..26169cd
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef BOOL_H
+#define BOOL_H
+
+#ifndef QCC_SUPPORT_BOOL
+    #define bool float
+
+    // Boolean Constants
+    const int true     = 1;
+    const int false = 0;
+#endif
+
+// Transitional aliases
+[[deprecated("use true")]] [[alias("true")]] const bool TRUE;
+[[deprecated("use false")]] [[alias("false")]] const bool FALSE;
+
+// get true/false value of a string with multiple different inputs
+float InterpretBoolean(string input)
+{
+    switch (strtolower(input))
+    {
+        case "yes":
+        case "true":
+        case "on":
+            return true;
+
+        case "no":
+        case "false":
+        case "off":
+            return false;
+
+        default: return stof(input);
+    }
+}
+
+float boolean(float value) { // if value is 0 return false (0), otherwise return true (1)
+    return (value == 0) ? false : true;
+}
+
+#endif
diff --git a/qcsrc/lib/counting.qh b/qcsrc/lib/counting.qh
new file mode 100644 (file)
index 0000000..81103a5
--- /dev/null
@@ -0,0 +1,223 @@
+#ifndef COUNTING_H
+#define COUNTING_H
+
+#include "i18n.qh"
+
+// ===============================================
+//  Time processing and counting functions/macros
+// ===============================================
+
+#define count_years_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
+#define count_years(time) count_fill(time, \
+               ZCTX(_("CI_ZER^%d years")), /* zeroth */ \
+               ZCTX(_("CI_FIR^%d year")),  /* first */ \
+               ZCTX(_("CI_SEC^%d years")), /* year */ \
+               ZCTX(_("CI_THI^%d years")), /* third */ \
+               ZCTX(_("CI_MUL^%d years"))) /* multi */
+
+#define count_weeks_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
+#define count_weeks(time) count_fill(time, \
+               ZCTX(_("CI_ZER^%d weeks")), /* zeroth */ \
+               ZCTX(_("CI_FIR^%d week")),  /* first */ \
+               ZCTX(_("CI_SEC^%d weeks")), /* week */ \
+               ZCTX(_("CI_THI^%d weeks")), /* third */ \
+               ZCTX(_("CI_MUL^%d weeks"))) /* multi */
+
+#define count_days_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
+#define count_days(time) count_fill(time, \
+               ZCTX(_("CI_ZER^%d days")), /* zeroth */ \
+               ZCTX(_("CI_FIR^%d day")),  /* first */ \
+               ZCTX(_("CI_SEC^%d days")), /* day */ \
+               ZCTX(_("CI_THI^%d days")), /* third */ \
+               ZCTX(_("CI_MUL^%d days"))) /* multi */
+
+#define count_hours_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
+#define count_hours(time) count_fill(time, \
+               ZCTX(_("CI_ZER^%d hours")), /* zeroth */ \
+               ZCTX(_("CI_FIR^%d hour")),  /* first */ \
+               ZCTX(_("CI_SEC^%d hours")), /* hour */ \
+               ZCTX(_("CI_THI^%d hours")), /* third */ \
+               ZCTX(_("CI_MUL^%d hours"))) /* multi */
+
+
+#define count_minutes_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
+#define count_minutes(time) count_fill(time, \
+               ZCTX(_("CI_ZER^%d minutes")), /* zeroth */ \
+               ZCTX(_("CI_FIR^%d minute")),  /* first */ \
+               ZCTX(_("CI_SEC^%d minutes")), /* minute */ \
+               ZCTX(_("CI_THI^%d minutes")), /* third */ \
+               ZCTX(_("CI_MUL^%d minutes"))) /* multi */
+
+#define count_seconds_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
+#define count_seconds(time) count_fill(time, \
+               ZCTX(_("CI_ZER^%d seconds")), /* zeroth */ \
+               ZCTX(_("CI_FIR^%d second")),  /* first */ \
+               ZCTX(_("CI_SEC^%d seconds")), /* second */ \
+               ZCTX(_("CI_THI^%d seconds")), /* third */ \
+               ZCTX(_("CI_MUL^%d seconds"))) /* multi */
+
+string count_ordinal(int interval)
+{
+       // This function is designed primarily for the English language, it's impossible
+       // to accomodate all languages unless we do a specific function for each one...
+       // and since that's not technically feasible/practical, this is all we've got folks.
+
+       // Basically, it just allows you to represent a number or count in different ways
+       // depending on the number... like, with count_ordinal you can provide integers
+       // and retrieve 1st, 2nd, 3rd, nth ordinal numbers in a clean and simple way.
+       if(floor((interval % 100)/10) * 10 != 10) // examples: 12th, 111th, 213th will not execute this block
+       {
+               // otherwise, check normally for 1st,2nd,3rd insertions
+               switch(interval % 10)
+               {
+                       case 1: return sprintf(_("%dst"), interval);
+                       case 2: return sprintf(_("%dnd"), interval);
+                       case 3: return sprintf(_("%drd"), interval);
+                       default: return sprintf(_("%dth"), interval);
+               }
+       }
+       else { return sprintf(_("%dth"), interval); }
+
+       return "";
+}
+
+string count_fill(float interval, string zeroth, string first, string second, string third, string multi)
+{
+       // This function is designed primarily for the English language, it's impossible
+       // to accomodate all languages unless we do a specific function for each one...
+       // and since that's not technically feasible/practical, this is all we've got folks.
+
+       // Here you can insert specific strings based on the interval number, so you could do
+       // i.e. count_seconds which outputs like this:
+       //   0 seconds
+       //   1 second
+       //   2 seconds
+       //   3 seconds
+       //   etc... minutes, hours, days, etc.
+
+       switch(floor(interval))
+       {
+               case 0: return sprintf(zeroth, interval);
+               case 1:
+               {
+                       if(interval == 1) // EXACTLY value of 1
+                               return sprintf(first, interval);
+                       else
+                               return sprintf(multi, interval);
+               }
+               case 2: return sprintf(second, interval);
+               case 3: return sprintf(third, interval);
+               default: return sprintf(multi, interval);
+       }
+       return "";
+}
+
+string process_time(float outputtype, float seconds)
+{
+       float tmp_hours = 0, tmp_minutes = 0, tmp_seconds = 0;
+       float tmp_years = 0, tmp_weeks = 0, tmp_days = 0;
+
+       tmp_seconds = floor(seconds);
+
+       if(tmp_seconds)
+       {
+               tmp_minutes = floor(tmp_seconds / 60);
+
+               if(tmp_minutes)
+               {
+                       tmp_seconds -= (tmp_minutes * 60);
+                       tmp_hours = floor(tmp_minutes / 60);
+
+                       if(tmp_hours)
+                       {
+                               tmp_minutes -= (tmp_hours * 60);
+                               tmp_days = floor(tmp_hours / 24);
+
+                               if(tmp_days)
+                               {
+                                       tmp_hours -= (tmp_days * 24);
+                                       tmp_weeks = floor(tmp_days / 7);
+
+                                       if(tmp_weeks)
+                                       {
+                                               tmp_days -= (tmp_weeks * 7);
+                                               tmp_years = floor(tmp_weeks / 52);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       switch(outputtype)
+       {
+               case 1: return sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds);
+               case 2:
+               {
+                       string output = "";
+
+                       output = count_seconds(tmp_seconds);
+
+                       if(tmp_minutes)
+                       {
+                               output = sprintf(
+                                       "%s%s",
+                                       count_minutes(tmp_minutes),
+                                       ((output != "") ? sprintf(", %s", output) : ""));
+                       }
+
+                       if(tmp_hours)
+                       {
+                               output = sprintf(
+                                       "%s%s",
+                                       count_hours(tmp_hours),
+                                       ((output != "") ? sprintf(", %s", output) : ""));
+                       }
+
+                       if(tmp_days)
+                       {
+                               output = sprintf(
+                                       "%s%s",
+                                       count_days(tmp_days),
+                                       ((output != "") ? sprintf(", %s", output) : ""));
+                       }
+
+                       if(tmp_weeks)
+                       {
+                               output = sprintf(
+                                       "%s%s",
+                                       count_weeks(tmp_weeks),
+                                       ((output != "") ? sprintf(", %s", output) : ""));
+                       }
+
+                       if(tmp_years)
+                       {
+                               output = sprintf(
+                                       "%s%s",
+                                       count_years(tmp_years),
+                                       ((output != "") ? sprintf(", %s", output) : ""));
+                       }
+
+                       return output;
+               }
+               case 3:
+               {
+                       string output = "";
+
+                       output = count_hours(tmp_hours);
+
+                       if(tmp_weeks) { tmp_days += (tmp_weeks * 7); }
+                       if(tmp_years) { tmp_days += (tmp_years * 365); }
+                       if(tmp_days)
+                       {
+                               output = sprintf(
+                                       "%s%s",
+                                       count_days(tmp_days),
+                                       ((output != "") ? sprintf(", %s", output) : ""));
+                       }
+
+                       return output;
+               }
+       }
+       return "";
+}
+#endif
diff --git a/qcsrc/lib/cvar.qh b/qcsrc/lib/cvar.qh
new file mode 100644 (file)
index 0000000..e30de50
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef CVAR_H
+#define CVAR_H
+
+#include "nil.qh"
+#include "static.qh"
+
+void RegisterCvars(void(string name, string def, string desc, bool archive, string file) f) { }
+
+/** escape the string to make it safe for consoles */
+string MakeConsoleSafe(string input)
+{
+       input = strreplace("\n", "", input);
+       input = strreplace("\\", "\\\\", input);
+       input = strreplace("$", "$$", input);
+       input = strreplace("\"", "\\\"", input);
+       return input;
+}
+
+void RegisterCvars_Set(string name, string def, string desc, bool archive, string file)
+{
+    string val = string_null;
+    if (cvar_type(name) & CVAR_TYPEFLAG_EXISTS) {
+        val = cvar_string(name);
+        // Need to unset first to change the default
+        localcmd(sprintf("\nunset %s\n", name));
+    }
+    localcmd(sprintf("\n%s %s \"%s\" \"%s\"\n", (archive ? "seta" : "set"), name, MakeConsoleSafe(def), MakeConsoleSafe(desc)));
+    if (val) {
+        localcmd(sprintf("\n%s \"%s\"\n", name, MakeConsoleSafe(val)));
+    }
+}
+
+#ifndef SVQC
+STATIC_INIT_LATE(Cvars) { RegisterCvars(RegisterCvars_Set); }
+#endif
+
+const noref bool default_bool = false;
+const noref int default_int = 0;
+const noref float default_float = 0;
+const noref string default_string = "";
+const noref vector default_vector = '0 0 0';
+
+#define repr_cvar_bool(x)   ((x) ? "1" : "0")
+#define repr_cvar_int(x)    (ftos(x))
+#define repr_cvar_float(x)  (ftos(x))
+#define repr_cvar_string(x) (x)
+#define repr_cvar_vector(x) (sprintf("%v", x))
+
+#define __AUTOCVAR(file, archive, var, type, desc, default) \
+    [[accumulate]] void RegisterCvars(void(string, string, string, bool, string) f) { f(#var, repr_cvar_##type(default), desc, archive, file); } \
+    type autocvar_##var = default
+#define AUTOCVAR_5(file, archive, var, type, desc) \
+    __AUTOCVAR(file, archive, var, type, desc, default_##type)
+#define AUTOCVAR_6(file, archive, var, type, default, desc) \
+    __AUTOCVAR(file, archive, var, type, desc, default)
+#define _AUTOCVAR(...) EVAL(OVERLOAD(AUTOCVAR, __FILE__, __VA_ARGS__))
+#define AUTOCVAR_SAVE(...) _AUTOCVAR(true, __VA_ARGS__)
+#define AUTOCVAR(...) _AUTOCVAR(false, __VA_ARGS__)
+
+#endif
diff --git a/qcsrc/lib/defer.qh b/qcsrc/lib/defer.qh
new file mode 100644 (file)
index 0000000..2a13611
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef MENUQC
+#ifndef DEFER_H
+#define DEFER_H
+#include "oo.qh"
+
+entityclass(Defer);
+class(Defer) .entity owner;
+class(Defer) .void() think;
+class(Defer) .float nextthink;
+
+/*
+==================
+SUB_Remove
+
+Remove self
+==================
+*/
+void SUB_Remove()
+{SELFPARAM();
+       remove (self);
+}
+
+void defer_think()
+{SELFPARAM();
+    self.think     = SUB_Remove;
+    self.nextthink = time;
+    WITH(entity, self, self.owner, self.use());
+}
+
+/*
+    Execute func() after time + fdelay.
+    self when func is executed = self when defer is called
+*/
+void defer(float fdelay, void() func)
+{SELFPARAM();
+    entity e;
+
+    e           = spawn();
+    e.owner     = self;
+    e.use       = func;
+    e.think     = defer_think;
+    e.nextthink = time + fdelay;
+}
+
+#endif
+#endif
diff --git a/qcsrc/lib/draw.qh b/qcsrc/lib/draw.qh
new file mode 100644 (file)
index 0000000..90abcb2
--- /dev/null
@@ -0,0 +1,133 @@
+#ifdef CSQC
+#ifndef DRAW_H
+#define DRAW_H
+
+#include "i18n.qh"
+#include "vector.qh"
+
+#include "../client/defs.qh"
+
+void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
+{
+       // I want to draw a quad...
+       // from and to are MIDPOINTS.
+
+       vector axis, thickdir, A, B, C, D;
+       float length_tex;
+
+       axis = normalize(to - from);
+       length_tex = aspect * vlen(to - from) / thickness;
+
+       // direction is perpendicular to the view normal, and perpendicular to the axis
+       thickdir = normalize(cross(axis, vieworg - from));
+
+       A = from - thickdir * (thickness / 2);
+       B = from + thickdir * (thickness / 2);
+       C = to + thickdir * (thickness / 2);
+       D = to - thickdir * (thickness / 2);
+
+       R_BeginPolygon(texture, drawflag);
+       R_PolygonVertex(A, '0 0 0' + shift * '1 0 0', rgb, theAlpha);
+       R_PolygonVertex(B, '0 1 0' + shift * '1 0 0', rgb, theAlpha);
+       R_PolygonVertex(C, '0 1 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha);
+       R_PolygonVertex(D, '0 0 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha);
+       R_EndPolygon();
+}
+
+// a border picture is a texture containing nine parts:
+//   1/4 width: left part
+//   1/2 width: middle part (stretched)
+//   1/4 width: right part
+// divided into
+//   1/4 height: top part
+//   1/2 height: middle part (stretched)
+//   1/4 height: bottom part
+void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
+{
+    if (theBorderSize.x < 0 && theBorderSize.y < 0) // draw whole image as it is
+    {
+               drawpic(theOrigin, pic, theSize, theColor, theAlpha, 0);
+               return;
+    }
+       if (theBorderSize.x == 0 && theBorderSize.y == 0) // no border
+       {
+               // draw only the central part
+               drawsubpic(theOrigin, theSize, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
+               return;
+       }
+
+       vector dX, dY;
+       vector width, height;
+       vector bW, bH;
+       //pic = draw_UseSkinFor(pic);
+       width = eX * theSize.x;
+       height = eY * theSize.y;
+       if(theSize.x <= theBorderSize.x * 2)
+       {
+               // not wide enough... draw just left and right then
+               bW = eX * (0.25 * theSize.x / (theBorderSize.x * 2));
+               if(theSize.y <= theBorderSize.y * 2)
+               {
+                       // not high enough... draw just corners
+                       bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
+                       drawsubpic(theOrigin,                 width * 0.5 + height * 0.5, pic, '0 0 0',           bW + bH, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + width   * 0.5, width * 0.5 + height * 0.5, pic, eX - bW,           bW + bH, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + height  * 0.5, width * 0.5 + height * 0.5, pic, eY - bH,           bW + bH, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
+               }
+               else
+               {
+                       dY = theBorderSize.x * eY;
+                       drawsubpic(theOrigin,                             width * 0.5          +     dY, pic, '0 0    0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + width * 0.5,               width * 0.5          +     dY, pic, '0 0    0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin                        + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0',           '0 0.5  0' + bW, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + width * 0.5          + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0' + eX - bW, '0 0.5  0' + bW, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin               + height - dY, width * 0.5          +     dY, pic, '0 0.75 0',           '0 0.25 0' + bW, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + width * 0.5 + height - dY, width * 0.5          +     dY, pic, '0 0.75 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
+               }
+       }
+       else
+       {
+               if(theSize.y <= theBorderSize.y * 2)
+               {
+                       // not high enough... draw just top and bottom then
+                       bH = eY * (0.25 * theSize.y / (theBorderSize.y * 2));
+                       dX = theBorderSize.x * eX;
+                       drawsubpic(theOrigin,                                         dX + height * 0.5, pic, '0    0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + dX,                        width - 2 * dX + height * 0.5, pic, '0.25 0 0',           '0.5  0 0' + bH, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + width - dX,                            dX + height * 0.5, pic, '0.75 0 0',           '0.25 0 0' + bH, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin              + height * 0.5,             dX + height * 0.5, pic, '0    0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + dX         + height * 0.5, width - 2 * dX + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5  0 0' + bH, theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + width - dX + height * 0.5,             dX + height * 0.5, pic, '0.75 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
+               }
+               else
+               {
+                       dX = theBorderSize.x * eX;
+                       dY = theBorderSize.x * eY;
+                       drawsubpic(theOrigin,                                        dX          +     dY, pic, '0    0    0', '0.25 0.25 0', theColor, theAlpha, 0);
+                       drawsubpic(theOrigin                  + dX,      width - 2 * dX          +     dY, pic, '0.25 0    0', '0.5  0.25 0', theColor, theAlpha, 0);
+                       drawsubpic(theOrigin          + width - dX,                  dX          +     dY, pic, '0.75 0    0', '0.25 0.25 0', theColor, theAlpha, 0);
+                       drawsubpic(theOrigin          + dY,                          dX + height - 2 * dY, pic, '0    0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
+                       drawsubpic(theOrigin          + dY         + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5  0.5  0', theColor, theAlpha, 0);
+                       drawsubpic(theOrigin          + dY + width - dX,             dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5  0', theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + height - dY,                          dX          +     dY, pic, '0    0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + height - dY         + dX, width - 2 * dX          +     dY, pic, '0.25 0.75 0', '0.5  0.25 0', theColor, theAlpha, 0);
+                       drawsubpic(theOrigin + height - dY + width - dX,             dX          +     dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
+               }
+       }
+}
+
+void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
+{
+       position.x -= 2 / 3 * strlen(text) * theScale.x;
+       drawstring(position, text, theScale, rgb, theAlpha, flag);
+}
+
+void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
+{
+       position.x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * theScale.x);
+       drawstring(position, text, theScale, rgb, theAlpha, flag);
+}
+
+#endif
+#endif
diff --git a/qcsrc/lib/file.qh b/qcsrc/lib/file.qh
new file mode 100644 (file)
index 0000000..f732bfe
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef FILE_H
+#define FILE_H
+
+bool fexists(string f)
+{
+    int fh = fopen(f, FILE_READ);
+    if (fh < 0)
+        return false;
+    fclose(fh);
+    return true;
+}
+
+#endif
diff --git a/qcsrc/lib/i18n.qh b/qcsrc/lib/i18n.qh
new file mode 100644 (file)
index 0000000..87c41cd
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef I18N_H
+#define I18N_H
+
+#include "log.qh"
+
+// translation helpers
+string prvm_language;
+
+string language_filename(string s)
+{
+    string fn = prvm_language;
+    if (fn == "" || fn == "dump")
+        return s;
+    fn = strcat(s, ".", fn);
+    int fh = fopen(fn, FILE_READ);
+    if (fh >= 0)
+    {
+        fclose(fh);
+        return fn;
+    }
+    return s;
+}
+
+string CTX(string s)
+{
+    int p = strstrofs(s, "^", 0);
+    if (p < 0)
+        return s;
+    return substring(s, p + 1, -1);
+}
+
+#define ZCTX(s) strzone(CTX(s))
+
+#endif
diff --git a/qcsrc/lib/lazy.qh b/qcsrc/lib/lazy.qh
new file mode 100644 (file)
index 0000000..f632b38
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef LAZY_H
+#define LAZY_H
+
+#include "oo.qh"
+
+CLASS(Lazy, Object)
+    ATTRIB(Lazy, m_get, entity(), func_null);
+    CONSTRUCTOR(Lazy, entity() _compute) { this.m_get = _compute; }
+ENDCLASS(Lazy)
+
+#define LAZY(id) __lazy_##id
+#define LAZY_NEW(id, compute) entity LAZY(id)() { \
+    static bool done; \
+    static entity it; \
+    if (!done) { it = compute; done = true; } \
+    return it; \
+}
+#endif
diff --git a/qcsrc/lib/log.qh b/qcsrc/lib/log.qh
new file mode 100644 (file)
index 0000000..3d186e3
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef LOG_H
+#define LOG_H
+
+#define _printferr(...)     error(sprintf(__VA_ARGS__))
+#define _printfbt(...)      backtrace(sprintf(__VA_ARGS__))
+#define printf(...)         print(sprintf(__VA_ARGS__))
+#define dprintf(...)        dprint(sprintf(__VA_ARGS__))
+#define _dprintf2(...)      do { if (autocvar_developer > 1) dprintf(__VA_ARGS__); } while (0)
+
+#define assert(expr, ...)   do { if (!(expr)) LOG_WARNINGF(__VA_ARGS__); } while (0)
+
+#define _LOG(f, level, s)   f("[::"level"] ["__FILE__":%s:%.0f] %s", __FUNC__, __LINE__, s)
+
+#define  LOG_FATAL(...)     _LOG_FATAL(strcat("", __VA_ARGS__))
+#define  LOG_FATALF(...)    _LOG_FATAL(sprintf(__VA_ARGS__))
+#define _LOG_FATAL(s)       _LOG(_printferr, "FATAL", s)
+
+#define  LOG_SEVERE(...)    _LOG_SEVERE(strcat("", __VA_ARGS__))
+#define  LOG_SEVEREF(...)   _LOG_SEVERE(sprintf(__VA_ARGS__))
+#define _LOG_SEVERE(s)      _LOG(_printfbt, "SEVERE", s)
+
+#define  LOG_WARNING(...)   _LOG_WARNING(strcat("", __VA_ARGS__))
+#define  LOG_WARNINGF(...)  _LOG_WARNING(sprintf(__VA_ARGS__))
+#define _LOG_WARNING(s)     _LOG(printf, "WARNING", s)
+
+#define  LOG_INFO(...)      do { if (autocvar_developer) _LOG_INFO(strcat("", __VA_ARGS__)); else print (__VA_ARGS__); } while (0)
+#define  LOG_INFOF(...)     do { if (autocvar_developer) _LOG_INFO(sprintf(__VA_ARGS__));    else printf(__VA_ARGS__); } while (0)
+#define _LOG_INFO(s)        _LOG(printf, "INFO", s)
+
+#define  LOG_TRACE(...)     _LOG_TRACE(strcat("", __VA_ARGS__))
+#define  LOG_TRACEF(...)    _LOG_TRACE(sprintf(__VA_ARGS__))
+#define _LOG_TRACE(s)       _LOG(dprintf, "TRACE", s)
+
+#define  LOG_DEBUG(...)     _LOG_DEBUG(strcat("", __VA_ARGS__))
+#define  LOG_DEBUGF(...)    _LOG_DEBUG(sprintf(__VA_ARGS__))
+#define _LOG_DEBUG(s)       _LOG(_dprintf2, "DEBUG", s)
+
+// TODO: this sucks, lets find a better way to do backtraces?
+#ifdef SVQC
+void builtin_remove(entity);
+#define _backtrace() builtin_remove(NULL)
+#else
+void remove(entity);
+#define _backtrace() remove(NULL)
+#endif
+
+noref int autocvar_developer;
+noref bool autocvar_prvm_backtraceforwarnings;
+
+#define backtrace(msg) do { \
+    int dev = autocvar_developer; \
+    bool war = autocvar_prvm_backtraceforwarnings; \
+    cvar_set("developer", "1"); \
+    cvar_set("prvm_backtraceforwarnings", "1"); \
+    print("\n--- CUT HERE ---\n", msg, "\n"); \
+    _backtrace(); \
+    print("\n--- CUT UNTIL HERE ---\n"); \
+    cvar_set("developer", ftos(dev)); \
+    cvar_set("prvm_backtraceforwarnings", ftos(war)); \
+} while (0)
+
+#define ASSERT(expr) do { if (!(expr)) LOG_FATAL("assertion failed: " #expr "\n"); } while (0)
+
+#endif
diff --git a/qcsrc/lib/math.qh b/qcsrc/lib/math.qh
new file mode 100644 (file)
index 0000000..1a707a4
--- /dev/null
@@ -0,0 +1,283 @@
+#ifndef MATH_H
+#define MATH_H
+
+void mean_accumulate(entity e, .float a, .float c, float mean, float value, float weight)
+{
+    if (weight == 0)
+        return;
+    if (mean == 0)
+        e.(a) *= pow(value, weight);
+    else
+        e.(a) += pow(value, mean) * weight;
+    e.(c) += weight;
+}
+
+float mean_evaluate(entity e, .float a, .float c, float mean)
+{
+    if (e.(c) == 0)
+        return 0;
+    if (mean == 0)
+        return pow(e.(a), 1.0 / e.(c));
+    else
+        return pow(e.(a) / e.(c), 1.0 / mean);
+}
+
+#define MEAN_ACCUMULATE(prefix,v,w) mean_accumulate(self,prefix##_accumulator,prefix##_count,prefix##_mean,v,w)
+#define MEAN_EVALUATE(prefix) mean_evaluate(self,prefix##_accumulator,prefix##_count,prefix##_mean)
+#define MEAN_DECLARE(prefix,m) float prefix##_mean = m; .float prefix##_count, prefix##_accumulator
+
+/*
+==================
+crandom
+
+Returns a random number between -1.0 and 1.0
+==================
+*/
+float crandom()
+{
+    return 2 * (random() - 0.5);
+}
+
+
+/*
+==================
+Angc used for animations
+==================
+*/
+
+
+float angc(float a1, float a2)
+{
+    while (a1 > 180) a1 -= 360;
+    while (a1 < -179) a1 += 360;
+    while (a2 > 180) a2 -= 360;
+    while (a2 < -179) a2 += 360;
+    float a = a1 - a2;
+    while (a > 180) a -= 360;
+    while (a < -179) a += 360;
+    return a;
+}
+
+float fsnap(float val,float fsize)
+{
+    return rint(val / fsize) * fsize;
+}
+
+vector vsnap(vector point,float fsize)
+{
+    vector vret;
+
+    vret.x = rint(point.x / fsize) * fsize;
+    vret.y = rint(point.y / fsize) * fsize;
+    vret.z = ceil(point.z / fsize) * fsize;
+
+    return vret;
+}
+
+vector lerpv(float t0, vector v0, float t1, vector v1, float t)
+{
+    return v0 + (v1 - v0) * ((t - t0) / (t1 - t0));
+}
+
+vector bezier_quadratic_getpoint(vector a, vector b, vector c, float t)
+{
+    return
+        (c - 2 * b + a) * (t * t) +
+        (b - a) * (2 * t) +
+        a;
+}
+
+vector bezier_quadratic_getderivative(vector a, vector b, vector c, float t)
+{
+    return
+        (c - 2 * b + a) * (2 * t) +
+        (b - a) * 2;
+}
+
+float cubic_speedfunc(float startspeedfactor, float endspeedfactor, float x)
+{
+    return
+        (((     startspeedfactor + endspeedfactor - 2
+        ) * x - 2 * startspeedfactor - endspeedfactor + 3
+        ) * x + startspeedfactor
+        ) * x;
+}
+
+bool cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor)
+{
+    if (startspeedfactor < 0 || endspeedfactor < 0)
+        return false;
+
+    /*
+    // if this is the case, the possible zeros of the first derivative are outside
+    // 0..1
+    We can calculate this condition as condition
+    if(se <= 3)
+        return true;
+    */
+
+    // better, see below:
+    if (startspeedfactor <= 3 && endspeedfactor <= 3)
+        return true;
+
+    // if this is the case, the first derivative has no zeros at all
+    float se = startspeedfactor + endspeedfactor;
+    float s_e = startspeedfactor - endspeedfactor;
+    if (3 * (se - 4) * (se - 4) + s_e * s_e <= 12) // an ellipse
+        return true;
+
+    // Now let s <= 3, s <= 3, s+e >= 3 (triangle) then we get se <= 6 (top right corner).
+    // we also get s_e <= 6 - se
+    // 3 * (se - 4)^2 + (6 - se)^2
+    // is quadratic, has value 12 at 3 and 6, and value < 12 in between.
+    // Therefore, above "better" check works!
+
+    return false;
+
+    // known good cases:
+    // (0, [0..3])
+    // (0.5, [0..3.8])
+    // (1, [0..4])
+    // (1.5, [0..3.9])
+    // (2, [0..3.7])
+    // (2.5, [0..3.4])
+    // (3, [0..3])
+    // (3.5, [0.2..2.3])
+    // (4, 1)
+
+    /*
+       On another note:
+       inflection point is always at (2s + e - 3) / (3s + 3e - 6).
+
+       s + e - 2 == 0: no inflection
+
+       s + e > 2:
+       0 < inflection < 1 if:
+       0 < 2s + e - 3 < 3s + 3e - 6
+       2s + e > 3 and 2e + s > 3
+
+       s + e < 2:
+       0 < inflection < 1 if:
+       0 > 2s + e - 3 > 3s + 3e - 6
+       2s + e < 3 and 2e + s < 3
+
+       Therefore: there is an inflection point iff:
+       e outside (3 - s)/2 .. 3 - s*2
+
+       in other words, if (s,e) in triangle (1,1)(0,3)(0,1.5) or in triangle (1,1)(3,0)(1.5,0)
+    */
+}
+
+/** continuous function mapping all reals into -1..1 */
+float float2range11(float f)
+{
+    return f / (fabs(f) + 1);
+}
+
+/** continuous function mapping all reals into 0..1 */
+float float2range01(float f)
+{
+    return 0.5 + 0.5 * float2range11(f);
+}
+
+float median(float a, float b, float c)
+{
+    return (a < c) ? bound(a, b, c) : bound(c, b, a);
+}
+
+float almost_equals(float a, float b)
+{
+    float eps = (max(a, -a) + max(b, -b)) * 0.001;
+    return a - b < eps && b - a < eps;
+}
+
+float almost_in_bounds(float a, float b, float c)
+{
+    float eps = (max(a, -a) + max(c, -c)) * 0.001;
+    if (a > c)
+        eps = -eps;
+    return b == median(a - eps, b, c + eps);
+}
+
+float power2of(float e)
+{
+    return pow(2, e);
+}
+
+float log2of(float x)
+{
+    // NOTE: generated code
+    if (x > 2048)
+        if (x > 131072)
+            if (x > 1048576)
+                if (x > 4194304)
+                    return 23;
+                else
+                    if (x > 2097152)
+                        return 22;
+                    else
+                        return 21;
+            else
+                if (x > 524288)
+                    return 20;
+                else
+                    if (x > 262144)
+                        return 19;
+                    else
+                        return 18;
+        else
+            if (x > 16384)
+                if (x > 65536)
+                    return 17;
+                else
+                    if (x > 32768)
+                        return 16;
+                    else
+                        return 15;
+            else
+                if (x > 8192)
+                    return 14;
+                else
+                    if (x > 4096)
+                        return 13;
+                    else
+                        return 12;
+    else
+        if (x > 32)
+            if (x > 256)
+                if (x > 1024)
+                    return 11;
+                else
+                    if (x > 512)
+                        return 10;
+                    else
+                        return 9;
+            else
+                if (x > 128)
+                    return 8;
+                else
+                    if (x > 64)
+                        return 7;
+                    else
+                        return 6;
+        else
+            if (x > 4)
+                if (x > 16)
+                    return 5;
+                else
+                    if (x > 8)
+                        return 4;
+                    else
+                        return 3;
+            else
+                if (x > 2)
+                    return 2;
+                else
+                    if (x > 1)
+                        return 1;
+                    else
+                        return 0;
+}
+
+
+#endif
diff --git a/qcsrc/lib/net.qh b/qcsrc/lib/net.qh
new file mode 100644 (file)
index 0000000..04faffc
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef NET_H
+#define NET_H
+
+#ifdef SVQC
+.int Version; // deprecated, use SendFlags
+.int SendFlags;
+.bool(entity to, int sendflags) SendEntity;
+.bool(entity this, entity to, int sendflags) SendEntity3;
+
+bool SendEntity_self(entity to, int sendflags) { return self.SendEntity3(self, to, sendflags); }
+
+void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
+{
+    if (!e.classname) e.classname = "net_linked";
+
+    if (!e.model || !self.modelindex) {
+        vector mi = e.mins;
+        vector ma = e.maxs;
+        _setmodel(e, "null");
+        setsize(e, mi, ma);
+    }
+
+    e.SendEntity = SendEntity_self;
+    e.SendEntity3 = sendfunc;
+    e.SendFlags = 0xFFFFFF;
+
+    if (!docull) e.effects |= EF_NODEPTHTEST;
+
+    if (dt) {
+        e.nextthink = time + dt;
+        e.think = SUB_Remove;
+    }
+}
+
+.void() uncustomizeentityforclient;
+.float uncustomizeentityforclient_set;
+
+void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
+{
+    e.customizeentityforclient = customizer;
+    e.uncustomizeentityforclient = uncustomizer;
+    e.uncustomizeentityforclient_set = !!uncustomizer;
+}
+
+void UncustomizeEntitiesRun()
+{
+    for (entity e = NULL; (e = findfloat(e, uncustomizeentityforclient_set, 1)); ) {
+        WITH(entity, self, e, e.uncustomizeentityforclient());
+    }
+}
+
+#endif
+
+#include "registry.qh"
+#include "sort.qh"
+
+.string netname;
+.int m_id;
+.void(entity this, bool isNew) m_read;
+
+#ifdef CSQC
+    #define Net_Accept() do { if (!this)    this = spawn(); } while (0)
+    #define Net_Reject() do { if (this)     remove(this);   } while (0)
+#else
+    #define WriteHeader(to, id) do { \
+        if (NET_##id##_istemp) WriteByte(to, SVC_TEMPENTITY); \
+        WriteByte(to, NET_##id.m_id); \
+    } while (0)
+#endif
+
+#ifdef CSQC
+    #define REGISTER_NET_LINKED(id, param) \
+        void Ent_Read##id(entity this, param) { this = self; } \
+        REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) { \
+            this.netname = #id; \
+            this.m_read = Ent_Read##id; \
+        } \
+        [[accumulate]] void Ent_Read##id(entity this, param)
+#else
+    #define REGISTER_NET_LINKED(id, param) \
+        const bool NET_##id##_istemp = false; \
+        REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) { \
+            this.netname = #id; \
+        }
+#endif
+
+REGISTRY(LinkedEntities, BIT(0))
+REGISTER_REGISTRY(RegisterLinkedEntities)
+REGISTRY_SORT(LinkedEntities, netname, 0)
+STATIC_INIT(RegisterLinkedEntities_renumber) {
+    for (int i = 0; i < LinkedEntities_COUNT; ++i) {
+        LinkedEntities[i].m_id = 100 + i;
+    }
+}
+
+#ifdef CSQC
+    #define REGISTER_NET_TEMP(id, param) \
+        void Net_Read##id(entity this, param); \
+        REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) { \
+            this.netname = #id; \
+            this.m_read = Net_Read##id; \
+        } \
+        void Net_Read##id(entity this, param)
+#else
+    #define REGISTER_NET_TEMP(id, param) \
+        const bool NET_##id##_istemp = true; \
+        REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) { \
+            this.netname = #id; \
+        }
+#endif
+
+REGISTRY(TempEntities, BIT(0))
+REGISTER_REGISTRY(RegisterTempEntities)
+REGISTRY_SORT(TempEntities, netname, 0)
+STATIC_INIT(RegisterTempEntities_renumber) {
+    for (int i = 0; i < TempEntities_COUNT; ++i) {
+        TempEntities[i].m_id = 115 + i;
+    }
+}
+
+#ifndef MENUQC
+#ifdef CSQC
+int ReadInt24_t()
+{
+    int v = ReadShort() << 8; // note: this is signed
+    v += ReadByte(); // note: this is unsigned
+    return v;
+}
+vector ReadInt48_t()
+{
+    vector v;
+    v.x = ReadInt24_t();
+    v.y = ReadInt24_t();
+    v.z = 0;
+    return v;
+}
+vector ReadInt72_t()
+{
+    vector v;
+    v.x = ReadInt24_t();
+    v.y = ReadInt24_t();
+    v.z = ReadInt24_t();
+    return v;
+}
+#else
+void WriteInt24_t(float dst, float val)
+{
+    float v;
+    WriteShort(dst, (v = floor(val >> 8)));
+    WriteByte(dst, val - (v << 8)); // 0..255
+}
+void WriteInt48_t(float dst, vector val)
+{
+    WriteInt24_t(dst, val.x);
+    WriteInt24_t(dst, val.y);
+}
+void WriteInt72_t(float dst, vector val)
+{
+    WriteInt24_t(dst, val.x);
+    WriteInt24_t(dst, val.y);
+    WriteInt24_t(dst, val.z);
+}
+#endif
+#endif
+
+#endif
diff --git a/qcsrc/lib/nil.qh b/qcsrc/lib/nil.qh
new file mode 100644 (file)
index 0000000..789b1f9
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef NIL_H
+#define NIL_H
+
+#if QCC_SUPPORT_NIL
+#define func_null nil
+#define string_null nil
+#else
+// the NULL function
+var void func_null(void);
+string string_null;
+#endif
+
+#endif
diff --git a/qcsrc/lib/oo.qh b/qcsrc/lib/oo.qh
new file mode 100644 (file)
index 0000000..fce18cb
--- /dev/null
@@ -0,0 +1,151 @@
+#ifndef OO_H
+#define OO_H
+
+#include "nil.qh"
+
+#ifdef MENUQC
+    #define NULL (null_entity)
+#else
+    #define NULL (world)
+#endif
+
+.string classname;
+/** Location entity was spawned from in source */
+.string sourceLocFile;
+.int sourceLocLine;
+entity _spawn();
+entity __spawn(string _classname, string _sourceFile, int _sourceLine) {
+    entity this = _spawn();
+    this.classname = _classname;
+    this.sourceLocFile = _sourceFile;
+    this.sourceLocLine = _sourceLine;
+    return this;
+}
+
+
+
+#define entityclass(...) EVAL(OVERLOAD(entityclass, __VA_ARGS__))
+#define entityclass_1(name) entityclass_2(name, Object)
+#ifndef QCC_SUPPORT_ENTITYCLASS
+    #define entityclass_2(name, base) typedef entity name
+    #define class(name)
+    #define new(class) __spawn(#class, __FILE__, __LINE__)
+#else
+    #define entityclass_2(name, base) entityclass name : base {}
+    #define class(name) [[class(name)]]
+    #define new(class) ((class) __spawn(#class, __FILE__, __LINE__))
+#endif
+
+// Classes have a `spawn##cname(entity)` constructor
+// The parameter is used across [[accumulate]] functions
+
+// Macros to hide this implementation detail:
+#ifdef GMQCC
+#define NEW(cname, ...) \
+    OVERLOAD(spawn##cname, new(cname), ##__VA_ARGS__)
+
+#define CONSTRUCT(cname, ...) \
+    OVERLOAD(spawn##cname, this, ##__VA_ARGS__)
+#else
+#define NEW_(cname, ...) \
+    OVERLOAD_(spawn##cname, __VA_ARGS__)
+#define NEW(cname, ...) \
+    NEW_(cname, new(cname), ##__VA_ARGS__)(new(cname), ##__VA_ARGS__)
+
+#define CONSTRUCT_(cname, ...) \
+    OVERLOAD_(spawn##cname, __VA_ARGS__)
+#define CONSTRUCT(cname, ...) \
+    CONSTRUCT_(cname, this, ##__VA_ARGS__)(this, ##__VA_ARGS__)
+#endif
+
+#define CONSTRUCTOR(cname, ...) \
+    cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__) { return = this; } \
+    [[accumulate]] cname OVERLOAD(spawn##cname, cname this, __VA_ARGS__)
+
+.string vtblname;
+.entity vtblbase;
+
+void RegisterClasses() { }
+STATIC_INIT(RegisterClasses) { RegisterClasses(); }
+
+#define VTBL(cname, base) \
+    INIT_STATIC(cname); \
+    entity cname##_vtbl; \
+    void cname##_vtbl_init() { \
+        cname e = new(vtbl); \
+        spawn##cname##_static(e); \
+        e.vtblname = #cname; \
+        /* Top level objects refer to themselves */ \
+        e.vtblbase = base##_vtbl ? base##_vtbl : e; \
+        cname##_vtbl = e; \
+    } \
+    ACCUMULATE_FUNCTION(RegisterClasses, cname##_vtbl_init)
+
+#define INIT_STATIC(cname) [[accumulate]] void spawn##cname##_static(cname this)
+#define INIT(cname) [[accumulate]] cname spawn##cname##_1(cname this)
+
+#define CLASS(cname, base)                  \
+    entityclass(cname, base);               \
+    class(cname) .bool instanceOf##cname;   \
+    VTBL(cname, base)                       \
+    INIT_STATIC(cname) {                    \
+        if (cname##_vtbl) {                 \
+            copyentity(cname##_vtbl, this); \
+            return;                         \
+        }                                   \
+        spawn##base##_static(this);         \
+        this.instanceOf##cname = true;      \
+    }                                       \
+    INIT(cname) {                           \
+        /* Only statically initialize the current class, it contains everything it inherits */ \
+        if (cname##_vtbl.vtblname == this.classname) { \
+            spawn##cname##_static(this);    \
+            this.classname = #cname;        \
+            this.vtblname = string_null;    \
+            this.vtblbase = cname##_vtbl;   \
+        }                                   \
+        spawn##base##_1(this);              \
+    }
+
+#define METHOD(cname, name, prototype)      \
+    class(cname) .prototype name;           \
+    prototype cname##_##name;               \
+    INIT_STATIC(cname) { this.name = cname##_##name; } \
+    prototype cname##_##name
+
+#define ATTRIB(cname, name, type, val)      \
+    class(cname) .type name;                \
+    INIT(cname) { this.name = val; }
+
+#define ATTRIBARRAY(cname, name, type, cnt) \
+    class(cname) .type name[cnt];
+
+#define ENDCLASS(cname) \
+    [[last]] INIT(cname) { return this; }
+
+#define SUPER(cname) (cname##_vtbl.vtblbase)
+#define super (this.vtblbase.vtblbase)
+
+#define spawn_static(this)
+#define spawn_1(this)
+#define _vtbl NULL
+CLASS(Object, );
+    METHOD(Object, describe, string(entity this)) {
+        string s = _("No description");
+        if (cvar("developer")) {
+            for (int i = 0, n = numentityfields(); i < n; ++i) {
+                string value = getentityfieldstring(i, this);
+                if (value != "") s = sprintf("%s\n%s = %s", s, entityfieldname(i), value);
+            }
+        }
+        return s;
+    }
+    METHOD(Object, display, void(entity this, void(string name, string icon) returns)) {
+        returns(sprintf("entity %i", this), "nopreview_map");
+    }
+ENDCLASS(Object)
+#undef spawn_static
+#undef spawn_1
+#undef _vtbl
+
+#endif
diff --git a/qcsrc/lib/player.qh b/qcsrc/lib/player.qh
new file mode 100644 (file)
index 0000000..f89a3b0
--- /dev/null
@@ -0,0 +1,34 @@
+#ifdef CSQC
+#ifndef PLAYER_H
+#define PLAYER_H
+
+#include "string.qh"
+
+#include "../client/main.qh"
+#include "../common/teams.qh"
+
+int GetPlayerColorForce(int i)
+{
+       if(!teamplay)
+               return 0;
+       else
+               return stof(getplayerkeyvalue(i, "colors")) & 15;
+}
+
+int GetPlayerColor(int i)
+{
+       if(!playerslots[i].gotscores) // unconnected
+               return NUM_SPECTATOR;
+       else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
+               return NUM_SPECTATOR;
+       else
+               return GetPlayerColorForce(i);
+}
+
+string GetPlayerName(int i)
+{
+       return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
+}
+
+#endif
+#endif
diff --git a/qcsrc/lib/prandom.qc b/qcsrc/lib/prandom.qc
deleted file mode 100644 (file)
index 4f58822..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "prandom.qh"
-
-// prandom - PREDICTABLE random number generator (not seeded yet)
-
-#ifdef USE_PRANDOM
-float prandom_seed;
-float prandom()
-{
-       float c;
-       c = crc16(false, strcat(ftos(prandom_seed), ftos(prandom_seed + M_PI)));
-       prandom_seed = c;
-
-#ifdef USE_PRANDOM_DEBUG
-       LOG_TRACE("RANDOM -> ", ftos(c), "\n");
-#endif
-
-       return c / 65536; // in [0..1[
-}
-
-vector prandomvec()
-{
-       vector v;
-
-       do
-       {
-               v.x = prandom();
-               v.y = prandom();
-               v.z = prandom();
-       }
-       while(v * v > 1);
-
-       return v;
-}
-
-void psrandom(float seed)
-{
-       prandom_seed = seed;
-#ifdef USE_PRANDOM_DEBUG
-       LOG_TRACE("SRANDOM ", ftos(seed), "\n");
-#endif
-}
-
-#ifdef USE_PRANDOM_DEBUG
-void prandom_debug()
-{
-       LOG_TRACE("Current random seed = ", ftos(prandom_seed), "\n");
-}
-#endif
-#endif
diff --git a/qcsrc/lib/prandom.qh b/qcsrc/lib/prandom.qh
deleted file mode 100644 (file)
index a7653a5..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef PRANDOM_H
-#define PRANDOM_H
-
-// prandom - PREDICTABLE random number generator
-
-#define USE_PRANDOM
-
-#ifdef USE_PRANDOM
-float prandom();
-vector prandomvec();
-
-void psrandom(float seed);
-#ifdef USE_PRANDOM_DEBUG
-void prandom_debug();
-#else
-#define prandom_debug()
-#endif
-#else
-#define prandom random
-#define prandomvec randomvec
-#define psrandom(x)
-#define prandom_debug()
-#endif
-#endif
diff --git a/qcsrc/lib/progname.qh b/qcsrc/lib/progname.qh
new file mode 100644 (file)
index 0000000..ed112a5
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef PROGNAME_H
+#define PROGNAME_H
+
+#if defined(MENUQC)
+    #define PROGNAME "MENUQC"
+#elif defined(SVQC)
+    #define PROGNAME "SVQC"
+#elif defined(CSQC)
+    #define PROGNAME "CSQC"
+#else
+    #error "Unable to detect PROGNAME"
+#endif
+
+#endif
diff --git a/qcsrc/lib/random.qc b/qcsrc/lib/random.qc
new file mode 100644 (file)
index 0000000..149323b
--- /dev/null
@@ -0,0 +1,81 @@
+#include "random.qh"
+
+void RandomSelection_Init()
+{
+    RandomSelection_totalweight = 0;
+    RandomSelection_chosen_ent = NULL;
+    RandomSelection_chosen_float = 0;
+    RandomSelection_chosen_string = string_null;
+    RandomSelection_best_priority = -1;
+}
+
+void RandomSelection_Add(entity e, float f, string s, float weight, float priority)
+{
+    if (priority > RandomSelection_best_priority)
+    {
+        RandomSelection_best_priority = priority;
+        RandomSelection_chosen_ent = e;
+        RandomSelection_chosen_float = f;
+        RandomSelection_chosen_string = s;
+        RandomSelection_totalweight = weight;
+    }
+    else if (priority == RandomSelection_best_priority)
+    {
+        RandomSelection_totalweight += weight;
+        if (random() * RandomSelection_totalweight <= weight)
+        {
+            RandomSelection_chosen_ent = e;
+            RandomSelection_chosen_float = f;
+            RandomSelection_chosen_string = s;
+        }
+    }
+}
+
+
+// prandom - PREDICTABLE random number generator (not seeded yet)
+
+#ifdef USE_PRANDOM
+float prandom_seed;
+float prandom()
+{
+    float c;
+    c = crc16(false, strcat(ftos(prandom_seed), ftos(prandom_seed + M_PI)));
+    prandom_seed = c;
+
+#ifdef USE_PRANDOM_DEBUG
+    LOG_TRACE("RANDOM -> ", ftos(c), "\n");
+#endif
+
+    return c / 65536; // in [0..1[
+}
+
+vector prandomvec()
+{
+    vector v;
+
+    do
+    {
+        v.x = prandom();
+        v.y = prandom();
+        v.z = prandom();
+    }
+    while(v * v > 1);
+
+    return v;
+}
+
+void psrandom(float seed)
+{
+    prandom_seed = seed;
+#ifdef USE_PRANDOM_DEBUG
+    LOG_TRACE("SRANDOM ", ftos(seed), "\n");
+#endif
+}
+
+#ifdef USE_PRANDOM_DEBUG
+void prandom_debug()
+{
+    LOG_TRACE("Current random seed = ", ftos(prandom_seed), "\n");
+}
+#endif
+#endif
diff --git a/qcsrc/lib/random.qh b/qcsrc/lib/random.qh
new file mode 100644 (file)
index 0000000..551cf21
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef RANDOM_H
+#define RANDOM_H
+
+float RandomSelection_totalweight;
+float RandomSelection_best_priority;
+entity RandomSelection_chosen_ent;
+float RandomSelection_chosen_float;
+string RandomSelection_chosen_string;
+
+void RandomSelection_Init();
+void RandomSelection_Add(entity e, float f, string s, float weight, float priority);
+
+// prandom - PREDICTABLE random number generator
+
+#define USE_PRANDOM
+
+#ifdef USE_PRANDOM
+float prandom();
+vector prandomvec();
+
+void psrandom(float seed);
+#ifdef USE_PRANDOM_DEBUG
+void prandom_debug();
+#else
+#define prandom_debug()
+#endif
+#else
+#define prandom random
+#define prandomvec randomvec
+#define psrandom(x)
+#define prandom_debug()
+#endif
+#endif
diff --git a/qcsrc/lib/registry.qh b/qcsrc/lib/registry.qh
new file mode 100644 (file)
index 0000000..688a711
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef REGISTRY_H
+#define REGISTRY_H
+
+#include "oo.qh"
+
+#define REGISTER_INIT(ns, id) [[accumulate]] void Register_##ns##_##id##_init(entity this)
+#define REGISTER_INIT_POST(ns, id) [[accumulate]] void Register_##ns##_##id##_init_post(entity this)
+
+#define REGISTRY(id, max) \
+    void Register##id() {} \
+    const int id##_MAX = max; \
+    noref entity id[id##_MAX], id##_first, id##_last; \
+    int id##_COUNT;
+
+/**
+ * Register a new entity with a global constructor.
+ * Must be followed by a semicolon or a function body with a `this` parameter.
+ * Wrapper macros may perform actions after user initialization like so:
+ *     #define REGISTER_FOO(id) \
+ *         REGISTER(RegisterFoos, FOO, FOOS, id, m_id, NEW(Foo)); \
+ *         REGISTER_INIT_POST(FOO, id) { \
+ *             print("Registering foo #", this.m_id + 1, "\n"); \
+ *         } \
+ *         REGISTER_INIT(FOO, id)
+ *
+ * Don't forget to forward declare `initfunc` and call `REGISTER_REGISTRY`:
+ *     void RegisterFoos();
+ *     REGISTER_REGISTRY(RegisterFoos)
+ *
+ * @param initfunc  The global constructor to accumulate into
+ * @param ns        Short for namespace, prefix for each global (ns##_##id)
+ * @param array     The array to add each entity to. Also requires `array##_first` and `array##_last` to be defined
+ * @param id        The identifier of the current entity being registered
+ * @param fld       The field to store the current count into
+ * @param inst      An expression to create a new instance, invoked for every registration
+ */
+#define REGISTER(initfunc, ns, array, id, fld, inst)            \
+    entity ns##_##id;                                           \
+    REGISTER_INIT(ns, id) { }                                   \
+    REGISTER_INIT_POST(ns, id) { }                              \
+    .entity enemy; /* internal next pointer */                  \
+    void Register_##ns##_##id() {                               \
+        if (array##_COUNT >= array##_MAX) LOG_FATALF("Registry capacity exceeded (%s)", ftos(array##_MAX)); \
+        entity this = inst;                                     \
+        ns##_##id = this;                                       \
+        this.fld = array##_COUNT;                               \
+        array[array##_COUNT++] = this;                          \
+        if (!array##_first)    array##_first = this;            \
+        if ( array##_last)     array##_last.enemy = this;       \
+        array##_last = this;                                    \
+        Register_##ns##_##id##_init(this);                      \
+        Register_##ns##_##id##_init_post(this);                 \
+    }                                                           \
+    ACCUMULATE_FUNCTION(initfunc, Register_##ns##_##id)         \
+    REGISTER_INIT(ns, id)
+
+#define REGISTRY_SORT(id, field, skip)                          \
+    void _REGISTRY_SWAP_##id(int i, int j, entity pass) {       \
+        i += skip; j += skip;                                   \
+        entity e = id[i];                                       \
+        id[i] = id[j];                                          \
+        id[j] = e;                                              \
+    }                                                           \
+    float _REGISTRY_CMP_##id(int i, int j, entity pass) {       \
+        i += skip; j += skip;                                   \
+        string a = id[i].field;                                 \
+        string b = id[j].field;                                 \
+        return strcasecmp(a, b);                                \
+    }                                                           \
+    STATIC_INIT(Registry_sort_##id) {                           \
+        heapsort(id##_COUNT - (skip), _REGISTRY_SWAP_##id, _REGISTRY_CMP_##id, NULL); \
+    }
+
+#endif
diff --git a/qcsrc/lib/replicate.qh b/qcsrc/lib/replicate.qh
new file mode 100644 (file)
index 0000000..6ff7713
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef REPLICATE_H
+#define REPLICATE_H
+#ifndef MENUQC
+
+#define REPLICATE(...) EVAL(OVERLOAD(REPLICATE, __VA_ARGS__))
+
+[[accumulate]] void ReplicateVars(entity this, string thisname, int i) { }
+
+#define REPLICATE_3(fld, type, var)         REPLICATE_4(fld, type, var, )
+#define REPLICATE_4(fld, type, var, func)   REPLICATE_##type(fld, var, func)
+#define REPLICATE_string(fld, var, func)    REPLICATE_7(fld, string, var, , \
+    { if (field) strunzone(field); field = strzone(it); }, \
+    { if (field) strunzone(field); field = string_null; }, \
+    { \
+        /* also initialize to the default value of func when requesting cvars */ \
+        string s = func(field); \
+        if (s != field) { \
+            strunzone(field); \
+            field = strzone(s); \
+        } \
+    })
+#define REPLICATE_float(fld, var, func)     REPLICATE_7(fld, float, var, func,  { field = stof(it); },          , )
+#define REPLICATE_bool(fld, var, func)      REPLICATE_7(fld, bool, var, func,   { field = boolean(stoi(it)); }, , )
+#define REPLICATE_int(fld, var, func)       REPLICATE_7(fld, int, var, func,    { field = stoi(it); },          , )
+
+#if defined(SVQC)
+    #define REPLICATE_7(fld, type, var, func, create, destroy, after) \
+        void ReplicateVars(entity this, string thisname, int i) { \
+            type field = this.fld; \
+            if (i < 0) { destroy } \
+            else { \
+                string it = func(argv(i + 1)); \
+                bool current = thisname == var; \
+                if (i > 0) { \
+                    if (current) { create } \
+                } else { \
+                    stuffcmd(this, "cl_cmd sendcvar " var "\n"); \
+                } \
+                if (current) { after } \
+            } \
+            this.fld = field; \
+        }
+#elif defined(CSQC)
+    // TODO
+    #define REPLICATE_7(fld, type, var, func, create, destroy, after)
+#endif
+
+#endif
+#endif
diff --git a/qcsrc/lib/sort.qh b/qcsrc/lib/sort.qh
new file mode 100644 (file)
index 0000000..0d3177a
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef SORT_H
+#define SORT_H
+
+/** is only ever called for i1 < i2 */
+typedef void(float i1, float i2, entity pass) swapfunc_t;
+/** <0 for <, ==0 for ==, >0 for > (like strcmp) */
+typedef float(float i1, float i2, entity pass) comparefunc_t;
+
+void heapsort(float n, swapfunc_t swap, comparefunc_t cmp, entity pass)
+{
+    int root, child;
+
+    // heapify
+    int start = floor((n - 2) / 2);
+    while (start >= 0) {
+        // siftdown(start, n - 1);
+        root = start;
+        while (root * 2 + 1 <= n - 1) {
+            child = root * 2 + 1;
+            if (child < n - 1 && cmp(child, child + 1, pass) < 0) {
+                child += 1;
+            }
+            if (cmp(root, child, pass) < 0) {
+                swap(root, child, pass);
+                root = child;
+            } else {
+                break;
+            }
+        }
+        // end of siftdown
+        --start;
+    }
+
+    // extract
+    int end = n - 1;
+    while (end > 0) {
+        swap(0, end, pass);
+        end -= 1;
+        // siftdown(0, end);
+        root = 0;
+        while (root * 2 + 1 <= end) {
+            child = root * 2 + 1;
+            if (child < end && cmp(child, child+1, pass) < 0) {
+                child += 1;
+            }
+            if (cmp(root, child, pass) < 0) {
+                swap(root, child, pass);
+                root = child;
+            } else {
+                break;
+            }
+        }
+        // end of siftdown
+    }
+}
+
+void shuffle(float n, swapfunc_t swap, entity pass)
+{
+    for (int i = 1; i < n; ++i) {
+        // swap i-th item at a random position from 0 to i
+        // proof for even distribution:
+        //   n = 1: obvious
+        //   n -> n+1:
+        //     item n+1 gets at any position with chance 1/(n+1)
+        //     all others will get their 1/n chance reduced by factor n/(n+1)
+        //     to be on place n+1, their chance will be 1/(n+1)
+        //     1/n * n/(n+1) = 1/(n+1)
+        //     q.e.d.
+        int j = floor(random() * (i + 1));
+        if (j != i)
+            swap(j, i, pass);
+    }
+}
+
+#endif
diff --git a/qcsrc/lib/spawnfunc.qh b/qcsrc/lib/spawnfunc.qh
new file mode 100644 (file)
index 0000000..1ab059c
--- /dev/null
@@ -0,0 +1,167 @@
+#ifndef SPAWNFUNC_H
+#define SPAWNFUNC_H
+
+/** If this global exists, only functions with spawnfunc_ name prefix qualify as spawn functions */
+noref bool require_spawnfunc_prefix;
+.bool spawnfunc_checked;
+
+// Optional type checking; increases compile time too much to be enabled by default
+#if 0
+bool entityfieldassignablefromeditor(int i) {
+    switch (entityfieldtype(i)) {
+        case FIELD_STRING:
+        case FIELD_FLOAT:
+        case FIELD_VECTOR:
+            return true;
+    }
+    return false;
+}
+
+#define _spawnfunc_checktypes(fld) if (fieldname == #fld) \
+    if (!entityfieldassignablefromeditor(i)) LOG_FATALF("Entity field '%s' cannot be whitelisted\n", fieldname);
+#else
+#define _spawnfunc_checktypes(fld)
+#endif
+#define _spawnfunc_check(fld) if (fieldname == #fld) \
+    continue;
+
+#define spawnfunc_1(id, whitelist) spawnfunc_2(id, whitelist)
+#define spawnfunc_2(id, whitelist) void spawnfunc_##id(entity this) { \
+    this = self; \
+    if (!this.spawnfunc_checked) { \
+        for (int i = 0, n = numentityfields(); i < n; ++i) { \
+            string value = getentityfieldstring(i, this); \
+            string fieldname = entityfieldname(i); \
+            whitelist(_spawnfunc_checktypes) \
+            if (value == "") continue; \
+            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); \
+        } \
+        this.spawnfunc_checked = true; \
+    } \
+} \
+[[accumulate]] void spawnfunc_##id(entity this)
+
+#define FIELD_SCALAR(fld, n) \
+    fld(n)
+#define FIELD_VEC(fld, n) \
+    fld(n) \
+    fld(n##_x) \
+    fld(n##_y) \
+    fld(n##_z)
+
+#define FIELDS_NONE(fld)
+#define FIELDS_ALL(fld) if (false)
+
+#define FIELDS_COMMON(fld) \
+    FIELD_SCALAR(fld, classname) \
+    FIELD_SCALAR(fld, spawnfunc_checked) \
+    /**/
+
+#define FIELDS_UNION(fld) \
+    FIELD_SCALAR(fld, Version) \
+    FIELD_SCALAR(fld, ammo_cells) \
+    FIELD_SCALAR(fld, ammo_nails) \
+    FIELD_SCALAR(fld, ammo_rockets) \
+    FIELD_SCALAR(fld, armorvalue) \
+    FIELD_SCALAR(fld, atten) \
+    FIELD_SCALAR(fld, bgmscriptdecay) \
+    FIELD_SCALAR(fld, bgmscriptsustain) \
+    FIELD_SCALAR(fld, bgmscript) \
+    FIELD_SCALAR(fld, button0) \
+    FIELD_SCALAR(fld, cnt) \
+    FIELD_SCALAR(fld, colormap) \
+    FIELD_SCALAR(fld, count) \
+    FIELD_SCALAR(fld, curvetarget) \
+    FIELD_SCALAR(fld, cvarfilter) \
+    FIELD_SCALAR(fld, debrisdamageforcescale) \
+    FIELD_SCALAR(fld, debrisfadetime) \
+    FIELD_SCALAR(fld, debristimejitter) \
+    FIELD_SCALAR(fld, debristime) \
+    FIELD_SCALAR(fld, debris) \
+    FIELD_SCALAR(fld, delay) \
+    FIELD_SCALAR(fld, dmgtime) \
+    FIELD_SCALAR(fld, dmg) \
+    FIELD_SCALAR(fld, dmg_edge) \
+    FIELD_SCALAR(fld, dmg_force) \
+    FIELD_SCALAR(fld, dmg_radius) \
+    FIELD_SCALAR(fld, effects) \
+    FIELD_SCALAR(fld, flags) \
+    FIELD_SCALAR(fld, fog) \
+    FIELD_SCALAR(fld, frags) \
+    FIELD_SCALAR(fld, frame) \
+    FIELD_SCALAR(fld, gametypefilter) \
+    FIELD_SCALAR(fld, geomtype) \
+    FIELD_SCALAR(fld, gravity) \
+    FIELD_SCALAR(fld, health) \
+    FIELD_SCALAR(fld, height) \
+    FIELD_SCALAR(fld, impulse) \
+    FIELD_SCALAR(fld, killtarget) \
+    FIELD_SCALAR(fld, lerpfrac) \
+    FIELD_SCALAR(fld, light_lev) \
+    FIELD_SCALAR(fld, lip) \
+    FIELD_SCALAR(fld, loddistance1) \
+    FIELD_SCALAR(fld, lodmodel1) \
+    FIELD_SCALAR(fld, ltime) \
+    FIELD_SCALAR(fld, mdl) \
+    FIELD_SCALAR(fld, message2) \
+    FIELD_SCALAR(fld, message) \
+    FIELD_SCALAR(fld, modelindex) \
+    FIELD_SCALAR(fld, modelscale) \
+    FIELD_SCALAR(fld, model) \
+    FIELD_SCALAR(fld, monster_moveflags) \
+    FIELD_SCALAR(fld, movetype) \
+    FIELD_SCALAR(fld, netname) \
+    FIELD_SCALAR(fld, nextthink) \
+    FIELD_SCALAR(fld, noalign) \
+    FIELD_SCALAR(fld, noise1) \
+    FIELD_SCALAR(fld, noise2) \
+    FIELD_SCALAR(fld, noise) \
+    FIELD_SCALAR(fld, phase) \
+    FIELD_SCALAR(fld, platmovetype) \
+    FIELD_SCALAR(fld, race_place) \
+    FIELD_SCALAR(fld, radius) \
+    FIELD_SCALAR(fld, respawntimejitter) \
+    FIELD_SCALAR(fld, respawntime) \
+    FIELD_SCALAR(fld, restriction) \
+    FIELD_SCALAR(fld, scale) \
+    FIELD_SCALAR(fld, skin) \
+    FIELD_SCALAR(fld, solid) \
+    FIELD_SCALAR(fld, sound1) \
+    FIELD_SCALAR(fld, sounds) \
+    FIELD_SCALAR(fld, spawnflags) \
+    FIELD_SCALAR(fld, speed) \
+    FIELD_SCALAR(fld, strength) \
+    FIELD_SCALAR(fld, target2) \
+    FIELD_SCALAR(fld, target3) \
+    FIELD_SCALAR(fld, target4) \
+    FIELD_SCALAR(fld, targetname) \
+    FIELD_SCALAR(fld, target) \
+    FIELD_SCALAR(fld, target_random) \
+    FIELD_SCALAR(fld, target_range) \
+    FIELD_SCALAR(fld, team) \
+    FIELD_SCALAR(fld, turret_scale_health) \
+    FIELD_SCALAR(fld, turret_scale_range) \
+    FIELD_SCALAR(fld, turret_scale_respawn) \
+    FIELD_SCALAR(fld, volume) \
+    FIELD_SCALAR(fld, wait) \
+    FIELD_SCALAR(fld, warpzone_fadeend) \
+    FIELD_SCALAR(fld, warpzone_fadestart) \
+    FIELD_SCALAR(fld, weapon) \
+    FIELD_VEC(fld, absmax) \
+    FIELD_VEC(fld, absmin) \
+    FIELD_VEC(fld, angles) \
+    FIELD_VEC(fld, avelocity) \
+    FIELD_VEC(fld, maxs) \
+    FIELD_VEC(fld, maxs) \
+    FIELD_VEC(fld, mins) \
+    FIELD_VEC(fld, modelscale_vec) \
+    FIELD_VEC(fld, origin) \
+    FIELD_VEC(fld, velocity) \
+    /**/
+
+#define spawnfunc(...) EVAL(OVERLOAD(spawnfunc, __VA_ARGS__, FIELDS_UNION))
+
+#endif
diff --git a/qcsrc/lib/static.qh b/qcsrc/lib/static.qh
new file mode 100644 (file)
index 0000000..d51a871
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef STATIC_H
+#define STATIC_H
+
+void __static_init_early() { }
+void __static_init() { CALL_ACCUMULATED_FUNCTION(__static_init_early); }
+#define static_init() CALL_ACCUMULATED_FUNCTION(__static_init)
+#define REGISTER_REGISTRY(func) ACCUMULATE_FUNCTION(__static_init_early, func)
+
+#define _STATIC_INIT(where, func) \
+    void _static_##func(); \
+    ACCUMULATE_FUNCTION(where, _static_##func) \
+    void _static_##func()
+
+#define STATIC_INIT(func)       _STATIC_INIT(__static_init_early,   func##_early)
+#define STATIC_INIT_LATE(func)  _STATIC_INIT(__static_init,         func)
+
+#endif
diff --git a/qcsrc/lib/string.qh b/qcsrc/lib/string.qh
new file mode 100644 (file)
index 0000000..ede2edf
--- /dev/null
@@ -0,0 +1,191 @@
+#ifndef STRING_H
+#define STRING_H
+
+#ifndef SVQC
+float stringwidth_colors(string s, vector theSize)
+{
+    return stringwidth(s, true, theSize);
+}
+
+float stringwidth_nocolors(string s, vector theSize)
+{
+    return stringwidth(s, false, theSize);
+}
+#endif
+
+// Timer (#5)
+//
+// TODO: macro
+string seconds_tostring(float sec)
+{
+    float minutes = floor(sec / 60);
+    sec -= minutes * 60;
+    return sprintf("%d:%02d", minutes, sec);
+}
+
+int ColorTranslateMode;
+
+string ColorTranslateRGB(string s)
+{
+    return (ColorTranslateMode & 1) ? strdecolorize(s) : s;
+}
+
+// color code replace, place inside of sprintf and parse the string... defaults described as constants
+// foreground/normal colors
+string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green  // primary priority (important names, etc)
+string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc)
+string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue   // tertiary priority or relatively inconsequential text
+string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red    // notice/attention grabbing texting
+// "kill" colors
+string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red    // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
+string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type
+string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue   // "good" or "beneficial" text (you fragging someone, etc)
+// background color
+string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text
+
+/** color code replace, place inside of sprintf and parse the string */
+string CCR(string input)
+{
+    // See the autocvar declarations in util.qh for default values
+
+    // foreground/normal colors
+    input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
+    input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
+    input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input);
+    input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input);
+
+    // "kill" colors
+    input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
+    input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input);
+    input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input);
+
+    // background colors
+    input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input);
+    input = strreplace("^N", "^7", input); // "none"-- reset to white...
+    return input;
+}
+
+bool startsWith(string haystack, string needle)
+{
+    return substring(haystack, 0, strlen(needle)) == needle;
+}
+
+bool startsWithNocase(string haystack, string needle)
+{
+    return strcasecmp(substring(haystack, 0, strlen(needle)), needle) == 0;
+}
+
+/** unzone the string, and return it as tempstring. Safe to be called on string_null */
+string fstrunzone(string s)
+{
+    if (!s) return s;
+    string sc = strcat(s, "");
+    strunzone(s);
+    return sc;
+}
+
+string car(string s)
+{
+    int o = strstrofs(s, " ", 0);
+    if (o < 0) return s;
+    return substring(s, 0, o);
+}
+
+string cdr(string s)
+{
+    int o = strstrofs(s, " ", 0);
+    if (o < 0) return string_null;
+    return substring(s, o + 1, strlen(s) - (o + 1));
+}
+
+string substring_range(string s, float b, float e)
+{
+    return substring(s, b, e - b);
+}
+
+string swapwords(string str, float i, float j)
+{
+    float n;
+    string s1, s2, s3, s4, s5;
+    float si, ei, sj, ej, s0, en;
+    n = tokenizebyseparator(str, " "); // must match g_maplist processing in ShuffleMaplist and "shuffle"
+    si = argv_start_index(i);
+    sj = argv_start_index(j);
+    ei = argv_end_index(i);
+    ej = argv_end_index(j);
+    s0 = argv_start_index(0);
+    en = argv_end_index(n-1);
+    s1 = substring_range(str, s0, si);
+    s2 = substring_range(str, si, ei);
+    s3 = substring_range(str, ei, sj);
+    s4 = substring_range(str, sj, ej);
+    s5 = substring_range(str, ej, en);
+    return strcat(s1, s4, s3, s2, s5);
+}
+
+string _shufflewords_str;
+void _shufflewords_swapfunc(float i, float j, entity pass)
+{
+    _shufflewords_str = swapwords(_shufflewords_str, i, j);
+}
+string shufflewords(string str)
+{
+    _shufflewords_str = str;
+    int n = tokenizebyseparator(str, " ");
+    shuffle(n, _shufflewords_swapfunc, NULL);
+    str = _shufflewords_str;
+    _shufflewords_str = string_null;
+    return str;
+}
+
+string unescape(string in)
+{
+    in = strzone(in); // but it doesn't seem to be necessary in my tests at least
+
+    int len = strlen(in);
+    string str = "";
+    for (int i = 0; i < len; ++i) {
+        string s = substring(in, i, 1);
+        if (s == "\\") {
+            s = substring(in, i + 1, 1);
+            if (s == "n")
+                str = strcat(str, "\n");
+            else if (s == "\\")
+                str = strcat(str, "\\");
+            else
+                str = strcat(str, substring(in, i, 2));
+            ++i;
+            continue;
+        }
+        str = strcat(str, s);
+    }
+    strunzone(in);
+    return str;
+}
+
+string strwords(string s, int w)
+{
+    int endpos = 0;
+    for (; w && endpos >= 0; --w) endpos = strstrofs(s, " ", endpos + 1);
+    if (endpos < 0) return s;
+    return substring(s, 0, endpos);
+}
+
+bool strhasword(string s, string w)
+{
+    return strstrofs(strcat(" ", s, " "), strcat(" ", w, " "), 0) >= 0;
+}
+
+int u8_strsize(string s)
+{
+    int l = 0;
+    for (int i = 0, c; (c = str2chr(s, i)) > 0; ++i, ++l)
+    {
+        l += (c >= 0x80);
+        l += (c >= 0x800);
+        l += (c >= 0x10000);
+    }
+    return l;
+}
+
+#endif
diff --git a/qcsrc/lib/struct.qh b/qcsrc/lib/struct.qh
new file mode 100644 (file)
index 0000000..507c417
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef STRUCT_H
+#define STRUCT_H
+
+#ifndef QCC_SUPPORT_STRUCT
+    #define _STRUCT_DECLARE(x, id, type, END) noref type x ##_## id ;
+    #define STRUCT_DECLARE(id, s) s(_STRUCT_DECLARE, id)
+
+    #define _STRUCT_PARAM_(x, id, type) type x ##_## id ,
+    #define _STRUCT_PARAM_END(x, id, type) type x ##_## id
+    #define _STRUCT_PARAM(x, id, type, isend) _STRUCT_PARAM_##isend(x, id, type)
+    #define STRUCT_PARAM(id, s) s(_STRUCT_PARAM, id)
+
+    #define _STRUCT_PASS_(x, id, type) x ##_## id ,
+    #define _STRUCT_PASS_END(x, id, type) x ##_## id
+    #define _STRUCT_PASS(x, id, type, END) _STRUCT_PASS_##END(x, id, type)
+    #define STRUCT_PASS(id, s) s(_STRUCT_PASS, id)
+
+    #define _STRUCT_STORE_DST(_, it) it
+    #define _STRUCT_STORE_SRC(it, _) it
+    #define _CONCAT3_(a, b, c) a ## b ## c
+    #define _CONCAT3(a, b, c) _CONCAT3_(a, b, c)
+    #define _STRUCT_STORE(x, id, type, END) _CONCAT3(_STRUCT_STORE_DST x, _, id) = _CONCAT3(_STRUCT_STORE_SRC x, _, id);
+    #define STRUCT_STORE(from, to, s) s(_STRUCT_STORE, (from, to))
+
+    #define STRUCT(id, ...)
+#else
+    #define STRUCT_DECLARE(id, type) type id;
+    #define STRUCT_PARAM(id, type) type id
+    #define STRUCT_PASS(id, type) id
+    #define STRUCT_STORE(from, to, s) to = from
+    #define _STRUCT_MEMBER(my, id, type, END) type id;
+    #define STRUCT(id, s) struct STRUCT_##id { s(_STRUCT_MEMBER, ) };
+#endif
+
+#endif
diff --git a/qcsrc/lib/vector.qh b/qcsrc/lib/vector.qh
new file mode 100644 (file)
index 0000000..b57e27a
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef VECTOR_H
+#define VECTOR_H
+
+const vector eX = '1 0 0';
+const vector eY = '0 1 0';
+const vector eZ = '0 0 1';
+
+vector randompos(vector m1, vector m2)
+{
+    vector v;
+    m2 = m2 - m1;
+    v_x = m2_x * random() + m1_x;
+    v_y = m2_y * random() + m1_y;
+    v_z = m2_z * random() + m1_z;
+    return     v;
+}
+
+float vlen2d(vector v)
+{
+    return sqrt(v.x * v.x + v.y * v.y);
+}
+
+float vlen_maxnorm2d(vector v)
+{
+    return max(v.x, v.y, -v.x, -v.y);
+}
+
+float vlen_minnorm2d(vector v)
+{
+    return min(max(v.x, -v.x), max(v.y, -v.y));
+}
+
+float dist_point_line(vector p, vector l0, vector ldir)
+{
+    ldir = normalize(ldir);
+
+    // remove the component in line direction
+    p = p - (p * ldir) * ldir;
+
+    // vlen of the remaining vector
+    return vlen(p);
+}
+
+/** requires that m2>m1 in all coordinates, and that m4>m3 */
+float boxesoverlap(vector m1, vector m2, vector m3, vector m4) {return m2_x >= m3_x && m1_x <= m4_x && m2_y >= m3_y && m1_y <= m4_y && m2_z >= m3_z && m1_z <= m4_z;}
+
+/** requires the same as boxesoverlap, but is a stronger condition */
+float boxinsidebox(vector smins, vector smaxs, vector bmins, vector bmaxs) {return smins.x >= bmins.x && smaxs.x <= bmaxs.x && smins.y >= bmins.y && smaxs.y <= bmaxs.y && smins.z >= bmins.z && smaxs.z <= bmaxs.z;}
+
+
+vector vec2(vector v)
+{
+    v.z = 0;
+    return v;
+}
+
+vector vec3(float x, float y, float z)
+{
+    vector v; v.x = x; v.y = y; v.z = z;
+    return v;
+}
+
+#ifndef MENUQC
+vector get_corner_position(entity box, int corner)
+{
+    switch (corner) {
+        case 1: return vec3(box.absmin.x, box.absmin.y, box.absmin.z);
+        case 2: return vec3(box.absmax.x, box.absmin.y, box.absmin.z);
+        case 3: return vec3(box.absmin.x, box.absmax.y, box.absmin.z);
+        case 4: return vec3(box.absmin.x, box.absmin.y, box.absmax.z);
+        case 5: return vec3(box.absmax.x, box.absmax.y, box.absmin.z);
+        case 6: return vec3(box.absmin.x, box.absmax.y, box.absmax.z);
+        case 7: return vec3(box.absmax.x, box.absmin.y, box.absmax.z);
+        case 8: return vec3(box.absmax.x, box.absmax.y, box.absmax.z);
+        default: return '0 0 0';
+    }
+}
+
+vector NearestPointOnBox(entity box, vector org)
+{
+    vector m1 = box.mins + box.origin;
+    vector m2 = box.maxs + box.origin;
+
+    vector ret;
+    ret.x = bound(m1.x, org.x, m2.x);
+    ret.y = bound(m1.y, org.y, m2.y);
+    ret.z = bound(m1.z, org.z, m2.z);
+    return ret;
+}
+#endif
+
+#endif
index d52ae4f719e07b5017216e0251a01a6749b5d9dd..5563b969d98bfb4751e29e661b2c97a6c5248c45 100644 (file)
@@ -4,6 +4,7 @@
 void setterDummy(entity, float);
 CLASS(Animation, Object)
        METHOD(Animation, configureAnimation, void(entity, entity, void(entity, float), float, float, float, float));
+       METHOD(Animation, update, void(entity, float, float, float));
        METHOD(Animation, setTimeStartEnd, void(entity, float, float));
        METHOD(Animation, setTimeStartDuration, void(entity, float, float));
        METHOD(Animation, setValueStartEnd, void(entity, float, float));
@@ -36,6 +37,12 @@ void Animation_configureAnimation(entity me, entity obj, void(entity, float) obj
        me.setValueStartEnd(me, animStartValue, animEndValue);
 }
 
+void Animation_update(entity me, float animDuration, float animStartValue, float animEndValue)
+{
+       me.setTimeStartDuration(me, time, animDuration);
+       me.setValueStartEnd(me, animStartValue, animEndValue);
+}
+
 void Animation_setTimeStartEnd(entity me, float s, float e)
 {
        me.startTime = s;
index 5085d3b4a94c3e9cc1f9aeff37174297bab92550..7c7dc70db94987fd0a9ec17da3cffec0f9333713 100644 (file)
@@ -2,14 +2,11 @@
 #ifndef GAMESETTINGS_H
 #define GAMESETTINGS_H
 
-void RegisterSettings();
-const int MAX_SETTINGS = 24;
-Lazy SETTINGS[MAX_SETTINGS], SETTINGS_first, SETTINGS_last;
-int SETTINGS_COUNT;
+REGISTRY(Settings, BIT(3))
+REGISTER_REGISTRY(RegisterSettings)
 #define REGISTER_SETTINGS(id, impl) \
     LAZY_NEW(id, impl) \
-    REGISTER(RegisterSettings, MENU, SETTINGS, SETTINGS_COUNT, id, m_id, NEW(Lazy, LAZY(id)))
-REGISTER_REGISTRY(RegisterSettings)
+    REGISTER(RegisterSettings, MENU, Settings, id, m_id, NEW(Lazy, LAZY(id)))
 
 #endif
 #endif
index 343bf1d93263403a97ea80bfa0160d8d8e442527..934e8cd3426e0579ff5066fea55349e2c3760dd8 100644 (file)
@@ -44,7 +44,7 @@ void Button_resizeNotify(entity me, vector relOrigin, vector relSize, vector abs
        if(me.srcMulti)
                me.keepspaceLeft = 0;
        else
-               me.keepspaceLeft = min(0.8, absSize.y / absSize.x);
+               me.keepspaceLeft = min(0.8, absSize.x == 0 ? 0 : (absSize.y / absSize.x));
        SUPER(Button).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 }
 void Button_configureButton(entity me, string txt, float sz, string gfx)
index e02642f69d54da9d134db6acb898c470c87a237f..ea170777eaf7245c26645fcd6c2a3dc8f5ed138e 100644 (file)
@@ -130,8 +130,8 @@ void Label_resizeNotify(entity me, vector relOrigin, vector relSize, vector absO
        SUPER(Label).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
        // absSize_y is height of label
-       me.realFontSize_y = me.fontSize / absSize.y;
-       me.realFontSize_x = me.fontSize / absSize.x;
+       me.realFontSize_y = absSize.y == 0 ? 0 : (me.fontSize / absSize.y);
+       me.realFontSize_x = absSize.x == 0 ? 0 : (me.fontSize / absSize.x);
        if(me.marginLeft)
                me.keepspaceLeft = me.marginLeft * me.realFontSize.x;
        if(me.marginRight)
index 9303eb27903dc6bb7273cd95d1e98661570bed1a..9210e14b384c90e262ece0be368b87e397cd1178 100644 (file)
@@ -416,6 +416,9 @@ void ListBox_updateControlTopBottom(entity me)
                }
        }
 }
+AUTOCVAR(menu_scroll_averaging_time, float, 0.16, "smooth scroll averaging time");
+// scroll faster while dragging the scrollbar
+AUTOCVAR(menu_scroll_averaging_time_pressed, float, 0.06, "smooth scroll averaging time when dragging the scrollbar");
 void ListBox_draw(entity me)
 {
        float i;
@@ -433,11 +436,11 @@ void ListBox_draw(entity me)
        }
        if(me.scrollPos != me.scrollPosTarget)
        {
-               float averaging_time = 0.16;
-               if(me.pressed == 1)
-                       averaging_time = 0.06; // scroll faster while dragging the scrollbar
+               float averaging_time = (me.pressed == 1)
+                       ? autocvar_menu_scroll_averaging_time_pressed
+                       : autocvar_menu_scroll_averaging_time;
                // this formula works with whatever framerate
-               float f = exp(-frametime / averaging_time);
+               float f = averaging_time ? exp(-frametime / averaging_time) : 0;
                me.scrollPos = me.scrollPos * f + me.scrollPosTarget * (1 - f);
                if(fabs(me.scrollPos - me.scrollPosTarget) < 0.001)
                        me.scrollPos = me.scrollPosTarget;
index 4654425431199bb1913b0c4ee54fefeac866f7db..3340e335cb9aebe22d7b305022a52074cd84f123 100644 (file)
@@ -15,6 +15,8 @@ CLASS(Slider, Label)
        METHOD(Slider, mouseRelease, float(entity, vector));
        METHOD(Slider, valueToText, string(entity, float));
        METHOD(Slider, toString, string(entity));
+       METHOD(Slider, setValue_allowAnim, void(entity, float, bool));
+       METHOD(Slider, setValue_noAnim, void(entity, float));
        METHOD(Slider, setValue, void(entity, float));
        METHOD(Slider, setSliderValue, void(entity, float));
        METHOD(Slider, showNotify, void(entity));
@@ -24,6 +26,7 @@ CLASS(Slider, Label)
        ATTRIB(Slider, value, float, 0)
        ATTRIB(Slider, animated, float, 1)
        ATTRIB(Slider, sliderValue, float, 0)
+       ATTRIB(Slider, sliderAnim, entity, world)
        ATTRIB(Slider, valueMin, float, 0)
        ATTRIB(Slider, valueMax, float, 0)
        ATTRIB(Slider, valueStep, float, 0)
@@ -48,16 +51,27 @@ ENDCLASS(Slider)
 #endif
 
 #ifdef IMPLEMENTATION
-void Slider_setValue(entity me, float val)
+void Slider_setValue_allowAnim(entity me, float val, bool allowAnim)
 {
-       if (me.animated) {
-               anim.removeObjAnim(anim, me);
-               makeHostedEasing(me, Slider_setSliderValue, easingQuadInOut, 1, me.sliderValue, val);
+       if(allowAnim && me.animated) {
+               float t = 0.5;
+               if(!me.sliderAnim)
+                       me.sliderAnim = makeHostedEasing(me, Slider_setSliderValue, easingQuadOut, t, me.sliderValue, val);
+               else
+                       me.sliderAnim.update(me.sliderAnim, t, me.sliderValue, val);
        } else {
                me.setSliderValue(me, val);
        }
        me.value = val;
 }
+void Slider_setValue_noAnim(entity me, float val)
+{
+       Slider_setValue_allowAnim(me, val, false);
+}
+void Slider_setValue(entity me, float val)
+{
+       Slider_setValue_allowAnim(me, val, true);
+}
 void Slider_setSliderValue(entity me, float val)
 {
        me.sliderValue = val;
@@ -69,7 +83,7 @@ string Slider_toString(entity me)
 void Slider_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
 {
        SUPER(Slider).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
-       me.controlWidth = absSize.y / absSize.x;
+       me.controlWidth = absSize.x == 0 ? 0 : (absSize.y / absSize.x);
 }
 string Slider_valueToText(entity me, float val)
 {
@@ -177,14 +191,10 @@ float Slider_keyUp(entity me, float key, float ascii, float shift)
 float Slider_mouseDrag(entity me, vector pos)
 {
        float hit;
-       float v, animed;
+       float v;
        if(me.disabled)
                return 0;
 
-       anim.removeObjAnim(anim, me);
-       animed = me.animated;
-       me.animated = false;
-
        if(me.pressed)
        {
                hit = 1;
@@ -194,17 +204,18 @@ float Slider_mouseDrag(entity me, vector pos)
                if(pos.y >= 1 + me.tolerance.y) hit = 0;
                if(hit)
                {
+                       // handle dragging
+                       me.pressed = 2;
+
                        v = median(0, (pos.x - me.pressOffset - 0.5 * me.controlWidth) / (1 - me.textSpace - me.controlWidth), 1) * (me.valueMax - me.valueMin) + me.valueMin;
                        if(me.valueStep)
                                v = floor(0.5 + v / me.valueStep) * me.valueStep;
-                       me.setValue(me, v);
+                       me.setValue_noAnim(me, v);
                }
                else
                        me.setValue(me, me.previousValue);
        }
 
-       me.animated = animed;
-
        return 1;
 }
 float Slider_mousePress(entity me, vector pos)
@@ -295,6 +306,14 @@ void Slider_draw(entity me)
                else
                        draw_Picture(eX * controlLeft, strcat(me.src, "_n"), eX * me.controlWidth + eY, me.color, 1);
        }
+
+       if(me.sliderAnim)
+       if(me.sliderAnim.isFinished(me.sliderAnim))
+       {
+               anim.removeObjAnim(anim, me);
+               me.sliderAnim = world;
+       }
+
        me.setText(me, me.valueToText(me, me.value));
        draw_alpha = save;
        SUPER(Slider).draw(me);
index 733b1d61255e155490021d7e12f6b53c61940acd..30b80c196d96884117def79c2c55496e65f34598 100644 (file)
@@ -6,6 +6,8 @@
 CLASS(TextSlider, Slider)
        METHOD(TextSlider, valueToText, string(entity, float));
        METHOD(TextSlider, valueToIdentifier, string(entity, float));
+       METHOD(TextSlider, setValueFromIdentifier_allowAnim, void(entity, string, bool));
+       METHOD(TextSlider, setValueFromIdentifier_noAnim, void(entity, string));
        METHOD(TextSlider, setValueFromIdentifier, void(entity, string));
        METHOD(TextSlider, getIdentifier, string(entity));
        METHOD(TextSlider, clearValues, void(entity));
@@ -35,16 +37,24 @@ string TextSlider_valueToText(entity me, int val)
                return _("Custom");
        return me.(valueStrings[val]);
 }
-void TextSlider_setValueFromIdentifier(entity me, string id)
+void TextSlider_setValueFromIdentifier_allowAnim(entity me, string id, bool allowAnim)
 {
        int i;
        for(i = 0; i < me.nValues; ++i)
                if(me.valueToIdentifier(me, i) == id)
                {
-                       SUPER(TextSlider).setValue( me, i );
+                       SUPER(TextSlider).setValue_allowAnim(me, i, allowAnim);
                        return;
                }
-       SUPER(TextSlider).setValue( me, -1 );
+       SUPER(TextSlider).setValue_allowAnim(me, -1, allowAnim);
+}
+void TextSlider_setValueFromIdentifier_noAnim(entity me, string id)
+{
+       TextSlider_setValueFromIdentifier_allowAnim(me, id, false);
+}
+void TextSlider_setValueFromIdentifier(entity me, string id)
+{
+       TextSlider_setValueFromIdentifier_allowAnim(me, id, true);
 }
 string TextSlider_getIdentifier(entity me)
 {
@@ -75,6 +85,6 @@ void TextSlider_insertValue(entity me, int pos, string theString, string theIden
 void TextSlider_configureTextSliderValues(entity me, string theDefault)
 {
        me.configureSliderValues(me, 0, 0, me.nValues - 1, 1, 1, 1);
-       me.setValueFromIdentifier(me, theDefault);
+       me.setValueFromIdentifier_noAnim(me, theDefault);
 }
 #endif
diff --git a/qcsrc/menu/progs.inc b/qcsrc/menu/progs.inc
new file mode 100644 (file)
index 0000000..ba7411b
--- /dev/null
@@ -0,0 +1,31 @@
+#include "../common/util-pre.qh"
+#include "../dpdefs/menudefs.qh"
+#include "../dpdefs/keycodes.qh"
+#include "../common/util-post.qh"
+
+#include "../lib/_all.inc"
+
+#include "oo/classes.qc"
+
+#include "draw.qc"
+#include "menu.qc"
+
+#include "command/all.qc"
+
+#include "xonotic/util.qc"
+
+#include "../common/campaign_file.qc"
+#include "../common/campaign_setup.qc"
+#include "../common/mapinfo.qc"
+#include "../common/playerstats.qc"
+#include "../common/util.qc"
+
+#include "../common/items/all.qc"
+#include "../common/monsters/all.qc"
+#include "../common/mutators/all.qc"
+#include "../common/vehicles/all.qc"
+#include "../common/weapons/all.qc"
+
+#if BUILD_MOD
+#include "../../mod/menu/progs.inc"
+#endif
index 92b10fa4cf374a8b5658b5aa51cc7cf38db073c9..1eb2b723d463454957f44af836200d27e2feeca7 100644 (file)
@@ -1,32 +1,2 @@
 ../../menu.dat
-
-../common/util-pre.qh
-../dpdefs/menudefs.qh
-../dpdefs/keycodes.qh
-../common/util-post.qh
-
-../lib/_all.inc
-
-oo/classes.qc
-
-draw.qc
-menu.qc
-
-command/all.qc
-
-xonotic/util.qc
-
-../common/campaign_file.qc
-../common/campaign_setup.qc
-../common/mapinfo.qc
-../common/playerstats.qc
-../common/util.qc
-
-../common/items/all.qc
-../common/monsters/all.qc
-../common/mutators/all.qc
-../common/vehicles/all.qc
-../common/weapons/all.qc
-
-
-../../mod/menu/progs.inc
+progs.inc
index 49cc571761885e394686651985b548d98af1f7c7..57ce0c80c312e73c7826110a6075dc8a6e9b4284 100644 (file)
@@ -12,12 +12,58 @@ CLASS(DataSource, Object)
      * returns `DataSource_false` if out of bounds
      * otherwise returns an entity or `DataSource_true`
      */
-    METHOD(DataSource, getEntry, entity(int i, void(string name, string icon) returns)) { return DataSource_false; }
+    METHOD(DataSource, getEntry, entity(entity this, int i, void(string name, string icon) returns)) { return DataSource_false; }
     /** return the index of the first match for `find`. optional */
-    METHOD(DataSource, indexOf, int(string find)) { return -1; }
+    METHOD(DataSource, indexOf, int(entity this, string find)) { return -1; }
     /** reload all entries matching `filter` returning how many matches were found */
-    METHOD(DataSource, reload, int(string filter)) { return 0; }
+    METHOD(DataSource, reload, int(entity this, string filter)) { return 0; }
     /** cleanup on shutdown. optional */
-    METHOD(DataSource, destroy, void(entity)) { }
+    METHOD(DataSource, destroy, void(entity this)) { }
 ENDCLASS(DataSource)
+
+
+CLASS(StringSource, DataSource)
+    ATTRIB(StringSource, StringSource_str, string, string_null)
+    ATTRIB(StringSource, StringSource_sep, string, string_null)
+    CONSTRUCTOR(StringSource, string str, string sep)
+    {
+        CONSTRUCT(StringSource);
+        this.StringSource_str = str;
+        this.StringSource_sep = sep;
+    }
+    METHOD(StringSource, getEntry, entity(entity this, int i, void(string name, string icon) returns))
+    {
+        int n = tokenizebyseparator(this.StringSource_str, this.StringSource_sep);
+        if (i < 0 || i >= n) return DataSource_false;
+        string s = argv(i);
+        if (returns) returns(s, string_null);
+        return DataSource_true;
+    }
+    METHOD(StringSource, reload, int(entity this, string filter))
+    {
+        return tokenizebyseparator(this.StringSource_str, this.StringSource_sep);
+    }
+ENDCLASS(StringSource)
+
+CLASS(CvarStringSource, StringSource)
+    ATTRIB(CvarStringSource, CvarStringSource_cvar, string, string_null)
+    CONSTRUCTOR(CvarStringSource, string cv, string sep)
+    {
+        CONSTRUCT(CvarStringSource);
+        this.CvarStringSource_cvar = cv;
+        this.StringSource_sep = sep;
+    }
+    METHOD(CvarStringSource, getEntry, entity(entity this, int i, void(string name, string icon) returns))
+    {
+        string s = this.CvarStringSource_cvar;
+        this.StringSource_str = s ? cvar_string(s) : string_null;
+        return super.getEntry(this, i, returns);
+    }
+    METHOD(CvarStringSource, reload, int(entity this, string filter))
+    {
+        string s = this.CvarStringSource_cvar;
+        this.StringSource_str = s ? cvar_string(s) : string_null;
+        return super.reload(this, filter);
+    }
+ENDCLASS(CvarStringSource)
 #endif
index 6b9556507441e7a55cce2f05ab69f744a2bc9749..9969a7b212c6f22e652c5a9e60e6bed84e645733 100644 (file)
@@ -27,8 +27,8 @@ void XonoticMonsterToolsDialog_fill(entity me)
                me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "wyvern", _("Wyvern")));
        me.TR(me);
                me.TDempty(me, 0.1);
-               me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Spawn"), '0 0 0', "cmd mobspawn $menu_monsters_edit_spawn $menu_monsters_edit_movetarget", 0));
-               me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Remove"), '0 0 0', "cmd mobkill", 0));
+               me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Spawn"), '0 0 0', "spawnmob $menu_monsters_edit_spawn $menu_monsters_edit_movetarget", 0));
+               me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Remove"), '0 0 0', "killmob", 0));
        me.TR(me);
                me.TD(me, 1, 0.5, e = makeXonoticCommandButton(_("Move target:"), '0 0 0', "editmob movetarget $menu_monsters_edit_movetarget", 0));
                me.TD(me, 1, 0.5, e = makeXonoticRadioButton(2, "menu_monsters_edit_movetarget", "1", _("Follow")));
index 0329f1ee7657837c1797a882e0cb11fa09c4e5cb..c751671a46960d8f1ee71311957f345591a2cc08 100644 (file)
@@ -64,6 +64,8 @@ string WeaponArenaString()
        return weaponarenastring;
 }
 
+AUTOCVAR(g_grappling_hook, bool, _("let players spawn with the grappling hook which allows them to pull themselves up"));
+
 string XonoticMutatorsDialog_toString(entity me)
 {
        string s;
@@ -88,7 +90,7 @@ string XonoticMutatorsDialog_toString(entity me)
                s = strcat(s, ", ", _("Low gravity"));
        if(cvar("g_cloaked"))
                s = strcat(s, ", ", _("Cloaked"));
-       if(cvar("g_grappling_hook"))
+       if(autocvar_g_grappling_hook)
                s = strcat(s, ", ", _("Hook"));
        if(cvar("g_midair"))
                s = strcat(s, ", ", _("Midair"));
index cde5d40a6efd2c9287208eb6c74505667aeb129b..3c1503b29774472af5b256b37930c7736c454d81 100644 (file)
@@ -5,21 +5,21 @@
 
 #include "datasource.qc"
 CLASS(SettingSource, DataSource)
-    METHOD(SettingSource, getEntry, entity(int i, void(string name, string icon) returns))
+    METHOD(SettingSource, getEntry, entity(entity this, int i, void(string name, string icon) returns))
     {
-        Lazy l = SETTINGS[i];
+        Lazy l = Settings[i];
         entity it = l.m_get();
         if (returns) returns(it.title, string_null);
         return it;
     }
-    METHOD(SettingSource, getEntryTooltip, entity(int i, void(string theTooltip) returns))
+    METHOD(SettingSource, getEntryTooltip, entity(entity this, int i, void(string theTooltip) returns))
     {
-        Lazy l = SETTINGS[i];
+        Lazy l = Settings[i];
         entity it = l.m_get();
         if (returns) returns(it.tooltip);
         return it;
     }
-    METHOD(SettingSource, reload, int(string filter)) { return SETTINGS_COUNT; }
+    METHOD(SettingSource, reload, int(entity this, string filter)) { return Settings_COUNT; }
 ENDCLASS(SettingSource)
 
 #include "listbox.qc"
@@ -53,7 +53,7 @@ CLASS(XonoticRegisteredSettingsList, XonoticListBox)
        METHOD(XonoticRegisteredSettingsList, drawListBoxItem, void(entity this, int i, vector absSize, bool isSelected, bool isFocused))
        {
                if (!this.source) return;
-               if (!this.source.getEntry(i, XonoticRegisteredSettingsList_getNameIcon_cb)) return;
+               if (!this.source.getEntry(this.source, i, XonoticRegisteredSettingsList_getNameIcon_cb)) return;
                string name = XonoticRegisteredSettingsList_cb_name;
                if (isSelected) {
                        draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
@@ -72,7 +72,7 @@ CLASS(XonoticRegisteredSettingsList, XonoticListBox)
                        clearTooltip(this);
                        return;
                }
-               if (!this.source.getEntryTooltip(this.focusedItem, XonoticRegisteredSettingsList_getTooltip_cb))
+               if (!this.source.getEntryTooltip(this, this.focusedItem, XonoticRegisteredSettingsList_getTooltip_cb))
                {
                        clearTooltip(this);
                        return;
@@ -90,7 +90,7 @@ CLASS(XonoticRegisteredSettingsList, XonoticListBox)
                        this.nItems = 0;
                        return;
                }
-               this.nItems = this.source.reload(this.stringFilter);
+               this.nItems = this.source.reload(this.source, this.stringFilter);
        }
        METHOD(XonoticRegisteredSettingsList, resizeNotify, void(entity this, vector relOrigin, vector relSize, vector absOrigin, vector absSize))
        {
@@ -119,14 +119,16 @@ CLASS(XonoticGameSettingsTab, XonoticTab)
        ATTRIB(XonoticGameSettingsTab, intendedWidth, float, 0.9)
     ATTRIB(XonoticGameSettingsTab, rows, float, 15.5)
     ATTRIB(XonoticGameSettingsTab, columns, float, 6.5)
-    ATTRIB(XonoticGameSettingsTab, topicList, entity, NEW(XonoticRegisteredSettingsList, NEW(SettingSource)))
+    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)
     METHOD(XonoticGameSettingsTab, topicChangeNotify, void(entity, entity this))
        {
                entity c = this.currentPanel;
                entity removing = this.currentItem;
-               entity adding = this.topicList.source.getEntry(this.topicList.selectedItem, func_null);
+               DataSource data = this.topicList.source;
+               entity adding = data.getEntry(data, this.topicList.selectedItem, func_null);
                if (removing == adding) return;
                if (removing) {
                        this.currentItem = NULL;
index 0bb27d12ad6fa9cf4e1434b5763ada34ca70559f..a64c77b0fff568b4776fe9d4d9ed725ff7e02ccc 100644 (file)
@@ -141,7 +141,7 @@ void Xonotic_KeyBinds_Read()
        KEYBIND_DEF(""                                      , _("User defined"));
 
        for(i = 1; i <= 32; ++i)
-               KEYBIND_DEF(strcat("+userbind ", itos(i)), strcat("$$", _("userbind"), itos(i)));
+               KEYBIND_DEF(strcat("+userbind ", itos(i)), strcat("$userbind", itos(i)));
 
        #undef KEYBIND_DEF
 }
index 27282207795580b122182c1b38c5c47546594d7f..ceeae22ea060f06fd39b071852cfa2cd4263ff5c 100644 (file)
@@ -41,6 +41,7 @@ entity makeXonoticRadioButton(float theGroup, string theCvar, string theValue, s
 void XonoticRadioButton_configureXonoticRadioButton(entity me, float theGroup, string theCvar, string theValue, string theText, string theTooltip)
 {
        me.cvarName = (theCvar) ? theCvar : string_null;
+       me.cvarValue = theValue;
        me.loadCvars(me);
        setZonedTooltip(me, theTooltip, theCvar);
        me.configureRadioButton(me, theText, me.fontSize, me.image, theGroup, 0);
index ca65c66218b12efe4561f37baa377e85e284edf4..7ecd7a9d0a4e6a03ead4ee4e262ddaea22136813 100644 (file)
@@ -71,7 +71,7 @@ void XonoticSlider_loadCvars(entity me)
        if (!me.cvarName)
                return;
 
-       me.setValue( me, cvar(me.cvarName) );
+       me.setValue_noAnim(me, cvar(me.cvarName));
 }
 void XonoticSlider_saveCvars(entity me)
 {
index c840fb07ef7b3e47a5bb65a20097351dbae5a71f..e577cba66407ce84db002f16a1d7c860e7a7a365 100644 (file)
@@ -62,9 +62,9 @@ void XonoticDecibelsSlider_loadCvars(entity me)
 
        // snapping
        if(v > fromDecibelOfSquare(me.valueMax - 0.5 * me.valueStep, me.valueMin))
-               Slider_setValue(me, me.valueMax);
+               Slider_setValue_noAnim(me, me.valueMax);
        else
-               Slider_setValue(me, me.valueStep * floor(0.5 + toDecibelOfSquare(v, me.valueMin) / me.valueStep) );
+               Slider_setValue_noAnim(me, me.valueStep * floor(0.5 + toDecibelOfSquare(v, me.valueMin) / me.valueStep));
 }
 void XonoticDecibelsSlider_saveCvars(entity me)
 {
index 0b2179d36eeede5497291f0afe6b8de486aed76e..1a7ee2c4a59101b65826e0ef2f1dce73485bc9d5 100644 (file)
@@ -32,7 +32,7 @@ void XonoticParticlesSlider_configureXonoticParticlesSlider(entity me)
 }
 void XonoticParticlesSlider_loadCvars(entity me)
 {
-       me.setValueFromIdentifier(me, sprintf("%s %s %s",
+       me.setValueFromIdentifier_noAnim(me, sprintf("%s %s %s",
                cvar_string("cl_particles_quality"),
                cvar_string("r_drawparticles_drawdistance"),
                cvar_string("cl_damageeffect")
index 8b91ecb1f3ad6180e7a2f84d9fede431a0e0d73c..c6d95b4304315381f3e3cbc973a572998079d244 100644 (file)
@@ -212,7 +212,7 @@ void XonoticResolutionSlider_loadResolutions(entity me, float fullscreen)
 }
 void XonoticResolutionSlider_loadCvars(entity me)
 {
-       me.setValueFromIdentifier(me, strcat(cvar_string("_menu_vid_width"), " ", cvar_string("_menu_vid_height"), " ", cvar_string("_menu_vid_pixelheight")));
+       me.setValueFromIdentifier_noAnim(me, strcat(cvar_string("_menu_vid_width"), " ", cvar_string("_menu_vid_height"), " ", cvar_string("_menu_vid_pixelheight")));
 }
 void XonoticResolutionSlider_saveCvars(entity me)
 {
index 5533a2361bf8bd2efc94cc42c4ad939f381b6ebe..ecf850f404f083b3548ed59138d7e34973c9ce80 100644 (file)
@@ -28,7 +28,7 @@ void XonoticScoreboardFadeTimeSlider_configureXonoticScoreboardFadeTimeSlider(en
 }
 void XonoticScoreboardFadeTimeSlider_loadCvars(entity me)
 {
-       me.setValueFromIdentifier(me, sprintf("%s %s",
+       me.setValueFromIdentifier_noAnim(me, sprintf("%s %s",
                cvar_string("scoreboard_fadeinspeed"),
                cvar_string("scoreboard_fadeoutspeed")
        ));
index 597772e340019f4d58077158dc710b619e3b5944..8c4682ee0ffbf9a25d5692bdd18ed1c267014777 100644 (file)
@@ -65,7 +65,7 @@ void XonoticTextSlider_loadCvars(entity me)
        float i;
        for(i = 1; i < n; ++i)
                s = strcat(s, " ", cvar_string(argv(i)));
-       me.setValueFromIdentifier(me, s);
+       me.setValueFromIdentifier_noAnim(me, s);
        if(me.value < 0 && n > 1)
        {
                // if it failed: check if all cvars have the same value
@@ -74,7 +74,7 @@ void XonoticTextSlider_loadCvars(entity me)
                        if(cvar_string(argv(i)) != cvar_string(argv(i-1)))
                                break;
                if(i >= n)
-                       me.setValueFromIdentifier(me, cvar_string(argv(0)));
+                       me.setValueFromIdentifier_noAnim(me, cvar_string(argv(0)));
        }
 }
 void XonoticTextSlider_saveCvars(entity me)
index 1b216a14bcb61499fb901d837c5bc920d1b593bc..f4faea62b92a3623530aa684f63a54fb58445590 100644 (file)
@@ -671,8 +671,8 @@ float updateCompression()
        GAMETYPE(MAPINFO_TYPE_ASSAULT) \
        if (cvar("developer")) GAMETYPE(MAPINFO_TYPE_RACE) \
        GAMETYPE(MAPINFO_TYPE_CTS) \
-       //GAMETYPE(MAPINFO_TYPE_INVASION) \
-       /* nothing */
+       /* GAMETYPE(MAPINFO_TYPE_INVASION) */ \
+       /**/
 
 int GameType_GetID(int cnt)
 {
index f874b616b25a8045311c028bf9abde739d1f84e7..1ec7115ef27c503b55cd6c723a2a14e97a77afba 100644 (file)
@@ -4,7 +4,7 @@ string vtos(vector v) = #27;
 void error(string e) = #10;
 float test();
 
-void spawnfunc_worldspawn()
+spawnfunc(worldspawn)
 {
        float r;
        LOG_TRACE("TESTCASE: START\n");
index a331362151dbd72144862b807241d731babf0584..3e99cabeb85d6e1bc37b1b44cc7785fb8167cfde 100644 (file)
@@ -9,4 +9,7 @@
 #include "../dpdefs/progsdefs.qh"
 #include "../dpdefs/dpextensions.qh"
 
+#include "../common/models/all.qh"
+#include "../common/sounds/all.qh"
+
 #endif
index 6647633ff9c9eec920d6f24d8ea73e9f55ca2e80..32742d82d9555e41330fa559acbee64314a1b7f3 100644 (file)
@@ -63,7 +63,7 @@ float movement_oddity(vector m0, vector m1)
 }
 
 void anticheat_physics()
-{
+{SELFPARAM();
        float f;
 
        // div0_evade -> SPECTATORS
@@ -150,13 +150,13 @@ void anticheat_physics()
 }
 
 void anticheat_spectatecopy(entity spectatee)
-{
+{SELFPARAM();
        // div0_evade -> SPECTATORS
        self.angles = spectatee.anticheat_div0_evade_v_angle;
 }
 
 void anticheat_prethink()
-{
+{SELFPARAM();
        // div0_evade -> SPECTATORS
        self.anticheat_div0_evade_offset = 0;
 }
@@ -173,7 +173,7 @@ string anticheat_display(float f, float tmin, float mi, float ma)
 }
 
 void anticheat_report()
-{
+{SELFPARAM();
        if(!autocvar_sv_eventlog)
                return;
        // TODO(divVerent): Use xonstat to acquire good thresholds.
@@ -198,7 +198,7 @@ void anticheat_report()
 }
 
 float anticheat_getvalue(string id)
-{
+{SELFPARAM();
        switch(id) {
                case "_time": return servertime - self.anticheat_jointime;
                case "speedhack": return MEAN_EVALUATE(anticheat_speedhack);
@@ -228,22 +228,22 @@ void anticheat_startframe()
 }
 
 void anticheat_fixangle()
-{
+{SELFPARAM();
        self.anticheat_fixangle_endtime = servertime + ANTILAG_LATENCY(self) + 0.2;
 }
 
 void anticheat_endframe()
-{
-       entity oldself = self;
-       FOR_EACH_CLIENT(self)
-               if (self.fixangle)
-                       anticheat_fixangle();
-       self = oldself;
+{SELFPARAM();
+       entity e;
+       FOR_EACH_CLIENT(e)
+               if (e.fixangle) {
+                       WITH(entity, self, e, anticheat_fixangle());
+               }
        anticheat_div0_evade_evasion_delta += frametime * (0.5 + random());
 }
 
 void anticheat_init()
-{
+{SELFPARAM();
        self.anticheat_speedhack_offset = 0;
        self.anticheat_jointime = servertime;
 }
index fcf209faca6ddbdb2e7e7ea44c4ee407dea503af..affd9437ed279b83675d7fdd3d9ab9b12d3cda6a 100644 (file)
@@ -335,8 +335,6 @@ float autocvar_g_freezetag_warmup;
 bool autocvar_g_full_getstatus_responses;
 bool autocvar_g_fullbrightitems;
 bool autocvar_g_fullbrightplayers;
-#define autocvar_g_grappling_hook cvar("g_grappling_hook")
-int autocvar_g_grappling_hook_tarzan;
 int autocvar_g_balance_grapplehook_pull_frozen;
 float autocvar_g_balance_grapplehook_nade_time;
 bool autocvar_g_balance_grapplehook_gravity;
@@ -416,22 +414,8 @@ float autocvar_g_multijump_speed;
 float autocvar_g_multijump_maxspeed;
 float autocvar_g_multijump_dodging = 1;
 string autocvar_g_mutatormsg;
-float autocvar_g_nexball_basketball_bouncefactor;
-float autocvar_g_nexball_basketball_bouncestop;
-float autocvar_g_nexball_basketball_carrier_highspeed;
-bool autocvar_g_nexball_basketball_meter;
-float autocvar_g_nexball_basketball_meter_maxpower;
-float autocvar_g_nexball_basketball_meter_minpower;
-float autocvar_g_nexball_delay_collect;
-float autocvar_g_nexball_delay_goal;
-float autocvar_g_nexball_delay_start;
-float autocvar_g_nexball_football_bouncefactor;
-float autocvar_g_nexball_football_bouncestop;
 int autocvar_g_nexball_goalleadlimit;
 #define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
-bool autocvar_g_nexball_radar_showallplayers;
-bool autocvar_g_nexball_sound_bounce;
-int autocvar_g_nexball_trail_color;
 //float autocvar_g_nick_flood_penalty;
 int autocvar_g_nick_flood_penalty_red;
 int autocvar_g_nick_flood_penalty_yellow;
@@ -702,6 +686,7 @@ int autocvar_g_monsters_max_perplayer;
 float autocvar_g_monsters_damageforcescale = 0.8;
 float autocvar_g_monsters_target_range;
 bool autocvar_g_monsters_target_infront;
+float autocvar_g_monsters_target_infront_range = 0.3;
 float autocvar_g_monsters_attack_range;
 int autocvar_g_monsters_score_kill;
 int autocvar_g_monsters_score_spawned;
@@ -738,6 +723,7 @@ float autocvar_g_random_gravity_positive;
 float autocvar_g_random_gravity_negative;
 float autocvar_g_random_gravity_delay;
 bool autocvar_g_nades;
+bool autocvar_g_nades_override_dropweapon = true;
 vector autocvar_g_nades_throw_offset;
 bool autocvar_g_nades_spawn;
 int autocvar_g_nades_spawn_count;
index 58ddfc0364f784e7ef60dd76055dd286ed9c6d15..4f750cdb4d48a5cc13d152c1decfd9b0d04a0257 100644 (file)
@@ -40,7 +40,7 @@ float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, f
                tracetossfaketarget = spawn();
        tracetossfaketarget.solid = savesolid;
        tracetossfaketarget.movetype = targ.movetype;
-       setmodel(tracetossfaketarget, targ.model); // no low precision
+       _setmodel(tracetossfaketarget, targ.model); // no low precision
        tracetossfaketarget.model = targ.model;
        tracetossfaketarget.modelindex = targ.modelindex;
        setsize(tracetossfaketarget, targ.mins, targ.maxs);
@@ -86,7 +86,7 @@ float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, f
 }
 
 void lag_update()
-{
+{SELFPARAM();
        if (self.lag1_time) if (time > self.lag1_time) {self.lag_func(self.lag1_time, self.lag1_float1, self.lag1_float2, self.lag1_entity1, self.lag1_vec1, self.lag1_vec2, self.lag1_vec3, self.lag1_vec4);self.lag1_time = 0;}
        if (self.lag2_time) if (time > self.lag2_time) {self.lag_func(self.lag2_time, self.lag2_float1, self.lag2_float2, self.lag2_entity1, self.lag2_vec1, self.lag2_vec2, self.lag2_vec3, self.lag2_vec4);self.lag2_time = 0;}
        if (self.lag3_time) if (time > self.lag3_time) {self.lag_func(self.lag3_time, self.lag3_float1, self.lag3_float2, self.lag3_entity1, self.lag3_vec1, self.lag3_vec2, self.lag3_vec3, self.lag3_vec4);self.lag3_time = 0;}
@@ -95,7 +95,7 @@ void lag_update()
 }
 
 float lag_additem(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
-{
+{SELFPARAM();
        if (self.lag1_time == 0) {self.lag1_time = t;self.lag1_float1 = f1;self.lag1_float2 = f2;self.lag1_entity1 = e1;self.lag1_vec1 = v1;self.lag1_vec2 = v2;self.lag1_vec3 = v3;self.lag1_vec4 = v4;return true;}
        if (self.lag2_time == 0) {self.lag2_time = t;self.lag2_float1 = f1;self.lag2_float2 = f2;self.lag2_entity1 = e1;self.lag2_vec1 = v1;self.lag2_vec2 = v2;self.lag2_vec3 = v3;self.lag2_vec4 = v4;return true;}
        if (self.lag3_time == 0) {self.lag3_time = t;self.lag3_float1 = f1;self.lag3_float2 = f2;self.lag3_entity1 = e1;self.lag3_vec1 = v1;self.lag3_vec2 = v2;self.lag3_vec3 = v3;self.lag3_vec4 = v4;return true;}
@@ -106,7 +106,7 @@ float lag_additem(float t, float f1, float f2, entity e1, vector v1, vector v2,
 }
 
 float bot_shouldattack(entity e)
-{
+{SELFPARAM();
        if (e.team == self.team)
        {
                if (e == self)
@@ -144,7 +144,7 @@ float bot_shouldattack(entity e)
 }
 
 void bot_lagfunc(float t, float f1, float f2, entity e1, vector v1, vector v2, vector v3, vector v4)
-{
+{SELFPARAM();
        if(self.flags & FL_INWATER)
        {
                self.bot_aimtarg = world;
@@ -167,7 +167,7 @@ void bot_lagfunc(float t, float f1, float f2, entity e1, vector v1, vector v2, v
 }
 
 float bot_aimdir(vector v, float maxfiredeviation)
-{
+{SELFPARAM();
        float dist, delta_t, blend;
        vector desiredang, diffang;
 
@@ -318,7 +318,7 @@ vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, flo
 }
 
 float bot_aim(float shotspeed, float shotspeedupward, float maxshottime, float applygravity)
-{
+{SELFPARAM();
        float f, r, hf, distanceratio;
        vector v;
        /*
index 64f5eb7d4ce3a026c7175631066dac3ae202419b..00051cadb9cbdeee1b806ac9a7f8ec104a97f4ff 100644 (file)
 #include "../../warpzonelib/util_server.qh"
 
 entity bot_spawn()
-{
-       entity oldself, bot;
-       bot = spawnclient();
+{SELFPARAM();
+       entity bot = spawnclient();
        if (bot)
        {
                currentbots = currentbots + 1;
-               oldself = self;
-               self = bot;
+               setself(bot);
                bot_setnameandstuff();
                ClientConnect();
                PutClientInServer();
-               self = oldself;
+               setself(this);
        }
        return bot;
 }
 
 void bot_think()
-{
+{SELFPARAM();
        if (self.bot_nextthink > time)
                return;
 
@@ -133,7 +131,7 @@ void bot_think()
 }
 
 void bot_setnameandstuff()
-{
+{SELFPARAM();
        string readfile, s;
        float file, tokens, prio;
        entity p;
@@ -302,42 +300,42 @@ void bot_custom_weapon_priority_setup()
        tokens = tokenizebyseparator(W_NumberWeaponOrder(autocvar_bot_ai_custom_weapon_priority_far)," ");
 
        int c = 0;
-       for(i=0; i < tokens && c < WEP_COUNT; ++i){
+       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 < WEP_COUNT)
+       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 < WEP_COUNT; ++i){
+       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 < WEP_COUNT)
+       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 < WEP_COUNT; ++i){
+       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 < WEP_COUNT)
+       if(c < Weapons_COUNT)
                bot_weapons_close[c] = -1;
 
        bot_custom_weapon = true;
@@ -389,7 +387,7 @@ void bot_relinkplayerlist()
 }
 
 void bot_clientdisconnect()
-{
+{SELFPARAM();
        if (!IS_BOT_CLIENT(self))
                return;
        bot_clearqueue(self);
@@ -412,7 +410,7 @@ void bot_clientdisconnect()
 }
 
 void bot_clientconnect()
-{
+{SELFPARAM();
        if (!IS_BOT_CLIENT(self))
                return;
        self.bot_preferredcolors = self.clientcolors;
index a796dc12d5220c870db79f9c1dd6c44b4b9754ed..d5a2794008019675759858141e47bdf83ef9e03c 100644 (file)
@@ -48,9 +48,9 @@ float bot_custom_weapon;
 float bot_distance_far;
 float bot_distance_close;
 
-float bot_weapons_far[WEP_MAXCOUNT];
-float bot_weapons_mid[WEP_MAXCOUNT];
-float bot_weapons_close[WEP_MAXCOUNT];
+float bot_weapons_far[Weapons_MAX];
+float bot_weapons_mid[Weapons_MAX];
+float bot_weapons_close[Weapons_MAX];
 
 entity bot_list;
 entity player_list;
index 5796fe60163346a5023ede6a39b4b560dc6bfa88..f69527916ce512ad8c3d94ac61e798883716f459 100644 (file)
@@ -14,7 +14,7 @@
 #include "../../../warpzonelib/common.qh"
 
 void havocbot_ai()
-{
+{SELFPARAM();
        if(self.draggedby)
                return;
 
@@ -102,7 +102,8 @@ void havocbot_ai()
 
                if(self.weapons)
                {
-                       WEP_ACTION(self.weapon, WR_AIM);
+                       Weapon w = get_weaponinfo(self.weapon);
+                       w.wr_aim(w);
                        if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self))
                        {
                                self.BUTTON_ATCK = false;
@@ -179,7 +180,7 @@ void havocbot_ai()
 }
 
 void havocbot_keyboard_movement(vector destorg)
-{
+{SELFPARAM();
        vector keyboard;
        float blend, maxspeed;
        float sk;
@@ -254,7 +255,7 @@ void havocbot_keyboard_movement(vector destorg)
 }
 
 void havocbot_bunnyhop(vector dir)
-{
+{SELFPARAM();
        float bunnyhopdistance;
        vector deviation;
        float maxspeed;
@@ -397,7 +398,7 @@ void havocbot_bunnyhop(vector dir)
 }
 
 void havocbot_movetogoal()
-{
+{SELFPARAM();
        vector destorg;
        vector diff;
        vector dir;
@@ -854,9 +855,9 @@ void havocbot_movetogoal()
 }
 
 void havocbot_chooseenemy()
-{
+{SELFPARAM();
        entity head, best, head2;
-       float rating, bestrating, i, hf;
+       float rating, bestrating, hf;
        vector eye, v;
        if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self))
        {
@@ -908,10 +909,29 @@ void havocbot_chooseenemy()
 
        self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
 
-       for(i = 0; ; ++i)
+       bool scan_transparent = false;
+       bool scan_secondary_targets = false;
+       bool have_secondary_targets = false;
+       while(true)
        {
-               while (head)
+               scan_secondary_targets = false;
+               :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)
@@ -925,20 +945,29 @@ void havocbot_chooseenemy()
                                        bestrating = rating;
                                }
                        }
-                       head = head.chain;
+               }
+
+               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 || self.weapons) // || self.weapon == WEP_RIFLE.m_id
                        break;
-               if(i)
+               if(scan_transparent)
                        break;
 
                // Set flags to see through transparent objects
                self.dphitcontentsmask |= DPCONTENTS_OPAQUE;
 
                head = head2;
+               scan_transparent = true;
        }
 
        // Restore hit flags
@@ -946,10 +975,12 @@ void havocbot_chooseenemy()
 
        self.enemy = best;
        self.havocbot_stickenemy = true;
+       if(best && best.classname == "misc_breakablemodel")
+               self.havocbot_stickenemy = false;
 }
 
 float havocbot_chooseweapon_checkreload(int new_weapon)
-{
+{SELFPARAM();
        // 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 :)
@@ -962,8 +993,9 @@ float havocbot_chooseweapon_checkreload(int new_weapon)
                float i, other_weapon_available = false;
                for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                {
+                       Weapon w = get_weaponinfo(i);
                        // if we are out of ammo for all other weapons, it's an emergency to switch to anything else
-                       if (WEP_ACTION(i, WR_CHECKAMMO1) + WEP_ACTION(i, WR_CHECKAMMO2))
+                       if (w.wr_checkammo1(w) + w.wr_checkammo2(w))
                                other_weapon_available = true;
                }
                if(other_weapon_available)
@@ -974,11 +1006,11 @@ float havocbot_chooseweapon_checkreload(int new_weapon)
 }
 
 void havocbot_chooseweapon()
-{
+{SELFPARAM();
        int i;
 
        // ;)
-       if(g_weaponarena_weapons == WEPSET_TUBA)
+       if(g_weaponarena_weapons == WEPSET(TUBA))
        {
                self.switchweapon = WEP_TUBA.m_id;
                return;
@@ -1035,7 +1067,7 @@ void havocbot_chooseweapon()
 
                // Choose weapons for far distance
                if ( distance > bot_distance_far ) {
-                       for(i=0; i < WEP_COUNT && bot_weapons_far[i] != -1 ; ++i){
+                       for(i=0; i < Weapons_COUNT && bot_weapons_far[i] != -1 ; ++i){
                                w = bot_weapons_far[i];
                                if ( client_hasweapon(self, w, true, false) )
                                {
@@ -1049,7 +1081,7 @@ void havocbot_chooseweapon()
 
                // Choose weapons for mid distance
                if ( distance > bot_distance_close) {
-                       for(i=0; i < WEP_COUNT && bot_weapons_mid[i] != -1 ; ++i){
+                       for(i=0; i < Weapons_COUNT && bot_weapons_mid[i] != -1 ; ++i){
                                w = bot_weapons_mid[i];
                                if ( client_hasweapon(self, w, true, false) )
                                {
@@ -1062,7 +1094,7 @@ void havocbot_chooseweapon()
                }
 
                // Choose weapons for close distance
-               for(i=0; i < WEP_COUNT && bot_weapons_close[i] != -1 ; ++i){
+               for(i=0; i < Weapons_COUNT && bot_weapons_close[i] != -1 ; ++i){
                        w = bot_weapons_close[i];
                        if ( client_hasweapon(self, w, true, false) )
                        {
@@ -1076,7 +1108,7 @@ void havocbot_chooseweapon()
 }
 
 void havocbot_aim()
-{
+{SELFPARAM();
        vector selfvel, enemyvel;
 //     if(self.flags & FL_INWATER)
 //             return;
@@ -1098,7 +1130,7 @@ void havocbot_aim()
 }
 
 float havocbot_moveto_refresh_route()
-{
+{SELFPARAM();
        // Refresh path to goal if necessary
        entity wp;
        wp = self.havocbot_personal_waypoint;
@@ -1109,7 +1141,7 @@ float havocbot_moveto_refresh_route()
 }
 
 float havocbot_moveto(vector pos)
-{
+{SELFPARAM();
        entity wp;
 
        if(self.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
@@ -1231,7 +1263,7 @@ float havocbot_resetgoal()
 }
 
 void havocbot_setupbot()
-{
+{SELFPARAM();
        self.bot_ai = havocbot_ai;
        self.cmd_moveto = havocbot_moveto;
        self.cmd_resetgoal = havocbot_resetgoal;
@@ -1240,7 +1272,7 @@ void havocbot_setupbot()
 }
 
 vector havocbot_dodge()
-{
+{SELFPARAM();
        // LordHavoc: disabled because this is too expensive
        return '0 0 0';
 #if 0
index 63888e45fc5f8d81af0ccf7734f91f02ce620b04..b1603c792ac033806577bcd189016cac89040674 100644 (file)
@@ -15,7 +15,7 @@ void() havocbot_role_kh_freelancer;
 
 
 void havocbot_goalrating_kh(float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy)
-{
+{SELFPARAM();
        entity head;
        for (head = kh_worldkeylist; head; head = head.kh_worldkeynext)
        {
@@ -44,7 +44,7 @@ void havocbot_goalrating_kh(float ratingscale_team, float ratingscale_dropped, f
 }
 
 void havocbot_role_kh_carrier()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -71,7 +71,7 @@ void havocbot_role_kh_carrier()
 }
 
 void havocbot_role_kh_defense()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -112,7 +112,7 @@ void havocbot_role_kh_defense()
 }
 
 void havocbot_role_kh_offense()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -154,7 +154,7 @@ void havocbot_role_kh_offense()
 }
 
 void havocbot_role_kh_freelancer()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -204,7 +204,7 @@ void havocbot_role_kh_freelancer()
 }
 
 void havocbot_chooserole_kh()
-{
+{SELFPARAM();
        float r;
 
        if(self.deadflag != DEAD_NO)
index c56f70598e60b696e4f18c7a70d6f20cce995633..037968f1367b30205fbeccad9ce569e401dcbb7d 100644 (file)
@@ -13,7 +13,7 @@
 .void() havocbot_role;
 
 void havocbot_goalrating_items(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
        entity head;
        entity player;
        float rating, d, discard, distance, friend_distance, enemy_distance;
@@ -138,7 +138,7 @@ void havocbot_goalrating_items(float ratingscale, vector org, float sradius)
 }
 
 void havocbot_goalrating_controlpoints(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
        entity head;
        head = findchain(classname, "dom_controlpoint");
        while (head)
@@ -157,7 +157,7 @@ void havocbot_goalrating_controlpoints(float ratingscale, vector org, float srad
 }
 
 void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
        entity head;
        int t;
        float distance;
@@ -214,7 +214,7 @@ void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradi
 // legacy bot role for standard gamemodes
 // go to best items
 void havocbot_role_generic()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -230,12 +230,12 @@ void havocbot_role_generic()
 }
 
 void havocbot_chooserole_generic()
-{
+{SELFPARAM();
        self.havocbot_role = havocbot_role_generic;
 }
 
 void havocbot_chooserole()
-{
+{SELFPARAM();
        LOG_TRACE("choosing a role...\n");
        self.bot_strategytime = 0;
        if (MUTATOR_CALLHOOK(HavocBot_ChooseRole, self))
index 72729ec8671bdbcf8a264295188ba89531f00b7d..99e3901b2b3cb095b771a89286c9b5ac1bcae721 100644 (file)
@@ -22,7 +22,7 @@ void bot_debug(string input)
 // can be traveled, used for waypoint linking and havocbot
 
 float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode)
-{
+{SELFPARAM();
        vector org;
        vector move;
        vector dir;
@@ -232,7 +232,7 @@ float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float
 
 // completely empty the goal stack, used when deciding where to go
 void navigation_clearroute()
-{
+{SELFPARAM();
        //print("bot ", etos(self), " clear\n");
        self.navigation_hasgoals = false;
        self.goalcurrent = world;
@@ -276,7 +276,7 @@ void navigation_clearroute()
 // 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 e)
-{
+{SELFPARAM();
        //print("bot ", etos(self), " push ", etos(e), "\n");
        self.goalstack31 = self.goalstack30;
        self.goalstack30 = self.goalstack29;
@@ -316,7 +316,7 @@ void navigation_pushroute(entity e)
 // (in other words: remove a prerequisite for reaching the later goals)
 // (used when a spawnfunc_waypoint is reached)
 void navigation_poproute()
-{
+{SELFPARAM();
        //print("bot ", etos(self), " pop\n");
        self.goalcurrent = self.goalstack01;
        self.goalstack01 = self.goalstack02;
@@ -449,7 +449,7 @@ entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
 
 // finds the waypoints near the bot initiating a navigation query
 float navigation_markroutes_nearestwaypoints(entity waylist, float maxdist)
-{
+{SELFPARAM();
        entity head;
        vector v, m1, m2, diff;
        float c;
@@ -520,7 +520,7 @@ void navigation_markroutes_checkwaypoint(entity w, entity wp, float cost2, vecto
 
 // queries the entire spawnfunc_waypoint network for pathes leading away from the bot
 void navigation_markroutes(entity fixed_source_waypoint)
-{
+{SELFPARAM();
        entity w, wp, waylist;
        float searching, cost, cost2;
        vector p;
@@ -679,7 +679,7 @@ void navigation_markroutes_inverted(entity fixed_source_waypoint)
 
 // updates the best goal according to a weighted calculation of travel cost and item value of a new proposed item
 void navigation_routerating(entity e, float f, float rangebias)
-{
+{SELFPARAM();
        entity nwp;
        vector o;
        if (!e)
@@ -861,7 +861,7 @@ void navigation_routerating(entity e, float f, float rangebias)
 
 // adds an item to the the goal stack with the path to a given item
 float navigation_routetogoal(entity e, vector startposition)
-{
+{SELFPARAM();
        self.goalentity = e;
 
        // if there is no goal, just exit
@@ -907,7 +907,7 @@ float navigation_routetogoal(entity e, vector startposition)
 // removes any currently touching waypoints from the goal stack
 // (this is how bots detect if they reached a goal)
 void navigation_poptouchedgoals()
-{
+{SELFPARAM();
        vector org, m1, m2;
        org = self.origin;
        m1 = org + self.mins;
@@ -993,7 +993,7 @@ void navigation_poptouchedgoals()
 
 // begin a goal selection session (queries spawnfunc_waypoint network)
 void navigation_goalrating_start()
-{
+{SELFPARAM();
        if(self.aistatus & AI_STATUS_STUCK)
                return;
 
@@ -1007,7 +1007,7 @@ void navigation_goalrating_start()
 
 // ends a goal selection session (updates goal stack to the best goal)
 void navigation_goalrating_end()
-{
+{SELFPARAM();
        if(self.aistatus & AI_STATUS_STUCK)
                return;
 
@@ -1067,7 +1067,7 @@ void botframe_updatedangerousobjects(float maxupdate)
 }
 
 void navigation_unstuck()
-{
+{SELFPARAM();
        float search_radius = 1000;
 
        if (!autocvar_bot_wander_enable)
@@ -1164,7 +1164,7 @@ void debugresetnodes()
 }
 
 void debugnode(vector node)
-{
+{SELFPARAM();
        if (!IS_PLAYER(self))
                return;
 
@@ -1207,7 +1207,7 @@ void debugnodestatus(vector position, float status)
 
 // Debug the goal stack visually
 void debuggoalstack()
-{
+{SELFPARAM();
        entity goal;
        vector org, go;
 
index a8dc92171746325702c23c1676d26bfd78c53fab..72951cd6628b36e574d77b98abac0b2bfd2d6a0b 100644 (file)
@@ -101,7 +101,7 @@ const int MAX_BOT_PLACES = 4;
 .entity bot_places[MAX_BOT_PLACES];
 .string bot_placenames[MAX_BOT_PLACES];
 entity bot_getplace(string placename)
-{
+{SELFPARAM();
        entity e;
        if(substring(placename, 0, 1) == "@")
        {
@@ -480,20 +480,20 @@ float bot_cmd_cc()
 }
 
 float bot_cmd_impulse()
-{
+{SELFPARAM();
        self.impulse = bot_cmd.bot_cmd_parm_float;
        return CMD_STATUS_FINISHED;
 }
 
 float bot_cmd_continue()
-{
+{SELFPARAM();
        self.bot_exec_status &= ~BOT_EXEC_STATUS_PAUSED;
        return CMD_STATUS_FINISHED;
 }
 
 .float bot_cmd_wait_time;
 float bot_cmd_wait()
-{
+{SELFPARAM();
        if(self.bot_exec_status & BOT_EXEC_STATUS_WAITING)
        {
                if(time>=self.bot_cmd_wait_time)
@@ -511,7 +511,7 @@ float bot_cmd_wait()
 }
 
 float bot_cmd_wait_until()
-{
+{SELFPARAM();
        if(time < bot_cmd.bot_cmd_parm_float + bot_barriertime)
        {
                self.bot_exec_status |= BOT_EXEC_STATUS_WAITING;
@@ -522,7 +522,7 @@ float bot_cmd_wait_until()
 }
 
 float bot_cmd_barrier()
-{
+{SELFPARAM();
        entity cl;
 
        // 0 = no barrier, 1 = waiting, 2 = waiting finished
@@ -561,14 +561,14 @@ float bot_cmd_barrier()
 }
 
 float bot_cmd_turn()
-{
+{SELFPARAM();
        self.v_angle_y = self.v_angle.y + bot_cmd.bot_cmd_parm_float;
        self.v_angle_y = self.v_angle.y - floor(self.v_angle.y / 360) * 360;
        return CMD_STATUS_FINISHED;
 }
 
 float bot_cmd_select_weapon()
-{
+{SELFPARAM();
        float id;
 
        id = bot_cmd.bot_cmd_parm_float;
@@ -593,7 +593,7 @@ const int CMD_CONDITION_true_BLOCK = 4;
 const int CMD_CONDITION_false_BLOCK = 8;
 
 float bot_cmd_eval(string expr)
-{
+{SELFPARAM();
        // Search for numbers
        if(strstrofs("0123456789", substring(expr, 0, 1), 0) >= 0)
        {
@@ -622,7 +622,7 @@ float bot_cmd_eval(string expr)
 }
 
 float bot_cmd_if()
-{
+{SELFPARAM();
        string expr, val_a, val_b;
        float cmpofs;
 
@@ -693,20 +693,20 @@ float bot_cmd_if()
 }
 
 float bot_cmd_else()
-{
+{SELFPARAM();
        self.bot_cmd_condition_status &= ~CMD_CONDITION_true_BLOCK;
        self.bot_cmd_condition_status |= CMD_CONDITION_false_BLOCK;
        return CMD_STATUS_FINISHED;
 }
 
 float bot_cmd_fi()
-{
+{SELFPARAM();
        self.bot_cmd_condition_status = CMD_CONDITION_NONE;
        return CMD_STATUS_FINISHED;
 }
 
 float bot_cmd_resetaim()
-{
+{SELFPARAM();
        self.v_angle = '0 0 0';
        return CMD_STATUS_FINISHED;
 }
@@ -717,7 +717,7 @@ float bot_cmd_resetaim()
 .vector bot_cmd_aim_end;
 
 float bot_cmd_aim()
-{
+{SELFPARAM();
        // Current direction
        if(self.bot_cmd_aim_endtime)
        {
@@ -768,7 +768,7 @@ float bot_cmd_aim()
 }
 
 float bot_cmd_aimtarget()
-{
+{SELFPARAM();
        if(self.bot_cmd_aim_endtime)
        {
                return bot_cmd_aim();
@@ -827,7 +827,7 @@ const int BOT_CMD_KEY_CROUCH        = 512;
 const int BOT_CMD_KEY_CHAT             = 1024;
 
 float bot_presskeys()
-{
+{SELFPARAM();
        self.movement = '0 0 0';
        self.BUTTON_JUMP = false;
        self.BUTTON_CROUCH = false;
@@ -876,7 +876,7 @@ float bot_presskeys()
 
 
 float bot_cmd_keypress_handler(string key, float enabled)
-{
+{SELFPARAM();
        switch(key)
        {
                case "all":
@@ -990,7 +990,7 @@ float bot_cmd_releasekey()
 }
 
 float bot_cmd_pause()
-{
+{SELFPARAM();
        self.button1        = 0;
        self.button8        = 0;
        self.BUTTON_USE     = 0;
@@ -1009,12 +1009,12 @@ float bot_cmd_pause()
 }
 
 float bot_cmd_moveto()
-{
+{SELFPARAM();
        return self.cmd_moveto(bot_cmd.bot_cmd_parm_vector);
 }
 
 float bot_cmd_movetotarget()
-{
+{SELFPARAM();
        entity e;
        e = bot_getplace(bot_cmd.bot_cmd_parm_string);
        if(!e)
@@ -1023,13 +1023,13 @@ float bot_cmd_movetotarget()
 }
 
 float bot_cmd_resetgoal()
-{
+{SELFPARAM();
        return self.cmd_resetgoal();
 }
 
 
 float bot_cmd_sound()
-{
+{SELFPARAM();
        string f;
        f = bot_cmd.bot_cmd_parm_string;
 
@@ -1050,14 +1050,14 @@ float bot_cmd_sound()
                atten = stof(argv(2));
 
        precache_sound(f);
-       sound(self, chan, sample, vol, atten);
+       _sound(self, chan, sample, vol, atten);
 
        return CMD_STATUS_FINISHED;
 }
 
 .entity tuba_note;
 float bot_cmd_debug_assert_canfire()
-{
+{SELFPARAM();
        float f;
        f = bot_cmd.bot_cmd_parm_float;
 
@@ -1100,7 +1100,7 @@ float bot_cmd_debug_assert_canfire()
 //
 
 void bot_command_executed(float rm)
-{
+{SELFPARAM();
        entity cmd;
 
        cmd = bot_cmd;
@@ -1112,7 +1112,7 @@ void bot_command_executed(float rm)
 }
 
 void bot_setcurrentcommand()
-{
+{SELFPARAM();
        bot_cmd = world;
 
        if(!self.bot_cmd_current)
@@ -1171,7 +1171,7 @@ void bot_resetqueues()
 // 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()
-{
+{SELFPARAM();
        float status, ispressingkey;
 
        // Find command
index ca209f9ca7ab4877c3ef0036c2d3756cf076a06f..8f50d0276a6efb67158ba9164649edbdec387c70 100644 (file)
@@ -66,7 +66,7 @@ entity waypoint_spawn(vector m1, vector m2, float f)
        {
                m1 = w.mins;
                m2 = w.maxs;
-               setmodel(w, "models/runematch/rune.mdl"); w.effects = EF_LOWPRECISION;
+               setmodel(w, MDL_WAYPOINT); w.effects = EF_LOWPRECISION;
                setsize(w, m1, m2);
                if (w.wpflags & WAYPOINTFLAG_ITEM)
                        w.colormod = '1 0 0';
@@ -162,7 +162,7 @@ void waypoint_addlink(entity from, entity to)
 // (precompile a list of all reachable waypoints from this spawnfunc_waypoint)
 // (SLOW!)
 void waypoint_think()
-{
+{SELFPARAM();
        entity e;
        vector sv, sm1, sm2, ev, em1, em2, dv;
 
@@ -269,7 +269,7 @@ void waypoint_schedulerelink(entity wp)
                vector m1, m2;
                m1 = wp.mins;
                m2 = wp.maxs;
-               setmodel(wp, "models/runematch/rune.mdl"); wp.effects = EF_LOWPRECISION;
+               setmodel(wp, MDL_WAYPOINT); wp.effects = EF_LOWPRECISION;
                setsize(wp, m1, m2);
                if (wp.wpflags & WAYPOINTFLAG_ITEM)
                        wp.colormod = '1 0 0';
@@ -293,7 +293,7 @@ void waypoint_schedulerelink(entity wp)
 }
 
 // spawnfunc_waypoint map entity
-void spawnfunc_waypoint()
+spawnfunc(waypoint)
 {
        setorigin(self, self.origin);
        // schedule a relink after other waypoints have had a chance to spawn
@@ -808,7 +808,7 @@ void waypoint_spawnforteleporter(entity e, vector destination, float timetaken)
 }
 
 entity waypoint_spawnpersonal(vector position)
-{
+{SELFPARAM();
        entity w;
 
        // drop the waypoint to a proper location:
index 87141c4bc35a48e26efb00468edc748aaf74d620..fde524bb94821ae89bd4ced22ecebed7e3d47e66 100644 (file)
@@ -38,7 +38,7 @@ float botframe_cachedwaypointlinks;
  * Functions
  */
 
-void spawnfunc_waypoint();
+spawnfunc(waypoint);
 void waypoint_addlink(entity from, entity to);
 void waypoint_think();
 void waypoint_clearlinks(entity wp);
index 82bc9036158a3f343cf41c35108c2028d6c5c25a..9912174dd8d17a5a024fd8ac9e77f5340e839b49 100644 (file)
@@ -11,7 +11,7 @@
 
 #include "../common/constants.qh"
 #include "../common/deathtypes.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
 #include "../common/util.qh"
 
 #include "../common/monsters/all.qh"
@@ -65,7 +65,7 @@ void CheatShutdownClient()
 }
 
 float CheatsAllowed(float i, float argc, float fr) // the cheat gets passed as argument for possible future ACL checking
-{
+{SELFPARAM();
        // dead people cannot cheat
        if(self.deadflag != DEAD_NO)
                return 0;
@@ -115,7 +115,7 @@ float CheatsAllowed(float i, float argc, float fr) // the cheat gets passed as a
 
 float num_autoscreenshot;
 void info_autoscreenshot_findtarget()
-{
+{SELFPARAM();
        entity e;
        e = find(world, targetname, self.target);
        if(!e)
@@ -129,7 +129,7 @@ void info_autoscreenshot_findtarget()
        self.angles_y = a.y;
        // we leave Rick Roll alone
 }
-void spawnfunc_info_autoscreenshot()
+spawnfunc(info_autoscreenshot)
 {
        if(++num_autoscreenshot > autocvar_g_max_info_autoscreenshot)
        {
@@ -142,7 +142,7 @@ void spawnfunc_info_autoscreenshot()
 }
 
 float CheatImpulse(float i)
-{
+{SELFPARAM();
        BEGIN_CHEAT_FUNCTION();
        switch(i)
        {
@@ -283,7 +283,7 @@ float CheatImpulse(float i)
                                e = self;
 
                        Send_Effect(EFFECT_ROCKET_EXPLODE, e.origin, '0 0 0', 1);
-                       sound(e, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+                       sound(e, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 
                        e2 = spawn();
                        setorigin(e2, e.origin);
@@ -301,13 +301,12 @@ float CheatImpulse(float i)
 void DragBox_Think();
 float drag_lastcnt;
 float CheatCommand(float argc)
-{
+{SELFPARAM();
        BEGIN_CHEAT_FUNCTION();
        string cmd;
        cmd = argv(0);
        switch(cmd)
        {
-               entity e;
                float effectnum, f;
                vector start, end;
                entity oldself;
@@ -362,7 +361,7 @@ float CheatCommand(float argc)
                                }
                                else
                                {
-                                       e = spawn();
+                                       entity e = spawn();
                                        e.model = strzone(argv(1));
                                        e.mdl = "rocket_explode";
                                        e.health = 1000;
@@ -373,10 +372,7 @@ float CheatCommand(float argc)
                                                e.angles = fixedvectoangles2(trace_plane_normal, v_forward);
                                                e.angles = AnglesTransform_ApplyToAngles(e.angles, '-90 0 0'); // so unrotated models work
                                        }
-                                       oldself = self;
-                                       self = e;
-                                       spawnfunc_func_breakable();
-                                       self = oldself;
+                                       WITH(entity, self, e, spawnfunc_func_breakable(e));
                                        // now, is it valid?
                                        if(f == 0)
                                        {
@@ -406,14 +402,14 @@ float CheatCommand(float argc)
                        }
                        sprint(self, "Usage: sv_cheats 1; restart; cmd penalty 5.0 AHAHAHAHAHAHAH))\n");
                        break;
-               case "dragbox_spawn":
+               case "dragbox_spawn": {
                        IS_CHEAT(0, argc, 0);
-                       e = spawn();
+                       entity e = spawn();
                        e.classname = "dragbox_box";
                        e.think = DragBox_Think;
                        e.nextthink = time;
                        e.solid = -1; // black
-                       setmodel(e, "null"); // network it
+                       setmodel(e, MDL_Null); // network it
                        if(argc == 4)
                                e.cnt = stof(argv(1));
                        else
@@ -422,7 +418,7 @@ float CheatCommand(float argc)
                        e.aiment = spawn();
                        e.aiment.classname = "dragbox_corner_1";
                        e.aiment.owner = e;
-                       setmodel(e.aiment, "models/marker.md3");
+                       setmodel(e.aiment, MDL_MARKER);
                        e.aiment.skin = 0;
                        setsize(e.aiment, '0 0 0', '0 0 0');
                        if(argc == 4)
@@ -436,7 +432,7 @@ float CheatCommand(float argc)
                        e.enemy = spawn();
                        e.enemy.classname = "dragbox_corner_2";
                        e.enemy.owner = e;
-                       setmodel(e.enemy, "models/marker.md3");
+                       setmodel(e.enemy, MDL_MARKER);
                        e.enemy.skin = 1;
                        setsize(e.enemy, '0 0 0', '0 0 0');
                        end = normalize(self.origin + self.view_ofs - e.aiment.origin);
@@ -460,14 +456,15 @@ float CheatCommand(float argc)
                        setorigin(e.killindicator.killindicator, '0 0 8');
                        DID_CHEAT();
                        break;
-               case "dragpoint_spawn":
+               }
+               case "dragpoint_spawn": {
                        IS_CHEAT(0, argc, 0);
-                       e = spawn();
+                       entity e = spawn();
                        e.classname = "dragpoint";
                        e.think = DragBox_Think;
                        e.nextthink = time;
                        e.solid = 0; // nothing special
-                       setmodel(e, "models/marker.md3");
+                       setmodel(e, MDL_MARKER);
                        setsize(e, PL_MIN, PL_MAX);
                        e.skin = 2;
                        if(argc == 3)
@@ -495,13 +492,14 @@ float CheatCommand(float argc)
                        setorigin(e.killindicator.killindicator, '0 0 56');
                        DID_CHEAT();
                        break;
+               }
                case "drag_remove":
                        IS_CHEAT(0, argc, 0);
                        RandomSelection_Init();
                        crosshair_trace(self);
-                       for(e = world; (e = find(e, classname, "dragbox_box")); )
+                       for(entity e = world; (e = find(e, classname, "dragbox_box")); )
                                RandomSelection_Add(e, 0, string_null, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
-                       for(e = world; (e = find(e, classname, "dragpoint")); )
+                       for(entity e = world; (e = find(e, classname, "dragpoint")); )
                                RandomSelection_Add(e, 0, string_null, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
                        if(RandomSelection_chosen_ent)
                        {
@@ -521,9 +519,9 @@ float CheatCommand(float argc)
                        {
                                RandomSelection_Init();
                                crosshair_trace(self);
-                               for(e = world; (e = find(e, classname, "dragbox_box")); )
+                               for(entity e = world; (e = find(e, classname, "dragbox_box")); )
                                        RandomSelection_Add(e, 0, string_null, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
-                               for(e = world; (e = find(e, classname, "dragpoint")); )
+                               for(entity e = world; (e = find(e, classname, "dragpoint")); )
                                        RandomSelection_Add(e, 0, string_null, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
                                if(RandomSelection_chosen_ent)
                                {
@@ -543,11 +541,11 @@ float CheatCommand(float argc)
                        {
                                f = fopen(argv(1), FILE_WRITE);
                                fputs(f, "cmd drag_clear\n");
-                               for(e = world; (e = find(e, classname, "dragbox_box")); )
+                               for(entity e = world; (e = find(e, classname, "dragbox_box")); )
                                {
                                        fputs(f, strcat("cmd dragbox_spawn ", ftos(e.cnt), " \"", vtos(e.aiment.origin), "\" \"", vtos(e.enemy.origin), "\"\n"));
                                }
-                               for(e = world; (e = find(e, classname, "dragpoint")); )
+                               for(entity e = world; (e = find(e, classname, "dragpoint")); )
                                {
                                        fputs(f, strcat("cmd dragpoint_spawn ", ftos(e.cnt), " \"", vtos(e.origin), "\"\n"));
                                }
@@ -562,7 +560,7 @@ float CheatCommand(float argc)
                        if(argc == 2)
                        {
                                f = fopen(argv(1), FILE_WRITE);
-                               for(e = world; (e = find(e, classname, "dragbox_box")); )
+                               for(entity e = world; (e = find(e, classname, "dragbox_box")); )
                                {
                                        fputs(f, "{\n");
                                        fputs(f, "\"classname\" \"trigger_race_checkpoint\"\n");
@@ -572,7 +570,7 @@ float CheatCommand(float argc)
                                        fputs(f, strcat("\"targetname\" \"checkpoint", ftos(e.cnt), "\"\n"));
                                        fputs(f, "}\n");
                                }
-                               for(e = world; (e = find(e, classname, "dragpoint")); )
+                               for(entity e = world; (e = find(e, classname, "dragpoint")); )
                                {
                                        start = '0 0 0';
                                        effectnum = 0;
@@ -628,15 +626,15 @@ float CheatCommand(float argc)
                        break;
                case "drag_clear":
                        IS_CHEAT(0, argc, 0);
-                       for(e = world; (e = find(e, classname, "dragbox_box")); )
+                       for(entity e = world; (e = find(e, classname, "dragbox_box")); )
                                remove(e);
-                       for(e = world; (e = find(e, classname, "dragbox_corner_1")); )
+                       for(entity e = world; (e = find(e, classname, "dragbox_corner_1")); )
                                remove(e);
-                       for(e = world; (e = find(e, classname, "dragbox_corner_2")); )
+                       for(entity e = world; (e = find(e, classname, "dragbox_corner_2")); )
                                remove(e);
-                       for(e = world; (e = find(e, classname, "dragpoint")); )
+                       for(entity e = world; (e = find(e, classname, "dragpoint")); )
                                remove(e);
-                       for(e = world; (e = find(e, classname, "drag_digit")); )
+                       for(entity e = world; (e = find(e, classname, "drag_digit")); )
                                remove(e);
                        DID_CHEAT();
                        break;
@@ -697,43 +695,38 @@ float CheatCommand(float argc)
                        break;
                case "usetarget":
                        IS_CHEAT(0, argc, 0);
-                       e = self;
-                       self = spawn();
+                       setself(spawn());
                        self.target = argv(1);
-                       activator = e;
+                       activator = this;
                        SUB_UseTargets();
                        remove(self);
-                       self = e;
+                       setself(this);
                        DID_CHEAT();
                        break;
                case "killtarget":
                        IS_CHEAT(0, argc, 0);
-                       e = self;
-                       self = spawn();
+                       setself(spawn());
                        self.killtarget = argv(1);
-                       activator = e;
+                       activator = this;
                        SUB_UseTargets();
                        remove(self);
-                       self = e;
+                       setself(this);
                        DID_CHEAT();
                        break;
                case "teleporttotarget":
                        IS_CHEAT(0, argc, 0);
-                       e = self;
-                       self = spawn();
+                       setself(spawn());
                        setorigin(self, self.origin);
                        self.classname = "cheattriggerteleport";
                        self.target = argv(1);
                        teleport_findtarget();
                        if(!wasfreed(self))
                        {
-                               Simple_TeleportPlayer(self, e);
+                               Simple_TeleportPlayer(self, this);
                                remove(self);
-                               self = e;
                                DID_CHEAT();
                        }
-                       else
-                               self = e;
+                       setself(this);
                        break;
        }
 
@@ -755,7 +748,7 @@ void Drag_MoveDrag(entity from, entity to);
 .entity dragentity;
 
 float CheatFrame()
-{
+{SELFPARAM();
        BEGIN_CHEAT_FUNCTION();
 
        // Dragging can be used as either a cheat, or a function for some objects. If sv_cheats is active,
@@ -799,7 +792,7 @@ float CheatFrame()
 .float dragmovetype;
 
 float Drag(float force_allow_pick, float ischeat)
-{
+{SELFPARAM();
        BEGIN_CHEAT_FUNCTION();
 
        // returns true when an entity has been picked up
@@ -1075,7 +1068,7 @@ void Drag_MoveDrag(entity from, entity to)
 }
 
 void DragBox_Think()
-{
+{SELFPARAM();
        if(self.aiment && self.enemy)
        {
                self.origin_x = (self.aiment.origin.x + self.enemy.origin.x) * 0.5;
@@ -1091,19 +1084,19 @@ void DragBox_Think()
        if(self.cnt == -1) // actually race_place -1
        {
                // show "10 10" for qualifying spawns
-               setmodel(self.killindicator, "models/sprites/10.spr32");
-               setmodel(self.killindicator.killindicator, "models/sprites/10.spr32");
+               setmodel(self.killindicator, MDL_NUM(10));
+               setmodel(self.killindicator.killindicator, MDL_NUM(10));
        }
        else if(self.cnt == -2) // actually race_place 0
        {
                // show "10 0" for loser spawns
-               setmodel(self.killindicator, "models/sprites/10.spr32");
-               setmodel(self.killindicator.killindicator, "models/sprites/0.spr32");
+               setmodel(self.killindicator, MDL_NUM(10));
+               setmodel(self.killindicator.killindicator, MDL_NUM(0));
        }
        else
        {
-               setmodel(self.killindicator, strcat("models/sprites/", ftos(self.cnt % 10), ".spr32"));
-               setmodel(self.killindicator.killindicator, strcat("models/sprites/", ftos(floor(self.cnt / 10)), ".spr32"));
+               setmodel(self.killindicator, MDL_NUM(self.cnt % 10));
+               setmodel(self.killindicator.killindicator, MDL_NUM(floor(self.cnt / 10)));
        }
 
        self.nextthink = time;
index 4d7b9fa0bf25a20d901ad6e231e525c070e74fbb..71efa5f9d931233f32899305692f023ceaea5d96 100644 (file)
@@ -53,7 +53,7 @@ void send_CSQC_teamnagger() {
        WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
 }
 
-float ClientData_Send(entity to, int sf)
+bool ClientData_Send(entity this, entity to, int sf)
 {
        if(to != self.owner)
        {
@@ -94,14 +94,14 @@ float ClientData_Send(entity to, int sf)
 }
 
 void ClientData_Attach()
-{
+{SELFPARAM();
        Net_LinkEntity(self.clientdata = spawn(), false, 0, ClientData_Send);
        self.clientdata.drawonlytoclient = self;
        self.clientdata.owner = self;
 }
 
 void ClientData_Detach()
-{
+{SELFPARAM();
        remove(self.clientdata);
        self.clientdata = world;
 }
@@ -172,7 +172,7 @@ string CheckPlayerModel(string plyermodel) {
 void setplayermodel(entity e, string modelname)
 {
        precache_model(modelname);
-       setmodel(e, modelname);
+       _setmodel(e, modelname);
        player_setupanimsformodel();
        UpdatePlayerSounds();
 }
@@ -186,7 +186,7 @@ putting a client as observer in the server
 */
 void FixPlayermodel();
 void PutObserverInServer (void)
-{
+{SELFPARAM();
        entity  spot;
     self.hud = HUD_NORMAL;
 
@@ -205,6 +205,7 @@ void PutObserverInServer (void)
        }
 
        self.frags = FRAGS_SPECTATOR;
+       self.bot_attack = false;
 
        MUTATOR_CALLHOOK(MakePlayerObserver);
 
@@ -292,7 +293,7 @@ void PutObserverInServer (void)
        self.weapons = '0 0 0';
        self.model = "";
        FixPlayermodel();
-       setmodel(self, "null");
+       setmodel(self, MDL_Null);
        self.drawonlytoclient = self;
 
        setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX); // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
@@ -316,7 +317,7 @@ void PutObserverInServer (void)
 
 .float model_randomizer;
 void FixPlayermodel()
-{
+{SELFPARAM();
        string defaultmodel;
        float defaultskin, chmdl, oldskin, n, i;
        vector m1, m2;
@@ -329,9 +330,8 @@ void FixPlayermodel()
        {
                if(teamplay)
                {
-                       string s;
-                       s = Static_Team_ColorName_Lower(self.team);
-                       if(s != "neutral")
+                       string s = Static_Team_ColorName_Lower(self.team);
+                       if (s != "neutral")
                        {
                                defaultmodel = cvar_string(strcat("sv_defaultplayermodel_", s));
                                defaultskin = cvar(strcat("sv_defaultplayerskin_", s));
@@ -406,15 +406,11 @@ void FixPlayermodel()
                                setcolor(self, stof(autocvar_sv_defaultplayercolors));
 }
 
-/*
-=============
-PutClientInServer
 
-Called when a client spawns in the server
-=============
-*/
-void PutClientInServer (void)
+/** Called when a client spawns in the server */
+void PutClientInServer()
 {
+       SELFPARAM();
        if(IS_BOT_CLIENT(self))
                self.classname = "player";
        else if(IS_REAL_CLIENT(self))
@@ -436,7 +432,7 @@ void PutClientInServer (void)
 
        if(IS_PLAYER(self))
        {
-               entity spot, oldself;
+               entity spot;
 
                accuracy_resend(self);
 
@@ -515,10 +511,10 @@ void PutClientInServer (void)
                if(g_weaponarena_random) // WEAPONTODO: more stuff that should be in a mutator. also: rename those cvars
                {
                        if(g_weaponarena_random_with_blaster)
-                               self.weapons &= ~WEPSET_BLASTER;
+                               self.weapons &= ~WEPSET(BLASTER);
                        W_RandomWeapons(self, g_weaponarena_random);
                        if(g_weaponarena_random_with_blaster)
-                               self.weapons |= WEPSET_BLASTER;
+                               self.weapons |= WEPSET(BLASTER);
                }
 
                self.items = start_items;
@@ -609,7 +605,7 @@ void PutClientInServer (void)
                        self.killcount = 0;
                }
 
-               CL_SpawnWeaponentity();
+               CL_SpawnWeaponentity(self);
                self.alpha = default_player_alpha;
                self.colormod = '1 1 1' * autocvar_g_player_brightness;
                self.exteriorweaponentity.alpha = default_weapon_alpha;
@@ -624,7 +620,8 @@ void PutClientInServer (void)
                // reset fields the weapons may use
                for (int j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       WEP_ACTION(j, WR_RESETPLAYER);
+                       Weapon w = get_weaponinfo(j);
+                       w.wr_resetplayer(w);
 
                        // all weapons must be fully loaded when we spawn
                        entity e = get_weaponinfo(j);
@@ -632,16 +629,12 @@ void PutClientInServer (void)
                                self.(weapon_load[j]) = e.reloading_ammo;
                }
 
-               oldself = self;
-               self = spot;
-                       activator = oldself;
-                               string s;
-                               s = self.target;
-                               self.target = string_null;
-                               SUB_UseTargets();
-                               self.target = s;
-                       activator = world;
-               self = oldself;
+               string s = spot.target;
+               spot.target = string_null;
+               activator = self;
+               WITH(entity, self, spot, SUB_UseTargets());
+               activator = world;
+               spot.target = s;
 
                Unfreeze(self);
 
@@ -674,7 +667,7 @@ void PutClientInServer (void)
 .float ebouncefactor, ebouncestop; // electro's values
 // TODO do we need all these fields, or should we stop autodetecting runtime
 // changes and just have a console command to update this?
-float ClientInit_SendEntity(entity to, int sf)
+bool ClientInit_SendEntity(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_INIT);
        WriteByte(MSG_ENTITY, g_nexball_meter_period * 32);
@@ -707,7 +700,7 @@ float ClientInit_SendEntity(entity to, int sf)
 }
 
 void ClientInit_CheckUpdate()
-{
+{SELFPARAM();
        self.nextthink = time;
        if(self.count != autocvar_g_balance_armor_blockpercent)
        {
@@ -737,18 +730,13 @@ void ClientInit_CheckUpdate()
 }
 
 void ClientInit_Spawn()
-{
-       entity o;
-       entity e;
-       e = spawn();
+{SELFPARAM();
+       entity e = spawn();
        e.classname = "clientinit";
        e.think = ClientInit_CheckUpdate;
        Net_LinkEntity(e, false, 0, ClientInit_SendEntity);
 
-       o = self;
-       self = e;
-       ClientInit_CheckUpdate();
-       self = o;
+       WITH(entity, self, e, ClientInit_CheckUpdate());
 }
 
 /*
@@ -768,7 +756,7 @@ SetChangeParms
 =============
 */
 void SetChangeParms (void)
-{
+{SELFPARAM();
        // save parms for level change
        parm1 = self.parm_idlesince - time;
 }
@@ -779,7 +767,7 @@ DecodeLevelParms
 =============
 */
 void DecodeLevelParms (void)
-{
+{SELFPARAM();
        // load parms
        self.parm_idlesince = parm1;
        if(self.parm_idlesince == -(86400 * 366))
@@ -799,7 +787,7 @@ Called when a client types 'kill' in the console
 
 .float clientkill_nexttime;
 void ClientKill_Now_TeamChange()
-{
+{SELFPARAM();
        if(self.killindicator_teamchange == -1)
        {
                JoinBestTeam( self, false, true );
@@ -816,7 +804,7 @@ void ClientKill_Now_TeamChange()
 }
 
 void ClientKill_Now()
-{
+{SELFPARAM();
        if(self.vehicle)
        {
            vehicles_exit(VHEF_RELEASE);
@@ -841,7 +829,7 @@ void ClientKill_Now()
        // now I am sure the player IS dead
 }
 void KillIndicator_Think()
-{
+{SELFPARAM();
        if (gameover)
        {
                self.owner.killindicator = world;
@@ -858,8 +846,7 @@ void KillIndicator_Think()
 
        if(self.cnt <= 0)
        {
-               self = self.owner;
-               ClientKill_Now(); // no oldself needed
+               WITH(entity, self, self.owner, ClientKill_Now());
                return;
        }
     else if(g_cts && self.health == 1) // health == 1 means that it's silent
@@ -870,7 +857,7 @@ void KillIndicator_Think()
        else
        {
                if(self.cnt <= 10)
-                       setmodel(self, strcat("models/sprites/", ftos(self.cnt), ".spr32"));
+                       setmodel(self, MDL_NUM(self.cnt));
                if(IS_REAL_CLIENT(self.owner))
                {
                        if(self.cnt <= 10)
@@ -883,7 +870,7 @@ void KillIndicator_Think()
 
 float clientkilltime;
 void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 = spec
-{
+{SELFPARAM();
        float killtime;
        float starttime;
        entity e;
@@ -987,7 +974,7 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2
 }
 
 void ClientKill (void)
-{
+{SELFPARAM();
        if(gameover) return;
        if(self.player_blocked) return;
        if(self.frozen) return;
@@ -1048,7 +1035,7 @@ Called once (not at each match start) when a client begins a connection to the s
 =============
 */
 void ClientPreConnect (void)
-{
+{SELFPARAM();
        if(autocvar_sv_eventlog)
        {
                GameLogEcho(sprintf(":connect:%d:%d:%s",
@@ -1069,7 +1056,7 @@ Called when a client connects to the server
 */
 void DecodeLevelParms (void);
 void ClientConnect (void)
-{
+{SELFPARAM();
        float t;
 
        if(IS_CLIENT(self))
@@ -1229,7 +1216,7 @@ void ClientConnect (void)
        else
                stuffcmd(self, "set _teams_available 0\n");
 
-       attach_entcs();
+       attach_entcs(self);
 
        bot_relinkplayerlist();
 
@@ -1250,7 +1237,7 @@ void ClientConnect (void)
                        Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
                }
 
-               if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET_TUBA))
+               if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET(TUBA)))
                        stuffcmd(self, "cl_cmd settemp chase_active 1\n");
        }
 
@@ -1264,7 +1251,7 @@ void ClientConnect (void)
 
        CheatInitClient();
 
-       CSQCMODEL_AUTOINIT();
+       CSQCMODEL_AUTOINIT(self);
 
        self.model_randomizer = random();
 
@@ -1272,10 +1259,7 @@ void ClientConnect (void)
                sv_notice_join();
 
        for (entity e = world; (e = findfloat(e, init_for_player_needed, 1)); ) {
-               entity oldself = self;
-               self = e;
-               e.init_for_player(oldself);
-               self = oldself;
+               WITH(entity, self, e, e.init_for_player(this));
        }
 
        MUTATOR_CALLHOOK(ClientConnect, self);
@@ -1290,7 +1274,7 @@ Called when a client disconnects from the server
 .entity chatbubbleentity;
 void ReadyCount();
 void ClientDisconnect (void)
-{
+{SELFPARAM();
        if(self.vehicle)
            vehicles_exit(VHEF_RELEASE);
 
@@ -1318,8 +1302,7 @@ void ClientDisconnect (void)
 
        bot_clientdisconnect();
 
-       if(self.entcs)
-               detach_entcs();
+       detach_entcs(self);
 
        if(autocvar_sv_eventlog)
                GameLogEcho(strcat(":part:", ftos(self.playerid)));
@@ -1374,7 +1357,7 @@ void ClientDisconnect (void)
 
 .float BUTTON_CHAT;
 void ChatBubbleThink()
-{
+{SELFPARAM();
        self.nextthink = time;
        if ((self.owner.alpha < 0) || self.owner.chatbubbleentity != self)
        {
@@ -1383,9 +1366,9 @@ void ChatBubbleThink()
                remove(self);
                return;
        }
-       
+
        self.mdl = "";
-       
+
        if ( !self.owner.deadflag && IS_PLAYER(self.owner) )
        {
                if ( self.owner.active_minigame )
@@ -1393,14 +1376,14 @@ void ChatBubbleThink()
                else if ( self.owner.BUTTON_CHAT )
                        self.mdl = "models/misc/chatbubble.spr";
        }
-       
+
        if ( self.model != self.mdl )
-               setmodel(self, self.mdl);
+               _setmodel(self, self.mdl);
 
 }
 
 void UpdateChatBubble()
-{
+{SELFPARAM();
        if (self.alpha < 0)
                return;
        // spawn a chatbubble entity if needed
@@ -1411,7 +1394,7 @@ void UpdateChatBubble()
                self.chatbubbleentity.exteriormodeltoclient = self;
                self.chatbubbleentity.think = ChatBubbleThink;
                self.chatbubbleentity.nextthink = time;
-               setmodel(self.chatbubbleentity, "models/misc/chatbubble.spr"); // precision set below
+               setmodel(self.chatbubbleentity, MDL_CHAT); // precision set below
                //setorigin(self.chatbubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1');
                setorigin(self.chatbubbleentity, '0 0 15' + self.maxs_z * '0 0 1');
                setattachment(self.chatbubbleentity, self, "");  // sticks to moving player better, also conserves bandwidth
@@ -1439,7 +1422,7 @@ void UpdateChatBubble()
 }*/
 
 void respawn(void)
-{
+{SELFPARAM();
        if(self.alpha >= 0 && autocvar_g_respawn_ghosts)
        {
                self.solid = SOLID_NOT;
@@ -1460,15 +1443,15 @@ void respawn(void)
 }
 
 void play_countdown(float finished, string samp)
-{
+{SELFPARAM();
        if(IS_REAL_CLIENT(self))
                if(floor(finished - time - frametime) != floor(finished - time))
                        if(finished - time < 6)
-                               sound (self, CH_INFO, samp, VOL_BASE, ATTEN_NORM);
+                               _sound (self, CH_INFO, samp, VOL_BASE, ATTEN_NORM);
 }
 
 void player_powerups (void)
-{
+{SELFPARAM();
        // add a way to see what the items were BEFORE all of these checks for the mutator hook
        int items_prev = self.items;
 
@@ -1489,7 +1472,7 @@ void player_powerups (void)
        {
                if (self.items & ITEM_Strength.m_itemid)
                {
-                       play_countdown(self.strength_finished, "misc/poweroff.wav");
+                       play_countdown(self.strength_finished, SND(POWEROFF));
                        self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
                        if (time > self.strength_finished)
                        {
@@ -1509,7 +1492,7 @@ void player_powerups (void)
                }
                if (self.items & ITEM_Shield.m_itemid)
                {
-                       play_countdown(self.invincible_finished, "misc/poweroff.wav");
+                       play_countdown(self.invincible_finished, SND(POWEROFF));
                        self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
                        if (time > self.invincible_finished)
                        {
@@ -1542,7 +1525,7 @@ void player_powerups (void)
                        }
                        else
                        {
-                               play_countdown(self.superweapons_finished, "misc/poweroff.wav");
+                               play_countdown(self.superweapons_finished, SND(POWEROFF));
                                if (time > self.superweapons_finished)
                                {
                                        self.items = self.items - (self.items & IT_SUPERWEAPON);
@@ -1631,7 +1614,7 @@ float CalcRotRegen(float current, float regenstable, float regenfactor, float re
 }
 
 void player_regen (void)
-{
+{SELFPARAM();
        float max_mod, regen_mod, rot_mod, limit_mod;
        max_mod = regen_mod = rot_mod = limit_mod = 1;
        regen_mod_max = max_mod;
@@ -1691,7 +1674,7 @@ void player_regen (void)
 
 float zoomstate_set;
 void SetZoomState(float z)
-{
+{SELFPARAM();
        if(z != self.zoomstate)
        {
                self.zoomstate = z;
@@ -1700,7 +1683,8 @@ void SetZoomState(float z)
        zoomstate_set = 1;
 }
 
-void GetPressedKeys(void) {
+void GetPressedKeys()
+{SELFPARAM();
        MUTATOR_CALLHOOK(GetPressedKeys);
        #define X(var,bit,flag) (flag ? var |= bit : var &= ~bit)
        X(self.pressedkeys, KEY_FORWARD,        self.movement_x > 0);
@@ -1721,7 +1705,8 @@ spectate mode routines
 ======================
 */
 
-void SpectateCopy(entity spectatee) {
+void SpectateCopy(entity spectatee)
+{SELFPARAM();
        MUTATOR_CALLHOOK(SpectateCopy, spectatee, self);
        self.armortype = spectatee.armortype;
        self.armorvalue = spectatee.armorvalue;
@@ -1797,7 +1782,7 @@ void SpectateCopy(entity spectatee) {
 }
 
 bool SpectateUpdate()
-{
+{SELFPARAM();
        if(!self.enemy)
            return false;
 
@@ -1813,7 +1798,7 @@ bool SpectateUpdate()
 }
 
 bool SpectateSet()
-{
+{SELFPARAM();
        if(!IS_PLAYER(self.enemy))
                return false;
 
@@ -1842,7 +1827,7 @@ void SetSpectator(entity player, entity spectatee)
 }
 
 bool Spectate(entity pl)
-{
+{SELFPARAM();
        if(g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
        if(DIFF_TEAM(pl, self))
                return false;
@@ -1853,7 +1838,7 @@ bool Spectate(entity pl)
 
 // Returns next available player to spectate if g_ca_spectate_enemies == 0
 entity CA_SpectateNext(entity start)
-{
+{SELFPARAM();
        if(SAME_TEAM(start, self))
                return start;
 
@@ -1874,7 +1859,7 @@ entity CA_SpectateNext(entity start)
 }
 
 bool SpectateNext()
-{
+{SELFPARAM();
        other = find(self.enemy, classname, "player");
 
        if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
@@ -1893,7 +1878,7 @@ bool SpectateNext()
 }
 
 bool SpectatePrev()
-{
+{SELFPARAM();
        // NOTE: chain order is from the highest to the lower entnum (unlike find)
        other = findchain(classname, "player");
        if (!other) // no player
@@ -1938,7 +1923,7 @@ Update a respawn countdown display.
 =============
 */
 void ShowRespawnCountdown()
-{
+{SELFPARAM();
        float number;
        if(self.deadflag == DEAD_NO) // just respawned?
                return;
@@ -1957,7 +1942,7 @@ void ShowRespawnCountdown()
 }
 
 void LeaveSpectatorMode()
-{
+{SELFPARAM();
        if(self.caplayer)
                return;
        if(nJoinAllowed(self))
@@ -1995,7 +1980,8 @@ void LeaveSpectatorMode()
  * it checks whether the number of currently playing players exceeds g_maxplayers.
  * @return int number of free slots for players, 0 if none
  */
-float nJoinAllowed(entity ignore) {
+float nJoinAllowed(entity ignore)
+{SELFPARAM();
        if(!ignore)
        // this is called that way when checking if anyone may be able to join (to build qcstatus)
        // so report 0 free slots if restricted
@@ -2034,7 +2020,8 @@ float nJoinAllowed(entity ignore) {
  * Checks whether the client is an observer or spectator, if so, he will get kicked after
  * g_maxplayers_spectator_blocktime seconds
  */
-void checkSpectatorBlock() {
+void checkSpectatorBlock()
+{SELFPARAM();
        if(IS_SPEC(self) || IS_OBSERVER(self))
        if(!self.caplayer)
        if(IS_REAL_CLIENT(self))
@@ -2047,7 +2034,7 @@ void checkSpectatorBlock() {
 }
 
 void PrintWelcomeMessage()
-{
+{SELFPARAM();
        if(self.motd_actived_time == 0)
        {
                if (autocvar_g_campaign) {
@@ -2094,7 +2081,7 @@ void PrintWelcomeMessage()
 }
 
 void ObserverThink()
-{
+{SELFPARAM();
        if ( self.impulse )
        {
                MinigameImpulse(self.impulse);
@@ -2129,7 +2116,7 @@ void ObserverThink()
 }
 
 void SpectatorThink()
-{
+{SELFPARAM();
        if ( self.impulse )
        {
                if(MinigameImpulse(self.impulse))
@@ -2184,7 +2171,7 @@ void SpectatorThink()
 
 void vehicles_enter (entity pl, entity veh);
 void PlayerUseKey()
-{
+{SELFPARAM();
        if (!IS_PLAYER(self))
                return;
 
@@ -2270,7 +2257,7 @@ void() nexball_setstatus;
 .float last_vehiclecheck;
 .int items_added;
 void PlayerPreThink (void)
-{
+{SELFPARAM();
        WarpZone_PlayerPhysics_FixVAngle();
 
        self.stat_game_starttime = game_starttime;
@@ -2558,14 +2545,12 @@ void PlayerPreThink (void)
 
                FixPlayermodel();
 
-               GrapplingHookFrame();
-
                // LordHavoc: allow firing on move frames (sub-ticrate), this gives better timing on slow servers
                //if(frametime)
                {
                        self.items &= ~self.items_added;
 
-                       W_WeaponFrame();
+                       W_WeaponFrame(self);
 
                        self.items_added = 0;
                        if(self.items & ITEM_Jetpack.m_itemid)
@@ -2626,15 +2611,14 @@ void PlayerPreThink (void)
        {
                self.teamkill_soundtime = 0;
 
-               entity oldpusher, oldself;
-
-               oldself = self; self = self.teamkill_soundsource;
-               oldpusher = self.pusher; self.pusher = oldself;
+               setself(self.teamkill_soundsource);
+               entity oldpusher = self.pusher;
+               self.pusher = this;
 
                PlayerSound(playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
 
                self.pusher = oldpusher;
-               self = oldself;
+               setself(this);
        }
 
        if(self.taunt_soundtime)
@@ -2661,7 +2645,7 @@ Called every frame for each client after the physics are run
 */
 .float idlekick_lasttimeleft;
 void PlayerPostThink (void)
-{
+{SELFPARAM();
        if(sv_maxidle > 0 && frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
        if(IS_REAL_CLIENT(self))
        if(IS_PLAYER(self) || sv_maxidle_spectatorsareidle)
@@ -2733,5 +2717,5 @@ void PlayerPostThink (void)
 
        playerdemo_write();
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
index dd010214e589a57cbbfc70033bf22e87f67e25bc..a594c83c7c93b72876eb6fc3a24f6a47342945e3 100644 (file)
@@ -51,7 +51,7 @@
  */
 
 void ImpulseCommands (void)
-{
+{SELFPARAM();
        int imp;
        vector org;
        float i;
@@ -134,7 +134,10 @@ void ImpulseCommands (void)
                                        W_PreviousWeapon(1);
                                        break;
                                case 20:
-                                       if(!forbidWeaponUse(self)) { WEP_ACTION(self.weapon, WR_RELOAD); }
+                                       if(!forbidWeaponUse(self)) {
+                                               Weapon w = get_weaponinfo(self.weapon);
+                                               w.wr_reload(w);
+                                       }
                                        break;
                        }
                }
@@ -158,11 +161,11 @@ void ImpulseCommands (void)
                else
                        self.impulse = imp; // retry in next frame
        }
-       else if(imp >= 230 && imp <= 253)
+       else if(imp >= WEP_IMPULSE_BEGIN && imp <= WEP_IMPULSE_END)
        {
                if(!self.vehicle)
                if(self.deadflag == DEAD_NO)
-                       W_SwitchWeapon (imp - 230 + WEP_FIRST);
+                       W_SwitchWeapon (imp - WEP_IMPULSE_BEGIN + WEP_FIRST);
                else
                        self.impulse = imp; // retry in next frame
        }
@@ -355,7 +358,7 @@ void ImpulseCommands (void)
                                                        setorigin(e, org);
                                                        LOG_INFO("spawn without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
                                                        e.effects |= EF_NODEPTHTEST;
-                                                       setmodel(e, self.model);
+                                                       _setmodel(e, self.model);
                                                        e.frame = self.frame;
                                                        e.skin = self.skin;
                                                        e.colormod = '8 0.5 8';
index 6310d7ff3ef3cb6daeefb423615dc0f8187161a7..e94ba628323711d0b469eaa0af9ba060788ebdfd 100644 (file)
@@ -25,7 +25,7 @@
 #include "../common/animdecide.qh"
 
 void CopyBody_Think(void)
-{
+{SELFPARAM();
        if(self.CopyBody_nextthink && time > self.CopyBody_nextthink)
        {
                self.CopyBody_think();
@@ -35,90 +35,88 @@ void CopyBody_Think(void)
                self.CopyBody_think = self.think;
                self.think = CopyBody_Think;
        }
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
        self.nextthink = time;
 }
 void CopyBody(float keepvelocity)
-{
-       entity oldself;
+{SELFPARAM();
        if (self.effects & EF_NODRAW)
                return;
-       oldself = self;
-       self = spawn();
-       self.enemy = oldself;
-       self.lip = oldself.lip;
-       self.colormap = oldself.colormap;
-       self.iscreature = oldself.iscreature;
-       self.teleportable = oldself.teleportable;
-       self.damagedbycontents = oldself.damagedbycontents;
-       self.angles = oldself.angles;
-       self.v_angle = oldself.v_angle;
-       self.avelocity = oldself.avelocity;
+       setself(spawn());
+       self.enemy = this;
+       self.lip = this.lip;
+       self.colormap = this.colormap;
+       self.iscreature = this.iscreature;
+       self.teleportable = this.teleportable;
+       self.damagedbycontents = this.damagedbycontents;
+       self.angles = this.angles;
+       self.v_angle = this.v_angle;
+       self.avelocity = this.avelocity;
        self.classname = "body";
-       self.damageforcescale = oldself.damageforcescale;
-       self.effects = oldself.effects;
-       self.glowmod = oldself.glowmod;
-       self.event_damage = oldself.event_damage;
-       self.anim_state = oldself.anim_state;
-       self.anim_time = oldself.anim_time;
-       self.anim_lower_action = oldself.anim_lower_action;
-       self.anim_lower_time = oldself.anim_lower_time;
-       self.anim_upper_action = oldself.anim_upper_action;
-       self.anim_upper_time = oldself.anim_upper_time;
-       self.anim_implicit_state = oldself.anim_implicit_state;
-       self.anim_implicit_time = oldself.anim_implicit_time;
-       self.anim_lower_implicit_action = oldself.anim_lower_implicit_action;
-       self.anim_lower_implicit_time = oldself.anim_lower_implicit_time;
-       self.anim_upper_implicit_action = oldself.anim_upper_implicit_action;
-       self.anim_upper_implicit_time = oldself.anim_upper_implicit_time;
-       self.dphitcontentsmask = oldself.dphitcontentsmask;
-       self.death_time = oldself.death_time;
-       self.pain_finished = oldself.pain_finished;
-       self.health = oldself.health;
-       self.armorvalue = oldself.armorvalue;
-       self.armortype = oldself.armortype;
-       self.model = oldself.model;
-       self.modelindex = oldself.modelindex;
-       self.skin = oldself.skin;
-       self.species = oldself.species;
-       self.movetype = oldself.movetype;
-       self.solid = oldself.solid;
-       self.ballistics_density = oldself.ballistics_density;
-       self.takedamage = oldself.takedamage;
-       self.customizeentityforclient = oldself.customizeentityforclient;
-       self.uncustomizeentityforclient = oldself.uncustomizeentityforclient;
-       self.uncustomizeentityforclient_set = oldself.uncustomizeentityforclient_set;
+       self.damageforcescale = this.damageforcescale;
+       self.effects = this.effects;
+       self.glowmod = this.glowmod;
+       self.event_damage = this.event_damage;
+       self.anim_state = this.anim_state;
+       self.anim_time = this.anim_time;
+       self.anim_lower_action = this.anim_lower_action;
+       self.anim_lower_time = this.anim_lower_time;
+       self.anim_upper_action = this.anim_upper_action;
+       self.anim_upper_time = this.anim_upper_time;
+       self.anim_implicit_state = this.anim_implicit_state;
+       self.anim_implicit_time = this.anim_implicit_time;
+       self.anim_lower_implicit_action = this.anim_lower_implicit_action;
+       self.anim_lower_implicit_time = this.anim_lower_implicit_time;
+       self.anim_upper_implicit_action = this.anim_upper_implicit_action;
+       self.anim_upper_implicit_time = this.anim_upper_implicit_time;
+       self.dphitcontentsmask = this.dphitcontentsmask;
+       self.death_time = this.death_time;
+       self.pain_finished = this.pain_finished;
+       self.health = this.health;
+       self.armorvalue = this.armorvalue;
+       self.armortype = this.armortype;
+       self.model = this.model;
+       self.modelindex = this.modelindex;
+       self.skin = this.skin;
+       self.species = this.species;
+       self.movetype = this.movetype;
+       self.solid = this.solid;
+       self.ballistics_density = this.ballistics_density;
+       self.takedamage = this.takedamage;
+       self.customizeentityforclient = this.customizeentityforclient;
+       self.uncustomizeentityforclient = this.uncustomizeentityforclient;
+       self.uncustomizeentityforclient_set = this.uncustomizeentityforclient_set;
        if (keepvelocity == 1)
-               self.velocity = oldself.velocity;
+               self.velocity = this.velocity;
        self.oldvelocity = self.velocity;
-       self.alpha = oldself.alpha;
-       self.fade_time = oldself.fade_time;
-       self.fade_rate = oldself.fade_rate;
-       //self.weapon = oldself.weapon;
-       setorigin(self, oldself.origin);
-       setsize(self, oldself.mins, oldself.maxs);
-       self.prevorigin = oldself.origin;
+       self.alpha = this.alpha;
+       self.fade_time = this.fade_time;
+       self.fade_rate = this.fade_rate;
+       //self.weapon = this.weapon;
+       setorigin(self, this.origin);
+       setsize(self, this.mins, this.maxs);
+       self.prevorigin = this.origin;
        self.reset = SUB_Remove;
 
-       Drag_MoveDrag(oldself, self);
+       Drag_MoveDrag(this, self);
 
        if(self.colormap <= maxclients && self.colormap > 0)
-               self.colormap = 1024 + oldself.clientcolors;
+               self.colormap = 1024 + this.clientcolors;
 
-       CSQCMODEL_AUTOINIT();
-       self.CopyBody_nextthink = oldself.nextthink;
-       self.CopyBody_think = oldself.think;
+       CSQCMODEL_AUTOINIT(self);
+       self.CopyBody_nextthink = this.nextthink;
+       self.CopyBody_think = this.think;
        self.nextthink = time;
        self.think = CopyBody_Think;
        // "bake" the current animation frame for clones (they don't get clientside animation)
        animdecide_load_if_needed(self);
        animdecide_setframes(self, false, frame, frame1time, frame2, frame2time);
 
-       self = oldself;
+       setself(this);
 }
 
 float player_getspecies()
-{
+{SELFPARAM();
        float s;
        get_model_parameters(self.model, self.skin);
        s = get_model_parameters_species;
@@ -129,14 +127,14 @@ float player_getspecies()
 }
 
 void player_setupanimsformodel()
-{
+{SELFPARAM();
        // load animation info
        animdecide_load_if_needed(self);
        animdecide_setstate(self, 0, false);
 }
 
 void player_anim (void)
-{
+{SELFPARAM();
        int deadbits = (self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
        if(self.deadflag) {
                if (!deadbits) {
@@ -169,7 +167,7 @@ void player_anim (void)
 }
 
 void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        float take, save;
        vector v;
        Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
@@ -184,11 +182,11 @@ void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int de
        if(sound_allowed(MSG_BROADCAST, attacker))
        {
                if (save > 10)
-                       sound (self, CH_SHOTS, "misc/armorimpact.wav", VOL_BASE, ATTEN_NORM);
+                       sound (self, CH_SHOTS, SND_ARMORIMPACT, VOL_BASE, ATTEN_NORM);
                else if (take > 30)
-                       sound (self, CH_SHOTS, "misc/bodyimpact2.wav", VOL_BASE, ATTEN_NORM);
+                       sound (self, CH_SHOTS, SND_BODYIMPACT2, VOL_BASE, ATTEN_NORM);
                else if (take > 10)
-                       sound (self, CH_SHOTS, "misc/bodyimpact1.wav", VOL_BASE, ATTEN_NORM);
+                       sound (self, CH_SHOTS, SND_BODYIMPACT1, VOL_BASE, ATTEN_NORM);
        }
 
        if (take > 50)
@@ -221,7 +219,7 @@ void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, int de
 }
 
 void calculate_player_respawn_time()
-{
+{SELFPARAM();
        if(g_ca)
                return;
 
@@ -308,7 +306,7 @@ void calculate_player_respawn_time()
 }
 
 void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        float take, save, dh, da;
        int j;
        vector v;
@@ -397,11 +395,11 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp
        if(sound_allowed(MSG_BROADCAST, attacker))
        {
                if (save > 10)
-                       sound (self, CH_SHOTS, "misc/armorimpact.wav", VOL_BASE, ATTEN_NORM);
+                       sound (self, CH_SHOTS, SND_ARMORIMPACT, VOL_BASE, ATTEN_NORM);
                else if (take > 30)
-                       sound (self, CH_SHOTS, "misc/bodyimpact2.wav", VOL_BASE, ATTEN_NORM);
+                       sound (self, CH_SHOTS, SND_BODYIMPACT2, VOL_BASE, ATTEN_NORM);
                else if (take > 10)
-                       sound (self, CH_SHOTS, "misc/bodyimpact1.wav", VOL_BASE, ATTEN_NORM); // FIXME possibly remove them?
+                       sound (self, CH_SHOTS, SND_BODYIMPACT1, VOL_BASE, ATTEN_NORM); // FIXME possibly remove them?
        }
 
        if (take > 50)
@@ -550,7 +548,8 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp
                MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, self, deathtype);
                excess = frag_damage;
 
-               WEP_ACTION(self.weapon, WR_PLAYERDEATH);
+               Weapon wep = get_weaponinfo(self.weapon);
+               wep.wr_playerdeath(wep);
 
                RemoveGrapplingHook(self);
 
@@ -632,7 +631,8 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp
                // reset fields the weapons may use just in case
                for (j = WEP_FIRST; j <= WEP_LAST; ++j)
                {
-                       WEP_ACTION(j, WR_RESETPLAYER);
+                       Weapon w = get_weaponinfo(j);
+                       w.wr_resetplayer(w);
                        ATTACK_FINISHED_FOR(self, j) = 0;
                }
        }
@@ -893,7 +893,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
                {
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
-                       FOR_EACH_REALCLIENT(head) 
+                       FOR_EACH_REALCLIENT(head)
                                if(head != source)
                                if(head.active_minigame == source.active_minigame)
                                        sprint(head, msgstr);
@@ -988,16 +988,15 @@ void PrecacheGlobalSound(string samplestring)
 
 void PrecachePlayerSounds(string f)
 {
-       float fh;
-       string s;
-       fh = fopen(f, FILE_READ);
-       if(fh < 0)
+       int fh = fopen(f, FILE_READ);
+       if (fh < 0)
                return;
-       while((s = fgets(fh)))
+       for (string s; (s = fgets(fh)); )
        {
-               if(tokenize_console(s) != 3)
+               int n = tokenize_console(s);
+               if (n != 3)
                {
-                       LOG_TRACE("Invalid sound info line: ", s, "\n");
+                       if (n != 0) LOG_TRACEF("Invalid sound info line: %s\n", s);
                        continue;
                }
                PrecacheGlobalSound(strcat(argv(1), " ", argv(2)));
@@ -1014,7 +1013,7 @@ void PrecachePlayerSounds(string f)
 }
 
 void ClearPlayerSounds()
-{
+{SELFPARAM();
 #define _VOICEMSG(m) if(self.playersound_##m) { strunzone(self.playersound_##m); self.playersound_##m = string_null; }
        ALLPLAYERSOUNDS
        ALLVOICEMSGS
@@ -1022,7 +1021,7 @@ void ClearPlayerSounds()
 }
 
 float LoadPlayerSounds(string f, float first)
-{
+{SELFPARAM();
        float fh;
        string s;
        var .string field;
@@ -1050,7 +1049,7 @@ float LoadPlayerSounds(string f, float first)
 }
 
 void UpdatePlayerSounds()
-{
+{SELFPARAM();
        if(self.modelindex == self.modelindex_for_playersound)
        if(self.skin == self.skin_for_playersound)
                return;
@@ -1064,7 +1063,7 @@ void UpdatePlayerSounds()
 }
 
 void FakeGlobalSound(string sample, float chan, float voicetype)
-{
+{SELFPARAM();
        float n;
        float tauntrand;
 
@@ -1139,7 +1138,7 @@ void FakeGlobalSound(string sample, float chan, float voicetype)
 }
 
 void GlobalSound(string sample, float chan, float voicetype)
-{
+{SELFPARAM();
        float n;
        float tauntrand;
 
@@ -1228,7 +1227,7 @@ void GlobalSound(string sample, float chan, float voicetype)
                        }
                        break;
                case VOICETYPE_PLAYERSOUND:
-                       sound(self, chan, sample, VOL_BASE, ATTEN_NORM);
+                       _sound(self, chan, sample, VOL_BASE, ATTEN_NORM);
                        break;
                default:
                        backtrace("Invalid voice type!");
@@ -1237,16 +1236,15 @@ void GlobalSound(string sample, float chan, float voicetype)
 }
 
 void PlayerSound(.string samplefield, float chan, float voicetype)
-{
+{SELFPARAM();
        GlobalSound(self.(samplefield), chan, voicetype);
 }
 
 void VoiceMessage(string type, string msg)
-{
-       var .string sample;
+{SELFPARAM();
        float voicetype, ownteam;
        float flood;
-       sample = GetVoiceMessageSampleField(type);
+       var .string sample = GetVoiceMessageSampleField(type);
 
        if(GetPlayerSoundSampleField_notFound)
        {
index a34752c9c76587b079be74788917a245343ebcdf..f849deb6a878119056aca16a3cfe81fd1995c89e 100644 (file)
@@ -40,7 +40,7 @@ void ClientKill_TeamChange (float targetteam); // 0 = don't change, -1 = auto, -
 // =========================================================
 
 float SV_ParseClientCommand_floodcheck()
-{
+{SELFPARAM();
        if (!timeout_status) // not while paused
        {
                if(time <= (self.cmd_floodtime + autocvar_sv_clientcommand_antispam_time))
@@ -63,7 +63,7 @@ float SV_ParseClientCommand_floodcheck()
 // =======================
 
 void ClientCommand_autoswitch(float request, float argc)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -88,7 +88,7 @@ void ClientCommand_autoswitch(float request, float argc)
 }
 
 void ClientCommand_clientversion(float request, float argc) // internal command, used only by code
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -131,7 +131,7 @@ void ClientCommand_clientversion(float request, float argc) // internal command,
 }
 
 void ClientCommand_mv_getpicture(float request, float argc) // internal command, used only by code
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -157,7 +157,7 @@ void ClientCommand_mv_getpicture(float request, float argc) // internal command,
 }
 
 void ClientCommand_join(float request)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -199,7 +199,7 @@ void ClientCommand_join(float request)
 }
 
 void ClientCommand_physics(float request, float argc)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -239,7 +239,7 @@ void ClientCommand_physics(float request, float argc)
 }
 
 void ClientCommand_ready(float request) // todo: anti-spam for toggling readyness
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -285,7 +285,7 @@ void ClientCommand_ready(float request) // todo: anti-spam for toggling readynes
 }
 
 void ClientCommand_say(float request, float argc, string command)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -305,7 +305,7 @@ void ClientCommand_say(float request, float argc, string command)
 }
 
 void ClientCommand_say_team(float request, float argc, string command)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -325,7 +325,7 @@ void ClientCommand_say_team(float request, float argc, string command)
 }
 
 void ClientCommand_selectteam(float request, float argc)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -397,7 +397,7 @@ void ClientCommand_selectteam(float request, float argc)
 }
 
 void ClientCommand_selfstuff(float request, string command)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -421,7 +421,7 @@ void ClientCommand_selfstuff(float request, string command)
 }
 
 void ClientCommand_sentcvar(float request, float argc, string command)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -455,7 +455,7 @@ void ClientCommand_sentcvar(float request, float argc, string command)
 }
 
 void ClientCommand_spectate(float request)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -500,7 +500,7 @@ void ClientCommand_spectate(float request)
 }
 
 void ClientCommand_suggestmap(float request, float argc)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -524,7 +524,7 @@ void ClientCommand_suggestmap(float request, float argc)
 }
 
 void ClientCommand_tell(float request, float argc, string command)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -575,7 +575,7 @@ void ClientCommand_tell(float request, float argc, string command)
 }
 
 void ClientCommand_voice(float request, float argc, string command)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -652,7 +652,7 @@ void ClientCommand_(float request)
        /* nothing */
 
 void ClientCommand_macro_help()
-{
+{SELFPARAM();
        #define CLIENT_COMMAND(name,function,description) \
                { sprint(self, "  ^2", name, "^7: ", description, "\n"); }
 
@@ -701,7 +701,7 @@ void ClientCommand_macro_write_aliases(float fh)
 // If this function exists, server game code parses clientcommand before the engine code gets it.
 
 void SV_ParseClientCommand(string command)
-{
+{SELFPARAM();
        // If invalid UTF-8, don't even parse it
        string command2 = "";
        float len = strlen(command);
index ee832bcc8529d3ec9ef3e104a96209c39fc588c4..5ddea150a974103a04946359bcc5dcf6b22638e1 100644 (file)
@@ -178,7 +178,7 @@ void print_to(entity to, string input)
 
 // used by CommonCommand_timeout() and CommonCommand_timein() to handle game pausing and messaging and such.
 void timeout_handler_reset()
-{
+{SELFPARAM();
        timeout_caller = world;
        timeout_time = 0;
        timeout_leadtime = 0;
@@ -187,7 +187,7 @@ void timeout_handler_reset()
 }
 
 void timeout_handler_think()
-{
+{SELFPARAM();
        entity tmp_player;
 
        switch(timeout_status)
@@ -312,7 +312,7 @@ void CommonCommand_cvar_purechanges(float request, entity caller)
 }
 
 void CommonCommand_editmob(int request, entity caller, int argc)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
index 396337a1871572ba9a9797652389943010aed35b..8c15819e05ad174a0ea24f09e573b92061554048 100644 (file)
@@ -227,7 +227,7 @@ void RadarMap_Next()
        radarmapper = world;
 }
 void RadarMap_Think()
-{
+{SELFPARAM();
        // rough map entity
        //   cnt: current line
        //   size: pixel width/height
index fdf82e368fffaa4826a95a0c772707754a8dbabb..d08588ff99c1a3501fe28992bee5329c1654b7c5 100644 (file)
@@ -41,7 +41,7 @@ void PutObserverInServer (void);
 
 //  used by GameCommand_make_mapinfo()
 void make_mapinfo_Think()
-{
+{SELFPARAM();
        if(MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, 0, 1))
        {
                LOG_INFO("Done rebuiling mapinfos.\n");
@@ -196,7 +196,7 @@ void GameCommand_allready(float request)
 }
 
 void GameCommand_allspec(float request, float argc)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -207,10 +207,9 @@ void GameCommand_allspec(float request, float argc)
 
                        FOR_EACH_REALPLAYER(client)
                        {
-                               self = client;
-                               if(self.caplayer)
-                                       self.caplayer = 0;
-                               PutObserverInServer();
+                               if (client.caplayer)
+                                       client.caplayer = 0;
+                               WITH(entity, self, client, PutObserverInServer());
                                ++i;
                        }
                        if(i) { bprint(strcat("Successfully forced all (", ftos(i), ") players to spectate", (reason ? strcat(" for reason: '", reason, "'") : ""), ".\n")); }
@@ -230,7 +229,7 @@ void GameCommand_allspec(float request, float argc)
 }
 
 void GameCommand_anticheat(float request, float argc)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -240,8 +239,7 @@ void GameCommand_anticheat(float request, float argc)
 
                        if(accepted > 0)
                        {
-                               self = client;
-                               anticheat_report();
+                               WITH(entity, self, client, anticheat_report());
                                return;
                        }
                        else
@@ -818,11 +816,11 @@ void GameCommand_gettaginfo(float request, float argc)
                        {
                                tmp_entity = spawn();
                                if(argv(1) == "w")
-                                       setmodel(tmp_entity, (nextent(world)).weaponentity.model);
+                                       _setmodel(tmp_entity, (nextent(world)).weaponentity.model);
                                else
                                {
                                        precache_model(argv(1));
-                                       setmodel(tmp_entity, argv(1));
+                                       _setmodel(tmp_entity, argv(1));
                                }
                                tmp_entity.frame = stof(argv(2));
                                if(substring(argv(3), 0, 1) == "#")
@@ -876,11 +874,11 @@ void GameCommand_animbench(float request, float argc)
                        {
                                tmp_entity = spawn();
                                if(argv(1) == "w")
-                                       setmodel(tmp_entity, (nextent(world)).weaponentity.model);
+                                       _setmodel(tmp_entity, (nextent(world)).weaponentity.model);
                                else
                                {
                                        precache_model(argv(1));
-                                       setmodel(tmp_entity, argv(1));
+                                       _setmodel(tmp_entity, argv(1));
                                }
                                float f1 = stof(argv(2));
                                float f2 = stof(argv(3));
@@ -1002,7 +1000,7 @@ void GameCommand_make_mapinfo(float request)
 }
 
 void GameCommand_moveplayer(float request, float argc)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -1039,10 +1037,9 @@ void GameCommand_moveplayer(float request, float argc)
                                        {
                                                if(!IS_SPEC(client) && !IS_OBSERVER(client))
                                                {
-                                                       self = client;
-                                                       if(self.caplayer)
-                                                               self.caplayer = 0;
-                                                       PutObserverInServer();
+                                                       if (client.caplayer)
+                                                               client.caplayer = 0;
+                                                       WITH(entity, self, client, PutObserverInServer());
 
                                                        successful = strcat(successful, (successful ? ", " : ""), client.netname);
                                                }
@@ -1171,7 +1168,7 @@ void GameCommand_nospectators(float request)
 }
 
 void GameCommand_playerdemo(float request, float argc)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -1194,8 +1191,7 @@ void GameCommand_playerdemo(float request, float argc)
                                                        return;
                                                }
 
-                                               self = client;
-                                               playerdemo_open_read(argv(next_token));
+                                               WITH(entity, self, client, playerdemo_open_read(argv(next_token)));
                                                return;
                                        }
 
@@ -1210,8 +1206,7 @@ void GameCommand_playerdemo(float request, float argc)
                                                        return;
                                                }
 
-                                               self = client;
-                                               playerdemo_open_write(argv(next_token));
+                                               WITH(entity, self, client, playerdemo_open_write(argv(next_token)));
                                                return;
                                        }
 
@@ -1344,7 +1339,7 @@ void GameCommand_setbots(float request, float argc)
 }
 
 void GameCommand_shuffleteams(float request)
-{
+{SELFPARAM();
        switch(request)
        {
                case CMD_REQUEST_COMMAND:
@@ -1409,7 +1404,7 @@ void GameCommand_shuffleteams(float request)
                                                                continue; // not a player, move on to next random slot
 
                                                        if(VerifyClientNumber(shuffleteams_players[z]))
-                                                               self = edict_num(shuffleteams_players[z]);
+                                                               setself(edict_num(shuffleteams_players[z]));
 
                                                        if(self.team != team_color)
                                                                MoveToTeam(self, team_color, 6);
index 4be48e124e82b98d38fb26c41c5df7dfe18efc29..c92ffd3e82a31dd065d8bd288a97b4cb0f71febe 100644 (file)
@@ -24,7 +24,7 @@
 // =============================================
 
 //  Nagger for players to know status of voting
-float Nagger_SendEntity(entity to, float sendflags)
+bool Nagger_SendEntity(entity this, entity to, float sendflags)
 {
        int nags, i, f, b;
        entity e;
@@ -348,52 +348,60 @@ void VoteThink()
 
 // Resets the state of all clients, items, weapons, waypoints, ... of the map.
 void reset_map(float dorespawn)
-{
-       entity oldself;
-       oldself = self;
+{SELFPARAM();
 
        if(time <= game_starttime && round_handler_IsActive())
                round_handler_Reset(game_starttime);
 
        MUTATOR_CALLHOOK(reset_map_global);
 
-       for(self = world; (self = nextent(self)); )
-       if(IS_NOT_A_CLIENT(self))
+       for(entity e = world; (e = nextent(e)); )
        {
-               if(self.reset)
+               setself(e);
+               if(IS_NOT_A_CLIENT(self))
                {
-                       self.reset();
-                       continue;
-               }
+                       if(self.reset)
+                       {
+                               self.reset();
+                               continue;
+                       }
 
-               if(self.team_saved)
-                       self.team = self.team_saved;
+                       if(self.team_saved)
+                               self.team = self.team_saved;
 
-               if(self.flags & FL_PROJECTILE) // remove any projectiles left
-                       remove(self);
+                       if(self.flags & FL_PROJECTILE) // remove any projectiles left
+                               remove(self);
+               }
        }
 
        // Waypoints and assault start come LAST
-       for(self = world; (self = nextent(self)); )
-       if(IS_NOT_A_CLIENT(self))
+       for(entity e = world; (e = nextent(e)); )
        {
-               if(self.reset2)
+               setself(e);
+               if(IS_NOT_A_CLIENT(self))
                {
-                       self.reset2();
-                       continue;
+                       if(self.reset2)
+                       {
+                               self.reset2();
+                               continue;
+                       }
                }
        }
 
-       FOR_EACH_PLAYER(self)
-       if(self.frozen)
-               Unfreeze(self);
+       entity e;
+       FOR_EACH_PLAYER(e)
+       if(e.frozen)
+       {
+               WITH(entity, self, e, Unfreeze(self));
+       }
 
        // Moving the player reset code here since the player-reset depends
        // on spawnpoint entities which have to be reset first --blub
        if(dorespawn)
        if(!MUTATOR_CALLHOOK(reset_map_players))
-       FOR_EACH_CLIENT(self) // reset all players
+       FOR_EACH_CLIENT(e) // reset all players
        {
+               setself(e);
                /*
                only reset players if a restart countdown is active
                this can either be due to cvar sv_ready_restart_after_countdown having set
@@ -418,12 +426,12 @@ void reset_map(float dorespawn)
        if(g_keyhunt)
                kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round + (game_starttime - time), kh_StartRound);
 
-       self = oldself;
+       setself(this);
 }
 
 // Restarts the map after the countdown is over (and cvar sv_ready_restart_after_countdown is set)
 void ReadyRestart_think()
-{
+{SELFPARAM();
        restart_mapalreadyrestarted = 1;
        reset_map(true);
        Score_ClearAll();
index 7cf81d762ee0e73b8b6f018ba16825c7d51fff99..7f17228fa23b0513b203f77a078bcc9dedd7205a 100644 (file)
@@ -1,6 +1,6 @@
 #include "controlpoint.qh"
 
-bool cpicon_send(entity to, int sf)
+bool cpicon_send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_CONTROLPOINT_ICON);
        WriteByte(MSG_ENTITY, sf);
index 5072e49002be11ab6a1dd845cbfacce27a75ed58..4a7edc2b94a782fb900fa7554760c522b171d8ed 100644 (file)
@@ -5,8 +5,6 @@
 
 #define INDEPENDENT_ATTACK_FINISHED
 
-noref float require_spawnfunc_prefix; // if this float exists, only functions with spawnfunc_ name prefix qualify as spawn functions
-
 #define BUTTON_ATCK       button0
 #define BUTTON_JUMP       button2
 #define BUTTON_ATCK2      button3
@@ -147,7 +145,9 @@ const float MAX_DAMAGEEXTRARADIUS = 16;
 .float pauserothealth_finished;
 .float pauserotarmor_finished;
 .float pauserotfuel_finished;
+// string overrides entity
 .string item_pickupsound;
+.entity item_pickupsound_ent;
 
 // definitions for weaponsystem
 // more WEAPONTODO: move these to their proper files
@@ -162,13 +162,12 @@ const float MAX_DAMAGEEXTRARADIUS = 16;
 
 // WEAPONTODO
 .float autoswitch;
-//float WEP_ACTION(float wpn, float wrequest);
 float client_hasweapon(entity cl, float wpn, float andammo, float complain);
-void w_clear();
-void w_ready();
+void w_clear(Weapon thiswep, entity actor, bool fire1, bool fire2);
+void w_ready(Weapon thiswep, entity actor, bool fire1, bool fire2);
 // VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies)
 .float weapon_nextthink;
-.void() weapon_think;
+.void(Weapon thiswep, entity actor, bool fire1, bool fire2) weapon_think;
 
 
 // weapon states (self.weaponentity.state)
@@ -262,7 +261,7 @@ WepSet weaponsInMap;
 
 float bot_waypoints_for_items;
 
-.float attack_finished_for[WEP_MAXCOUNT];
+.float attack_finished_for[Weapons_MAX];
 .float attack_finished_single;
 #ifdef INDEPENDENT_ATTACK_FINISHED
 #define ATTACK_FINISHED_FOR(ent,w) ((ent).(attack_finished_for[(w) - WEP_FIRST]))
@@ -303,10 +302,6 @@ float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end)
 
 float next_pingtime;
 
-.float Version;
-.int SendFlags;
-.bool(entity to, int sendflags) SendEntity;
-
 // player sounds, voice messages
 // TODO implemented fall and falling
 #define ALLPLAYERSOUNDS \
@@ -351,6 +346,7 @@ ALLVOICEMSGS
 //             _VOICEMSG(droppedflag) \
 //             _VOICEMSG(negative) \
 //             _VOICEMSG(seenenemy) \
+//      /**/
 
 string globalsound_fall;
 string globalsound_metalfall;
@@ -469,7 +465,7 @@ float client_cefc_accumulator;
 float client_cefc_accumulatortime;
 #endif
 
-.float weapon_load[WEP_MAXCOUNT];
+.float weapon_load[Weapons_MAX];
 .int ammo_none; // used by the reloading system, must always be 0
 .float clip_load;
 .float old_clip_load;
index 40dbf1aefa9f99822433ffbdae96ddd2fbf3cd6e..768eae30b2eb1a16493ae9bc74eaf51d0f8d0e58 100644 (file)
@@ -1,34 +1,10 @@
+#include "ent_cs.qh"
 #include "_all.qh"
 
-#include "defs.qh"
-#include "mutators/mutators_include.qh"
-
-/**
- * The point of these entities is to avoid the problems
- * with clientprediction.
- * If you add SendEntity to players, the engine will not
- * do any prediction anymore, and you'd have to write the whole
- * prediction code in CSQC, you want that? :P
- * Data can depend on gamemode. For now, it serves as GPS entities
- * in onslaught... YAY ;)
- */
-
-// Beware: do not redefine those in other files
-// and NO, you cannot use ".version", which already exists (at least
-// it did when I added this) But you have to use .Version
-// Capital V
-
-.entity entcs;
-
-void entcs_init()
-{
-       LOG_INFO("Initializing ClientSide information entities\n");
-}
-
 float entcs_customize()
 {
-       entity o;
-       o = self.owner;
+       SELFPARAM();
+       entity o = self.owner;
        if(o.deadflag != DEAD_NO)
                return false;
        if (!IS_PLAYER(o))
@@ -42,76 +18,70 @@ float entcs_customize()
        return true;
 }
 
-float entcs_send(entity to, int sf)
+bool entcs_send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_ENTCS);
        WriteByte(MSG_ENTITY, sf);
-       if(sf & 1)
-               WriteByte(MSG_ENTITY, num_for_edict(self.owner)-1);
-       if(sf & 2)
+       if(sf & BIT(0))
+               WriteByte(MSG_ENTITY, num_for_edict(self.owner) - 1);
+       if(sf & BIT(1))
        {
                WriteShort(MSG_ENTITY, self.origin.x);
                WriteShort(MSG_ENTITY, self.origin.y);
                WriteShort(MSG_ENTITY, self.origin.z);
        }
-       if(sf & 4)
+       if(sf & BIT(2))
                WriteByte(MSG_ENTITY, self.angles.y * 256.0 / 360);
-       if(sf & 8)
+       if(sf & BIT(3))
                WriteByte(MSG_ENTITY, self.health / 10); // FIXME use a better scale?
-       if(sf & 16)
+       if(sf & BIT(4))
                WriteByte(MSG_ENTITY, self.armorvalue / 10); // FIXME use a better scale?
        return true;
 }
 
 void entcs_think()
 {
+       SELFPARAM();
        self.nextthink = time + 0.033333333333; // increase this to like 0.15 once the client can do smoothing
-
-       entity o;
-       o = self.owner;
-
-       if(o.origin != self.origin)
+       entity o = self.owner;
+       if (o.origin != self.origin)
        {
                setorigin(self, o.origin);
-               self.SendFlags |= 2;
+               self.SendFlags |= BIT(1);
        }
-       if(o.angles.y != self.angles.y)
+       if (o.angles.y != self.angles.y)
        {
                self.angles = o.angles;
-               self.SendFlags |= 4;
+               self.SendFlags |= BIT(2);
        }
-       if(o.health != self.health)
+       if (o.health != self.health)
        {
                self.health = o.health;
-               self.SendFlags |= 8;
+               self.SendFlags |= BIT(3);
        }
-       if(o.armorvalue != self.armorvalue)
+       if (o.armorvalue != self.armorvalue)
        {
                self.armorvalue = o.armorvalue;
-               self.SendFlags |= 16;
+               self.SendFlags |= BIT(4);
        }
 }
 
-entity attach_entcs()
+entity attach_entcs(entity e)
 {
-       entity ent;
-
-       ent = spawn();
-       ent.classname = "entcs_sender_v2";
-       ent.owner = self;
+       entity ent = e.entcs = new(entcs_sender);
+       ent.owner = e;
        ent.think = entcs_think;
        ent.nextthink = time;
 
        Net_LinkEntity(ent, false, 0, entcs_send);
        ent.customizeentityforclient = entcs_customize;
 
-       self.entcs = ent;
-
        return ent;
 }
 
-void detach_entcs()
+void detach_entcs(entity e)
 {
-       remove(self.entcs);
-       self.entcs = world;
+       if (!e.entcs) return;
+       remove(e.entcs);
+       e.entcs = NULL;
 }
index 05821f9ba3081b9ff19694940ae5662f581fd000..1cfc854c0964184ddb5f37cc10413171212911b8 100644 (file)
  * in onslaught... YAY ;)
  */
 
-// Beware: do not redefine those in other files
-// and NO, you cannot use ".version", which already exists (at least
-// it did when I added this) But you have to use .Version
-// Capital V
-
 .entity entcs;
 
-void entcs_init();
-
 float entcs_customize();
 
-float entcs_send(entity to, int sf);
+bool entcs_send(entity this, entity to, int sf);
 
 void entcs_think();
 
-entity attach_entcs();
+entity attach_entcs(entity e);
+
+void detach_entcs(entity e);
 
-void detach_entcs();
 #endif
index 0807c924c2d1f584afb153c5039e06f282306944..5cae69239ddfb084153e706e5867a8f91d460565 100644 (file)
@@ -10,7 +10,7 @@
 #include "weapons/accuracy.qh"
 #include "weapons/csqcprojectile.qh"
 #include "weapons/selection.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
 #include "../common/constants.qh"
 #include "../common/deathtypes.qh"
 #include "../common/notifications.qh"
@@ -22,7 +22,7 @@
 #include "../csqcmodellib/sv_model.qh"
 #include "../warpzonelib/common.qh"
 
-float Damage_DamageInfo_SendEntity(entity to, int sf)
+bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_DAMAGEINFO);
        WriteShort(MSG_ENTITY, self.projectiledeathtype);
@@ -67,7 +67,7 @@ void UpdateFrags(entity player, float f)
 }
 
 void GiveFrags (entity attacker, entity targ, float f, int deathtype)
-{
+{SELFPARAM();
        // TODO route through PlayerScores instead
        if(gameover) return;
 
@@ -142,17 +142,9 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
        }
 
        // FIXME fix the mess this is (we have REAL points now!)
-       entity oldself;
-       oldself = self;
-       self = attacker;
-       if(MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f))
+       if(MUTATOR_CALLHOOK(GiveFragsForKill, self, attacker, targ, f))
        {
                f = frag_score;
-               self = oldself;
-       }
-       else
-       {
-               self = oldself;
        }
 
        attacker.totalfrags += f;
@@ -273,7 +265,8 @@ float Obituary_WeaponDeath(
        if(death_weapon)
        {
                w_deathtype = deathtype;
-               int death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
+               Weapon w = get_weaponinfo(death_weapon);
+               int death_message = ((murder) ? w.wr_killmessage : w.wr_suicidemessage)(w);
                w_deathtype = false;
 
                if (death_message)
@@ -544,7 +537,7 @@ void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
 }
 
 void Ice_Think()
-{
+{SELFPARAM();
        if(!self.owner.frozen || self.owner.iceblock != self)
        {
                remove(self);
@@ -555,7 +548,7 @@ void Ice_Think()
 }
 
 void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypoint)
-{
+{SELFPARAM();
        if(!IS_PLAYER(targ) && !IS_MONSTER(targ)) // only specified entities can be freezed
                return;
 
@@ -568,6 +561,7 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo
        targ.revive_progress = ((frozen_type == 3) ? 1 : 0);
        targ.health = ((frozen_type == 3) ? targ_maxhealth : 1);
        targ.revive_speed = freeze_time;
+       self.bot_attack = false;
 
        entity ice, head;
        ice = spawn();
@@ -577,18 +571,14 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo
        ice.think = Ice_Think;
        ice.nextthink = time;
        ice.frame = floor(random() * 21); // ice model has 20 different looking frames
-       setmodel(ice, "models/ice/ice.md3");
+       setmodel(ice, MDL_ICE);
        ice.alpha = 1;
        ice.colormod = Team_ColorRGB(targ.team);
        ice.glowmod = ice.colormod;
        targ.iceblock = ice;
        targ.revival_time = 0;
 
-       entity oldself;
-       oldself = self;
-       self = ice;
-       Ice_Think();
-       self = oldself;
+       WITH(entity, self, ice, Ice_Think());
 
        RemoveGrapplingHook(targ);
 
@@ -603,6 +593,9 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo
 
 void Unfreeze (entity targ)
 {
+       if(!targ.frozen)
+               return;
+
        if(targ.frozen && targ.frozen != 3) // only reset health if target was frozen
                targ.health = ((IS_PLAYER(targ)) ? start_health : targ.max_health);
 
@@ -610,6 +603,7 @@ void Unfreeze (entity targ)
        targ.frozen = 0;
        targ.revive_progress = 0;
        targ.revival_time = time;
+       self.bot_attack = true;
 
        WaypointSprite_Kill(targ.waypointsprite_attached);
 
@@ -624,7 +618,7 @@ void Unfreeze (entity targ)
 }
 
 void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        float mirrordamage;
        float mirrorforce;
        float complainteamdamage = 0;
@@ -635,9 +629,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
        if (gameover || targ.killcount == -666)
                return;
 
-       entity oldself;
-       oldself = self;
-       self = targ;
+       setself(targ);
         damage_targ = targ;
         damage_inflictor = inflictor;
         damage_attacker = attacker;
@@ -655,7 +647,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                if(IS_PLAYER(targ))
                        if(SAME_TEAM(targ, attacker))
                        {
-                               self = oldself;
+                               setself(this);
                                return;
                        }
        }
@@ -775,8 +767,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                {
                        Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
 
-                       entity oldself = self;
-                       self = targ;
+                       setself(targ);
                        entity spot = SelectSpawnPoint (false);
 
                        if(spot)
@@ -806,7 +797,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                                Send_Effect(EFFECT_TELEPORT, self.origin, '0 0 0', 1);
                        }
 
-                       self = oldself;
+                       setself(this);
                }
 
                if(!g_instagib)
@@ -923,7 +914,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
        if (damage != 0 || (self.damageforcescale && vlen(force)))
        if (self.event_damage)
                self.event_damage (inflictor, attacker, damage, deathtype, hitloc, force);
-       self = oldself;
+       setself(this);
 
        // apply mirror damage if any
        if(mirrordamage > 0 || mirrorforce > 0)
@@ -1313,7 +1304,7 @@ void Fire_ApplyEffect(entity e)
 }
 
 void fireburner_think()
-{
+{SELFPARAM();
        // for players, this is done in the regular loop
        if(wasfreed(self.owner))
        {
index 8d7db7f5dcf05a46e3804b0acf2d5aa16de0731d..e7430690e4be3f157c9cfeca32b77a07cec285eb 100644 (file)
@@ -35,7 +35,7 @@
 .float dmg_force;
 .float dmg_radius;
 
-float Damage_DamageInfo_SendEntity(entity to, int sf);
+bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf);
 
 void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner);
 
index d63a2ade0d8453e809204465d9f9acdd35c3369d..ec66994280b9874c70af8ddd3cbcfc5e89e76671 100644 (file)
@@ -65,7 +65,6 @@ And you should be done!
 ============================================*/
 
 .float hook_length;
-.float hook_switchweapon;
 
 void RemoveGrapplingHook(entity pl)
 {
@@ -80,7 +79,7 @@ void RemoveGrapplingHook(entity pl)
 }
 
 void GrapplingHookReset(void)
-{
+{SELFPARAM();
        if(self.realowner.hook == self)
                RemoveGrapplingHook(self.owner);
        else // in any case:
@@ -89,9 +88,9 @@ void GrapplingHookReset(void)
 
 void GrapplingHookThink();
 void GrapplingHook_Stop()
-{
+{SELFPARAM();
        Send_Effect(EFFECT_HOOK_IMPACT, self.origin, '0 0 0', 1);
-       sound (self, CH_SHOTS, W_Sound("hook_impact"), VOL_BASE, ATTEN_NORM);
+       sound (self, CH_SHOTS, SND_HOOK_IMPACT, VOL_BASE, ATTEN_NORM);
 
        self.state = 1;
        self.think = GrapplingHookThink;
@@ -103,7 +102,7 @@ void GrapplingHook_Stop()
 }
 
 .vector hook_start, hook_end;
-float GrapplingHookSend(entity to, int sf)
+bool GrapplingHookSend(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_HOOK);
        sf = sf & 0x7F;
@@ -129,8 +128,10 @@ float GrapplingHookSend(entity to, int sf)
        return true;
 }
 
+int autocvar_g_grappling_hook_tarzan;
+
 void GrapplingHookThink()
-{
+{SELFPARAM();
        float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
        vector dir, org, end, v0, dv, v, myorg, vs;
        if(self.realowner.hook != self) // how did that happen?
@@ -300,7 +301,7 @@ void GrapplingHookThink()
 }
 
 void GrapplingHookTouch (void)
-{
+{SELFPARAM();
        if(other.movetype == MOVETYPE_FOLLOW)
                return;
        PROJECTILE_TOUCH;
@@ -318,7 +319,7 @@ void GrapplingHookTouch (void)
 }
 
 void GrapplingHook_Damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.health <= 0)
                return;
 
@@ -340,7 +341,7 @@ void GrapplingHook_Damage (entity inflictor, entity attacker, float damage, int
 }
 
 void FireGrapplingHook (void)
-{
+{SELFPARAM();
        entity missile;
        vector org;
        vector vs;
@@ -357,7 +358,7 @@ void FireGrapplingHook (void)
        vs = hook_shotorigin[s];
 
        // UGLY WORKAROUND: play this on CH_WEAPON_B so it can't cut off fire sounds
-       sound (self, CH_WEAPON_B, W_Sound("hook_fire"), VOL_BASE, ATTEN_NORM);
+       sound (self, CH_WEAPON_B, SND_HOOK_FIRE, VOL_BASE, ATTEN_NORM);
        org = self.origin + self.view_ofs + v_forward * vs.x + v_right * -vs.y + v_up * vs.z;
 
        tracebox(self.origin + self.view_ofs, '-3 -3 -3', '3 3 3', org, MOVE_NORMAL, self);
@@ -375,7 +376,7 @@ void FireGrapplingHook (void)
        missile.movetype = ((autocvar_g_balance_grapplehook_gravity) ? MOVETYPE_TOSS : MOVETYPE_FLY);
        PROJECTILE_MAKETRIGGER(missile);
 
-       //setmodel (missile, "models/hook.md3"); // precision set below
+       //setmodel (missile, MDL_HOOK); // precision set below
        setsize (missile, '-3 -3 -3', '3 3 3');
        setorigin (missile, org);
 
@@ -403,114 +404,6 @@ void FireGrapplingHook (void)
        Net_LinkEntity(missile, false, 0, GrapplingHookSend);
 }
 
-//  void GrapplingHookFrame()
-//  {
-//         // this function has been modified for Xonotic
-// -       if (self.BUTTON_HOOK && g_grappling_hook)
-//         {
-// -               if (!self.hook && self.hook_time <= time && !self.button6_pressed_before)
-// -                       if (timeoutStatus != 2) //only allow the player to fire the grappling hook if the game is not paused (timeout)
-// -                               FireGrapplingHook();
-//         }
-// -       else
-//         {
-//                 if (self.hook)
-//                         RemoveGrapplingHook(self);
-//         }
-// -       self.button6_pressed_before = self.BUTTON_HOOK;
-//         /*
-//         // if I have no hook or it's not pulling yet, make sure I'm not flying!
-//         if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY)
-
-void GrapplingHookFrame()
-{
-       if(g_grappling_hook && timeout_status != TIMEOUT_ACTIVE && self.weapon != WEP_HOOK.m_id && !self.vehicle)
-       {
-               // offhand hook controls
-               if(self.BUTTON_HOOK)
-               {
-                       if (!(self.hook || (self.hook_state & HOOK_WAITING_FOR_RELEASE)) && (time > self.hook_refire))
-                       {
-                               self.hook_state |= HOOK_FIRING;
-                               self.hook_state |= HOOK_WAITING_FOR_RELEASE;
-                       }
-               }
-               else
-               {
-                       self.hook_state |= HOOK_REMOVING;
-                       self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
-               }
-
-               self.hook_state &= ~HOOK_RELEASING;
-               if(self.BUTTON_CROUCH && autocvar_g_balance_grapplehook_crouchslide)
-               {
-                       self.hook_state &= ~HOOK_PULLING;
-                       //self.hook_state |= HOOK_RELEASING;
-               }
-               else
-               {
-                       self.hook_state |= HOOK_PULLING;
-                       //self.hook_state &= ~HOOK_RELEASING;
-               }
-       }
-       else if(!g_grappling_hook && self.switchweapon != WEP_HOOK.m_id && !self.vehicle)
-       {
-               if(self.BUTTON_HOOK && !self.hook_switchweapon)
-                       W_SwitchWeapon(WEP_HOOK.m_id);
-       }
-       self.hook_switchweapon = self.BUTTON_HOOK;
-
-       if(!g_grappling_hook && self.weapon != WEP_HOOK.m_id)
-       {
-               self.hook_state &= ~HOOK_FIRING;
-               self.hook_state |= HOOK_REMOVING;
-       }
-
-       if (self.hook_state & HOOK_FIRING)
-       {
-               if (self.hook)
-                       RemoveGrapplingHook(self);
-               FireGrapplingHook();
-               self.hook_state &= ~HOOK_FIRING;
-               self.hook_refire = max(self.hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor());
-       }
-       else if(self.hook_state & HOOK_REMOVING)
-       {
-               if (self.hook)
-                       RemoveGrapplingHook(self);
-               self.hook_state &= ~HOOK_REMOVING;
-       }
-
-       /*
-       // if I have no hook or it's not pulling yet, make sure I'm not flying!
-       if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY)
-       {
-               self.movetype = MOVETYPE_WALK;
-       }
-       if(self.impulse == GRAPHOOK_FIRE && self.hook_time <= time && g_grappling_hook)
-       {
-               // fire hook
-               FireGrapplingHook();
-               return;
-       }
-       else if(self.hookimpulse == GRAPHOOK_RELEASE)
-       {
-               // remove hook, reset movement type
-               RemoveGrapplingHook(self);
-               return;
-       }
-       */
-       /*else // make sure the player's movetype is correct
-       {
-               //if(self.hook == world && self.movetype == MOVETYPE_FLY)
-               if((self.hook == world || !self.hook.state) && self.movetype == MOVETYPE_FLY)
-               {
-                       self.movetype = MOVETYPE_WALK;
-               }
-       }*/
-       // note: The hook entity does the actual pulling
-}
-
 void GrappleHookInit()
 {
        if(g_grappling_hook)
@@ -522,7 +415,8 @@ void GrappleHookInit()
        }
        else
        {
-               WEP_ACTION(WEP_HOOK.m_id, WR_INIT);
+               Weapon w = WEP_HOOK;
+               w.wr_init(w);
                hook_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 1);
                hook_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 2);
                hook_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 3);
@@ -531,7 +425,7 @@ void GrappleHookInit()
 }
 
 void SetGrappleHookBindings()
-{
+{SELFPARAM();
        // this function has been modified for Xonotic
        // don't remove these lines! old server or demos coud overwrite the new aliases
        stuffcmd(self, "alias +hook +button6\n");
index aa641a56bc84bc927299e4715f2c456fbd05e205..140a93cfdf02bafe87d983aba29479ee16a94a7c 100644 (file)
@@ -3,7 +3,6 @@
 
 // Wazat's grappling hook
 .entity                hook;
-void GrapplingHookFrame();
 void RemoveGrapplingHook(entity pl);
 void SetGrappleHookBindings();
 // (note: you can change the hook impulse #'s to whatever you please)
index f7382d1666b15b6c295903b3fa90260be3c720a2..bd5232a1c93338c5de9e164531cd5296798b0730 100644 (file)
@@ -86,7 +86,7 @@ void dynlight_use()
        else
                self.light_lev = 0;
 }
-void spawnfunc_dynlight()
+spawnfunc(dynlight)
 {
        if (!self.light_lev)
                self.light_lev = 200;
index 62b2cfb51dd5d3a5c9a52a38b78d9654c0e97e58..781ecc612e7d3f2f968e524c954d6a766022b716 100644 (file)
@@ -10,7 +10,7 @@
 .float modelscale;
 
 void g_model_setcolormaptoactivator (void)
-{
+{SELFPARAM();
        if(teamplay)
        {
                if(activator.team)
@@ -24,13 +24,13 @@ void g_model_setcolormaptoactivator (void)
 }
 
 void g_clientmodel_setcolormaptoactivator (void)
-{
+{SELFPARAM();
        g_model_setcolormaptoactivator();
        self.SendFlags |= (8 | 1);
 }
 
 void g_clientmodel_use(void)
-{
+{SELFPARAM();
        if (self.antiwall_flag == 1)
        {
                self.inactive = 1;
@@ -45,7 +45,7 @@ void g_clientmodel_use(void)
 }
 
 void g_model_dropbyspawnflags()
-{
+{SELFPARAM();
        if((self.spawnflags & 3) == 1) // ALIGN_ORIGIN
        {
                traceline(self.origin, self.origin - '0 0 4096', MOVE_NOMONSTERS, self);
@@ -64,7 +64,7 @@ void g_model_dropbyspawnflags()
 }
 
 void g_clientmodel_dropbyspawnflags()
-{
+{SELFPARAM();
        vector o0;
        o0 = self.origin;
        g_model_dropbyspawnflags();
@@ -72,7 +72,7 @@ void g_clientmodel_dropbyspawnflags()
                self.SendFlags |= 2;
 }
 
-float g_clientmodel_genericsendentity (entity to, int sf)
+bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
 {
        sf = sf & 0x0F;
        if(self.angles != '0 0 0')
@@ -177,15 +177,15 @@ float g_clientmodel_genericsendentity (entity to, int sf)
        self.default_solid = sol;
 
 // non-solid model entities:
-void spawnfunc_misc_gamemodel()         { self.angles_x = -self.angles.x; G_MODEL_INIT      (SOLID_NOT) } // model entity
-void spawnfunc_misc_clientmodel()       { self.angles_x = -self.angles.x; G_CLIENTMODEL_INIT(SOLID_NOT) } // model entity
-void spawnfunc_misc_models()            { self.angles_x = -self.angles.x; G_MODEL_INIT      (SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
+spawnfunc(misc_gamemodel)         { self.angles_x = -self.angles.x; G_MODEL_INIT      (SOLID_NOT) } // model entity
+spawnfunc(misc_clientmodel)       { self.angles_x = -self.angles.x; G_CLIENTMODEL_INIT(SOLID_NOT) } // model entity
+spawnfunc(misc_models)            { self.angles_x = -self.angles.x; G_MODEL_INIT      (SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
 
 // non-solid brush entities:
-void spawnfunc_func_illusionary()       { G_MODEL_INIT      (SOLID_NOT) } // Q1 name (WARNING: MISPREDICTED)
-void spawnfunc_func_clientillusionary() { G_CLIENTMODEL_INIT(SOLID_NOT) } // brush entity
-void spawnfunc_func_static()            { G_MODEL_INIT      (SOLID_NOT) } // DEPRECATED old alias name from some other game
+spawnfunc(func_illusionary)       { G_MODEL_INIT      (SOLID_NOT) } // Q1 name (WARNING: MISPREDICTED)
+spawnfunc(func_clientillusionary) { G_CLIENTMODEL_INIT(SOLID_NOT) } // brush entity
+spawnfunc(func_static)            { G_MODEL_INIT      (SOLID_NOT) } // DEPRECATED old alias name from some other game
 
 // solid brush entities
-void spawnfunc_func_wall()              { G_MODEL_INIT      (SOLID_BSP) } // Q1 name
-void spawnfunc_func_clientwall()        { G_CLIENTMODEL_INIT(SOLID_BSP) } // brush entity (WARNING: MISPREDICTED)
+spawnfunc(func_wall)              { G_MODEL_INIT      (SOLID_BSP) } // Q1 name
+spawnfunc(func_clientwall)        { G_CLIENTMODEL_INIT(SOLID_BSP) } // brush entity (WARNING: MISPREDICTED)
index 3a242dcf32a81f157220ee8f95446589193aeaec..585ac42e085b56852be47ac023d9d11976e92404 100644 (file)
@@ -5,7 +5,7 @@
 #include "command/common.qh"
 #include "../warpzonelib/common.qh"
 
-void spawnfunc_info_null (void)
+spawnfunc(info_null)
 {
        remove(self);
        // if anything breaks, tell the mapper to fix his map! info_null is meant to remove itself immediately.
@@ -281,7 +281,7 @@ vector findbetterlocation (vector org, float mindist)
 }
 
 float LOD_customize()
-{
+{SELFPARAM();
        float d;
 
        if(autocvar_loddebug)
@@ -309,12 +309,12 @@ float LOD_customize()
 }
 
 void LOD_uncustomize()
-{
+{SELFPARAM();
        self.modelindex = self.lodmodelindex0;
 }
 
 void LODmodel_attach()
-{
+{SELFPARAM();
        entity e;
 
        if(!self.loddistance1)
@@ -354,13 +354,13 @@ void LODmodel_attach()
                ma = self.maxs;
 
                precache_model(self.lodmodel1);
-               setmodel(self, self.lodmodel1);
+               _setmodel(self, self.lodmodel1);
                self.lodmodelindex1 = self.modelindex;
 
                if(self.lodmodel2 != "")
                {
                        precache_model(self.lodmodel2);
-                       setmodel(self, self.lodmodel2);
+                       _setmodel(self, self.lodmodel2);
                        self.lodmodelindex2 = self.modelindex;
                }
 
@@ -374,7 +374,7 @@ void LODmodel_attach()
 }
 
 void ApplyMinMaxScaleAngles(entity e)
-{
+{SELFPARAM();
        if(e.angles.x != 0 || e.angles.z != 0 || self.avelocity.x != 0 || self.avelocity.z != 0) // "weird" rotation
        {
                e.maxs = '1 1 1' * vlen(
@@ -401,7 +401,7 @@ void ApplyMinMaxScaleAngles(entity e)
 }
 
 void SetBrushEntityModel()
-{
+{SELFPARAM();
        if(self.model != "")
        {
                precache_model(self.model);
@@ -409,11 +409,11 @@ void SetBrushEntityModel()
                {
                        vector mi = self.mins;
                        vector ma = self.maxs;
-                       setmodel(self, self.model); // no precision needed
+                       _setmodel(self, self.model); // no precision needed
                        setsize(self, mi, ma);
                }
                else
-                       setmodel(self, self.model); // no precision needed
+                       _setmodel(self, self.model); // no precision needed
                InitializeEntity(self, LODmodel_attach, INITPRIO_FINDTARGET);
        }
        setorigin(self, self.origin);
@@ -421,7 +421,7 @@ void SetBrushEntityModel()
 }
 
 void SetBrushEntityModelNoLOD()
-{
+{SELFPARAM();
        if(self.model != "")
        {
                precache_model(self.model);
@@ -429,11 +429,11 @@ void SetBrushEntityModelNoLOD()
                {
                        vector mi = self.mins;
                        vector ma = self.maxs;
-                       setmodel(self, self.model); // no precision needed
+                       _setmodel(self, self.model); // no precision needed
                        setsize(self, mi, ma);
                }
                else
-                       setmodel(self, self.model); // no precision needed
+                       _setmodel(self, self.model); // no precision needed
        }
        setorigin(self, self.origin);
        ApplyMinMaxScaleAngles(self);
@@ -446,7 +446,7 @@ InitTrigger
 */
 
 void SetMovedir()
-{
+{SELFPARAM();
        if (self.movedir != '0 0 0')
                self.movedir = normalize(self.movedir);
        else
@@ -459,7 +459,7 @@ void SetMovedir()
 }
 
 void InitTrigger()
-{
+{SELFPARAM();
 // trigger angles are used for one-way touches.  An angle of 0 is assumed
 // to mean no restrictions, so use a yaw of 360 instead.
        SetMovedir ();
@@ -471,7 +471,7 @@ void InitTrigger()
 }
 
 void InitSolidBSPTrigger()
-{
+{SELFPARAM();
 // trigger angles are used for one-way touches.  An angle of 0 is assumed
 // to mean no restrictions, so use a yaw of 360 instead.
        SetMovedir ();
@@ -483,7 +483,7 @@ void InitSolidBSPTrigger()
 }
 
 float InitMovingBrushTrigger()
-{
+{SELFPARAM();
 // trigger angles are used for one-way touches.  An angle of 0 is assumed
 // to mean no restrictions, so use a yaw of 360 instead.
        self.solid = SOLID_BSP;
index d62bbb6124e57bd014b2976bde0d5532990b5f98..77f49ae5a9930d1b75911377490437ce48bcd10b 100644 (file)
@@ -8,7 +8,7 @@ void() SUB_CalcAngleMoveDone;
 //void() SUB_UseTargets;
 void() SUB_Remove;
 
-void spawnfunc_info_null (void);
+spawnfunc(info_null);
 
 void setanim(entity e, vector anim, float looping, float override, float restart);
 
index 5bc8aafd377202719e58dd38569a70afedb452c5..2a885f901ab2f0b7100326430fa6963ea31c6855 100644 (file)
@@ -1,7 +1,7 @@
 #include "g_violence.qh"
 #include "_all.qh"
 
-float Violence_GibSplash_SendEntity(entity to, int sf)
+bool Violence_GibSplash_SendEntity(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_GIBSPLASH);
        WriteByte(MSG_ENTITY, self.state); // actually type
@@ -15,7 +15,7 @@ float Violence_GibSplash_SendEntity(entity to, int sf)
 
 // TODO maybe convert this to a TE?
 void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker)
-{
+{SELFPARAM();
        if(g_cts) // no gibs in CTS
                return;
 
index 98d2b811fcd2858cec93686b65fd3e35da9fd7ea..6a33ac4418407602a97e8c5932e4f87d3c174e09 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef G_VIOLENCE_H
 #define G_VIOLENCE_H
 
-float Violence_GibSplash_SendEntity(entity to, int sf);
+bool Violence_GibSplash_SendEntity(entity this, entity to, int sf);
 
 // TODO maybe convert this to a TE?
 void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker);
index 15c1ae68deebc79c6ede8126f218c3f4febb7c59..a0f9a3f131ab2e2552340692736ad82fd398d324 100644 (file)
 #include "scores.qh"
 #include "teamplay.qh"
 #include "weapons/weaponstats.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
 #include "../common/constants.qh"
 #include "../common/deathtypes.qh"
-#include "../common/effects.qh"
+#include "../common/effects/effects.qh"
 #include "../common/mapinfo.qh"
 #include "../common/monsters/all.qh"
 #include "../common/monsters/sv_monsters.qh"
@@ -41,7 +41,7 @@ const float LATENCY_THINKRATE = 10;
 .float latency_time;
 entity pingplreport;
 void PingPLReport_Think()
-{
+{SELFPARAM();
        float delta;
        entity e;
 
@@ -117,7 +117,7 @@ void SetDefaultAlpha()
 }
 
 void GotoFirstMap()
-{
+{SELFPARAM();
        float n;
        if(autocvar__sv_init)
        {
@@ -512,33 +512,29 @@ void detect_maptype()
 }
 
 entity randomseed;
-float RandomSeed_Send(entity to, int sf)
+bool RandomSeed_Send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_RANDOMSEED);
        WriteShort(MSG_ENTITY, self.cnt);
        return true;
 }
 void RandomSeed_Think()
-{
+{SELFPARAM();
        self.cnt = bound(0, floor(random() * 65536), 65535);
        self.nextthink = time + 5;
 
        self.SendFlags |= 1;
 }
 void RandomSeed_Spawn()
-{
+{SELFPARAM();
        randomseed = spawn();
        randomseed.think = RandomSeed_Think;
        Net_LinkEntity(randomseed, false, 0, RandomSeed_Send);
 
-       entity oldself;
-       oldself = self;
-       self = randomseed;
-       self.think(); // sets random seed and nextthink
-       self = oldself;
+       WITH(entity, self, randomseed, randomseed.think()); // sets random seed and nextthink
 }
 
-void spawnfunc___init_dedicated_server(void)
+spawnfunc(__init_dedicated_server)
 {
        // handler for _init/_init map (only for dedicated server initialization)
 
@@ -561,7 +557,6 @@ void spawnfunc___init_dedicated_server(void)
 
        // needs to be done so early because of the constants they create
        static_init();
-       CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
 
@@ -576,7 +571,7 @@ void ClientInit_Spawn();
 void WeaponStats_Init();
 void WeaponStats_Shutdown();
 void Physics_AddStats();
-void spawnfunc_worldspawn (void)
+spawnfunc(worldspawn)
 {
        float fd, l, j, n;
        string s;
@@ -608,12 +603,9 @@ void spawnfunc_worldspawn (void)
 
        // needs to be done so early because of the constants they create
        static_init();
-       CALL_ACCUMULATED_FUNCTION(RegisterTurrets);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
 
-       initialize_minigames();
-
        ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
 
        TemporaryDB = db_create();
@@ -666,7 +658,6 @@ void spawnfunc_worldspawn (void)
 
        PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
 
-       precache_model ("null"); // we need this one before InitGameplayMode
        InitGameplayMode();
        readlevelcvars();
        GrappleHookInit();
@@ -697,10 +688,6 @@ void spawnfunc_worldspawn (void)
                MUTATOR_CALLHOOK(BuildMutatorsString, s);
                s = ret_string;
 
-               // simple, probably not good in the mutator system
-               if(autocvar_g_grappling_hook)
-                       s = strcat(s, ":grappling_hook");
-
                // initialiation stuff, not good in the mutator system
                if(!autocvar_g_use_ammunition)
                        s = strcat(s, ":no_use_ammunition");
@@ -925,7 +912,7 @@ void spawnfunc_worldspawn (void)
        world_initialized = 1;
 }
 
-void spawnfunc_light (void)
+spawnfunc(light)
 {
        //makestatic (self); // Who the f___ did that?
        remove(self);
@@ -1013,22 +1000,6 @@ string Map_Filename(float position)
        return strcat("maps/", argv(position), ".bsp");
 }
 
-string strwords(string s, float w)
-{
-       float endpos;
-       for(endpos = 0; w && endpos >= 0; --w)
-               endpos = strstrofs(s, " ", endpos + 1);
-       if(endpos < 0)
-               return s;
-       else
-               return substring(s, 0, endpos);
-}
-
-float strhasword(string s, string w)
-{
-       return strstrofs(strcat(" ", s, " "), strcat(" ", w, " "), 0) >= 0;
-}
-
 void Map_MarkAsRecent(string m)
 {
        cvar_set("g_maplist_mostrecent", strwords(strcat(m, " ", autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
@@ -1318,7 +1289,7 @@ When the player presses attack or jump, change to the next level
 */
 .float autoscreenshot;
 void IntermissionThink()
-{
+{SELFPARAM();
        FixIntermissionClient(self);
 
        float server_screenshot = (autocvar_sv_autoscreenshot && self.cvar_cl_autoscreenshot);
@@ -1595,7 +1566,7 @@ Exit deathmatch games upon conditions
 ============
 */
 void CheckRules_Player()
-{
+{SELFPARAM();
        if (gameover)   // someone else quit the game already
                return;
 
@@ -1694,7 +1665,7 @@ void ClearWinners(void)
 // they win. Otherwise the defending team wins once the timelimit passes.
 void assault_new_round();
 float WinningCondition_Assault()
-{
+{SELFPARAM();
        float status;
 
        WinningConditionHelper(); // set worldstatus
@@ -1727,11 +1698,7 @@ float WinningCondition_Assault()
                        }
                        else
                        {
-                               entity oldself;
-                               oldself = self;
-                               self = ent;
-                               assault_new_round();
-                               self = oldself;
+                               WITH(entity, self, ent, assault_new_round());
                        }
                }
        }
@@ -2202,19 +2169,20 @@ string GotoMap(string m)
 
 
 void EndFrame()
-{
+{SELFPARAM();
        anticheat_endframe();
 
        float altime;
-       FOR_EACH_REALCLIENT(self)
+       entity e_;
+       FOR_EACH_REALCLIENT(e_)
        {
-               entity e = IS_SPEC(self) ? self.enemy : self;
+               entity e = IS_SPEC(e_) ? e_.enemy : e_;
                if(e.typehitsound)
-                       self.typehit_time = time;
+                       e_.typehit_time = time;
                else if(e.damage_dealt)
                {
-                       self.hit_time = time;
-                       self.damage_dealt_total += ceil(e.damage_dealt);
+                       e_.hit_time = time;
+                       e_.damage_dealt_total += ceil(e.damage_dealt);
                }
        }
        altime = time + frametime * (1 + autocvar_g_antilag_nudge);
@@ -2223,14 +2191,18 @@ void EndFrame()
        // add another frametime because client shows everything with
        // 1 frame of lag (cl_nolerp 0). The last +1 however should not be
        // needed!
-       FOR_EACH_CLIENT(self)
+       FOR_EACH_CLIENT(e_)
+       {
+               e_.typehitsound = false;
+               e_.damage_dealt = 0;
+               setself(e_);
+               antilag_record(e_, altime);
+       }
+       FOR_EACH_MONSTER(e_)
        {
-               self.typehitsound = false;
-               self.damage_dealt = 0;
-               antilag_record(self, altime);
+               setself(e_);
+               antilag_record(e_, altime);
        }
-       FOR_EACH_MONSTER(self)
-               antilag_record(self, altime);
 }
 
 
@@ -2241,7 +2213,7 @@ void EndFrame()
 float redirection_timeout;
 float redirection_nextthink;
 float RedirectionThink()
-{
+{SELFPARAM();
        float clients_found;
 
        if(redirection_target == "")
@@ -2263,8 +2235,10 @@ float RedirectionThink()
        redirection_nextthink = time + 1;
 
        clients_found = 0;
-       FOR_EACH_REALCLIENT(self)
+       entity e;
+       FOR_EACH_REALCLIENT(e)
        {
+               setself(e);
                // TODO add timer
                LOG_INFO("Redirecting: sending connect command to ", self.netname, "\n");
                if(redirection_target == "self")
index 3e0b5171f249350679e64ec0cf9896ed4933227d..2a1c0b2f861ab34b1035e0087880e97d67c5849c 100644 (file)
@@ -1,6 +1,6 @@
 #include "generator.qh"
 
-bool generator_send(entity to, int sf)
+bool generator_send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_GENERATOR);
        WriteByte(MSG_ENTITY, sf);
@@ -30,7 +30,7 @@ bool generator_send(entity to, int sf)
 }
 
 void generator_link(void() spawnproc)
-{
+{SELFPARAM();
        Net_LinkEntity(self, true, 0, generator_send);
        self.think              = spawnproc;
        self.nextthink  = time;
index cbdb36e05f4e0f5669ac2d1bb6a57f66c7f01686..003c2b1d6855f1f93fed3d1ae078dbf2e8c841b9 100644 (file)
@@ -6,5 +6,5 @@ const vector GENERATOR_MAX = '52 52 75';
 const int GSF_STATUS = 4;
 const int GSF_SETUP = 8;
 
-bool generator_send(entity to, int sf);
+bool generator_send(entity this, entity to, int sf);
 #endif
index 671137a645f37ae20583d838732205f1304f29e4..5bf648a0b5995b7269e7e10ceb09af334088ba44 100644 (file)
@@ -200,7 +200,7 @@ void OnlineBanList_URI_Get_Callback(float id, float status, string data)
 }
 
 void OnlineBanList_Think()
-{
+{SELFPARAM();
        float argc;
        string uri;
        float i, n;
index 1518151f2c85b457fff515b37634030b68f838b0..713fbf6c3df57e87a8c704e7916da1ba11e562b0 100644 (file)
@@ -69,7 +69,8 @@ item_key
 /**
  * Key touch handler.
  */
-void item_key_touch(void) {
+void item_key_touch()
+{SELFPARAM();
        if (!IS_PLAYER(other))
                return;
 
@@ -86,7 +87,8 @@ void item_key_touch(void) {
 /**
  * Spawn a key with given model, key code and color.
  */
-void spawn_item_key() {
+void spawn_item_key()
+{SELFPARAM();
        precache_model(self.model);
 
        if (self.spawnflags & 1) // FLOATING
@@ -101,7 +103,7 @@ void spawn_item_key() {
 
        self.mdl = self.model;
        self.effects = EF_LOWPRECISION;
-       setmodel(self, self.model);
+       _setmodel(self, self.model);
        //setsize(self, '-16 -16 -24', '16 16 32');
        setorigin(self, self.origin + '0 0 32');
        setsize(self, '-16 -16 -56', '16 16 0');
@@ -146,7 +148,8 @@ This is the only correct way to put keys on the map!
 
 itemkeys MUST always have exactly one bit set.
 */
-void spawnfunc_item_key() {
+spawnfunc(item_key)
+{
        string _netname;
        vector _colormod;
 
@@ -231,7 +234,7 @@ void spawnfunc_item_key() {
                self.message = strzone(strcat("You've picked up the ", self.netname, "!"));
 
        if (self.noise == "")
-               self.noise = "misc/itempickup.wav";
+               self.noise = SND(ITEMPICKUP);
 
        // save the name for later
        item_keys_names[lowestbit(self.itemkeys)] = self.netname;
@@ -252,10 +255,11 @@ FLOATING: the item will float in air, instead of aligning to the floor by fallin
 ---------NOTES----------
 Don't use this entity on new maps! Use item_key instead.
 */
-void spawnfunc_item_key1(void) {
-       self.classname = "item_key";
-       self.itemkeys = ITEM_KEY_BIT(1);
-       spawnfunc_item_key();
+spawnfunc(item_key1)
+{
+       this.classname = "item_key";
+       this.itemkeys = ITEM_KEY_BIT(1);
+       spawnfunc_item_key(this);
 };
 
 /*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING
@@ -270,8 +274,9 @@ FLOATING: the item will float in air, instead of aligning to the floor by fallin
 ---------NOTES----------
 Don't use this entity on new maps! Use item_key instead.
 */
-void spawnfunc_item_key2(void) {
-       self.classname = "item_key";
-       self.itemkeys = ITEM_KEY_BIT(0);
-       spawnfunc_item_key();
+spawnfunc(item_key2)
+{
+       this.classname = "item_key";
+       this.itemkeys = ITEM_KEY_BIT(0);
+       spawnfunc_item_key(this);
 };
index d453606d3946419c660cd4693d98730010b3f874..a8e027df1e1769187e919842d46bac97e1c2005a 100644 (file)
@@ -123,7 +123,7 @@ void MapVote_UnzoneStrings()
 }
 
 string MapVote_Suggest(string m)
-{
+{SELFPARAM();
        float i;
        if(m == "")
                return "That's not how to use this command.";
@@ -263,7 +263,7 @@ void MapVote_Init()
 }
 
 void MapVote_SendPicture(float id)
-{
+{SELFPARAM();
        msg_entity = self;
        WriteByte(MSG_ONE, SVC_TEMPENTITY);
        WriteByte(MSG_ONE, TE_CSQC_PICTURE);
@@ -343,7 +343,7 @@ void GameTypeVote_SendOption(int i)
        }
 }
 
-float MapVote_SendEntity(entity to, int sf)
+bool MapVote_SendEntity(entity this, entity to, int sf)
 {
        float i;
 
index 55b8c2ea275665975078982819647dd378889b7e..57bbd51d0e1f1c17cf8966c10e3a3c1276b8c2f6 100644 (file)
@@ -241,7 +241,7 @@ string NearestLocation(vector p)
 }
 
 string formatmessage(string msg)
-{
+{SELFPARAM();
        float p, p1, p2;
        float n;
        vector cursor;
@@ -299,6 +299,8 @@ string formatmessage(string msg)
                        case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;
                        case "s": replacement = ftos(vlen(self.velocity - self.velocity_z * '0 0 1')); break;
                        case "S": replacement = ftos(vlen(self.velocity)); break;
+                       case "t": replacement = seconds_tostring(ceil(max(0, autocvar_timelimit * 60 + game_starttime - time))); break;
+                       case "T": replacement = seconds_tostring(floor(time - game_starttime)); break;
                        default:
                        {
                                MUTATOR_CALLHOOK(FormatMessage, escape, replacement, msg);
@@ -323,7 +325,7 @@ Called with:
   >0: receives a cvar from name=argv(f) value=argv(f+1)
 */
 void GetCvars_handleString(string thisname, float f, .string field, string name)
-{
+{SELFPARAM();
        if (f < 0)
        {
                if (self.(field))
@@ -343,7 +345,7 @@ void GetCvars_handleString(string thisname, float f, .string field, string name)
                stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
 }
 void GetCvars_handleString_Fixup(string thisname, float f, .string field, string name, string(string) func)
-{
+{SELFPARAM();
        GetCvars_handleString(thisname, f, field, name);
        if (f >= 0) // also initialize to the fitting value for "" when sending cvars out
                if (thisname == name)
@@ -357,7 +359,7 @@ void GetCvars_handleString_Fixup(string thisname, float f, .string field, string
                }
 }
 void GetCvars_handleFloat(string thisname, float f, .float field, string name)
-{
+{SELFPARAM();
        if (f < 0)
        {
        }
@@ -370,7 +372,7 @@ void GetCvars_handleFloat(string thisname, float f, .float field, string name)
                stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
 }
 void GetCvars_handleFloatOnce(string thisname, float f, .float field, string name)
-{
+{SELFPARAM();
        if (f < 0)
        {
        }
@@ -393,7 +395,7 @@ void GetCvars_handleFloatOnce(string thisname, float f, .float field, string nam
        }
 }
 string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(string wo)
-{
+{SELFPARAM();
        string o;
        o = W_FixWeaponOrder_ForceComplete(wo);
        if(self.weaponorder_byimpulse)
@@ -405,7 +407,7 @@ string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(string wo)
        return o;
 }
 void GetCvars(float f)
-{
+{SELFPARAM();
        string s = string_null;
 
        if (f > 0)
@@ -417,6 +419,8 @@ void GetCvars(float f)
 
        Notification_GetCvars();
 
+       ReplicateVars(this, s, f);
+
        GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch");
        GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot");
        GetCvars_handleFloat(s, f, cvar_cl_jetpack_jump, "cl_jetpack_jump");
@@ -497,8 +501,6 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still ne
        else
                d = !(!weaponinfo.weaponstart);
 
-       if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
-               d |= (i == WEP_HOOK.m_id);
        if(!g_cts && (weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED)) // never default mutator blocked guns
                d = 0;
 
@@ -704,7 +706,7 @@ void readplayerstartcvars()
 
        MUTATOR_CALLHOOK(SetStartItems);
 
-       if ((start_items & ITEM_Jetpack.m_itemid) || (g_grappling_hook && (start_weapons & WEPSET_HOOK)))
+       if (start_items & ITEM_Jetpack.m_itemid)
        {
                start_items |= ITEM_JetpackRegen.m_itemid;
                start_ammo_fuel = max(start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
@@ -717,8 +719,10 @@ void readplayerstartcvars()
        for (i = WEP_FIRST; i <= WEP_LAST; ++i)
        {
                e = get_weaponinfo(i);
-               if(precache_weapons & WepSet_FromWeapon(i))
-                       WEP_ACTION(i, WR_INIT);
+               if(precache_weapons & WepSet_FromWeapon(i)) {
+                       Weapon w = get_weaponinfo(i);
+                       w.wr_init(w);
+               }
        }
 
        start_ammo_shells = max(0, start_ammo_shells);
@@ -762,14 +766,6 @@ float sound_allowed(float destin, entity e)
     return true;
 }
 
-#undef sound
-void sound(entity e, float chan, string samp, float vol, float attenu)
-{
-    if (!sound_allowed(MSG_BROADCAST, e))
-        return;
-    sound7(e, chan, samp, vol, attenu, 0, 0);
-}
-
 void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float attenu)
 {
     float entno, idx;
@@ -845,7 +841,7 @@ void stopsoundto(float _dest, entity e, float chan)
     if (entno >= 8192 || chan < 0 || chan > 7)
     {
         float idx, sflags;
-        idx = precache_sound_index("misc/null.wav");
+        idx = precache_sound_index(SND(Null));
         sflags = SND_LARGEENTITY;
         if (idx >= 256)
             sflags |= SND_LARGESOUND;
@@ -893,7 +889,7 @@ float spamsound(entity e, float chan, string samp, float vol, float _atten)
     if (time > e.spamtime)
     {
         e.spamtime = time;
-        sound(e, chan, samp, vol, _atten);
+        _sound(e, chan, samp, vol, _atten);
         return true;
     }
     return false;
@@ -918,7 +914,7 @@ void play2all(string samp)
     if (autocvar_bot_sound_monopoly)
         return;
 
-    sound(world, CH_INFO, samp, VOL_BASE, ATTEN_NONE);
+    _sound(world, CH_INFO, samp, VOL_BASE, ATTEN_NONE);
 }
 
 void PrecachePlayerSounds(string f);
@@ -970,10 +966,8 @@ void precache_all_playermodels(string pattern)
 }
 
 void precache()
-{
+{SELFPARAM();
     // gamemode related things
-    precache_model ("models/misc/chatbubble.spr");
-       precache_model("models/ice/ice.md3");
 
     // Precache all player models if desired
     if (autocvar_sv_precacheplayermodels)
@@ -1013,53 +1007,8 @@ void precache()
     }
 
     // gore and miscellaneous sounds
-    //precache_sound ("misc/h2ohit.wav");
-    precache_model ("models/hook.md3");
-    precache_sound ("misc/armorimpact.wav");
-    precache_sound ("misc/bodyimpact1.wav");
-    precache_sound ("misc/bodyimpact2.wav");
-    precache_sound ("misc/gib.wav");
-    precache_sound ("misc/gib_splat01.wav");
-    precache_sound ("misc/gib_splat02.wav");
-    precache_sound ("misc/gib_splat03.wav");
-    precache_sound ("misc/gib_splat04.wav");
     PrecacheGlobalSound((globalsound_fall = "misc/hitground 4"));
     PrecacheGlobalSound((globalsound_metalfall = "misc/metalhitground 4"));
-    precache_sound ("misc/null.wav");
-    precache_sound ("misc/spawn.wav");
-    precache_sound ("misc/talk.wav");
-    precache_sound ("misc/teleport.wav");
-    precache_sound ("misc/poweroff.wav");
-    precache_sound ("player/lava.wav");
-    precache_sound ("player/slime.wav");
-
-    precache_model ("models/sprites/0.spr32");
-    precache_model ("models/sprites/1.spr32");
-    precache_model ("models/sprites/2.spr32");
-    precache_model ("models/sprites/3.spr32");
-    precache_model ("models/sprites/4.spr32");
-    precache_model ("models/sprites/5.spr32");
-    precache_model ("models/sprites/6.spr32");
-    precache_model ("models/sprites/7.spr32");
-    precache_model ("models/sprites/8.spr32");
-    precache_model ("models/sprites/9.spr32");
-    precache_model ("models/sprites/10.spr32");
-
-    // common weapon precaches
-       precache_sound (W_Sound("reload")); // until weapons have individual reload sounds, precache the reload sound here
-    precache_sound (W_Sound("weapon_switch"));
-    precache_sound (W_Sound("weaponpickup"));
-    precache_sound (W_Sound("unavailable"));
-    precache_sound (W_Sound("dryfire"));
-    if (g_grappling_hook)
-    {
-        precache_sound (W_Sound("hook_fire")); // hook
-        precache_sound (W_Sound("hook_impact")); // hook
-    }
-
-    precache_model("models/elaser.mdl");
-    precache_model("models/laser.mdl");
-    precache_model("models/ebomb.mdl");
 
 #if 0
     // Disabled this code because it simply does not work (e.g. ignores bgmvolume, overlaps with "cd loop" controlled tracks).
@@ -1074,8 +1023,6 @@ void precache()
         ambientsound ('0 0 0', self.noise, VOL_BASE, ATTEN_NONE);
     }
 #endif
-
-#include "precache-for-csqc.inc"
 }
 
 
@@ -1111,7 +1058,7 @@ void make_safe_for_remove(entity e)
 }
 
 void objerror(string s)
-{
+{SELFPARAM();
     make_safe_for_remove(self);
     builtin_objerror(s);
 }
@@ -1144,10 +1091,8 @@ void InitializeEntity(entity e, void(void) func, float order)
     if (!e || e.initialize_entity)
     {
         // make a proxy initializer entity
-        entity e_old;
-        e_old = e;
-        e = spawn();
-        e.classname = "initialize_entity";
+        entity e_old = e;
+        e = new(initialize_entity);
         e.enemy = e_old;
     }
 
@@ -1173,91 +1118,45 @@ void InitializeEntity(entity e, void(void) func, float order)
     }
 }
 void InitializeEntitiesRun()
-{
-    entity startoflist;
-    startoflist = initialize_entity_first;
-    initialize_entity_first = world;
+{SELFPARAM();
+    entity startoflist = initialize_entity_first;
+    initialize_entity_first = NULL;
     remove = remove_except_protected;
-    for (self = startoflist; self; self = self.initialize_entity_next)
+    for (entity e = startoflist; e; e = e.initialize_entity_next)
     {
-       self.remove_except_protected_forbidden = 1;
+               e.remove_except_protected_forbidden = 1;
     }
-    for (self = startoflist; self; )
+    for (entity e = startoflist; e; )
     {
-        entity e;
-        var void(void) func;
-        e = self.initialize_entity_next;
-        func = self.initialize_entity;
-        self.initialize_entity_order = 0;
-        self.initialize_entity = func_null;
-        self.initialize_entity_next = world;
-       self.remove_except_protected_forbidden = 0;
-        if (self.classname == "initialize_entity")
+               e.remove_except_protected_forbidden = 0;
+        e.initialize_entity_order = 0;
+       entity next = e.initialize_entity_next;
+        e.initialize_entity_next = NULL;
+        var void() func = e.initialize_entity;
+        e.initialize_entity = func_null;
+        if (e.classname == "initialize_entity")
         {
-            entity e_old;
-            e_old = self.enemy;
-            builtin_remove(self);
-            self = e_old;
+            entity wrappee = e.enemy;
+            builtin_remove(e);
+            e = wrappee;
+        }
+        //dprint("Delayed initialization: ", e.classname, "\n");
+        if (func)
+        {
+               WITH(entity, self, e, func());
         }
-        //dprint("Delayed initialization: ", self.classname, "\n");
-        if(func)
-            func();
         else
         {
-            eprint(self);
-            backtrace(strcat("Null function in: ", self.classname, "\n"));
+            eprint(e);
+            backtrace(strcat("Null function in: ", e.classname, "\n"));
         }
-        self = e;
+        e = next;
     }
     remove = remove_unsafely;
 }
 
-void UncustomizeEntitiesRun()
-{
-    entity oldself;
-    oldself = self;
-    for (self = world; (self = findfloat(self, uncustomizeentityforclient_set, 1)); )
-        self.uncustomizeentityforclient();
-    self = oldself;
-}
-void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
-{
-    e.customizeentityforclient = customizer;
-    e.uncustomizeentityforclient = uncustomizer;
-    e.uncustomizeentityforclient_set = !!uncustomizer;
-}
-
-void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc)
-{
-    vector mi, ma;
-
-    if (e.classname == "")
-        e.classname = "net_linked";
-
-    if (e.model == "" || self.modelindex == 0)
-    {
-        mi = e.mins;
-        ma = e.maxs;
-        setmodel(e, "null");
-        setsize(e, mi, ma);
-    }
-
-    e.SendEntity = sendfunc;
-    e.SendFlags = 0xFFFFFF;
-
-    if (!docull)
-        e.effects |= EF_NODEPTHTEST;
-
-    if (dt)
-    {
-        e.nextthink = time + dt;
-        e.think = SUB_Remove;
-    }
-}
-
-
 .float(entity) isEliminated;
-float EliminatedPlayers_SendEntity(entity to, float sendflags)
+bool EliminatedPlayers_SendEntity(entity this, entity to, float sendflags)
 {
        float i, f, b;
        entity e;
@@ -1293,7 +1192,7 @@ void EliminatedPlayers_Init(float(entity) isEliminated_func)
 
 
 void adaptor_think2touch()
-{
+{SELFPARAM();
     entity o;
     o = other;
     other = world;
@@ -1302,7 +1201,7 @@ void adaptor_think2touch()
 }
 
 void adaptor_think2use()
-{
+{SELFPARAM();
     entity o, a;
     o = other;
     a = activator;
@@ -1314,7 +1213,7 @@ void adaptor_think2use()
 }
 
 void adaptor_think2use_hittype_splash() // for timed projectile detonation
-{
+{SELFPARAM();
        if(!(self.flags & FL_ONGROUND)) // if onground, we ARE touching something, but HITTYPE_SPLASH is to be networked if the damage causing projectile is not touching ANYTHING
                self.projectiledeathtype |= HITTYPE_SPLASH;
        adaptor_think2use();
@@ -1322,13 +1221,13 @@ void adaptor_think2use_hittype_splash() // for timed projectile detonation
 
 // deferred dropping
 void DropToFloor_Handler()
-{
+{SELFPARAM();
     builtin_droptofloor();
     self.dropped_origin = self.origin;
 }
 
 void droptofloor()
-{
+{SELFPARAM();
     InitializeEntity(self, DropToFloor_Handler, INITPRIO_DROPTOFLOOR);
 }
 
@@ -1384,7 +1283,7 @@ float tracebox_hits_box(vector start, vector mi, vector ma, vector end, vector t
 }
 
 float SUB_NoImpactCheck()
-{
+{SELFPARAM();
        // zero hitcontents = this is not the real impact, but either the
        // mirror-impact of something hitting the projectile instead of the
        // projectile hitting the something, or a touchareagrid one. Neither of
@@ -1421,7 +1320,7 @@ float SUB_NoImpactCheck()
 
 void W_Crylink_Dequeue(entity e);
 float WarpZone_Projectile_Touch_ImpactFilter_Callback()
-{
+{SELFPARAM();
        if(SUB_OwnerCheck())
                return true;
        if(SUB_NoImpactCheck())
@@ -1492,7 +1391,7 @@ string uid2name(string myuid) {
        return s;
 }
 
-float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
+float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
 {
     float m, i;
     vector start, org, delta, end, enddown, mstart;
@@ -1501,8 +1400,8 @@ float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, f
     m = e.dphitcontentsmask;
     e.dphitcontentsmask = goodcontents | badcontents;
 
-    org = world.mins;
-    delta = world.maxs - world.mins;
+    org = boundmin;
+    delta = boundmax - boundmin;
 
     start = end = org;
 
@@ -1603,6 +1502,11 @@ float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, f
         return false;
 }
 
+float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
+{
+       return MoveToRandomLocationWithinBounds(e, world.mins, world.maxs, goodcontents, badcontents, badsurfaceflags, attempts, maxaboveground, minviewdistance);
+}
+
 void write_recordmarker(entity pl, float tstart, float dt)
 {
     GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
@@ -1697,7 +1601,7 @@ vector shotorg_adjust_values(vector vecs, float y_is_right, float visual, float
 }
 
 vector shotorg_adjust(vector vecs, float y_is_right, float visual)
-{
+{SELFPARAM();
        return shotorg_adjust_values(vecs, y_is_right, visual, self.owner.cvar_cl_gunalign);
 }
 
@@ -1786,7 +1690,7 @@ vector gettaginfo_relative(entity e, float tag)
 
 .float scale2;
 
-float modeleffect_SendEntity(entity to, int sf)
+bool modeleffect_SendEntity(entity this, entity to, int sf)
 {
        float f;
        WriteByte(MSG_ENTITY, ENT_CLIENT_MODELEFFECT);
@@ -1839,7 +1743,7 @@ void modeleffect_spawn(string m, float s, float f, vector o, vector v, vector an
        float sz;
        e = spawn();
        e.classname = "modeleffect";
-       setmodel(e, m);
+       _setmodel(e, m);
        e.frame = f;
        setorigin(e, o);
        e.velocity = v;
index f1f003820d1b8c736c48261847a34a83f4699164..007de3cac6c35e501b727e135e09896f83888263 100644 (file)
@@ -8,7 +8,7 @@
 
 #include "../common/constants.qh"
 #include "../common/mapinfo.qh"
-#include "../common/turrets/turrets.qh"
+#include "../common/turrets/all.qh"
 
 #ifdef RELEASE
 #define cvar_string_normal builtin_cvar_string
@@ -29,8 +29,6 @@ float cvar_normal(string n)
 #define cvar_set_normal builtin_cvar_set
 
 .vector dropped_origin;
-.void(void) uncustomizeentityforclient;
-.float uncustomizeentityforclient_set;
 .float nottargeted;
 
 entity eliminatedPlayers;
@@ -61,9 +59,6 @@ void precache_all_playermodels(string pattern);
 
 void soundat(entity e, vector o, float chan, string samp, float vol, float _atten);
 
-void defer(float fdelay, void() func);
-
-void UncustomizeEntitiesRun();
 void InitializeEntitiesRun();
 
 void stopsoundto(float _dest, entity e, float chan);
@@ -106,6 +101,8 @@ float LostMovetypeFollow(entity ent);
 
 string uid2name(string myuid);
 
+float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance);
+
 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance);
 
 string NearestLocation(vector p);
@@ -336,7 +333,6 @@ void readlevelcvars(void)
        sv_foginterval = cvar("sv_foginterval");
        g_cloaked = cvar("g_cloaked");
        g_footsteps = cvar("g_footsteps");
-       g_grappling_hook = cvar("g_grappling_hook");
        g_jetpack = cvar("g_jetpack");
        sv_maxidle = cvar("sv_maxidle");
        sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");
@@ -420,8 +416,10 @@ void readlevelcvars(void)
        if (!warmup_stage)
                game_starttime = time + cvar("g_start_delay");
 
-       for(int i = WEP_FIRST; i <= WEP_LAST; ++i)
-               WEP_ACTION(i, WR_INIT);
+       for(int i = WEP_FIRST; i <= WEP_LAST; ++i) {
+               Weapon w = get_weaponinfo(i);
+               w.wr_init(w);
+       }
 
        readplayerstartcvars();
 }
@@ -460,6 +458,5 @@ entity initialize_entity_first;
 float sound_allowed(float dest, entity e);
 void InitializeEntity(entity e, void(void) func, float order);
 void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer);
-void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc);
 
 #endif
index 994849f5572cfa712148705297c363cf48cbf079..acacba093a80dc2547da6206b6735dae9fa9ddab 100644 (file)
@@ -8,7 +8,7 @@
     self.velocity = movelib_dragvec(self.velocity,0.02,0.5);
 **/
 vector movelib_dragvec(float drag, float exp_)
-{
+{SELFPARAM();
     float lspeed,ldrag;
 
     lspeed = vlen(self.velocity);
@@ -40,7 +40,7 @@ float movelib_dragflt(float fspeed,float drag,float exp_)
     self.velocity = movelib_inertmove_byspeed(self.velocity,newvel,1000,0.1,0.9);
 **/
 vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,float oldmax)
-{
+{SELFPARAM();
     float influense;
 
     influense = vlen(self.velocity) * (1 / vel_max);
@@ -51,12 +51,12 @@ vector movelib_inertmove_byspeed(vector vel_new, float vel_max,float newmin,floa
 }
 
 vector movelib_inertmove(vector new_vel,float new_bias)
-{
+{SELFPARAM();
     return new_vel * new_bias + self.velocity * (1-new_bias);
 }
 
 void movelib_move(vector force,float max_velocity,float drag,float theMass,float breakforce)
-{
+{SELFPARAM();
     float deltatime;
     float acceleration;
     float mspeed;
@@ -164,7 +164,7 @@ void movelib_update(vector dir,float force)
 */
 
 void movelib_beak_simple(float force)
-{
+{SELFPARAM();
     float mspeed;
     vector mdir;
     float vz;
@@ -183,7 +183,7 @@ Yed need to set v_up and v_forward (generally by calling makevectors) before cal
 #endif
 
 void movelib_groundalign4point(float spring_length, float spring_up, float blendrate, float _max)
-{
+{SELFPARAM();
     vector a, b, c, d, e, r, push_angle, ahead, side;
 
     push_angle.y = 0;
index e867e049a398cb1b253638644c6836573094a6d4..1492b9f6af3d07a06aa8a782a8d4a846ea60bea0 100644 (file)
@@ -12,7 +12,7 @@ MUTATOR_HOOKABLE(MakePlayerObserver, EV_MakePlayerObserver)
 
 /** */
 #define EV_PutClientInServer(i, o) \
-    /** client wanting to spawn */ i(entity, self) \
+    /** client wanting to spawn */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(PutClientInServer, EV_PutClientInServer);
 
@@ -106,6 +106,7 @@ MUTATOR_HOOKABLE(PlayerJump, EV_PlayerJump);
 
 /** called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill */
 #define EV_GiveFragsForKill(i, o) \
+    /**/ i(entity, __self) \
     /** same as self */ i(entity, frag_attacker) \
     /**/ i(entity, frag_target) \
     /**/ i(float, frag_score) \
@@ -128,7 +129,7 @@ MUTATOR_HOOKABLE(GetTeamCount, EV_GetTeamCount);
 /** copies variables for spectating "other" to "self" */
 #define EV_SpectateCopy(i, o) \
     /**/ i(entity, other) \
-    /**/ i(entity, self) \
+    /**/ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(SpectateCopy, EV_SpectateCopy);
 
@@ -167,7 +168,7 @@ MUTATOR_HOOKABLE(SetStartItems, EV_NO_ARGS);
 
 /** called every frame. customizes the waypoint for spectators */
 #define EV_CustomizeWaypoint(i, o) \
-    /** waypoint */ i(entity, self) \
+    /** waypoint */ i(entity, __self) \
     /** player; other.enemy = spectator */ i(entity, other) \
     /**/
 MUTATOR_HOOKABLE(CustomizeWaypoint, EV_CustomizeWaypoint);
@@ -180,13 +181,13 @@ MUTATOR_HOOKABLE(FilterItem, EV_NO_ARGS);
 
 /** return error to request removal */
 #define EV_TurretSpawn(i, o) \
-    /** turret */ i(entity, self) \
+    /** turret */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(TurretSpawn, EV_TurretSpawn);
 
 /** return error to not attack */
 #define EV_TurretFire(i, o) \
-    /** turret */ i(entity, self) \
+    /** turret */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(TurretFire, EV_TurretFire);
 
@@ -224,7 +225,7 @@ MUTATOR_HOOKABLE(GetCvars, EV_NO_ARGS); // NOTE: Can't use EV_GetCvars because o
 
 /** can edit any "just fired" projectile */
 #define EV_EditProjectile(i, o) \
-    /**/ i(entity, self) \
+    /**/ i(entity, __self) \
     /**/ i(entity, other) \
     /**/
 MUTATOR_HOOKABLE(EditProjectile, EV_EditProjectile);
@@ -256,7 +257,7 @@ MUTATOR_HOOKABLE(MonsterRespawn, EV_MonsterRespawn);
     /**/ i(entity, other) \
     /**/ o(entity, other) \
     /**/
-.void() monster_loot;
+.void(entity this) monster_loot;
 MUTATOR_HOOKABLE(MonsterDropItem, EV_MonsterDropItem);
 
 /**
@@ -338,7 +339,7 @@ MUTATOR_HOOKABLE(PlayerDamaged, EV_PlayerDamaged);
 
 /** called at the end of player_powerups() in cl_client.qc, used for manipulating the values which are set by powerup items. */
 #define EV_PlayerPowerups(i, o) \
-    /**/ i(entity, self) \
+    /**/ i(entity, __self) \
     /**/ i(int, olditems) \
     /**/
 int olditems;
@@ -416,7 +417,7 @@ MUTATOR_HOOKABLE(SV_ParseServerCommand, EV_SV_ParseServerCommand);
  * return 1 to make the spawnpoint unusable
  */
 #define EV_Spawn_Score(i, o) \
-    /** player wanting to spawn */ i(entity, self) \
+    /** player wanting to spawn */ i(entity, __self) \
     /** spot to be evaluated */ i(entity, spawn_spot) \
     /** _x is priority, _y is "distance" */ i(vector, spawn_score) \
     /**/ o(vector, spawn_score) \
@@ -438,12 +439,12 @@ MUTATOR_HOOKABLE(SetModname, EV_SetModname);
  * return 1 to remove an item
  */
 #define EV_Item_Spawn(i, o) \
-    /** the item */ i(entity, self) \
+    /** the item */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(Item_Spawn, EV_Item_Spawn);
 
 #define EV_SetWeaponreplace(i, o) \
-    /** map entity */ i(entity, self) \
+    /** map entity */ i(entity, __self) \
     /** weapon info */ i(entity, other) \
     /**/ i(string, ret_string) \
     /**/ o(string, ret_string) \
@@ -473,7 +474,7 @@ MUTATOR_HOOKABLE(BotShouldAttack, EV_BotShouldAttack);
  * allows you to strip a player of an item if they go through the teleporter to help prevent cheating
  */
 #define EV_PortalTeleport(i, o) \
-    /**/ i(entity, self) \
+    /**/ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(PortalTeleport, EV_PortalTeleport);
 
@@ -484,7 +485,7 @@ MUTATOR_HOOKABLE(PortalTeleport, EV_PortalTeleport);
  * in a special manner using this hook
  */
 #define EV_HelpMePing(i, o) \
-    /** the player who pressed impulse 33 */ i(entity, self) \
+    /** the player who pressed impulse 33 */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(HelpMePing, EV_HelpMePing);
 
@@ -511,7 +512,7 @@ MUTATOR_HOOKABLE(VehicleEnter, EV_VehicleEnter);
  * return true to stop player from entering the vehicle
  */
 #define EV_VehicleTouch(i, o) \
-    /** vehicle */ i(entity, self) \
+    /** vehicle */ i(entity, __self) \
     /** player */ i(entity, other) \
     /**/
 MUTATOR_HOOKABLE(VehicleTouch, EV_VehicleTouch);
@@ -528,13 +529,13 @@ MUTATOR_HOOKABLE(VehicleExit, EV_VehicleExit);
 
 /** called when a speedrun is aborted and the player is teleported back to start position */
 #define EV_AbortSpeedrun(i, o) \
-    /** player */ i(entity, self) \
+    /** player */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(AbortSpeedrun, EV_AbortSpeedrun);
 
 /** called at when a item is touched. Called early, can edit item properties. */
 #define EV_ItemTouch(i, o) \
-    /** item */ i(entity, self) \
+    /** item */ i(entity, __self) \
     /** player */ i(entity, other) \
     /**/
 MUTATOR_HOOKABLE(ItemTouch, EV_ItemTouch);
@@ -547,12 +548,12 @@ enum {
 
 /** called at when a player connect */
 #define EV_ClientConnect(i, o) \
-    /** player */ i(entity, self) \
+    /** player */ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(ClientConnect, EV_ClientConnect);
 
 #define EV_HavocBot_ChooseRole(i, o) \
-    /**/ i(entity, self) \
+    /**/ i(entity, __self) \
     /**/
 MUTATOR_HOOKABLE(HavocBot_ChooseRole, EV_HavocBot_ChooseRole);
 
@@ -581,7 +582,7 @@ MUTATOR_HOOKABLE(GetModelParams, EV_GetModelParams);
 
 /** called when a bullet has hit a target */
 #define EV_FireBullet_Hit(i, o) \
-    /**/ i(entity, self) \
+    /**/ i(entity, __self) \
     /**/ i(entity, bullet_hit) \
     /**/ i(vector, bullet_startpos) \
     /**/ i(vector, bullet_endpos) \
@@ -608,7 +609,7 @@ MUTATOR_HOOKABLE(FixPlayermodel, EV_FixPlayermodel);
 MUTATOR_HOOKABLE(Scores_CountFragsRemaining, EV_NO_ARGS);
 
 #define EV_GrappleHookThink(i, o) \
-    /**/ i(entity, self) \
+    /**/ i(entity, __self) \
     /**/ i(int, hook_tarzan) \
     /**/ o(int, hook_tarzan) \
     /**/ i(entity, hook_pullentity) \
@@ -622,7 +623,7 @@ float hook_velmultiplier;
 MUTATOR_HOOKABLE(GrappleHookThink, EV_GrappleHookThink);
 
 #define EV_BuffModel_Customize(i, o) \
-    /**/ i(entity, self) \
+    /**/ i(entity, __self) \
     /**/ i(entity, buff_player) \
     /**/
 entity buff_player;
@@ -630,7 +631,7 @@ MUTATOR_HOOKABLE(BuffModel_Customize, EV_BuffModel_Customize);
 
 /** called at when a buff is touched. Called early, can edit buff properties. */
 #define EV_BuffTouch(i, o) \
-    /** item */ i(entity, self) \
+    /** item */ i(entity, __self) \
     /** player */ i(entity, other) \
     /**/
 MUTATOR_HOOKABLE(BuffTouch, EV_BuffTouch);
index 7e13b334d38d5e56a9547d89ddaaaa86e766e966..1a10e3c6c9c789107fc0b80901f63bc7d941230f 100644 (file)
@@ -7,26 +7,25 @@
 
 // random functions
 void assault_objective_use()
-{
+{SELFPARAM();
        // activate objective
        self.health = 100;
        //print("^2Activated objective ", self.targetname, "=", etos(self), "\n");
        //print("Activator is ", activator.classname, "\n");
 
-       entity oldself;
-       oldself = self;
-
-       for(self = world; (self = find(self, target, oldself.targetname)); )
+       for (entity e = world; (e = find(e, target, this.targetname)); )
        {
-               if(self.classname == "target_objective_decrease")
-                       target_objective_decrease_activate();
+               if (e.classname == "target_objective_decrease")
+               {
+                       WITH(entity, self, e, target_objective_decrease_activate());
+               }
        }
 
-       self = oldself;
+       setself(this);
 }
 
 vector target_objective_spawn_evalfunc(entity player, entity spot, vector current)
-{
+{SELFPARAM();
        if(self.health < 0 || self.health >= ASSAULT_VALUE_INACTIVE)
                return '-1 0 0';
        return current;
@@ -35,13 +34,13 @@ vector target_objective_spawn_evalfunc(entity player, entity spot, vector curren
 // reset this objective. Used when spawning an objective
 // and when a new round starts
 void assault_objective_reset()
-{
+{SELFPARAM();
        self.health = ASSAULT_VALUE_INACTIVE;
 }
 
 // decrease the health of targeted objectives
 void assault_objective_decrease_use()
-{
+{SELFPARAM();
        if(activator.team != assault_attacker_team)
        {
                // wrong team triggered decrease
@@ -70,25 +69,24 @@ void assault_objective_decrease_use()
                        PlayerTeamScore_Add(activator, SP_ASSAULT_OBJECTIVES, ST_ASSAULT_OBJECTIVES, 1);
                        self.enemy.health = -1;
 
-                       entity oldself, oldactivator, head;
+                       entity oldactivator, head;
 
-                       oldself = self;
-                       self = oldself.enemy;
+                       setself(this.enemy);
                        if(self.message)
                        FOR_EACH_PLAYER(head)
                                centerprint(head, self.message);
 
                        oldactivator = activator;
-                       activator = oldself;
+                       activator = this;
                        SUB_UseTargets();
                        activator = oldactivator;
-                       self = oldself;
+                       setself(this);
                }
        }
 }
 
 void assault_setenemytoobjective()
-{
+{SELFPARAM();
        entity objective;
        for(objective = world; (objective = find(objective, targetname, self.target)); )
        {
@@ -107,7 +105,7 @@ void assault_setenemytoobjective()
 }
 
 float assault_decreaser_sprite_visible(entity e)
-{
+{SELFPARAM();
        entity decreaser;
 
        decreaser = self.assault_decreaser;
@@ -119,7 +117,7 @@ float assault_decreaser_sprite_visible(entity e)
 }
 
 void target_objective_decrease_activate()
-{
+{SELFPARAM();
        entity ent, spr;
        self.owner = world;
        for(ent = world; (ent = find(ent, target, self.targetname)); )
@@ -154,46 +152,37 @@ void target_objective_decrease_findtarget()
 }
 
 void target_assault_roundend_reset()
-{
+{SELFPARAM();
        //print("round end reset\n");
        self.cnt = self.cnt + 1; // up round counter
        self.winning = 0; // up round
 }
 
 void target_assault_roundend_use()
-{
+{SELFPARAM();
        self.winning = 1; // round has been won by attackers
 }
 
 void assault_roundstart_use()
-{
+{SELFPARAM();
        activator = self;
        SUB_UseTargets();
 
-       entity ent, oldself;
-
        //(Re)spawn all turrets
-       oldself = self;
-       ent = find(world, classname, "turret_main");
-       while(ent) {
+       for(entity ent = NULL; (ent = find(ent, classname, "turret_main")); ) {
                // Swap turret teams
                if(ent.team == NUM_TEAM_1)
                        ent.team = NUM_TEAM_2;
                else
                        ent.team = NUM_TEAM_1;
 
-               self = ent;
-
                // Dubbles as teamchange
-               turret_respawn();
-
-               ent = find(ent, classname, "turret_main");
+               WITH(entity, self, ent, turret_respawn());
        }
-       self = oldself;
 }
 
 void assault_wall_think()
-{
+{SELFPARAM();
        if(self.enemy.health < 0)
        {
                self.model = "";
@@ -213,27 +202,27 @@ void assault_wall_think()
 void vehicles_clearreturn(entity veh);
 void vehicles_spawn();
 void assault_new_round()
-{
-    entity oldself;
+{SELFPARAM();
        //bprint("ASSAULT: new round\n");
 
-       oldself = self;
        // Eject players from vehicles
-    FOR_EACH_PLAYER(self)
+       entity e;
+    FOR_EACH_PLAYER(e)
     {
-        if(self.vehicle)
-            vehicles_exit(VHEF_RELEASE);
+        if(e.vehicle)
+        {
+               WITH(entity, self, e, vehicles_exit(VHEF_RELEASE));
+        }
     }
 
-    self = findchainflags(vehicle_flags, VHF_ISVEHICLE);
-    while(self)
+    for (entity e_ = findchainflags(vehicle_flags, VHF_ISVEHICLE); e_; e_ = e_.chain)
     {
+       setself(e_);
         vehicles_clearreturn(self);
         vehicles_spawn();
-        self = self.chain;
     }
 
-    self = oldself;
+    setself(this);
 
        // up round counter
        self.winning = self.winning + 1;
@@ -262,23 +251,23 @@ void assault_new_round()
 }
 
 // spawnfuncs
-void spawnfunc_info_player_attacker()
+spawnfunc(info_player_attacker)
 {
        if (!g_assault) { remove(self); return; }
 
        self.team = NUM_TEAM_1; // red, gets swapped every round
-       spawnfunc_info_player_deathmatch();
+       spawnfunc_info_player_deathmatch(this);
 }
 
-void spawnfunc_info_player_defender()
+spawnfunc(info_player_defender)
 {
        if (!g_assault) { remove(self); return; }
 
        self.team = NUM_TEAM_2; // blue, gets swapped every round
-       spawnfunc_info_player_deathmatch();
+       spawnfunc_info_player_deathmatch(this);
 }
 
-void spawnfunc_target_objective()
+spawnfunc(target_objective)
 {
        if (!g_assault) { remove(self); return; }
 
@@ -289,7 +278,7 @@ void spawnfunc_target_objective()
        self.spawn_evalfunc = target_objective_spawn_evalfunc;
 }
 
-void spawnfunc_target_objective_decrease()
+spawnfunc(target_objective_decrease)
 {
        if (!g_assault) { remove(self); return; }
 
@@ -307,7 +296,7 @@ void spawnfunc_target_objective_decrease()
 }
 
 // destructible walls that can be used to trigger target_objective_decrease
-void spawnfunc_func_assault_destructible()
+spawnfunc(func_assault_destructible)
 {
        if (!g_assault) { remove(self); return; }
 
@@ -319,23 +308,23 @@ void spawnfunc_func_assault_destructible()
        else
                self.team = NUM_TEAM_1;
 
-       spawnfunc_func_breakable();
+       spawnfunc_func_breakable(this);
 }
 
-void spawnfunc_func_assault_wall()
+spawnfunc(func_assault_wall)
 {
        if (!g_assault) { remove(self); return; }
 
        self.classname = "func_assault_wall";
        self.mdl = self.model;
-       setmodel(self, self.mdl);
+       _setmodel(self, self.mdl);
        self.solid = SOLID_BSP;
        self.think = assault_wall_think;
        self.nextthink = time;
        InitializeEntity(self, assault_setenemytoobjective, INITPRIO_FINDTARGET);
 }
 
-void spawnfunc_target_assault_roundend()
+spawnfunc(target_assault_roundend)
 {
        if (!g_assault) { remove(self); return; }
 
@@ -346,7 +335,7 @@ void spawnfunc_target_assault_roundend()
        self.reset = target_assault_roundend_reset;
 }
 
-void spawnfunc_target_assault_roundstart()
+spawnfunc(target_assault_roundstart)
 {
        if (!g_assault) { remove(self); return; }
 
@@ -359,7 +348,7 @@ void spawnfunc_target_assault_roundstart()
 
 // legacy bot code
 void havocbot_goalrating_ast_targets(float ratingscale)
-{
+{SELFPARAM();
        entity ad, best, wp, tod;
        float radius, found, bestvalue;
        vector p;
@@ -445,7 +434,7 @@ void havocbot_goalrating_ast_targets(float ratingscale)
 }
 
 void havocbot_role_ast_offense()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
        {
                self.havocbot_attack_time = 0;
@@ -479,7 +468,7 @@ void havocbot_role_ast_offense()
 }
 
 void havocbot_role_ast_defense()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
        {
                self.havocbot_attack_time = 0;
@@ -530,7 +519,7 @@ void havocbot_role_ast_setrole(entity bot, float role)
 }
 
 void havocbot_ast_reset_role(entity bot)
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -542,7 +531,7 @@ void havocbot_ast_reset_role(entity bot)
 
 // mutator hooks
 MUTATOR_HOOKFUNCTION(assault_PlayerSpawn)
-{
+{SELFPARAM();
        if(self.team == assault_attacker_team)
                Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_ASSAULT_ATTACKING);
        else
@@ -552,7 +541,7 @@ MUTATOR_HOOKFUNCTION(assault_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(assault_TurretSpawn)
-{
+{SELFPARAM();
        if(!self.team || self.team == MAX_SHOT_DISTANCE)
                self.team = 5; // this gets reversed when match starts?
 
@@ -560,14 +549,14 @@ MUTATOR_HOOKFUNCTION(assault_TurretSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(assault_VehicleSpawn)
-{
+{SELFPARAM();
        self.nextthink = time + 0.5;
 
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(assault_BotRoles)
-{
+{SELFPARAM();
        havocbot_ast_reset_role(self);
        return true;
 }
index f4c4f6826d34be248dc7e9b49df280161d6e7980..570fc38016ca43cca22568cab450e85e969dc583 100644 (file)
@@ -163,7 +163,7 @@ float ca_isEliminated(entity e)
 }
 
 MUTATOR_HOOKFUNCTION(ca_PlayerSpawn)
-{
+{SELFPARAM();
        self.caplayer = 1;
        if(!warmup_stage)
                eliminatedPlayers.SendFlags |= 1;
@@ -171,7 +171,7 @@ MUTATOR_HOOKFUNCTION(ca_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(ca_PutClientInServer)
-{
+{SELFPARAM();
        if(!allowed_to_spawn)
        if(IS_PLAYER(self)) // this is true even when player is trying to join
        {
@@ -188,9 +188,11 @@ MUTATOR_HOOKFUNCTION(ca_PutClientInServer)
 }
 
 MUTATOR_HOOKFUNCTION(ca_reset_map_players)
-{
-       FOR_EACH_CLIENT(self)
+{SELFPARAM();
+       entity e;
+       FOR_EACH_CLIENT(e)
        {
+               setself(e);
                self.killcount = 0;
                if(!self.caplayer && IS_BOT_CLIENT(self))
                {
@@ -208,7 +210,7 @@ MUTATOR_HOOKFUNCTION(ca_reset_map_players)
 }
 
 MUTATOR_HOOKFUNCTION(ca_ClientConnect)
-{
+{SELFPARAM();
        self.classname = "observer";
        return 1;
 }
@@ -226,7 +228,7 @@ MUTATOR_HOOKFUNCTION(ca_GetTeamCount)
 }
 
 entity ca_LastPlayerForTeam()
-{
+{SELFPARAM();
        entity pl, last_pl = world;
        FOR_EACH_PLAYER(pl)
        {
@@ -253,7 +255,7 @@ void ca_LastPlayerForTeam_Notify()
 }
 
 MUTATOR_HOOKFUNCTION(ca_PlayerDies)
-{
+{SELFPARAM();
        ca_LastPlayerForTeam_Notify();
        if(!allowed_to_spawn)
                self.respawn_flags =  RESPAWN_SILENT;
@@ -263,7 +265,7 @@ MUTATOR_HOOKFUNCTION(ca_PlayerDies)
 }
 
 MUTATOR_HOOKFUNCTION(ca_ClientDisconnect)
-{
+{SELFPARAM();
        if(self.caplayer == 1)
                ca_LastPlayerForTeam_Notify();
        return 1;
@@ -275,7 +277,7 @@ MUTATOR_HOOKFUNCTION(ca_ForbidPlayerScore_Clear)
 }
 
 MUTATOR_HOOKFUNCTION(ca_MakePlayerObserver)
-{
+{SELFPARAM();
        if(self.caplayer == 1)
                ca_LastPlayerForTeam_Notify();
        if(self.killindicator_teamchange == -2)
@@ -326,7 +328,7 @@ MUTATOR_HOOKFUNCTION(ca_PlayerDamage)
 }
 
 MUTATOR_HOOKFUNCTION(ca_FilterItem)
-{
+{SELFPARAM();
        if(autocvar_g_powerups <= 0)
        if(self.flags & FL_POWERUP)
                return true;
index 0df123e3a44655d7bc1f602ea7f97504068e1e9f..108b8dda6f369b10163cdc376d968e90e6d65a49 100644 (file)
@@ -179,7 +179,7 @@ void ctf_CaptureShield_Update(entity player, bool wanted_status)
 }
 
 bool ctf_CaptureShield_Customize()
-{
+{SELFPARAM();
        if(!other.ctf_captureshielded) { return false; }
        if(CTF_SAMETEAM(self, other)) { return false; }
 
@@ -187,7 +187,7 @@ bool ctf_CaptureShield_Customize()
 }
 
 void ctf_CaptureShield_Touch()
-{
+{SELFPARAM();
        if(!other.ctf_captureshielded) { return; }
        if(CTF_SAMETEAM(self, other)) { return; }
 
@@ -199,7 +199,7 @@ void ctf_CaptureShield_Touch()
 }
 
 void ctf_CaptureShield_Spawn(entity flag)
-{
+{SELFPARAM();
        entity shield = spawn();
 
        shield.enemy = self;
@@ -214,7 +214,7 @@ void ctf_CaptureShield_Spawn(entity flag)
        shield.scale = 0.5;
 
        setorigin(shield, self.origin);
-       setmodel(shield, "models/ctf/shield.md3");
+       setmodel(shield, MDL_CTF_SHIELD);
        setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs);
 }
 
@@ -239,7 +239,7 @@ void ctf_Handle_Drop(entity flag, entity player, int droptype)
 
        // messages and sounds
        Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_LOST_) : INFO_CTF_LOST_NEUTRAL), player.netname);
-       sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTEN_NONE);
+       _sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTEN_NONE);
        ctf_EventLog("dropped", player.team, player);
 
        // scoring
@@ -296,7 +296,7 @@ void ctf_Handle_Retrieve(entity flag, entity player)
        flag.ctf_status = FLAG_CARRY;
 
        // messages and sounds
-       sound(player, CH_TRIGGER, flag.snd_flag_pass, VOL_BASE, ATTEN_NORM);
+       _sound(player, CH_TRIGGER, flag.snd_flag_pass, VOL_BASE, ATTEN_NORM);
        ctf_EventLog("receive", flag.team, player);
 
        FOR_EACH_REALPLAYER(tmp_player)
@@ -363,7 +363,7 @@ void ctf_Handle_Throw(entity player, entity receiver, int droptype)
                        flag.ctf_status = FLAG_PASSING;
 
                        // other
-                       sound(player, CH_TRIGGER, flag.snd_flag_touch, VOL_BASE, ATTEN_NORM);
+                       _sound(player, CH_TRIGGER, flag.snd_flag_touch, VOL_BASE, ATTEN_NORM);
                        WarpZone_TrailParticles(world, _particleeffectnum(flag.passeffect), player.origin, targ_origin);
                        ctf_EventLog("pass", flag.team, player);
                        break;
@@ -436,7 +436,7 @@ void ctf_Handle_Capture(entity flag, entity toucher, int capturetype)
        // messages and sounds
        Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((enemy_flag.team) ? APP_TEAM_ENT_4(enemy_flag, CENTER_CTF_CAPTURE_) : CENTER_CTF_CAPTURE_NEUTRAL));
        ctf_CaptureRecord(enemy_flag, player);
-       sound(player, CH_TRIGGER, ((ctf_oneflag) ? player_team_flag.snd_flag_capture : ((DIFF_TEAM(player, flag)) ? enemy_flag.snd_flag_capture : flag.snd_flag_capture)), VOL_BASE, ATTEN_NONE);
+       _sound(player, CH_TRIGGER, ((ctf_oneflag) ? player_team_flag.snd_flag_capture : ((DIFF_TEAM(player, flag)) ? enemy_flag.snd_flag_capture : flag.snd_flag_capture)), VOL_BASE, ATTEN_NONE);
 
        switch(capturetype)
        {
@@ -485,7 +485,7 @@ void ctf_Handle_Return(entity flag, entity player)
                Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT_4(flag, CENTER_CTF_RETURN_));
                Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(flag, INFO_CTF_RETURN_), player.netname);
        }
-       sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE);
+       _sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE);
        ctf_EventLog("return", flag.team, player);
 
        // scoring
@@ -573,7 +573,7 @@ void ctf_Handle_Pickup(entity flag, entity player, int pickuptype)
        else
                Send_Notification(NOTIF_ONE, tmp_entity, MSG_CHOICE, ((SAME_TEAM(flag, player)) ? CHOICE_CTF_PICKUP_ENEMY_TEAM : CHOICE_CTF_PICKUP_ENEMY), Team_ColorCode(player.team), player.netname);
 
-       sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTEN_NONE);
+       _sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTEN_NONE);
 
        // scoring
        PlayerScore_Add(player, SP_CTF_PICKUPS, 1);
@@ -641,7 +641,7 @@ void ctf_CheckFlagReturn(entity flag, int returntype)
                                case RETURN_TIMEOUT:
                                        { Send_Notification(NOTIF_ALL, world, MSG_INFO, ((flag.team) ? APP_TEAM_ENT_4(flag, INFO_CTF_FLAGRETURN_TIMEOUT_) : INFO_CTF_FLAGRETURN_TIMEOUT_NEUTRAL)); break; }
                        }
-                       sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTEN_NONE);
+                       _sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTEN_NONE);
                        ctf_EventLog("returned", flag.team, world);
                        ctf_RespawnFlag(flag);
                }
@@ -649,7 +649,7 @@ void ctf_CheckFlagReturn(entity flag, int returntype)
 }
 
 bool ctf_Stalemate_Customize()
-{
+{SELFPARAM();
        // make spectators see what the player would see
        entity e, wp_owner;
        e = WaypointSprite_getviewentity(other);
@@ -730,7 +730,7 @@ void ctf_CheckStalemate(void)
 }
 
 void ctf_FlagDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
        {
                if(autocvar_g_ctf_flag_return_damage_delay)
@@ -754,7 +754,7 @@ void ctf_FlagDamage(entity inflictor, entity attacker, float damage, int deathty
 }
 
 void ctf_FlagThink()
-{
+{SELFPARAM();
        // declarations
        entity tmp_entity;
 
@@ -846,11 +846,10 @@ void ctf_FlagThink()
                                self.health = 0;
                                ctf_CheckFlagReturn(self, RETURN_SPEEDRUN);
 
-                               tmp_entity = self;
-                               self = self.owner;
+                               setself(self.owner);
                                self.impulse = CHIMPULSE_SPEEDRUN; // move the player back to the waypoint they set
                                ImpulseCommands();
-                               self = tmp_entity;
+                               setself(this);
                        }
                        if(autocvar_g_ctf_stalemate)
                        {
@@ -903,7 +902,7 @@ void ctf_FlagThink()
 }
 
 void ctf_FlagTouch()
-{
+{SELFPARAM();
        if(gameover) { return; }
        if(trace_dphitcontents & (DPCONTENTS_PLAYERCLIP | DPCONTENTS_MONSTERCLIP)) { return; }
 
@@ -942,7 +941,7 @@ void ctf_FlagTouch()
                if(time > self.wait) // if we haven't in a while, play a sound/effect
                {
                        Send_Effect_(self.toucheffect, self.origin, '0 0 0', 1);
-                       sound(self, CH_TRIGGER, self.snd_flag_touch, VOL_BASE, ATTEN_NORM);
+                       _sound(self, CH_TRIGGER, self.snd_flag_touch, VOL_BASE, ATTEN_NORM);
                        self.wait = time + FLAG_TOUCHRATE;
                }
                return;
@@ -1049,7 +1048,7 @@ void ctf_RespawnFlag(entity flag)
 }
 
 void ctf_Reset()
-{
+{SELFPARAM();
        if(self.owner)
                if(IS_PLAYER(self.owner))
                        ctf_Handle_Throw(self.owner, world, DROP_RESET);
@@ -1058,7 +1057,7 @@ void ctf_Reset()
 }
 
 void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf_FlagSetup()
-{
+{SELFPARAM();
        // bot waypoints
        waypoint_spawnforitem_force(self, self.origin);
        self.nearestwaypointtimeout = 0; // activate waypointing again
@@ -1085,15 +1084,14 @@ void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf
 
 void set_flag_string(entity flag, .string field, string value, string teamname)
 {
-       if(flag.field == "")
-               flag.field = strzone(sprintf(value,teamname));
+       if(flag.(field) == "")
+               flag.(field) = strzone(sprintf(value,teamname));
 }
 
 void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag entity on the map as a spawnfunc
-{
+{SELFPARAM();
        // declarations
-       string teamname = Static_Team_ColorName_Lower(teamnumber);
-       self = flag; // for later usage with droptofloor()
+       setself(flag); // for later usage with droptofloor()
 
        // main setup
        flag.ctf_worldflagnext = ctf_worldflaglist; // link flag into ctf_worldflaglist
@@ -1125,6 +1123,7 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        flag.nextthink = time + FLAG_THINKRATE;
        flag.ctf_status = FLAG_BASE;
 
+       string teamname = Static_Team_ColorName_Lower(teamnumber);
        // appearence
        if(!flag.scale)                         { flag.scale = FLAG_SCALE; }
        if(flag.skin == 0)                      { flag.skin = cvar(sprintf("g_ctf_flag_%s_skin", teamname)); }
@@ -1134,28 +1133,22 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        set_flag_string(flag, capeffect,        "%s_cap",               teamname);
 
        // sounds
-       set_flag_string(flag, snd_flag_taken,           "ctf/%s_taken.wav",     teamname);
-       set_flag_string(flag, snd_flag_returned,        "ctf/%s_returned.wav",  teamname);
-       set_flag_string(flag, snd_flag_capture,         "ctf/%s_capture.wav",   teamname);
-       set_flag_string(flag, snd_flag_dropped,         "ctf/%s_dropped.wav",   teamname);
-       if(flag.snd_flag_respawn == "")         { flag.snd_flag_respawn = "ctf/flag_respawn.wav"; } // if there is ever a team-based sound for this, update the code to match.
-       if(flag.snd_flag_touch == "")           { flag.snd_flag_touch = "ctf/touch.wav"; } // again has no team-based sound
-       if(flag.snd_flag_pass == "")            { flag.snd_flag_pass = "ctf/pass.wav"; } // same story here
-
-       // precache
-       precache_sound(flag.snd_flag_taken);
-       precache_sound(flag.snd_flag_returned);
-       precache_sound(flag.snd_flag_capture);
+       flag.snd_flag_taken = SND(CTF_TAKEN(teamnumber));
+       flag.snd_flag_returned = SND(CTF_RETURNED(teamnumber));
+       flag.snd_flag_capture = SND(CTF_CAPTURE(teamnumber));
+       flag.snd_flag_dropped = SND(CTF_DROPPED(teamnumber));
+       if (flag.snd_flag_respawn == "") flag.snd_flag_respawn = SND(CTF_RESPAWN); // if there is ever a team-based sound for this, update the code to match.
        precache_sound(flag.snd_flag_respawn);
-       precache_sound(flag.snd_flag_dropped);
+       if (flag.snd_flag_touch == "") flag.snd_flag_touch = SND(CTF_TOUCH); // again has no team-based sound
        precache_sound(flag.snd_flag_touch);
+       if (flag.snd_flag_pass == "") flag.snd_flag_pass = SND(CTF_PASS); // same story here
        precache_sound(flag.snd_flag_pass);
+
+       // precache
        precache_model(flag.model);
-       precache_model("models/ctf/shield.md3");
-       precache_model("models/ctf/shockwavetransring.md3");
 
        // appearence
-       setmodel(flag, flag.model); // precision set below
+       _setmodel(flag, flag.model); // precision set below
        setsize(flag, FLAG_MIN, FLAG_MAX);
        setorigin(flag, (flag.origin + FLAG_SPAWN_OFFSET));
 
@@ -1197,7 +1190,7 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        else // drop to floor, automatically find a platform and set that as spawn origin
        {
                flag.noalign = false;
-               self = flag;
+               setself(flag);
                droptofloor();
                flag.movetype = MOVETYPE_TOSS;
        }
@@ -1293,7 +1286,7 @@ int havocbot_ctf_teamcount(entity bot, vector org, float tc_radius)
 }
 
 void havocbot_goalrating_ctf_ourflag(float ratingscale)
-{
+{SELFPARAM();
        entity head;
        head = ctf_worldflaglist;
        while (head)
@@ -1307,7 +1300,7 @@ void havocbot_goalrating_ctf_ourflag(float ratingscale)
 }
 
 void havocbot_goalrating_ctf_ourbase(float ratingscale)
-{
+{SELFPARAM();
        entity head;
        head = ctf_worldflaglist;
        while (head)
@@ -1323,7 +1316,7 @@ void havocbot_goalrating_ctf_ourbase(float ratingscale)
 }
 
 void havocbot_goalrating_ctf_enemyflag(float ratingscale)
-{
+{SELFPARAM();
        entity head;
        head = ctf_worldflaglist;
        while (head)
@@ -1350,7 +1343,7 @@ void havocbot_goalrating_ctf_enemyflag(float ratingscale)
 }
 
 void havocbot_goalrating_ctf_enemybase(float ratingscale)
-{
+{SELFPARAM();
        if (!bot_waypoints_for_items)
        {
                havocbot_goalrating_ctf_enemyflag(ratingscale);
@@ -1368,7 +1361,7 @@ void havocbot_goalrating_ctf_enemybase(float ratingscale)
 }
 
 void havocbot_goalrating_ctf_ourstolenflag(float ratingscale)
-{
+{SELFPARAM();
        entity mf;
 
        mf = havocbot_ctf_find_flag(self);
@@ -1404,7 +1397,7 @@ void havocbot_goalrating_ctf_droppedflags(float ratingscale, vector org, float d
 }
 
 void havocbot_goalrating_ctf_carrieritems(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
        entity head;
        float t;
        head = findchainfloat(bot_pickup, true);
@@ -1491,7 +1484,7 @@ void havocbot_ctf_reset_role(entity bot)
 }
 
 void havocbot_role_ctf_carrier()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
        {
                havocbot_ctf_reset_role(self);
@@ -1532,7 +1525,7 @@ void havocbot_role_ctf_carrier()
 }
 
 void havocbot_role_ctf_escort()
-{
+{SELFPARAM();
        entity mf, ef;
 
        if(self.deadflag != DEAD_NO)
@@ -1592,7 +1585,7 @@ void havocbot_role_ctf_escort()
 }
 
 void havocbot_role_ctf_offense()
-{
+{SELFPARAM();
        entity mf, ef;
        vector pos;
 
@@ -1674,7 +1667,7 @@ void havocbot_role_ctf_offense()
 
 // Retriever (temporary role):
 void havocbot_role_ctf_retriever()
-{
+{SELFPARAM();
        entity mf;
 
        if(self.deadflag != DEAD_NO)
@@ -1722,7 +1715,7 @@ void havocbot_role_ctf_retriever()
 }
 
 void havocbot_role_ctf_middle()
-{
+{SELFPARAM();
        entity mf;
 
        if(self.deadflag != DEAD_NO)
@@ -1773,7 +1766,7 @@ void havocbot_role_ctf_middle()
 }
 
 void havocbot_role_ctf_defense()
-{
+{SELFPARAM();
        entity mf;
 
        if(self.deadflag != DEAD_NO)
@@ -1897,7 +1890,7 @@ void havocbot_role_ctf_setrole(entity bot, int role)
 // ==============
 
 MUTATOR_HOOKFUNCTION(ctf_PlayerPreThink)
-{
+{SELFPARAM();
        entity flag;
        int t = 0, t2 = 0, t3 = 0;
 
@@ -2001,7 +1994,7 @@ MUTATOR_HOOKFUNCTION(ctf_GiveFragsForKill)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_RemovePlayer)
-{
+{SELFPARAM();
        entity flag; // temporary entity for the search method
 
        if(self.flagcarried)
@@ -2018,7 +2011,7 @@ MUTATOR_HOOKFUNCTION(ctf_RemovePlayer)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_PortalTeleport)
-{
+{SELFPARAM();
        if(self.flagcarried)
        if(!autocvar_g_ctf_portalteleport)
                { ctf_Handle_Throw(self, world, DROP_NORMAL); }
@@ -2027,7 +2020,7 @@ MUTATOR_HOOKFUNCTION(ctf_PortalTeleport)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE || gameover) { return false; }
 
        entity player = self;
@@ -2120,7 +2113,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_HelpMePing)
-{
+{SELFPARAM();
        if(self.wps_flagcarrier) // update the flagcarrier waypointsprite with "NEEDING HELP" notification
        {
                self.wps_helpme_time = time;
@@ -2174,7 +2167,7 @@ MUTATOR_HOOKFUNCTION(ctf_VehicleExit)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_AbortSpeedrun)
-{
+{SELFPARAM();
        if(self.flagcarried)
        {
                Send_Notification(NOTIF_ALL, world, MSG_INFO, ((self.flagcarried.team) ? APP_TEAM_ENT_4(self.flagcarried, INFO_CTF_FLAGRETURN_ABORTRUN_) : INFO_CTF_FLAGRETURN_ABORTRUN_NEUTRAL));
@@ -2220,7 +2213,7 @@ MUTATOR_HOOKFUNCTION(ctf_MatchEnd)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_BotRoles)
-{
+{SELFPARAM();
        havocbot_ctf_reset_role(self);
        return true;
 }
@@ -2233,7 +2226,7 @@ MUTATOR_HOOKFUNCTION(ctf_GetTeamCount)
 }
 
 MUTATOR_HOOKFUNCTION(ctf_SpectateCopy)
-{
+{SELFPARAM();
        self.ctf_flagstatus = other.ctf_flagstatus;
        return false;
 }
@@ -2254,7 +2247,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team1()
+spawnfunc(item_flag_team1)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2272,7 +2265,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team2()
+spawnfunc(item_flag_team2)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2290,7 +2283,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team3()
+spawnfunc(item_flag_team3)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2308,7 +2301,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_team4()
+spawnfunc(item_flag_team4)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2326,7 +2319,7 @@ Keys:
 "noise3" sound played when flag is lost in the field and respawns itself...
 "noise4" sound played when flag is dropped by a player...
 "noise5" sound played when flag touches the ground... */
-void spawnfunc_item_flag_neutral()
+spawnfunc(item_flag_neutral)
 {
        if(!g_ctf) { remove(self); return; }
        if(!cvar("g_ctf_oneflag")) { remove(self); return; }
@@ -2340,7 +2333,7 @@ Note: If you use spawnfunc_ctf_team entities you must define at least 2!  Howeve
 Keys:
 "netname" Name of the team (for example Red, Blue, Green, Yellow, Life, Death, Offense, Defense, etc)...
 "cnt" Scoreboard color of the team (for example 4 is red and 13 is blue)... */
-void spawnfunc_ctf_team()
+spawnfunc(ctf_team)
 {
        if(!g_ctf) { remove(self); return; }
 
@@ -2349,15 +2342,15 @@ void spawnfunc_ctf_team()
 }
 
 // compatibility for quake maps
-void spawnfunc_team_CTF_redflag()    { spawnfunc_item_flag_team1();    }
-void spawnfunc_team_CTF_blueflag()   { spawnfunc_item_flag_team2();    }
-void spawnfunc_team_CTF_redplayer()  { spawnfunc_info_player_team1();  }
-void spawnfunc_team_CTF_blueplayer() { spawnfunc_info_player_team2();  }
-void spawnfunc_team_CTF_redspawn()   { spawnfunc_info_player_team1();  }
-void spawnfunc_team_CTF_bluespawn()  { spawnfunc_info_player_team2();  }
+spawnfunc(team_CTF_redflag)    { spawnfunc_item_flag_team1(this);    }
+spawnfunc(team_CTF_blueflag)   { spawnfunc_item_flag_team2(this);    }
+spawnfunc(team_CTF_redplayer)  { spawnfunc_info_player_team1(this);  }
+spawnfunc(team_CTF_blueplayer) { spawnfunc_info_player_team2(this);  }
+spawnfunc(team_CTF_redspawn)   { spawnfunc_info_player_team1(this);  }
+spawnfunc(team_CTF_bluespawn)  { spawnfunc_info_player_team2(this);  }
 
-void team_CTF_neutralflag()                     { spawnfunc_item_flag_neutral();  }
-void team_neutralobelisk()                      { spawnfunc_item_flag_neutral();  }
+void team_CTF_neutralflag()                     { SELFPARAM(); spawnfunc_item_flag_neutral(self);  }
+void team_neutralobelisk()                      { SELFPARAM(); spawnfunc_item_flag_neutral(self);  }
 
 
 // ==============
@@ -2382,16 +2375,11 @@ void ctf_ScoreRules(int teams)
 // code from here on is just to support maps that don't have flag and team entities
 void ctf_SpawnTeam (string teamname, int teamcolor)
 {
-       entity oldself;
-       oldself = self;
-       self = spawn();
-       self.classname = "ctf_team";
-       self.netname = teamname;
-       self.cnt = teamcolor;
-
-       spawnfunc_ctf_team();
-
-       self = oldself;
+       entity this = new(ctf_team);
+       this.netname = teamname;
+       this.cnt = teamcolor;
+       this.spawnfunc_checked = true;
+       WITH(entity, self, this, spawnfunc_ctf_team(this));
 }
 
 void ctf_DelayedInit() // Do this check with a delay so we can wait for teams to be set up.
index 04c589ce181a3d920bd0bd744ff923eb08f7e4e3..f9b478232aee988a6cd636fd2f652bdc62794c1a 100644 (file)
@@ -8,7 +8,7 @@
 // legacy bot roles
 .float race_checkpoint;
 void havocbot_role_cts()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -57,7 +57,7 @@ void cts_EventLog(string mode, entity actor) // use an alias for easy changing a
 }
 
 MUTATOR_HOOKFUNCTION(cts_PlayerPhysics)
-{
+{SELFPARAM();
        // force kbd movement for fairness
        float wishspeed;
        vector wishvel;
@@ -142,7 +142,7 @@ MUTATOR_HOOKFUNCTION(cts_ResetMap)
 }
 
 MUTATOR_HOOKFUNCTION(cts_PlayerPreThink)
-{
+{SELFPARAM();
        if(IS_SPEC(self) || IS_OBSERVER(self))
        if(g_race_qualifying)
        if(msg_entity.enemy.race_laptime)
@@ -152,7 +152,7 @@ MUTATOR_HOOKFUNCTION(cts_PlayerPreThink)
 }
 
 MUTATOR_HOOKFUNCTION(cts_ClientConnect)
-{
+{SELFPARAM();
        race_PreparePlayer();
        self.race_checkpoint = -1;
 
@@ -179,7 +179,7 @@ MUTATOR_HOOKFUNCTION(cts_ClientConnect)
 }
 
 MUTATOR_HOOKFUNCTION(cts_MakePlayerObserver)
-{
+{SELFPARAM();
        if(PlayerScore_Add(self, SP_RACE_FASTEST, 0))
                self.frags = FRAGS_LMS_LOSER;
        else
@@ -192,7 +192,7 @@ MUTATOR_HOOKFUNCTION(cts_MakePlayerObserver)
 }
 
 MUTATOR_HOOKFUNCTION(cts_PlayerSpawn)
-{
+{SELFPARAM();
        if(spawn_spot.target == "")
                // Emergency: this wasn't a real spawnpoint. Can this ever happen?
                race_PreparePlayer();
@@ -207,7 +207,7 @@ MUTATOR_HOOKFUNCTION(cts_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(cts_PutClientInServer)
-{
+{SELFPARAM();
        if(IS_PLAYER(self))
        if(!gameover)
        {
@@ -222,20 +222,20 @@ MUTATOR_HOOKFUNCTION(cts_PutClientInServer)
 }
 
 MUTATOR_HOOKFUNCTION(cts_PlayerDies)
-{
+{SELFPARAM();
        self.respawn_flags |= RESPAWN_FORCE;
        race_AbandonRaceCheck(self);
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(cts_BotRoles)
-{
+{SELFPARAM();
        self.havocbot_role = havocbot_role_cts;
        return true;
 }
 
 MUTATOR_HOOKFUNCTION(cts_PlayerPostThink)
-{
+{SELFPARAM();
        if(self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1)
        {
                if (!self.stored_netname)
@@ -258,7 +258,7 @@ MUTATOR_HOOKFUNCTION(cts_ForbidThrowing)
 }
 
 MUTATOR_HOOKFUNCTION(cts_FilterItem)
-{
+{SELFPARAM();
        if(self.classname == "droppedweapon")
                return true;
 
index 7b392a0663af09b0b65be533388aee3cb211b083..34b2875105a6f404588ad6d05477c2920230c369 100644 (file)
@@ -21,7 +21,7 @@ void set_dom_state(entity e)
 }
 
 void dompoint_captured ()
-{
+{SELFPARAM();
        entity head;
        float old_delay, old_team, real_team;
 
@@ -61,9 +61,9 @@ void dompoint_captured ()
 
        if (head.noise != "")
                if(self.enemy)
-                       sound(self.enemy, CH_TRIGGER, head.noise, VOL_BASE, ATTEN_NORM);
+                       _sound(self.enemy, CH_TRIGGER, head.noise, VOL_BASE, ATTEN_NORM);
                else
-                       sound(self, CH_TRIGGER, head.noise, VOL_BASE, ATTEN_NORM);
+                       _sound(self, CH_TRIGGER, head.noise, VOL_BASE, ATTEN_NORM);
        if (head.noise1 != "")
                play2all(head.noise1);
 
@@ -129,7 +129,7 @@ void dompoint_captured ()
 }
 
 void AnimateDomPoint()
-{
+{SELFPARAM();
        if(self.pain_finished > time)
                return;
        self.pain_finished = time + self.t_width;
@@ -142,7 +142,7 @@ void AnimateDomPoint()
 }
 
 void dompointthink()
-{
+{SELFPARAM();
        float fragamt;
 
        self.nextthink = time + 0.1;
@@ -186,7 +186,7 @@ void dompointthink()
 }
 
 void dompointtouch()
-{
+{SELFPARAM();
        entity head;
        if (!IS_PLAYER(other))
                return;
@@ -241,7 +241,7 @@ void dompointtouch()
 }
 
 void dom_controlpoint_setup()
-{
+{SELFPARAM();
        entity head;
        // find the spawnfunc_dom_team representing unclaimed points
        head = find(world, classname, "dom_team");
@@ -252,7 +252,7 @@ void dom_controlpoint_setup()
 
        // copy important properties from spawnfunc_dom_team entity
        self.goalentity = head;
-       setmodel(self, head.mdl); // precision already set
+       _setmodel(self, head.mdl); // precision already set
        self.skin = head.skin;
 
        self.cnt = -1;
@@ -385,7 +385,7 @@ void Domination_RoundStart()
 
 //go to best items, or control points you don't own
 void havocbot_role_dom()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -408,10 +408,12 @@ MUTATOR_HOOKFUNCTION(dom_GetTeamCount)
 }
 
 MUTATOR_HOOKFUNCTION(dom_ResetMap)
-{
+{SELFPARAM();
        total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0;
-       FOR_EACH_PLAYER(self)
+       entity e;
+       FOR_EACH_PLAYER(e)
        {
+               setself(e);
                PutClientInServer();
                self.player_blocked = 1;
                if(IS_REAL_CLIENT(self))
@@ -421,7 +423,7 @@ MUTATOR_HOOKFUNCTION(dom_ResetMap)
 }
 
 MUTATOR_HOOKFUNCTION(dom_PlayerSpawn)
-{
+{SELFPARAM();
        if(domination_roundbased)
        if(!round_handler_IsRoundStarted())
                self.player_blocked = 1;
@@ -431,13 +433,13 @@ MUTATOR_HOOKFUNCTION(dom_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(dom_ClientConnect)
-{
+{SELFPARAM();
        set_dom_state(self);
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(dom_BotRoles)
-{
+{SELFPARAM();
        self.havocbot_role = havocbot_role_dom;
        return true;
 }
@@ -445,7 +447,7 @@ MUTATOR_HOOKFUNCTION(dom_BotRoles)
 /*QUAKED spawnfunc_dom_controlpoint (0 .5 .8) (-16 -16 -24) (16 16 32)
 Control point for Domination gameplay.
 */
-void spawnfunc_dom_controlpoint()
+spawnfunc(dom_controlpoint)
 {
        if(!g_domination)
        {
@@ -490,7 +492,7 @@ Keys:
  (this is a global sound, like "Red team has captured a control point")
 */
 
-void spawnfunc_dom_team()
+spawnfunc(dom_team)
 {
        if(!g_domination || autocvar_g_domination_teams_override >= 2)
        {
@@ -503,7 +505,7 @@ void spawnfunc_dom_team()
        if (self.noise1 != "")
                precache_sound(self.noise1);
        self.classname = "dom_team";
-       setmodel(self, self.model); // precision not needed
+       _setmodel(self, self.model); // precision not needed
        self.mdl = self.model;
        self.dmg = self.modelindex;
        self.model = "";
@@ -541,10 +543,8 @@ void ScoreRules_dom(float teams)
 
 // code from here on is just to support maps that don't have control point and team entities
 void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, string capsound, string capnarration, string capmessage)
-{
-       entity oldself;
-       oldself = self;
-       self = spawn();
+{SELFPARAM();
+       setself(spawn());
        self.classname = "dom_team";
        self.netname = teamname;
        self.cnt = teamcolor;
@@ -555,7 +555,7 @@ void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float p
        self.message = capmessage;
 
        // this code is identical to spawnfunc_dom_team
-       setmodel(self, self.model); // precision not needed
+       _setmodel(self, self.model); // precision not needed
        self.mdl = self.model;
        self.dmg = self.modelindex;
        self.model = "";
@@ -564,31 +564,30 @@ void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float p
        self.team = self.cnt + 1;
 
        //eprint(self);
-       self = oldself;
+       setself(this);
 }
 
+void _spawnfunc_dom_controlpoint() { SELFPARAM(); spawnfunc_dom_controlpoint(self); }
 void dom_spawnpoint(vector org)
-{
-       entity oldself;
-       oldself = self;
-       self = spawn();
+{SELFPARAM();
+       setself(spawn());
        self.classname = "dom_controlpoint";
-       self.think = spawnfunc_dom_controlpoint;
+       self.think = _spawnfunc_dom_controlpoint;
        self.nextthink = time;
        setorigin(self, org);
-       spawnfunc_dom_controlpoint();
-       self = oldself;
+       spawnfunc_dom_controlpoint(this);
+       setself(this);
 }
 
 // spawn some default teams if the map is not set up for domination
 void dom_spawnteams(float teams)
 {
-       dom_spawnteam("Red", NUM_TEAM_1-1, "models/domination/dom_red.md3", 0, "domination/claim.wav", "", "Red team has captured a control point");
-       dom_spawnteam("Blue", NUM_TEAM_2-1, "models/domination/dom_blue.md3", 0, "domination/claim.wav", "", "Blue team has captured a control point");
+       dom_spawnteam("Red", NUM_TEAM_1-1, "models/domination/dom_red.md3", 0, SND(DOM_CLAIM), "", "Red team has captured a control point");
+       dom_spawnteam("Blue", NUM_TEAM_2-1, "models/domination/dom_blue.md3", 0, SND(DOM_CLAIM), "", "Blue team has captured a control point");
        if(teams >= 3)
-               dom_spawnteam("Yellow", NUM_TEAM_3-1, "models/domination/dom_yellow.md3", 0, "domination/claim.wav", "", "Yellow team has captured a control point");
+               dom_spawnteam("Yellow", NUM_TEAM_3-1, "models/domination/dom_yellow.md3", 0, SND(DOM_CLAIM), "", "Yellow team has captured a control point");
        if(teams >= 4)
-               dom_spawnteam("Pink", NUM_TEAM_4-1, "models/domination/dom_pink.md3", 0, "domination/claim.wav", "", "Pink team has captured a control point");
+               dom_spawnteam("Pink", NUM_TEAM_4-1, "models/domination/dom_pink.md3", 0, SND(DOM_CLAIM), "", "Pink team has captured a control point");
        dom_spawnteam("", 0, "models/domination/dom_unclaimed.md3", 0, "", "", "");
 }
 
@@ -624,13 +623,6 @@ void dom_DelayedInit() // Do this check with a delay so we can wait for teams to
 
 void dom_Initialize()
 {
-       precache_model("models/domination/dom_red.md3");
-       precache_model("models/domination/dom_blue.md3");
-       precache_model("models/domination/dom_yellow.md3");
-       precache_model("models/domination/dom_pink.md3");
-       precache_model("models/domination/dom_unclaimed.md3");
-       precache_sound("domination/claim.wav");
-
        InitializeEntity(world, dom_DelayedInit, INITPRIO_GAMETYPE);
 }
 
index 1fa168d63fbe84a9aa957afdb0760161d25a49d2..e7790c974d435776dee2da7ddd8344bf7e453d6e 100644 (file)
@@ -134,7 +134,7 @@ float freezetag_CheckWinner()
 }
 
 entity freezetag_LastPlayerForTeam()
-{
+{SELFPARAM();
        entity pl, last_pl = world;
        FOR_EACH_PLAYER(pl)
        {
@@ -162,7 +162,7 @@ void freezetag_LastPlayerForTeam_Notify()
 }
 
 void freezetag_Add_Score(entity attacker)
-{
+{SELFPARAM();
        if(attacker == self)
        {
                // you froze your own dumb self
@@ -180,7 +180,7 @@ void freezetag_Add_Score(entity attacker)
 }
 
 void freezetag_Freeze(entity attacker)
-{
+{SELFPARAM();
        if(self.frozen)
                return;
 
@@ -195,7 +195,7 @@ void freezetag_Freeze(entity attacker)
 }
 
 void freezetag_Unfreeze(entity attacker)
-{
+{SELFPARAM();
        self.freezetag_frozen_time = 0;
        self.freezetag_frozen_timeout = 0;
 
@@ -218,7 +218,7 @@ void() havocbot_role_ft_freeing;
 void() havocbot_role_ft_offense;
 
 void havocbot_goalrating_freeplayers(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
        entity head;
        float distance;
 
@@ -244,7 +244,7 @@ void havocbot_goalrating_freeplayers(float ratingscale, vector org, float sradiu
 }
 
 void havocbot_role_ft_offense()
-{
+{SELFPARAM();
        entity head;
        float unfrozen;
 
@@ -285,7 +285,7 @@ void havocbot_role_ft_offense()
 }
 
 void havocbot_role_ft_freeing()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -319,7 +319,7 @@ void havocbot_role_ft_freeing()
 // ==============
 
 MUTATOR_HOOKFUNCTION(freezetag_RemovePlayer)
-{
+{SELFPARAM();
        self.health = 0; // neccessary to update correctly alive stats
        if(!self.frozen)
                freezetag_LastPlayerForTeam_Notify();
@@ -329,7 +329,7 @@ MUTATOR_HOOKFUNCTION(freezetag_RemovePlayer)
 }
 
 MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
-{
+{SELFPARAM();
        if(round_handler_IsActive())
        if(round_handler_CountdownRunning())
        {
@@ -383,7 +383,7 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
 }
 
 MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
-{
+{SELFPARAM();
        if(self.freezetag_frozen_timeout == -1) // if PlayerSpawn is called by reset_map_players
                return 1; // do nothing, round is starting right now
 
@@ -406,13 +406,15 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(freezetag_reset_map_players)
-{
-       FOR_EACH_PLAYER(self)
+{SELFPARAM();
+       entity e;
+       FOR_EACH_PLAYER(e)
        {
-               self.killcount = 0;
-               self.freezetag_frozen_timeout = -1;
+               e.killcount = 0;
+               e.freezetag_frozen_timeout = -1;
+               setself(e);
                PutClientInServer();
-               self.freezetag_frozen_timeout = 0;
+               e.freezetag_frozen_timeout = 0;
        }
        freezetag_count_alive_players();
        return 1;
@@ -425,7 +427,7 @@ MUTATOR_HOOKFUNCTION(freezetag_GiveFragsForKill)
 }
 
 MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink)
-{
+{SELFPARAM();
        float n;
 
        if(gameover)
@@ -540,7 +542,7 @@ MUTATOR_HOOKFUNCTION(freezetag_SetStartItems)
 }
 
 MUTATOR_HOOKFUNCTION(freezetag_BotRoles)
-{
+{SELFPARAM();
        if (!self.deadflag)
        {
                if (random() < 0.5)
index c4750d98228fc6279e3bfa2bbe5f2ba9c83ca0bf..5209b225f1084629f085a6cf65b9cc0b86ef7a22 100644 (file)
@@ -6,15 +6,17 @@
 #include "../../common/monsters/spawn.qh"
 #include "../../common/monsters/sv_monsters.qh"
 
-void spawnfunc_invasion_spawnpoint()
+spawnfunc(invasion_spawnpoint)
 {
        if(!g_invasion) { remove(self); return; }
 
        self.classname = "invasion_spawnpoint";
 
        if(autocvar_g_invasion_zombies_only) // precache only if it hasn't been already
-       if(self.monsterid)
-               MON_ACTION(self.monsterid, MR_PRECACHE);
+       if(self.monsterid) {
+               Monster mon = get_monsterinfo(self.monsterid);
+               mon.mr_precache(mon);
+       }
 }
 
 float invasion_PickMonster(float supermonster_count)
@@ -261,7 +263,7 @@ void Invasion_RoundStart()
 }
 
 MUTATOR_HOOKFUNCTION(invasion_MonsterDies)
-{
+{SELFPARAM();
        if(!(self.spawnflags & MONSTERFLAG_RESPAWNED))
        {
                inv_numkilled += 1;
@@ -283,7 +285,7 @@ MUTATOR_HOOKFUNCTION(invasion_MonsterDies)
 }
 
 MUTATOR_HOOKFUNCTION(invasion_MonsterSpawn)
-{
+{SELFPARAM();
        if(!(self.spawnflags & MONSTERFLAG_SPAWNED))
                return true;
 
@@ -304,7 +306,7 @@ MUTATOR_HOOKFUNCTION(invasion_MonsterSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(invasion_OnEntityPreSpawn)
-{
+{SELFPARAM();
        if(startsWith(self.classname, "monster_"))
        if(!(self.spawnflags & MONSTERFLAG_SPAWNED))
                return true;
@@ -327,7 +329,7 @@ MUTATOR_HOOKFUNCTION(invasion_PlayerRegen)
 }
 
 MUTATOR_HOOKFUNCTION(invasion_PlayerSpawn)
-{
+{SELFPARAM();
        self.bot_attack = false;
        return false;
 }
@@ -344,7 +346,7 @@ MUTATOR_HOOKFUNCTION(invasion_PlayerDamage)
 }
 
 MUTATOR_HOOKFUNCTION(invasion_PlayerCommand)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE) // command was already handled?
                return false;
 
@@ -430,9 +432,10 @@ void invasion_DelayedInit() // Do this check with a delay so we can wait for tea
 
 void invasion_Initialize()
 {
-       if(autocvar_g_invasion_zombies_only)
-               MON_ACTION(MON_ZOMBIE.monsterid, MR_PRECACHE);
-       else
+       if(autocvar_g_invasion_zombies_only) {
+               Monster mon = MON_ZOMBIE;
+               mon.mr_precache(mon);
+       } else
        {
                float i;
                entity mon;
@@ -442,7 +445,7 @@ void invasion_Initialize()
                        if((mon.spawnflags & MONSTER_TYPE_FLY) || (mon.spawnflags & MONSTER_TYPE_SWIM))
                                continue; // flying/swimming monsters not yet supported
 
-                       MON_ACTION(i, MR_PRECACHE);
+                       mon.mr_precache(mon);
                }
        }
 
index 96765796a1de7967bd938b17e00facdf70f3a8a5..b265e41d3d5ae47a29097f683546e602da99e87a 100644 (file)
@@ -27,7 +27,7 @@ void ka_EventLog(string mode, entity actor) // use an alias for easy changing an
 
 void ka_TouchEvent();
 void ka_RespawnBall() // runs whenever the ball needs to be relocated
-{
+{SELFPARAM();
        if(gameover) { return; }
        vector oldballorigin = self.origin;
 
@@ -53,11 +53,11 @@ void ka_RespawnBall() // runs whenever the ball needs to be relocated
        WaypointSprite_Spawn(WP_KaBall, 0, 0, self, '0 0 64', world, self.team, self, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER);
        WaypointSprite_Ping(self.waypointsprite_attachedforcarrier);
 
-       sound(self, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+       sound(self, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
 }
 
 void ka_TimeScoring()
-{
+{SELFPARAM();
        if(self.owner.ballcarried)
        { // add points for holding the ball after a certain amount of time
                if(autocvar_g_keepaway_score_timepoints)
@@ -69,7 +69,7 @@ void ka_TimeScoring()
 }
 
 void ka_TouchEvent() // runs any time that the ball comes in contact with something
-{
+{SELFPARAM();
        if(gameover) { return; }
        if(!self) { return; }
        if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
@@ -82,7 +82,7 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth
        if (!IS_PLAYER(other))
        {  // The ball just touched an object, most likely the world
                Send_Effect(EFFECT_BALL_SPARKS, self.origin, '0 0 0', 1);
-               sound(self, CH_TRIGGER, "keepaway/touch.wav", VOL_BASE, ATTEN_NORM);
+               sound(self, CH_TRIGGER, SND_KA_TOUCH, VOL_BASE, ATTEN_NORM);
                return;
        }
        else if(self.wait > time) { return; }
@@ -112,7 +112,7 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth
        Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_KEEPAWAY_PICKUP, other.netname);
        Send_Notification(NOTIF_ALL_EXCEPT, other, MSG_CENTER, CENTER_KEEPAWAY_PICKUP, other.netname);
        Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_KEEPAWAY_PICKUP_SELF);
-       sound(self.owner, CH_TRIGGER, "keepaway/pickedup.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+       sound(self.owner, CH_TRIGGER, SND_KA_PICKEDUP, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
 
        // scoring
        PlayerScore_Add(other, SP_KEEPAWAY_PICKUPS, 1);
@@ -154,7 +154,7 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los
        ka_EventLog("dropped", plyr);
        Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_KEEPAWAY_DROPPED, plyr.netname);
        Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEEPAWAY_DROPPED, plyr.netname);
-       sound(other, CH_TRIGGER, "keepaway/dropped.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+       sound(other, CH_TRIGGER, SND_KA_DROPPED, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
 
        // scoring
        // PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1); Not anymore, this is 100% the same as pickups and is useless.
@@ -167,7 +167,7 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los
 }
 
 void ka_Reset() // used to clear the ballcarrier whenever the match switches from warmup to normal
-{
+{SELFPARAM();
        if((self.owner) && (IS_PLAYER(self.owner)))
                ka_DropEvent(self.owner);
 
@@ -187,7 +187,7 @@ void ka_Reset() // used to clear the ballcarrier whenever the match switches fro
 // ================
 
 void havocbot_goalrating_ball(float ratingscale, vector org)
-{
+{SELFPARAM();
        float t;
        entity ball_owner;
        ball_owner = ka_ball.owner;
@@ -206,7 +206,7 @@ void havocbot_goalrating_ball(float ratingscale, vector org)
 }
 
 void havocbot_role_ka_carrier()
-{
+{SELFPARAM();
        if (self.deadflag != DEAD_NO)
                return;
 
@@ -229,7 +229,7 @@ void havocbot_role_ka_carrier()
 }
 
 void havocbot_role_ka_collector()
-{
+{SELFPARAM();
        if (self.deadflag != DEAD_NO)
                return;
 
@@ -257,7 +257,7 @@ void havocbot_role_ka_collector()
 // ==============
 
 MUTATOR_HOOKFUNCTION(ka_Scoring)
-{
+{SELFPARAM();
        if((frag_attacker != frag_target) && (IS_PLAYER(frag_attacker)))
        {
                if(frag_target.ballcarried) { // add to amount of times killing carrier
@@ -284,7 +284,7 @@ MUTATOR_HOOKFUNCTION(ka_GiveFragsForKill)
 }
 
 MUTATOR_HOOKFUNCTION(ka_PlayerPreThink)
-{
+{SELFPARAM();
        // clear the item used for the ball in keepaway
        self.items &= ~IT_KEY1;
 
@@ -296,7 +296,7 @@ MUTATOR_HOOKFUNCTION(ka_PlayerPreThink)
 }
 
 MUTATOR_HOOKFUNCTION(ka_PlayerUseKey)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE == 0)
        if(self.ballcarried)
        {
@@ -338,13 +338,13 @@ MUTATOR_HOOKFUNCTION(ka_PlayerDamage) // for changing damage and force values th
 }
 
 MUTATOR_HOOKFUNCTION(ka_RemovePlayer)
-{
+{SELFPARAM();
        if(self.ballcarried) { ka_DropEvent(self); } // a player with the ball has left the match, drop it
        return 0;
 }
 
 MUTATOR_HOOKFUNCTION(ka_PlayerPowerups)
-{
+{SELFPARAM();
        // In the future this hook is supposed to allow me to do some extra stuff with waypointsprites and invisibility powerup
        // So bare with me until I can fix a certain bug with ka_ballcarrier_waypointsprite_visible_for_player()
 
@@ -357,7 +357,7 @@ MUTATOR_HOOKFUNCTION(ka_PlayerPowerups)
 }
 
 MUTATOR_HOOKFUNCTION(ka_PlayerPhysics)
-{
+{SELFPARAM();
        if(self.ballcarried)
        {
                self.stat_sv_airspeedlimit_nonqw *= autocvar_g_keepaway_ballcarrier_highspeed;
@@ -367,7 +367,7 @@ MUTATOR_HOOKFUNCTION(ka_PlayerPhysics)
 }
 
 MUTATOR_HOOKFUNCTION(ka_BotShouldAttack)
-{
+{SELFPARAM();
        // if neither player has ball then don't attack unless the ball is on the ground
        if(!checkentity.ballcarried && !self.ballcarried && ka_ball.owner)
                return true;
@@ -375,7 +375,7 @@ MUTATOR_HOOKFUNCTION(ka_BotShouldAttack)
 }
 
 MUTATOR_HOOKFUNCTION(ka_BotRoles)
-{
+{SELFPARAM();
        if (self.ballcarried)
                self.havocbot_role = havocbot_role_ka_carrier;
        else
@@ -396,7 +396,7 @@ void ka_SpawnBall() // loads various values for the ball, runs only once at star
        e = spawn();
        e.model = "models/orbs/orbblue.md3";
        precache_model(e.model);
-       setmodel(e, e.model);
+       _setmodel(e, e.model);
        setsize(e, '-16 -16 -20', '16 16 20'); // 20 20 20 was too big, player is only 16 16 24... gotta cheat with the Z (20) axis so that the particle isn't cut off
        e.classname = "keepawayball";
        e.damageforcescale = autocvar_g_keepawayball_damageforcescale;
@@ -428,11 +428,6 @@ void ka_Initialize() // run at the start of a match, initiates game mode
        if(!g_keepaway)
                return;
 
-       precache_sound("keepaway/pickedup.wav");
-       precache_sound("keepaway/dropped.wav");
-       precache_sound("keepaway/respawn.wav");
-       precache_sound("keepaway/touch.wav");
-
        ka_ScoreRules();
        ka_SpawnBall();
 }
index fe53c1fcc4dbaf39c7b11da153a19e154f7d159a..be45c3db0c3785f51f9d5f62744961b7c09ec117 100644 (file)
@@ -63,12 +63,6 @@ float kh_interferemsg_time, kh_interferemsg_team;
 .float kh_previous_owner_playerid;
 .float kh_cp_duration;
 
-string kh_sound_capture = "kh/capture.wav";
-string kh_sound_destroy = "kh/destroy.wav";
-string kh_sound_drop = "kh/drop.wav";
-string kh_sound_collect = "kh/collect.wav";
-string kh_sound_alarm = "kh/alarm.wav";  // the new siren/alarm
-
 float kh_key_dropped, kh_key_carried;
 
 const float ST_KH_CAPS = 1;
@@ -92,7 +86,7 @@ void kh_ScoreRules(float teams)
 }
 
 float kh_KeyCarrier_waypointsprite_visible_for_player(entity e)  // runs all the time
-{
+{SELFPARAM();
        if(!IS_PLAYER(e) || self.team != e.team)
                if(!kh_tracking_enabled)
                        return false;
@@ -101,7 +95,7 @@ float kh_KeyCarrier_waypointsprite_visible_for_player(entity e)  // runs all the
 }
 
 float kh_Key_waypointsprite_visible_for_player(entity e) // ??
-{
+{SELFPARAM();
        if(!kh_tracking_enabled)
                return false;
        if(!self.owner)
@@ -154,7 +148,7 @@ void kh_Controller_SetThink(float t, kh_Think_t func)  // runs occasionaly
 }
 void kh_WaitForPlayers();
 void kh_Controller_Think()  // called a lot
-{
+{SELFPARAM();
        if(intermission_running)
                return;
        if(self.cnt > 0)
@@ -386,9 +380,9 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                        {
                                if (!k.owner) continue;
                                entity first = WP_Null;
-                               FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
+                               FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
                                entity third = WP_Null;
-                               FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
+                               FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
                                WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFinish, third);
                        }
                }
@@ -401,9 +395,9 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                        {
                                if (!k.owner) continue;
                                entity first = WP_Null;
-                               FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
+                               FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model1, LAMBDA(first = it; break));
                                entity third = WP_Null;
-                               FOREACH(WAYPOINTS, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
+                               FOREACH(Waypoints, it.netname == k.owner.waypointsprite_attachedforcarrier.model3, LAMBDA(third = it; break));
                                WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, first, WP_KeyCarrierFriend, third);
                        }
                }
@@ -411,7 +405,7 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
 }
 
 void kh_Key_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(self.owner)
                return;
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
@@ -430,7 +424,7 @@ void kh_Key_Damage(entity inflictor, entity attacker, float damage, int deathtyp
 
 void kh_Key_Collect(entity key, entity player)  //a player picks up a dropped key
 {
-       sound(player, CH_TRIGGER, kh_sound_collect, VOL_BASE, ATTEN_NORM);
+       sound(player, CH_TRIGGER, SND_KH_COLLECT, VOL_BASE, ATTEN_NORM);
 
        if(key.kh_dropperteam != player.team)
        {
@@ -444,7 +438,7 @@ void kh_Key_Collect(entity key, entity player)  //a player picks up a dropped ke
 }
 
 void kh_Key_Touch()  // runs many, many times when a key has been dropped and can be picked up
-{
+{SELFPARAM();
        if(intermission_running)
                return;
 
@@ -575,7 +569,7 @@ void kh_WinnerTeam(float teem)  // runs when a team wins // Samual: Teem?.... TE
        midpoint = midpoint * (1 / kh_teams);
        te_customflash(midpoint, 1000, 1, Team_ColorRGB(teem) * 0.5 + '0.5 0.5 0.5');  // make the color >=0.5 in each component
 
-       play2all(kh_sound_capture);
+       play2all(SND(KH_CAPTURE));
        kh_FinishRound();
 }
 
@@ -664,14 +658,14 @@ void kh_LoserTeam(float teem, entity lostkey)  // runs when a player pushes a fl
 
        Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(lostkey, INFO_KEYHUNT_LOST_), lostkey.kh_previous_owner.netname);
 
-       play2all(kh_sound_destroy);
+       play2all(SND(KH_DESTROY));
        te_tarexplosion(lostkey.origin);
 
        kh_FinishRound();
 }
 
 void kh_Key_Think()  // runs all the time
-{
+{SELFPARAM();
        entity head;
        //entity player;  // needed by FOR_EACH_PLAYER
 
@@ -696,7 +690,7 @@ void kh_Key_Think()  // runs all the time
        {
                if(self.siren_time < time)
                {
-                       sound(self.owner, CH_TRIGGER, kh_sound_alarm, VOL_BASE, ATTEN_NORM);  // play a simple alarm
+                       sound(self.owner, CH_TRIGGER, SND_KH_ALARM, VOL_BASE, ATTEN_NORM);  // play a simple alarm
                        self.siren_time = time + 2.5;  // repeat every 2.5 seconds
                }
 
@@ -729,7 +723,7 @@ void kh_Key_Think()  // runs all the time
 }
 
 void key_reset()
-{
+{SELFPARAM();
        kh_Key_AssignTo(self, world);
        kh_Key_Remove(self);
 }
@@ -832,7 +826,7 @@ void kh_Key_DropOne(entity key)
        key.pushltime = time + autocvar_g_balance_keyhunt_protecttime;
        key.kh_dropperteam = key.team;
 
-       sound(player, CH_TRIGGER, kh_sound_drop, VOL_BASE, ATTEN_NORM);
+       sound(player, CH_TRIGGER, SND_KH_DROP, VOL_BASE, ATTEN_NORM);
 }
 
 void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
@@ -858,7 +852,7 @@ void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
                        if(suicide)
                                key.kh_dropperteam = player.team;
                }
-               sound(player, CH_TRIGGER, kh_sound_drop, VOL_BASE, ATTEN_NORM);
+               sound(player, CH_TRIGGER, SND_KH_DROP, VOL_BASE, ATTEN_NORM);
        }
 }
 
@@ -1003,17 +997,6 @@ float kh_HandleFrags(entity attacker, entity targ, float f)  // adds to the play
 
 void kh_Initialize()  // sets up th KH environment
 {
-       precache_sound(kh_sound_capture);
-       precache_sound(kh_sound_destroy);
-       precache_sound(kh_sound_drop);
-       precache_sound(kh_sound_collect);
-       precache_sound(kh_sound_alarm);  // the new siren
-
-#ifdef KH_PLAYER_USE_CARRIEDMODEL
-       precache_model("models/keyhunt/key-carried.md3");
-#endif
-       precache_model("models/keyhunt/key.md3");
-
        // setup variables
        kh_teams = autocvar_g_keyhunt_teams_override;
        if(kh_teams < 2)
@@ -1025,7 +1008,7 @@ void kh_Initialize()  // sets up th KH environment
        kh_controller.think = kh_Controller_Think;
        kh_Controller_SetThink(0, kh_WaitForPlayers);
 
-       setmodel(kh_controller, "models/keyhunt/key.md3");
+       setmodel(kh_controller, MDL_KH_KEY);
        kh_key_dropped = kh_controller.modelindex;
        /*
        dprint(vtos(kh_controller.mins));
@@ -1033,7 +1016,7 @@ void kh_Initialize()  // sets up th KH environment
        dprint("\n");
        */
 #ifdef KH_PLAYER_USE_CARRIEDMODEL
-       setmodel(kh_controller, "models/keyhunt/key-carried.md3");
+       setmodel(kh_controller, MDL_KH_KEY_CARRIED);
        kh_key_carried = kh_controller.modelindex;
 #else
        kh_key_carried = kh_key_dropped;
@@ -1058,13 +1041,13 @@ void kh_finalize()
 // register this as a mutator
 
 MUTATOR_HOOKFUNCTION(kh_Key_DropAll)
-{
+{SELFPARAM();
        kh_Key_DropAll(self, true);
        return 0;
 }
 
 MUTATOR_HOOKFUNCTION(kh_PlayerDies)
-{
+{SELFPARAM();
        if(self == other)
                kh_Key_DropAll(self, true);
        else if(IS_PLAYER(other))
@@ -1093,13 +1076,13 @@ MUTATOR_HOOKFUNCTION(kh_GetTeamCount)
 }
 
 MUTATOR_HOOKFUNCTION(kh_SpectateCopy)
-{
+{SELFPARAM();
        self.kh_state = other.kh_state;
        return 0;
 }
 
 MUTATOR_HOOKFUNCTION(kh_PlayerUseKey)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE == 0)
        {
                entity k;
index 85f2e1ed237e2af51209b1bcf8235ffc0a711955..b9395b913a2ad018feeca4540da7dc7adebb513d 100644 (file)
@@ -35,17 +35,20 @@ MUTATOR_HOOKFUNCTION(lms_ResetMap)
 }
 
 MUTATOR_HOOKFUNCTION(lms_ResetPlayers)
-{
+{SELFPARAM();
+       entity e;
        if(restart_mapalreadyrestarted || (time < game_starttime))
-       FOR_EACH_CLIENT(self)
-       if(IS_PLAYER(self))
-               PlayerScore_Add(self, SP_LMS_LIVES, LMS_NewPlayerLives());
+       FOR_EACH_CLIENT(e)
+       if(IS_PLAYER(e))
+       {
+               WITH(entity, self, e, PlayerScore_Add(e, SP_LMS_LIVES, LMS_NewPlayerLives()));
+       }
 
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(lms_PlayerPreSpawn)
-{
+{SELFPARAM();
        // player is dead and becomes observer
        // FIXME fix LMS scoring for new system
        if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0)
@@ -58,14 +61,14 @@ MUTATOR_HOOKFUNCTION(lms_PlayerPreSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(lms_PlayerDies)
-{
+{SELFPARAM();
        self.respawn_flags |= RESPAWN_FORCE;
 
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(lms_RemovePlayer)
-{
+{SELFPARAM();
        // Only if the player cannot play at all
        if(PlayerScore_Add(self, SP_LMS_RANK, 0) == 666)
                self.frags = FRAGS_SPECTATOR;
@@ -82,7 +85,7 @@ MUTATOR_HOOKFUNCTION(lms_RemovePlayer)
 }
 
 MUTATOR_HOOKFUNCTION(lms_ClientConnect)
-{
+{SELFPARAM();
        self.classname = "player";
        campaign_bots_may_start = 1;
 
@@ -96,7 +99,7 @@ MUTATOR_HOOKFUNCTION(lms_ClientConnect)
 }
 
 MUTATOR_HOOKFUNCTION(lms_PlayerThink)
-{
+{SELFPARAM();
        if(self.deadflag == DEAD_DYING)
                self.deadflag = DEAD_RESPAWNING;
 
@@ -159,7 +162,7 @@ MUTATOR_HOOKFUNCTION(lms_KeepScore)
 }
 
 MUTATOR_HOOKFUNCTION(lms_FilterItem)
-{
+{SELFPARAM();
        if(autocvar_g_lms_extra_lives)
        if(self.itemdef == ITEM_HealthMega)
        {
@@ -171,7 +174,7 @@ MUTATOR_HOOKFUNCTION(lms_FilterItem)
 }
 
 MUTATOR_HOOKFUNCTION(lms_ItemTouch)
-{
+{SELFPARAM();
        // give extra lives for mega health
        if (self.items & ITEM_HealthMega.m_itemid)
        {
index 6b8d5a07d7ee9c9f44a27927092254d46ceae2ae..f65e058433ec146ec9799b5d77d672c1bb68c49b 100644 (file)
@@ -3,6 +3,21 @@
 
 #include "gamemode.qh"
 
+float autocvar_g_nexball_basketball_bouncefactor;
+float autocvar_g_nexball_basketball_bouncestop;
+float autocvar_g_nexball_basketball_carrier_highspeed;
+bool autocvar_g_nexball_basketball_meter;
+float autocvar_g_nexball_basketball_meter_maxpower;
+float autocvar_g_nexball_basketball_meter_minpower;
+float autocvar_g_nexball_delay_collect;
+float autocvar_g_nexball_delay_goal;
+float autocvar_g_nexball_delay_start;
+float autocvar_g_nexball_football_bouncefactor;
+float autocvar_g_nexball_football_bouncestop;
+bool autocvar_g_nexball_radar_showallplayers;
+bool autocvar_g_nexball_sound_bounce;
+int autocvar_g_nexball_trail_color;
+
 float autocvar_g_nexball_safepass_turnrate;
 float autocvar_g_nexball_safepass_maxdist;
 float autocvar_g_nexball_safepass_holdtime;
@@ -51,26 +66,24 @@ void LogNB(string mode, entity actor)
 }
 
 void ball_restart(void)
-{
+{SELFPARAM();
        if(self.owner)
                DropBall(self, self.owner.origin, '0 0 0');
        ResetBall();
 }
 
 void nexball_setstatus(void)
-{
-       entity oldself;
+{SELFPARAM();
        self.items &= ~IT_KEY1;
        if(self.ballcarried)
        {
                if(self.ballcarried.teamtime && (self.ballcarried.teamtime < time))
                {
                        bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
-                       oldself = self;
-                       self = self.ballcarried;
+                       setself(self.ballcarried);
                        DropBall(self, self.owner.origin, '0 0 0');
                        ResetBall();
-                       self = oldself;
+                       setself(this);
                }
                else
                        self.items |= IT_KEY1;
@@ -78,7 +91,7 @@ void nexball_setstatus(void)
 }
 
 void relocate_nexball(void)
-{
+{SELFPARAM();
        tracebox(self.origin, BALL_MINS, BALL_MAXS, self.origin, true, self);
        if(trace_startsolid)
        {
@@ -95,7 +108,7 @@ void relocate_nexball(void)
 }
 
 void DropOwner(void)
-{
+{SELFPARAM();
        entity ownr;
        ownr = self.owner;
        DropBall(self, ownr.origin, ownr.velocity);
@@ -105,7 +118,7 @@ void DropOwner(void)
 }
 
 void GiveBall(entity plyr, entity ball)
-{
+{SELFPARAM();
        entity ownr;
 
        if((ownr = ball.owner))
@@ -153,15 +166,15 @@ void GiveBall(entity plyr, entity ball)
                ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold;
        }
 
-       ownr = self;
-       self = plyr;
-       self.weaponentity.weapons = self.weapons;
-       self.weaponentity.switchweapon = self.weapon;
-       self.weapons = WEPSET_PORTO;
-       WEP_ACTION(WEP_PORTO.m_id, WR_RESETPLAYER);
-       self.switchweapon = WEP_PORTO.m_id;
-       W_SwitchWeapon(WEP_PORTO.m_id);
-       self = ownr;
+       plyr.weaponentity.weapons = plyr.weapons;
+       plyr.weaponentity.switchweapon = plyr.weapon;
+       plyr.weapons = WEPSET(NEXBALL);
+       setself(plyr);
+       Weapon w = WEP_NEXBALL;
+       w.wr_resetplayer(w);
+       plyr.switchweapon = WEP_NEXBALL.m_id;
+       W_SwitchWeapon(WEP_NEXBALL.m_id);
+       setself(this);
 }
 
 void DropBall(entity ball, vector org, vector vel)
@@ -196,7 +209,7 @@ void DropBall(entity ball, vector org, vector vel)
 }
 
 void InitBall(void)
-{
+{SELFPARAM();
        if(gameover) return;
        self.flags &= ~FL_ONGROUND;
        self.movetype = MOVETYPE_BOUNCE;
@@ -210,13 +223,13 @@ void InitBall(void)
        self.teamtime = 0;
        self.pusher = world;
        self.team = false;
-       sound(self, CH_TRIGGER, self.noise1, VOL_BASE, ATTEN_NORM);
+       _sound(self, CH_TRIGGER, self.noise1, VOL_BASE, ATTEN_NORM);
        WaypointSprite_Ping(self.waypointsprite_attachedforcarrier);
        LogNB("init", world);
 }
 
 void ResetBall(void)
-{
+{SELFPARAM();
        if(self.cnt < 2)        // step 1
        {
                if(time == self.teamtime)
@@ -252,12 +265,12 @@ void ResetBall(void)
 }
 
 void football_touch(void)
-{
+{SELFPARAM();
        if(other.solid == SOLID_BSP)
        {
                if(time > self.lastground + 0.1)
                {
-                       sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+                       _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
                        self.lastground = time;
                }
                if(vlen(self.velocity) && !self.cnt)
@@ -298,7 +311,7 @@ void football_touch(void)
 }
 
 void basketball_touch(void)
-{
+{SELFPARAM();
        if(other.ballcarried)
        {
                football_touch();
@@ -313,14 +326,14 @@ void basketball_touch(void)
        }
        else if(other.solid == SOLID_BSP)
        {
-               sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
+               _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
                if(vlen(self.velocity) && !self.cnt)
                        self.nextthink = min(time + autocvar_g_nexball_delay_idle, self.teamtime);
        }
 }
 
 void GoalTouch(void)
-{
+{SELFPARAM();
        entity ball;
        float isclient, pscore, otherteam;
        string pname;
@@ -379,7 +392,7 @@ void GoalTouch(void)
                pscore = 1;
        }
 
-       sound(ball, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NONE);
+       _sound(ball, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NONE);
 
        if(ball.team && pscore)
        {
@@ -411,7 +424,7 @@ void GoalTouch(void)
 //=======================//
 //        team ents       //
 //=======================//
-void spawnfunc_nexball_team(void)
+spawnfunc(nexball_team)
 {
        if(!g_nexball)
        {
@@ -486,7 +499,7 @@ void nb_delayedinit(void)
 //=======================//
 
 void SpawnBall(void)
-{
+{SELFPARAM();
        if(!g_nexball) { remove(self); return; }
 
 //     balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
@@ -498,7 +511,7 @@ void SpawnBall(void)
        }
 
        precache_model(self.model);
-       setmodel(self, self.model);
+       _setmodel(self, self.model);
        setsize(self, BALL_MINS, BALL_MAXS);
        ball_scale = self.scale;
 
@@ -518,13 +531,13 @@ void SpawnBall(void)
        if(!autocvar_g_nexball_sound_bounce)
                self.noise = "";
        else if(self.noise == "")
-               self.noise = "sound/nexball/bounce.wav";
+               self.noise = SND(NB_BOUNCE);
        //bounce sound placeholder (FIXME)
        if(self.noise1 == "")
-               self.noise1 = "sound/nexball/drop.wav";
+               self.noise1 = SND(NB_DROP);
        //ball drop sound placeholder (FIXME)
        if(self.noise2 == "")
-               self.noise2 = "sound/nexball/steal.wav";
+               self.noise2 = SND(NB_STEAL);
        //stealing sound placeholder (FIXME)
        if(self.noise) precache_sound(self.noise);
        precache_sound(self.noise1);
@@ -537,7 +550,7 @@ void SpawnBall(void)
        self.nextthink = game_starttime + autocvar_g_nexball_delay_start;
 }
 
-void spawnfunc_nexball_basketball(void)
+spawnfunc(nexball_basketball)
 {
        nexball_mode |= NBM_BASKETBALL;
        self.classname = "nexball_basketball";
@@ -560,7 +573,7 @@ void spawnfunc_nexball_basketball(void)
        SpawnBall();
 }
 
-void spawnfunc_nexball_football(void)
+spawnfunc(nexball_football)
 {
        nexball_mode |= NBM_FOOTBALL;
        self.classname = "nexball_football";
@@ -572,7 +585,7 @@ void spawnfunc_nexball_football(void)
 }
 
 float nb_Goal_Customize()
-{
+{SELFPARAM();
        entity e, wp_owner;
        e = WaypointSprite_getviewentity(other);
        wp_owner = self.owner;
@@ -582,7 +595,7 @@ float nb_Goal_Customize()
 }
 
 void SpawnGoal(void)
-{
+{SELFPARAM();
        if(!g_nexball) { remove(self); return; }
 
        EXACTTRIGGER_INIT;
@@ -601,40 +614,40 @@ void SpawnGoal(void)
        self.touch = GoalTouch;
 }
 
-void spawnfunc_nexball_redgoal(void)
+spawnfunc(nexball_redgoal)
 {
        self.team = NUM_TEAM_1;
        SpawnGoal();
 }
-void spawnfunc_nexball_bluegoal(void)
+spawnfunc(nexball_bluegoal)
 {
        self.team = NUM_TEAM_2;
        SpawnGoal();
 }
-void spawnfunc_nexball_yellowgoal(void)
+spawnfunc(nexball_yellowgoal)
 {
        self.team = NUM_TEAM_3;
        SpawnGoal();
 }
-void spawnfunc_nexball_pinkgoal(void)
+spawnfunc(nexball_pinkgoal)
 {
        self.team = NUM_TEAM_4;
        SpawnGoal();
 }
 
-void spawnfunc_nexball_fault(void)
+spawnfunc(nexball_fault)
 {
        self.team = GOAL_FAULT;
        if(self.noise == "")
-               self.noise = "misc/typehit.wav";
+               self.noise = SND(TYPEHIT);
        SpawnGoal();
 }
 
-void spawnfunc_nexball_out(void)
+spawnfunc(nexball_out)
 {
        self.team = GOAL_OUT;
        if(self.noise == "")
-               self.noise = "misc/typehit.wav";
+               self.noise = SND(TYPEHIT);
        SpawnGoal();
 }
 
@@ -642,34 +655,34 @@ void spawnfunc_nexball_out(void)
 //Spawnfuncs preserved for compatibility
 //
 
-void spawnfunc_ball(void)
+spawnfunc(ball)
 {
-       spawnfunc_nexball_football();
+       spawnfunc_nexball_football(this);
 }
-void spawnfunc_ball_football(void)
+spawnfunc(ball_football)
 {
-       spawnfunc_nexball_football();
+       spawnfunc_nexball_football(this);
 }
-void spawnfunc_ball_basketball(void)
+spawnfunc(ball_basketball)
 {
-       spawnfunc_nexball_basketball();
+       spawnfunc_nexball_basketball(this);
 }
 // The "red goal" is defended by blue team. A ball in there counts as a point for red.
-void spawnfunc_ball_redgoal(void)
+spawnfunc(ball_redgoal)
 {
-       spawnfunc_nexball_bluegoal();   // I blame Revenant
+       spawnfunc_nexball_bluegoal(this);       // I blame Revenant
 }
-void spawnfunc_ball_bluegoal(void)
+spawnfunc(ball_bluegoal)
 {
-       spawnfunc_nexball_redgoal();    // but he didn't mean to cause trouble :p
+       spawnfunc_nexball_redgoal(this);        // but he didn't mean to cause trouble :p
 }
-void spawnfunc_ball_fault(void)
+spawnfunc(ball_fault)
 {
-       spawnfunc_nexball_fault();
+       spawnfunc_nexball_fault(this);
 }
-void spawnfunc_ball_bound(void)
+spawnfunc(ball_bound)
 {
-       spawnfunc_nexball_out();
+       spawnfunc_nexball_out(this);
 }
 
 //=======================//
@@ -678,7 +691,7 @@ void spawnfunc_ball_bound(void)
 
 
 void W_Nexball_Think()
-{
+{SELFPARAM();
        //dprint("W_Nexball_Think\n");
        //vector new_dir = steerlib_arrive(self.enemy.origin, 2500);
        vector new_dir = normalize(self.enemy.origin + '0 0 50' - self.origin);
@@ -693,7 +706,7 @@ void W_Nexball_Think()
 }
 
 void W_Nexball_Touch(void)
-{
+{SELFPARAM();
        entity ball, attacker;
        attacker = self.owner;
        //self.think = func_null;
@@ -708,7 +721,7 @@ void W_Nexball_Touch(void)
                        if(!attacker.ballcarried)
                        {
                                LogNB("stole", attacker);
-                               sound(other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTEN_NORM);
+                               _sound(other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTEN_NORM);
 
                                if(SAME_TEAM(attacker, other) && time > attacker.teamkill_complain)
                                {
@@ -724,13 +737,13 @@ void W_Nexball_Touch(void)
 }
 
 void W_Nexball_Attack(float t)
-{
+{SELFPARAM();
        entity ball;
        float mul, mi, ma;
        if(!(ball = self.ballcarried))
                return;
 
-       W_SetupShot(self, false, 4, "nexball/shoot1.wav", CH_WEAPON_A, 0);
+       W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0);
        tracebox(w_shotorg, BALL_MINS, BALL_MAXS, w_shotorg, MOVE_WORLDONLY, world);
        if(trace_startsolid)
        {
@@ -760,11 +773,11 @@ void W_Nexball_Attack(float t)
 }
 
 void W_Nexball_Attack2(void)
-{
+{SELFPARAM();
        if(self.ballcarried.enemy)
        {
                entity _ball = self.ballcarried;
-               W_SetupShot(self, false, 4, "nexball/shoot1.wav", CH_WEAPON_A, 0);
+               W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0);
                DropBall(_ball, w_shotorg, trigger_push_calculatevelocity(_ball.origin, _ball.enemy, 32));
                _ball.think = W_Nexball_Think;
                _ball.nextthink = time;
@@ -774,11 +787,8 @@ void W_Nexball_Attack2(void)
        if(!autocvar_g_nexball_tackling)
                return;
 
-       entity missile;
-       if(!(balls & BALL_BASKET))
-               return;
-       W_SetupShot(self, false, 2, "nexball/shoot2.wav", CH_WEAPON_A, 0);
-       missile = spawn();
+       W_SetupShot(self, false, 2, SND(NB_SHOOT2), CH_WEAPON_A, 0);
+       entity missile = spawn();
 
        missile.owner = self;
        missile.classname = "ballstealer";
@@ -803,7 +813,7 @@ void W_Nexball_Attack2(void)
 }
 
 float ball_customize()
-{
+{SELFPARAM();
        if(!self.owner)
        {
                self.effects &= ~EF_FLAME;
@@ -829,58 +839,51 @@ float ball_customize()
        return true;
 }
 
-float w_nexball_weapon(float req)
-{
-       if(req == WR_THINK)
+       METHOD(BallStealer, wr_think, void(BallStealer thiswep, entity actor, bool fire1, bool fire2))
        {
-               if(self.BUTTON_ATCK)
-                       if(weapon_prepareattack(0, autocvar_g_balance_nexball_primary_refire))
+               if(fire1)
+                       if(weapon_prepareattack(thiswep, actor, false, autocvar_g_balance_nexball_primary_refire))
                                if(autocvar_g_nexball_basketball_meter)
                                {
                                        if(self.ballcarried && !self.metertime)
                                                self.metertime = time;
                                        else
-                                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
+                                               weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
                                }
                                else
                                {
                                        W_Nexball_Attack(-1);
-                                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
+                                       weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
                                }
-               if(self.BUTTON_ATCK2)
-                       if(weapon_prepareattack(1, autocvar_g_balance_nexball_secondary_refire))
+               if(fire2)
+                       if(weapon_prepareattack(thiswep, actor, true, autocvar_g_balance_nexball_secondary_refire))
                        {
                                W_Nexball_Attack2();
-                               weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready);
+                               weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready);
                        }
 
-               if(!self.BUTTON_ATCK && self.metertime && self.ballcarried)
+               if(!fire1 && self.metertime && self.ballcarried)
                {
                        W_Nexball_Attack(time - self.metertime);
                        // DropBall or stealing will set metertime back to 0
-                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
+                       weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
                }
        }
-       else if(req == WR_INIT)
+       METHOD(BallStealer, wr_setup, void(BallStealer thiswep))
        {
-               precache_model(W_Model("g_porto.md3"));
-               precache_model(W_Model("v_porto.md3"));
-               precache_model(W_Model("h_porto.iqm"));
-               precache_model("models/elaser.mdl");
-               precache_sound("nexball/shoot1.wav");
-               precache_sound("nexball/shoot2.wav");
-               precache_sound("misc/typehit.wav");
+               //weapon_setup(WEP_PORTO.m_id);
        }
-       else if(req == WR_SETUP)
+       METHOD(BallStealer, wr_checkammo1, bool(BallStealer thiswep))
        {
-               //weapon_setup(WEP_PORTO.m_id);
+               return true;
+       }
+       METHOD(BallStealer, wr_checkammo2, bool(BallStealer thiswep))
+       {
+               return true;
        }
-       // No need to check WR_CHECKAMMO* or WR_AIM, it should always return true
-       return true;
-}
 
 MUTATOR_HOOKFUNCTION(nexball_BallDrop)
-{
+{SELFPARAM();
        if(self.ballcarried && g_nexball)
                DropBall(self.ballcarried, self.origin, self.velocity);
 
@@ -888,7 +891,7 @@ MUTATOR_HOOKFUNCTION(nexball_BallDrop)
 }
 
 MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink)
-{
+{SELFPARAM();
        makevectors(self.v_angle);
        if(nexball_mode & NBM_BASKETBALL)
        {
@@ -936,7 +939,8 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink)
                        if(self.weaponentity.weapons)
                        {
                                self.weapons = self.weaponentity.weapons;
-                               WEP_ACTION(WEP_PORTO.m_id, WR_RESETPLAYER);
+                               Weapon w = WEP_NEXBALL;
+                               w.wr_resetplayer(w);
                                self.switchweapon = self.weaponentity.switchweapon;
                                W_SwitchWeapon(self.switchweapon);
 
@@ -952,11 +956,11 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink)
 }
 
 MUTATOR_HOOKFUNCTION(nexball_PlayerSpawn)
-{
+{SELFPARAM();
        self.weaponentity.weapons = '0 0 0';
 
        if(nexball_mode & NBM_BASKETBALL)
-               self.weapons |= WEPSET_PORTO;
+               self.weapons |= WEPSET(NEXBALL);
        else
                self.weapons = '0 0 0';
 
@@ -964,7 +968,7 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(nexball_PlayerPhysics)
-{
+{SELFPARAM();
        if(self.ballcarried)
        {
                self.stat_sv_airspeedlimit_nonqw *= autocvar_g_nexball_basketball_carrier_highspeed;
@@ -973,25 +977,18 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerPhysics)
        return false;
 }
 
-MUTATOR_HOOKFUNCTION(nexball_SetStartItems)
-{
-       start_items |= IT_UNLIMITED_SUPERWEAPONS; // FIXME BAD BAD BAD BAD HACK, NEXBALL SHOULDN'T ABUSE PORTO'S WEAPON SLOT
-
-       return false;
-}
-
 MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing)
-{
-       if(self.weapon == WEP_MORTAR.m_id)
+{SELFPARAM();
+       if(self.weapon == WEP_NEXBALL.m_id)
                return true;
 
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(nexball_FilterItem)
-{
+{SELFPARAM();
        if(self.classname == "droppedweapon")
-       if(self.weapon == WEP_MORTAR.m_id)
+       if(self.weapon == WEP_NEXBALL.m_id)
                return true;
 
        return false;
@@ -1005,7 +1002,6 @@ MUTATOR_DEFINITION(gamemode_nexball)
        MUTATOR_HOOK(PlayerSpawn, nexball_PlayerSpawn, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerPreThink, nexball_PlayerPreThink, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerPhysics, nexball_PlayerPhysics, CBC_ORDER_ANY);
-       MUTATOR_HOOK(SetStartItems, nexball_SetStartItems, CBC_ORDER_ANY);
        MUTATOR_HOOK(ForbidThrowCurrentWeapon, nexball_ForbidThrowing, CBC_ORDER_ANY);
        MUTATOR_HOOK(FilterItem, nexball_FilterItem, CBC_ORDER_ANY);
 
@@ -1027,10 +1023,12 @@ MUTATOR_DEFINITION(gamemode_nexball)
                radar_showennemies = autocvar_g_nexball_radar_showallplayers;
 
                InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
+               WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
        }
 
        MUTATOR_ONROLLBACK_OR_REMOVE
        {
+               WEP_NEXBALL.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
                // we actually cannot roll back nb_delayedinit here
                // BUT: we don't need to! If this gets called, adding always
                // succeeds.
diff --git a/qcsrc/server/mutators/gamemode_nexball_weapon.qc b/qcsrc/server/mutators/gamemode_nexball_weapon.qc
new file mode 100644 (file)
index 0000000..ae882bb
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef GAMEMODE_NEXBALL_WEAPON_H
+#define GAMEMODE_NEXBALL_WEAPON_H
+
+CLASS(BallStealer, PortoLaunch)
+/* flags     */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* impulse   */ ATTRIB(BallStealer, impulse, int, 0);
+/* refname   */ ATTRIB(BallStealer, netname, string, "ballstealer");
+/* wepname   */ ATTRIB(BallStealer, message, string, _("Ball Stealer"));
+ENDCLASS(BallStealer)
+REGISTER_WEAPON(NEXBALL, NEW(BallStealer));
+
+#endif
index 33bebd04ccd44821dfd8106b18e012e50384acc8..ebfc22bb5f9ceb82ebb58c297632ad867eadc7c6 100644 (file)
@@ -9,7 +9,7 @@
 // =======================
 
 bool ons_CaptureShield_Customize()
-{
+{SELFPARAM();
        entity e = WaypointSprite_getviewentity(other);
 
        if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, e.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return false; }
@@ -19,7 +19,7 @@ bool ons_CaptureShield_Customize()
 }
 
 void ons_CaptureShield_Touch()
-{
+{SELFPARAM();
        if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, other.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return; }
        if(!IS_PLAYER(other)) { return; }
        if(SAME_TEAM(other, self)) { return; }
@@ -31,7 +31,7 @@ void ons_CaptureShield_Touch()
 
        if(IS_REAL_CLIENT(other))
        {
-               play2(other, "onslaught/damageblockedbyshield.wav");
+               play2(other, SND(ONS_DAMAGEBLOCKEDBYSHIELD));
 
                if(self.enemy.classname == "onslaught_generator")
                        Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_GENERATOR_SHIELDED);
@@ -41,7 +41,7 @@ void ons_CaptureShield_Touch()
 }
 
 void ons_CaptureShield_Reset()
-{
+{SELFPARAM();
        self.colormap = self.enemy.colormap;
        self.team = self.enemy.team;
 }
@@ -66,7 +66,7 @@ void ons_CaptureShield_Spawn(entity generator, bool is_generator)
 
        precache_model(shield.model);
        setorigin(shield, generator.origin);
-       setmodel(shield, shield.model);
+       _setmodel(shield, shield.model);
        setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs);
 }
 
@@ -84,7 +84,7 @@ void ons_debug(string input)
        }
 }
 
-void setmodel_fixsize(entity e, string m)
+void setmodel_fixsize(entity e, Model m)
 {
        setmodel(e, m);
        FixSize(e);
@@ -228,7 +228,7 @@ void onslaught_updatelinks()
 // Main Link Functions
 // ===================
 
-bool ons_Link_Send(entity to, int sendflags)
+bool ons_Link_Send(entity this, entity to, int sendflags)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
        WriteByte(MSG_ENTITY, sendflags);
@@ -252,7 +252,7 @@ bool ons_Link_Send(entity to, int sendflags)
 }
 
 void ons_Link_CheckUpdate()
-{
+{SELFPARAM();
        // TODO check if the two sides have moved (currently they won't move anyway)
        float cc = 0, cc1 = 0, cc2 = 0;
 
@@ -271,7 +271,7 @@ void ons_Link_CheckUpdate()
 }
 
 void ons_DelayedLinkSetup()
-{
+{SELFPARAM();
        self.goalentity = find(world, targetname, self.target);
        self.enemy = find(world, targetname, self.target2);
        if(!self.goalentity) { objerror("can not find target\n"); }
@@ -344,9 +344,7 @@ int ons_ControlPoint_Attackable(entity cp, int teamnumber)
 }
 
 void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
-       entity oself;
-
+{SELFPARAM();
        if(damage <= 0) { return; }
 
        if (self.owner.isshielded)
@@ -355,7 +353,7 @@ void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damag
                if (time > self.pain_finished)
                        if (IS_PLAYER(attacker))
                        {
-                               play2(attacker, "onslaught/damageblockedbyshield.wav");
+                               play2(attacker, SND(ONS_DAMAGEBLOCKEDBYSHIELD));
                                self.pain_finished = time + 1;
                                attacker.typehitsound += 1; // play both sounds (shield is way too quiet)
                        }
@@ -366,7 +364,7 @@ void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damag
        if(IS_PLAYER(attacker))
        if(time - ons_notification_time[self.team] > 10)
        {
-               play2team(self.team, "onslaught/controlpoint_underattack.wav");
+               play2team(self.team, SND(ONS_CONTROLPOINT_UNDERATTACK));
                ons_notification_time[self.team] = time;
        }
 
@@ -380,13 +378,13 @@ void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damag
        pointparticles(particleeffectnum(EFFECT_SPARKS), hitloc, force*-1, 1);
        //sound on every hit
        if (random() < 0.5)
-               sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTEN_NORM);
+               sound(self, CH_TRIGGER, SND_ONS_HIT1, VOL_BASE+0.3, ATTEN_NORM);
        else
-               sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTEN_NORM);
+               sound(self, CH_TRIGGER, SND_ONS_HIT2, VOL_BASE+0.3, ATTEN_NORM);
 
        if (self.health < 0)
        {
-               sound(self, CH_TRIGGER, W_Sound("grenade_impact"), VOL_BASE, ATTEN_NORM);
+               sound(self, CH_TRIGGER, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
                pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, '0 0 0', 1);
                Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_CPDESTROYED_), self.owner.message, attacker.netname);
 
@@ -404,15 +402,14 @@ void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damag
                onslaught_updatelinks();
 
                // Use targets now (somebody make sure this is in the right place..)
-               oself = self;
-               self = self.owner;
+               setself(self.owner);
                activator = self;
                SUB_UseTargets ();
-               self = oself;
+               setself(this);
 
                self.owner.waslinked = self.owner.islinked;
                if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
-                       setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad.md3");
+                       setmodel_fixsize(self.owner, MDL_ONS_CP_PAD1);
                //setsize(self, '-32 -32 0', '32 32 8');
 
                remove(self);
@@ -422,8 +419,7 @@ void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damag
 }
 
 void ons_ControlPoint_Icon_Think()
-{
-       entity oself;
+{SELFPARAM();
        self.nextthink = time + ONS_CP_THINKRATE;
 
        if(autocvar_g_onslaught_cp_proxydecap)
@@ -478,11 +474,10 @@ void ons_ControlPoint_Icon_Think()
                if(!self.owner.islinked)
                        self.owner.team = 0;
 
-               oself = self;
-               self = self.owner;
+               setself(self.owner);
                activator = self;
                SUB_UseTargets ();
-               self = oself;
+               setself(this);
 
                self.owner.team = t;
 
@@ -495,15 +490,14 @@ void ons_ControlPoint_Icon_Think()
                Send_Effect(EFFECT_ELECTRIC_SPARKS, self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
 
                if(random() > 0.8)
-                       sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_PAIN, SND_ONS_SPARK1, VOL_BASE, ATTEN_NORM);
                else if (random() > 0.5)
-                       sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_PAIN, SND_ONS_SPARK2, VOL_BASE, ATTEN_NORM);
        }
 }
 
 void ons_ControlPoint_Icon_BuildThink()
-{
-       entity oself;
+{SELFPARAM();
        int a;
 
        self.nextthink = time + ONS_CP_THINKRATE;
@@ -522,11 +516,11 @@ void ons_ControlPoint_Icon_BuildThink()
                self.health = self.max_health;
                self.count = autocvar_g_onslaught_cp_regen * ONS_CP_THINKRATE; // slow repair rate from now on
                self.think = ons_ControlPoint_Icon_Think;
-               sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTEN_NORM);
+               sound(self, CH_TRIGGER, SND_ONS_CONTROLPOINT_BUILT, VOL_BASE, ATTEN_NORM);
                self.owner.iscaptured = true;
                self.solid = SOLID_BBOX;
 
-               Send_Effect_(sprintf("%s_cap", Static_Team_ColorName_Lower(self.owner.team)), self.owner.origin, '0 0 0', 1);
+               Send_Effect(EFFECT_CAP(self.owner.team), self.owner.origin, '0 0 0', 1);
 
                WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
                WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
@@ -545,16 +539,15 @@ void ons_ControlPoint_Icon_BuildThink()
                onslaught_updatelinks();
 
                // Use targets now (somebody make sure this is in the right place..)
-               oself = self;
-               self = self.owner;
+               setself(self.owner);
                activator = self;
                SUB_UseTargets ();
-               self = oself;
+               setself(this);
 
                self.SendFlags |= CPSF_SETUP;
        }
-       if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
-               setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad2.md3");
+       if(self.owner.model != MDL_ONS_CP_PAD2.model_str())
+               setmodel_fixsize(self.owner, MDL_ONS_CP_PAD2);
 
        if(random() < 0.9 - self.health / self.max_health)
                Send_Effect(EFFECT_RAGE, self.origin + 10 * randomvec(), '0 0 -1', 1);
@@ -579,13 +572,13 @@ void ons_ControlPoint_Icon_Spawn(entity cp, entity player)
        e.colormap = 1024 + (e.team - 1) * 17;
        e.count = (e.max_health - e.health) * ONS_CP_THINKRATE / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
 
-       sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTEN_NORM);
+       sound(e, CH_TRIGGER, SND_ONS_CONTROLPOINT_BUILD, VOL_BASE, ATTEN_NORM);
 
        cp.goalentity = e;
        cp.team = e.team;
        cp.colormap = e.colormap;
 
-       Send_Effect_(sprintf("%sflag_touch", Static_Team_ColorName_Lower(player.team)), e.origin, '0 0 0', 1);
+       Send_Effect(EFFECT_FLAG_TOUCH(player.team), e.origin, '0 0 0', 1);
 
        WaypointSprite_UpdateBuildFinished(cp.sprite, time + (e.max_health - e.health) / (e.count / ONS_CP_THINKRATE));
        WaypointSprite_UpdateRule(cp.sprite,cp.team,SPRITERULE_TEAMPLAY);
@@ -655,7 +648,7 @@ void ons_ControlPoint_UpdateSprite(entity e)
 }
 
 void ons_ControlPoint_Touch()
-{
+{SELFPARAM();
        entity toucher = other;
        int attackable;
 
@@ -692,13 +685,13 @@ void ons_ControlPoint_Touch()
 }
 
 void ons_ControlPoint_Think()
-{
+{SELFPARAM();
        self.nextthink = time + ONS_CP_THINKRATE;
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 void ons_ControlPoint_Reset()
-{
+{SELFPARAM();
        if(self.goalentity)
                remove(self.goalentity);
 
@@ -711,7 +704,7 @@ void ons_ControlPoint_Reset()
        self.think = ons_ControlPoint_Think;
        self.ons_toucher = world;
        self.nextthink = time + ONS_CP_THINKRATE;
-       setmodel_fixsize(self, "models/onslaught/controlpoint_pad.md3");
+       setmodel_fixsize(self, MDL_ONS_CP_PAD1);
 
        WaypointSprite_UpdateMaxHealth(self.sprite, 0);
        WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
@@ -721,23 +714,23 @@ void ons_ControlPoint_Reset()
        activator = self;
        SUB_UseTargets(); // to reset the structures, playerspawns etc.
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 void ons_DelayedControlPoint_Setup(void)
-{
+{SELFPARAM();
        onslaught_updatelinks();
 
        // captureshield setup
        ons_CaptureShield_Spawn(self, false);
 
-       CSQCMODEL_AUTOINIT();
+       CSQCMODEL_AUTOINIT(self);
 }
 
 void ons_ControlPoint_Setup(entity cp)
-{
+{SELFPARAM();
        // declarations
-       self = cp; // for later usage with droptofloor()
+       setself(cp); // for later usage with droptofloor()
 
        // main setup
        cp.ons_worldcpnext = ons_worldcplist; // link control point into ons_worldcplist
@@ -758,27 +751,8 @@ void ons_ControlPoint_Setup(entity cp)
 
        if(cp.message == "") { cp.message = "a"; }
 
-       // precache - TODO: clean up!
-       precache_model("models/onslaught/controlpoint_pad.md3");
-       precache_model("models/onslaught/controlpoint_pad2.md3");
-       precache_model("models/onslaught/controlpoint_shield.md3");
-       precache_model("models/onslaught/controlpoint_icon.md3");
-       precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
-       precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
-       precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
-       precache_model("models/onslaught/controlpoint_icon_gib1.md3");
-       precache_model("models/onslaught/controlpoint_icon_gib2.md3");
-       precache_model("models/onslaught/controlpoint_icon_gib4.md3");
-       precache_sound("onslaught/controlpoint_build.wav");
-       precache_sound("onslaught/controlpoint_built.wav");
-       precache_sound(W_Sound("grenade_impact"));
-       precache_sound("onslaught/damageblockedbyshield.wav");
-       precache_sound("onslaught/controlpoint_underattack.wav");
-       precache_sound("onslaught/ons_spark1.wav");
-       precache_sound("onslaught/ons_spark2.wav");
-
        // appearence
-       setmodel_fixsize(cp, "models/onslaught/controlpoint_pad.md3");
+       setmodel_fixsize(cp, MDL_ONS_CP_PAD1);
 
        // control point placement
        if((cp.spawnflags & 1) || cp.noalign) // don't drop to floor, just stay at fixed location
@@ -790,7 +764,7 @@ void ons_ControlPoint_Setup(entity cp)
        {
                setorigin(cp, cp.origin + '0 0 20');
                cp.noalign = false;
-               self = cp;
+               setself(cp);
                droptofloor();
                cp.movetype = MOVETYPE_TOSS;
        }
@@ -842,7 +816,7 @@ void ons_Generator_UpdateSprite(entity e)
 }
 
 void ons_GeneratorDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(damage <= 0) { return; }
        if(warmup_stage || gameover) { return; }
        if(!round_handler_IsRoundStarted()) { return; }
@@ -855,7 +829,7 @@ void ons_GeneratorDamage(entity inflictor, entity attacker, float damage, int de
                        if (time > self.pain_finished)
                                if (IS_PLAYER(attacker))
                                {
-                                       play2(attacker, "onslaught/damageblockedbyshield.wav");
+                                       play2(attacker, SND(ONS_DAMAGEBLOCKEDBYSHIELD));
                                        attacker.typehitsound += 1;
                                        self.pain_finished = time + 1;
                                }
@@ -866,7 +840,7 @@ void ons_GeneratorDamage(entity inflictor, entity attacker, float damage, int de
                        self.pain_finished = time + 10;
                        entity head;
                        FOR_EACH_REALPLAYER(head) if(SAME_TEAM(head, self)) { Send_Notification(NOTIF_ONE, head, MSG_CENTER, CENTER_GENERATOR_UNDERATTACK); }
-                       play2team(self.team, "onslaught/generator_underattack.wav");
+                       play2team(self.team, SND(ONS_GENERATOR_UNDERATTACK));
                }
        }
        self.health = self.health - damage;
@@ -907,7 +881,7 @@ void ons_GeneratorDamage(entity inflictor, entity attacker, float damage, int de
        // Throw some flaming gibs on damage, more damage = more chance for gib
        if(random() < damage/220)
        {
-               sound(self, CH_TRIGGER, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+               sound(self, CH_TRIGGER, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
        }
        else
        {
@@ -916,16 +890,16 @@ void ons_GeneratorDamage(entity inflictor, entity attacker, float damage, int de
 
                //sound on every hit
                if (random() < 0.5)
-                       sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_TRIGGER, SND_ONS_HIT1, VOL_BASE, ATTEN_NORM);
                else
-                       sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_TRIGGER, SND_ONS_HIT2, VOL_BASE, ATTEN_NORM);
        }
 
        self.SendFlags |= GSF_STATUS;
 }
 
 void ons_GeneratorThink()
-{
+{SELFPARAM();
        entity e;
        self.nextthink = time + GEN_THINKRATE;
        if (!gameover)
@@ -938,7 +912,7 @@ void ons_GeneratorThink()
                                if(SAME_TEAM(e, self))
                                {
                                        Send_Notification(NOTIF_ONE, e, MSG_CENTER, CENTER_ONS_NOTSHIELDED_TEAM);
-                    soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTEN_NONE);    // FIXME: unique sound?
+                    soundto(MSG_ONE, e, CHAN_AUTO, SND(KH_ALARM), VOL_BASE, ATTEN_NONE);    // FIXME: unique sound?
                 }
                                else
                                        Send_Notification(NOTIF_ONE, e, MSG_CENTER, APP_TEAM_NUM_4(self.team, CENTER_ONS_NOTSHIELDED_));
@@ -948,7 +922,7 @@ void ons_GeneratorThink()
 }
 
 void ons_GeneratorReset()
-{
+{SELFPARAM();
        self.team = self.team_saved;
        self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
        self.takedamage = DAMAGE_AIM;
@@ -973,7 +947,7 @@ void ons_GeneratorReset()
 }
 
 void ons_DelayedGeneratorSetup()
-{
+{SELFPARAM();
        // bot waypoints
        waypoint_spawnforitem_force(self, self.origin);
        self.nearestwaypointtimeout = 0; // activate waypointing again
@@ -989,7 +963,7 @@ void ons_DelayedGeneratorSetup()
 
 
 void onslaught_generator_touch()
-{
+{SELFPARAM();
        if ( IS_PLAYER(other) )
        if ( SAME_TEAM(self,other) )
        if ( self.iscaptured )
@@ -999,10 +973,10 @@ void onslaught_generator_touch()
 }
 
 void ons_GeneratorSetup(entity gen) // called when spawning a generator entity on the map as a spawnfunc
-{
+{SELFPARAM();
        // declarations
        int teamnumber = gen.team;
-       self = gen; // for later usage with droptofloor()
+       setself(gen); // for later usage with droptofloor()
 
        // main setup
        gen.ons_worldgeneratornext = ons_worldgeneratorlist; // link generator into ons_worldgeneratorlist
@@ -1025,20 +999,6 @@ void ons_GeneratorSetup(entity gen) // called when spawning a generator entity o
        gen.isshielded = true;
        gen.touch = onslaught_generator_touch;
 
-       // precache - TODO: clean up!
-       precache_model("models/onslaught/generator_shield.md3");
-       precache_model("models/onslaught/gen_gib1.md3");
-       precache_model("models/onslaught/gen_gib2.md3");
-       precache_model("models/onslaught/gen_gib3.md3");
-       precache_sound("onslaught/generator_decay.wav");
-       precache_sound(W_Sound("grenade_impact"));
-       precache_sound(W_Sound("rocket_impact"));
-       precache_sound("onslaught/generator_underattack.wav");
-       precache_sound("onslaught/shockwave.wav");
-       precache_sound("onslaught/ons_hit1.wav");
-       precache_sound("onslaught/ons_hit2.wav");
-       precache_sound("onslaught/generator_underattack.wav");
-
        // appearence
        // model handled by CSQC
        setsize(gen, GENERATOR_MIN, GENERATOR_MAX);
@@ -1046,7 +1006,7 @@ void ons_GeneratorSetup(entity gen) // called when spawning a generator entity o
        gen.colormap = 1024 + (teamnumber - 1) * 17;
 
        // generator placement
-       self = gen;
+       setself(gen);
        droptofloor();
 
        // waypointsprites
@@ -1116,7 +1076,7 @@ bool Onslaught_CheckWinner()
                if (!wpforenemy_announced)
                {
                        Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT);
-                       sound(world, CH_INFO, "onslaught/generator_decay.wav", VOL_BASE, ATTEN_NONE);
+                       sound(world, CH_INFO, SND_ONS_GENERATOR_DECAY, VOL_BASE, ATTEN_NONE);
 
                        wpforenemy_announced = true;
                }
@@ -1170,7 +1130,7 @@ bool Onslaught_CheckWinner()
 
        ons_stalemate = false;
 
-       play2all(sprintf("ctf/%s_capture.wav", Static_Team_ColorName_Lower(winner_team)));
+       play2all(SND(CTF_CAPTURE(winner_team)));
 
        round_handler_Init(7, autocvar_g_onslaught_warmup, autocvar_g_onslaught_round_timelimit);
 
@@ -1210,7 +1170,7 @@ void Onslaught_RoundStart()
 // NOTE: LEGACY CODE, needs to be re-written!
 
 void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
-{
+{SELFPARAM();
        entity head;
        float t, c;
        int i;
@@ -1284,7 +1244,7 @@ void havocbot_role_ons_setrole(entity bot, int role)
 }
 
 int havocbot_ons_teamcount(entity bot, int role)
-{
+{SELFPARAM();
        int c = 0;
        entity head;
 
@@ -1297,7 +1257,7 @@ int havocbot_ons_teamcount(entity bot, int role)
 }
 
 void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
-{
+{SELFPARAM();
        entity cp, cp1, cp2, best, pl, wp;
        float radius, bestvalue;
        int c;
@@ -1415,7 +1375,7 @@ void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
 }
 
 bool havocbot_goalrating_ons_generator_attack(float ratingscale)
-{
+{SELFPARAM();
        entity g, wp, bestwp;
        bool found;
        int best;
@@ -1471,7 +1431,7 @@ bool havocbot_goalrating_ons_generator_attack(float ratingscale)
 }
 
 void havocbot_role_ons_offense()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
        {
                self.havocbot_attack_time = 0;
@@ -1506,17 +1466,17 @@ void havocbot_role_ons_offense()
 }
 
 void havocbot_role_ons_assistant()
-{
+{SELFPARAM();
        havocbot_ons_reset_role(self);
 }
 
 void havocbot_role_ons_defense()
-{
+{SELFPARAM();
        havocbot_ons_reset_role(self);
 }
 
 void havocbot_ons_reset_role(entity bot)
-{
+{SELFPARAM();
        entity head;
        int c = 0;
 
@@ -1548,7 +1508,7 @@ void havocbot_ons_reset_role(entity bot)
  * if max_dist is positive, only control points within this range will be considered
  */
 entity ons_Nearest_ControlPoint(vector pos, float max_dist)
-{
+{SELFPARAM();
        entity tmp_entity, closest_target = world;
        tmp_entity = findchain(classname, "onslaught_controlpoint");
        while(tmp_entity)
@@ -1579,7 +1539,7 @@ entity ons_Nearest_ControlPoint(vector pos, float max_dist)
  * This function only check distances on the XY plane, disregarding Z
  */
 entity ons_Nearest_ControlPoint_2D(vector pos, float max_dist)
-{
+{SELFPARAM();
        entity tmp_entity, closest_target = world;
        vector delta;
        float smallest_distance = 0, distance;
@@ -1626,7 +1586,7 @@ entity ons_Nearest_ControlPoint_2D(vector pos, float max_dist)
  * find the number of control points and generators in the same team as self
  */
 int ons_Count_SelfControlPoints()
-{
+{SELFPARAM();
        entity tmp_entity;
        tmp_entity = findchain(classname, "onslaught_controlpoint");
        int n = 0;
@@ -1679,7 +1639,7 @@ bool ons_Teleport(entity player, entity tele_target, float range, bool tele_effe
                                if ( tele_effects )
                                {
                                        Send_Effect(EFFECT_TELEPORT, player.origin, '0 0 0', 1);
-                                       sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
+                                       sound (player, CH_TRIGGER, SND_TELEPORT, VOL_BASE, ATTEN_NORM);
                                }
                                setorigin(player, loc);
                                player.angles = '0 1 0' * ( theta * RAD2DEG + 180 );
@@ -1702,24 +1662,25 @@ bool ons_Teleport(entity player, entity tele_target, float range, bool tele_effe
 // ==============
 
 MUTATOR_HOOKFUNCTION(ons_ResetMap)
-{
-       FOR_EACH_PLAYER(self)
+{SELFPARAM();
+       entity e;
+       FOR_EACH_PLAYER(e)
        {
-               self.ons_roundlost = false;
-               self.ons_deathloc = '0 0 0';
-               PutClientInServer();
+               e.ons_roundlost = false;
+               e.ons_deathloc = '0 0 0';
+               WITH(entity, self, e, PutClientInServer());
        }
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(ons_RemovePlayer)
-{
+{SELFPARAM();
        self.ons_deathloc = '0 0 0';
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
-{
+{SELFPARAM();
        if(!round_handler_IsRoundStarted())
        {
                self.player_blocked = true;
@@ -1845,7 +1806,7 @@ MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(ons_PlayerDies)
-{
+{SELFPARAM();
        frag_target.ons_deathloc = frag_target.origin;
        entity l;
        for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
@@ -1865,7 +1826,7 @@ MUTATOR_HOOKFUNCTION(ons_PlayerDies)
 }
 
 MUTATOR_HOOKFUNCTION(ons_MonsterThink)
-{
+{SELFPARAM();
        entity e = find(world, targetname, self.target);
        if (e != world)
                self.team = e.team;
@@ -1874,7 +1835,7 @@ MUTATOR_HOOKFUNCTION(ons_MonsterThink)
 }
 
 void ons_MonsterSpawn_Delayed()
-{
+{SELFPARAM();
        entity e, own = self.owner;
 
        if(!own) { remove(self); return; }
@@ -1895,7 +1856,7 @@ void ons_MonsterSpawn_Delayed()
 }
 
 MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
-{
+{SELFPARAM();
        entity e = spawn();
        e.owner = self;
        InitializeEntity(e, ons_MonsterSpawn_Delayed, INITPRIO_FINDTARGET);
@@ -1904,7 +1865,7 @@ MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
 }
 
 void ons_TurretSpawn_Delayed()
-{
+{SELFPARAM();
        entity e, own = self.owner;
 
        if(!own) { remove(self); return; }
@@ -1926,7 +1887,7 @@ void ons_TurretSpawn_Delayed()
 }
 
 MUTATOR_HOOKFUNCTION(ons_TurretSpawn)
-{
+{SELFPARAM();
        entity e = spawn();
        e.owner = self;
        InitializeEntity(e, ons_TurretSpawn_Delayed, INITPRIO_FINDTARGET);
@@ -1935,7 +1896,7 @@ MUTATOR_HOOKFUNCTION(ons_TurretSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(ons_BotRoles)
-{
+{SELFPARAM();
        havocbot_ons_reset_role(self);
        return true;
 }
@@ -1959,13 +1920,13 @@ MUTATOR_HOOKFUNCTION(ons_GetTeamCount)
 }
 
 MUTATOR_HOOKFUNCTION(ons_SpectateCopy)
-{
+{SELFPARAM();
        self.ons_roundlost = other.ons_roundlost; // make spectators see it too
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(ons_SV_ParseClientCommand)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE) // command was already handled?
                return false;
 
@@ -2029,7 +1990,7 @@ MUTATOR_HOOKFUNCTION(ons_SV_ParseClientCommand)
 }
 
 MUTATOR_HOOKFUNCTION(ons_PlayerUseKey)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE || gameover) { return false; }
 
        if((time > self.teleport_antispam) && (self.deadflag == DEAD_NO) && !self.vehicle)
@@ -2064,7 +2025,7 @@ keys:
 "target" - first control point.
 "target2" - second control point.
  */
-void spawnfunc_onslaught_link()
+spawnfunc(onslaught_link)
 {
        if(!g_onslaught) { remove(self); return; }
 
@@ -2089,7 +2050,7 @@ keys:
 "message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
  */
 
-void spawnfunc_onslaught_controlpoint()
+spawnfunc(onslaught_controlpoint)
 {
        if(!g_onslaught) { remove(self); return; }
 
@@ -2105,7 +2066,7 @@ keys:
 "team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
 "targetname" - name that spawnfunc_onslaught_link entities will use to target this.
  */
-void spawnfunc_onslaught_generator()
+spawnfunc(onslaught_generator)
 {
        if(!g_onslaught) { remove(self); return; }
        if(!self.team) { objerror("team must be set"); }
@@ -2134,11 +2095,6 @@ void ons_DelayedInit() // Do this check with a delay so we can wait for teams to
 
 void ons_Initialize()
 {
-       precache_sound("ctf/red_capture.wav");
-       precache_sound("ctf/blue_capture.wav");
-       precache_sound("ctf/yellow_capture.wav");
-       precache_sound("ctf/pink_capture.wav");
-
        ons_captureshield_force = autocvar_g_onslaught_shield_force;
 
        addstat(STAT_ROUNDLOST, AS_INT, ons_roundlost);
index a7a832281a870ec8d3a32fb56e51f0f1c218181c..d51b33ec2f3eb048de0bafd1a809398e664d26e0 100644 (file)
@@ -8,7 +8,7 @@
 // legacy bot roles
 .float race_checkpoint;
 void havocbot_role_race()
-{
+{SELFPARAM();
        if(self.deadflag != DEAD_NO)
                return;
 
@@ -64,7 +64,7 @@ void race_EventLog(string mode, entity actor) // use an alias for easy changing
 }
 
 MUTATOR_HOOKFUNCTION(race_PlayerPhysics)
-{
+{SELFPARAM();
        // force kbd movement for fairness
        float wishspeed;
        vector wishvel;
@@ -149,7 +149,7 @@ MUTATOR_HOOKFUNCTION(race_ResetMap)
 }
 
 MUTATOR_HOOKFUNCTION(race_PlayerPreThink)
-{
+{SELFPARAM();
        if(IS_SPEC(self) || IS_OBSERVER(self))
        if(g_race_qualifying)
        if(msg_entity.enemy.race_laptime)
@@ -159,7 +159,7 @@ MUTATOR_HOOKFUNCTION(race_PlayerPreThink)
 }
 
 MUTATOR_HOOKFUNCTION(race_ClientConnect)
-{
+{SELFPARAM();
        race_PreparePlayer();
        self.race_checkpoint = -1;
 
@@ -186,7 +186,7 @@ MUTATOR_HOOKFUNCTION(race_ClientConnect)
 }
 
 MUTATOR_HOOKFUNCTION(race_MakePlayerObserver)
-{
+{SELFPARAM();
        if(g_race_qualifying)
        if(PlayerScore_Add(self, SP_RACE_FASTEST, 0))
                self.frags = FRAGS_LMS_LOSER;
@@ -200,7 +200,7 @@ MUTATOR_HOOKFUNCTION(race_MakePlayerObserver)
 }
 
 MUTATOR_HOOKFUNCTION(race_PlayerSpawn)
-{
+{SELFPARAM();
        if(spawn_spot.target == "")
                // Emergency: this wasn't a real spawnpoint. Can this ever happen?
                race_PreparePlayer();
@@ -215,7 +215,7 @@ MUTATOR_HOOKFUNCTION(race_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(race_PutClientInServer)
-{
+{SELFPARAM();
        if(IS_PLAYER(self))
        if(!gameover)
        {
@@ -230,20 +230,20 @@ MUTATOR_HOOKFUNCTION(race_PutClientInServer)
 }
 
 MUTATOR_HOOKFUNCTION(race_PlayerDies)
-{
+{SELFPARAM();
        self.respawn_flags |= RESPAWN_FORCE;
        race_AbandonRaceCheck(self);
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(race_BotRoles)
-{
+{SELFPARAM();
        self.havocbot_role = havocbot_role_race;
        return true;
 }
 
 MUTATOR_HOOKFUNCTION(race_PlayerPostThink)
-{
+{SELFPARAM();
        if(self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1)
        {
                if (!self.stored_netname)
index fda2161a6b99f48cefaf9e5d6de25af927a6ecdd..451e4a55c32536d35ac84ec33b1b0add8dde0bec 100644 (file)
@@ -8,7 +8,7 @@ Note: If you use spawnfunc_tdm_team entities you must define at least 2!  Howeve
 Keys:
 "netname" Name of the team (for example Red, Blue, Green, Yellow, Life, Death, Offense, Defense, etc)...
 "cnt" Scoreboard color of the team (for example 4 is red and 13 is blue)... */
-void spawnfunc_tdm_team()
+spawnfunc(tdm_team)
 {
        if(!g_tdm || !self.cnt) { remove(self); return; }
 
@@ -19,16 +19,11 @@ void spawnfunc_tdm_team()
 // code from here on is just to support maps that don't have team entities
 void tdm_SpawnTeam (string teamname, float teamcolor)
 {
-       entity oldself;
-       oldself = self;
-       self = spawn();
-       self.classname = "tdm_team";
-       self.netname = teamname;
-       self.cnt = teamcolor;
-
-       spawnfunc_tdm_team();
-
-       self = oldself;
+       entity this = new(tdm_team);
+       this.netname = teamname;
+       this.cnt = teamcolor;
+       this.spawnfunc_checked = true;
+       WITH(entity, self, this, spawnfunc_tdm_team(this));
 }
 
 void tdm_DelayedInit()
index d68ff388f8583ae472366f513232a097e4bbb37e..da9a608f0156a6bc047aebf8bf98886921673830 100644 (file)
@@ -5,7 +5,7 @@
 .float bloodloss_timer;
 
 MUTATOR_HOOKFUNCTION(bloodloss_PlayerThink)
-{
+{SELFPARAM();
        if(IS_PLAYER(self))
        if(self.health <= autocvar_g_bloodloss && self.deadflag == DEAD_NO)
        {
@@ -25,7 +25,7 @@ MUTATOR_HOOKFUNCTION(bloodloss_PlayerThink)
 }
 
 MUTATOR_HOOKFUNCTION(bloodloss_PlayerJump)
-{
+{SELFPARAM();
        if(self.health <= autocvar_g_bloodloss)
                return true;
 
index 4433055b61b27f570298759fdff64f1fd78f251a..7aeadce75efde15406d80af051ecdfb9c4ec3e78 100644 (file)
@@ -4,19 +4,19 @@
 
 #include "mutator.qh"
 
-#include "../../common/buffs.qh"
+#include "../../common/buffs/all.qh"
 
 entity buff_FirstFromFlags(int _buffs)
 {
        if (flags)
        {
-               FOREACH(BUFFS, it.m_itemid & _buffs, LAMBDA(return it));
+               FOREACH(Buffs, it.m_itemid & _buffs, LAMBDA(return it));
        }
-       return BUFF_NULL;
+       return BUFF_Null;
 }
 
 bool buffs_BuffModel_Customize()
-{
+{SELFPARAM();
        entity player, myowner;
        bool same_team;
 
@@ -47,7 +47,7 @@ bool buffs_BuffModel_Customize()
 void buffs_BuffModel_Spawn(entity player)
 {
        player.buff_model = spawn();
-       setmodel(player.buff_model, BUFF_MODEL);
+       setmodel(player.buff_model, MDL_BUFF);
        setsize(player.buff_model, '0 0 -40', '0 0 40');
        setattachment(player.buff_model, player, "");
        setorigin(player.buff_model, '0 0 1' * (player.buff_model.maxs.z * 1));
@@ -65,7 +65,7 @@ vector buff_GlowColor(entity buff)
 }
 
 void buff_Effect(entity player, string eff)
-{
+{SELFPARAM();
        if(!autocvar_g_buffs_effects) { return; }
 
        if(time >= self.buff_effect_delay)
@@ -77,7 +77,7 @@ void buff_Effect(entity player, string eff)
 
 // buff item
 float buff_Waypoint_visible_for_player(entity plr)
-{
+{SELFPARAM();
        if(!self.owner.buff_active && !self.owner.buff_activetime)
                return false;
 
@@ -92,14 +92,14 @@ float buff_Waypoint_visible_for_player(entity plr)
 void buff_Waypoint_Spawn(entity e)
 {
        entity buff = buff_FirstFromFlags(e.buffs);
-       entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_POWERUP);
+       entity wp = WaypointSprite_Spawn(WP_Buff, 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs.z, world, e.team, e, buff_waypoint, true, RADARICON_Buff);
        wp.wp_extra = buff.m_id;
-       WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_POWERUP, e.glowmod);
+       WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_Buff, e.glowmod);
        e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player;
 }
 
 void buff_SetCooldown(float cd)
-{
+{SELFPARAM();
        cd = max(0, cd);
 
        if(!self.buff_waypoint)
@@ -111,7 +111,7 @@ void buff_SetCooldown(float cd)
 }
 
 void buff_Respawn(entity ent)
-{
+{SELFPARAM();
        if(gameover) { return; }
 
        vector oldbufforigin = ent.origin;
@@ -140,11 +140,11 @@ void buff_Respawn(entity ent)
 
        WaypointSprite_Ping(ent.buff_waypoint);
 
-       sound(ent, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
+       sound(ent, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
 }
 
 void buff_Touch()
-{
+{SELFPARAM();
        if(gameover) { return; }
 
        if(ITEM_TOUCH_NEEDKILL())
@@ -178,7 +178,7 @@ void buff_Touch()
                        Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ITEM_BUFF_LOST, other.netname, buffid);
 
                        other.buffs = 0;
-                       //sound(other, CH_TRIGGER, "relics/relic_effect.wav", VOL_BASE, ATTN_NORM);
+                       //sound(other, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
                }
                else { return; } // do nothing
        }
@@ -191,13 +191,13 @@ void buff_Touch()
        Send_Notification(NOTIF_ALL_EXCEPT, other, MSG_INFO, INFO_ITEM_BUFF, other.netname, buffid);
 
        Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(self), '0 0 0', 1);
-       sound(other, CH_TRIGGER, "misc/shield_respawn.wav", VOL_BASE, ATTN_NORM);
+       sound(other, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTN_NORM);
        other.buffs |= (self.buffs);
 }
 
 float buff_Available(entity buff)
 {
-       if (buff == BUFF_NULL)
+       if (buff == BUFF_Null)
                return false;
        if (buff == BUFF_AMMO && ((start_items & IT_UNLIMITED_WEAPON_AMMO) || (start_items & IT_UNLIMITED_AMMO) || (cvar("g_melee_only"))))
                return false;
@@ -211,7 +211,7 @@ float buff_Available(entity buff)
 void buff_NewType(entity ent, float cb)
 {
        RandomSelection_Init();
-       FOREACH(BUFFS, buff_Available(it), LAMBDA(
+       FOREACH(Buffs, buff_Available(it), LAMBDA(
                it.buff_seencount += 1;
                // if it's already been chosen, give it a lower priority
                RandomSelection_Add(world, it.m_itemid, string_null, 1, max(0.2, 1 / it.buff_seencount));
@@ -220,7 +220,7 @@ void buff_NewType(entity ent, float cb)
 }
 
 void buff_Think()
-{
+{SELFPARAM();
        if(self.buffs != self.oldbuffs)
        {
                entity buff = buff_FirstFromFlags(self.buffs);
@@ -228,7 +228,7 @@ void buff_Think()
                self.glowmod = buff_GlowColor(buff);
                self.skin = buff.m_skin;
 
-               setmodel(self, BUFF_MODEL);
+               setmodel(self, MDL_BUFF);
 
                if(self.buff_waypoint)
                {
@@ -271,7 +271,7 @@ void buff_Think()
                if(!self.buff_activetime)
                {
                        self.buff_active = true;
-                       sound(self, CH_TRIGGER, "misc/strength_respawn.wav", VOL_BASE, ATTN_NORM);
+                       sound(self, CH_TRIGGER, SND_STRENGTH_RESPAWN, VOL_BASE, ATTN_NORM);
                        Send_Effect(EFFECT_ITEM_RESPAWN, CENTER_OR_VIEWOFS(self), '0 0 0', 1);
                }
        }
@@ -291,14 +291,14 @@ void buff_Think()
 }
 
 void buff_Waypoint_Reset()
-{
+{SELFPARAM();
        WaypointSprite_Kill(self.buff_waypoint);
 
        if(self.buff_activetime) { buff_Waypoint_Spawn(self); }
 }
 
 void buff_Reset()
-{
+{SELFPARAM();
        if(autocvar_g_buffs_randomize)
                buff_NewType(self, self.buffs);
        self.owner = world;
@@ -311,7 +311,7 @@ void buff_Reset()
 }
 
 float buff_Customize()
-{
+{SELFPARAM();
        entity player = WaypointSprite_getviewentity(other);
        if(!self.buff_active || (self.team && DIFF_TEAM(player, self)))
        {
@@ -330,15 +330,14 @@ float buff_Customize()
 }
 
 void buff_Init(entity ent)
-{
+{SELFPARAM();
        if(!cvar("g_buffs")) { remove(ent); return; }
 
        if(!teamplay && ent.team) { ent.team = 0; }
 
        entity buff = buff_FirstFromFlags(self.buffs);
 
-       entity oldself = self;
-       self = ent;
+       setself(ent);
        if(!self.buffs || buff_Available(buff))
                buff_NewType(self, 0);
 
@@ -369,13 +368,13 @@ void buff_Init(entity ent)
        if(self.noalign)
                self.movetype = MOVETYPE_NONE; // reset by random location
 
-       setmodel(self, BUFF_MODEL);
+       setmodel(self, MDL_BUFF);
        setsize(self, BUFF_MIN, BUFF_MAX);
 
        if(cvar("g_buffs_random_location") || (self.spawnflags & 64))
                buff_Respawn(self);
 
-       self = oldself;
+       setself(this);
 }
 
 void buff_Init_Compat(entity ent, entity replacement)
@@ -400,7 +399,7 @@ void buff_SpawnReplacement(entity ent, entity old)
 }
 
 void buff_Vengeance_DelayedDamage()
-{
+{SELFPARAM();
        if(self.enemy)
                Damage(self.enemy, self.owner, self.owner, self.dmg, DEATH_BUFF, self.enemy.origin, '0 0 0');
 
@@ -520,7 +519,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerDamage_Calculate)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_PlayerSpawn)
-{
+{SELFPARAM();
        self.buffs = 0;
        // reset timers here to prevent them continuing after re-spawn
        self.buff_disability_time = 0;
@@ -529,7 +528,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_PlayerPhysics)
-{
+{SELFPARAM();
        if(self.buffs & BUFF_SPEED.m_itemid)
        {
                self.stat_sv_maxspeed *= autocvar_g_buffs_speed_speed;
@@ -552,7 +551,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerPhysics)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_PlayerJump)
-{
+{SELFPARAM();
        if(self.buffs & BUFF_JUMP.m_itemid)
                player_jumpheight = autocvar_g_buffs_jump_height;
 
@@ -560,7 +559,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerJump)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_MonsterMove)
-{
+{SELFPARAM();
        if(time < self.buff_disability_time)
        {
                monster_speed_walk *= autocvar_g_buffs_disability_speed;
@@ -571,7 +570,7 @@ MUTATOR_HOOKFUNCTION(buffs_MonsterMove)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_PlayerDies)
-{
+{SELFPARAM();
        if(self.buffs)
        {
                int buffid = buff_FirstFromFlags(self.buffs).m_id;
@@ -588,7 +587,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerDies)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_PlayerUseKey)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE || gameover) { return false; }
        if(self.buffs)
        {
@@ -597,14 +596,14 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerUseKey)
                Send_Notification(NOTIF_ALL_EXCEPT, self, MSG_INFO, INFO_ITEM_BUFF_LOST, self.netname, buffid);
 
                self.buffs = 0;
-               sound(self, CH_TRIGGER, "relics/relic_effect.wav", VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
                return true;
        }
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(buffs_PlayerThrowKey)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE || gameover) { return false; }
 
        if(self.buffs & BUFF_SWAPPER.m_itemid)
@@ -662,8 +661,8 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerThrowKey)
                        Send_Effect(EFFECT_ELECTRO_COMBO, their_org, '0 0 0', 1);
                        Send_Effect(EFFECT_ELECTRO_COMBO, my_org, '0 0 0', 1);
 
-                       sound(self, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NORM);
-                       sound(closest, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NORM);
+                       sound(closest, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NORM);
 
                        // TODO: add a counter to handle how many times one can teleport, and a delay to prevent spam
                        self.buffs = 0;
@@ -674,7 +673,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerThrowKey)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_RemovePlayer)
-{
+{SELFPARAM();
        if(self.buff_model)
        {
                remove(self.buff_model);
@@ -689,7 +688,7 @@ MUTATOR_HOOKFUNCTION(buffs_RemovePlayer)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_CustomizeWaypoint)
-{
+{SELFPARAM();
        entity e = WaypointSprite_getviewentity(other);
 
        // if you have the invisibility powerup, sprites ALWAYS are restricted to your team
@@ -702,7 +701,7 @@ MUTATOR_HOOKFUNCTION(buffs_CustomizeWaypoint)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_OnEntityPreSpawn)
-{
+{SELFPARAM();
        if(autocvar_g_buffs_replace_powerups)
        switch(self.classname)
        {
@@ -718,7 +717,7 @@ MUTATOR_HOOKFUNCTION(buffs_OnEntityPreSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_WeaponRate)
-{
+{SELFPARAM();
        if(self.buffs & BUFF_SPEED.m_itemid)
                weapon_rate *= autocvar_g_buffs_speed_rate;
 
@@ -729,7 +728,7 @@ MUTATOR_HOOKFUNCTION(buffs_WeaponRate)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_WeaponSpeed)
-{
+{SELFPARAM();
        if(self.buffs & BUFF_SPEED.m_itemid)
                ret_float *= autocvar_g_buffs_speed_weaponspeed;
 
@@ -742,7 +741,7 @@ MUTATOR_HOOKFUNCTION(buffs_WeaponSpeed)
 .float buff_time;
 
 MUTATOR_HOOKFUNCTION(buffs_PlayerThink)
-{
+{SELFPARAM();
        if(gameover || self.deadflag != DEAD_NO) { return false; }
 
        if(time < self.buff_disability_time)
@@ -772,7 +771,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerThink)
                        if(buff_lost >= 2)
                        {
                                Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_BUFF_DROP, buffid); // TODO: special timeout message?
-                               sound(self, CH_TRIGGER, "relics/relic_effect.wav", VOL_BASE, ATTN_NORM);
+                               sound(self, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
                        }
                        self.buffs = 0;
                }
@@ -784,13 +783,12 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerThink)
                for(other = world; (other = findflags(other, flags, FL_ITEM)); )
                if(boxesoverlap(self.absmin - pickup_size, self.absmax + pickup_size, other.absmin, other.absmax))
                {
-                       entity oldself = self;
-                       self = other;
-                       other = oldself;
+                       setself(other);
+                       other = this;
                        if(self.touch)
                                self.touch();
                        other = self;
-                       self = oldself;
+                       setself(this);
                }
        }
 
@@ -808,7 +806,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerThink)
        if(self.buffs != self.oldbuffs)
        {
                entity buff = buff_FirstFromFlags(self.buffs);
-               float bufftime = buff != BUFF_NULL ? buff.m_time(buff) : 0;
+               float bufftime = buff != BUFF_Null ? buff.m_time(buff) : 0;
                self.buff_time = (bufftime) ? time + bufftime : 0;
 
                BUFF_ONADD(BUFF_AMMO)
@@ -889,7 +887,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerThink)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_SpectateCopy)
-{
+{SELFPARAM();
        self.buffs = other.buffs;
        return false;
 }
@@ -909,7 +907,7 @@ MUTATOR_HOOKFUNCTION(buffs_VehicleExit)
 }
 
 MUTATOR_HOOKFUNCTION(buffs_PlayerRegen)
-{
+{SELFPARAM();
        if(self.buffs & BUFF_MEDIC.m_itemid)
        {
                regen_mod_rot = autocvar_g_buffs_medic_rot;
@@ -959,13 +957,6 @@ void buffs_DelayedInit()
 
 void buffs_Initialize()
 {
-       precache_model(BUFF_MODEL);
-       precache_sound("misc/strength_respawn.wav");
-       precache_sound("misc/shield_respawn.wav");
-       precache_sound("relics/relic_effect.wav");
-       precache_sound(W_Sound("rocket_impact"));
-       precache_sound("keepaway/respawn.wav");
-
        addstat(STAT_BUFFS, AS_INT, buffs);
        addstat(STAT_BUFF_TIME, AS_FLOAT, buff_time);
 
index 29e59316f216cd729f0fb012e29e1504cbf2e64b..10d84ef4e55301dc161b623f17563d6401c99a11 100644 (file)
@@ -24,8 +24,6 @@
 .int oldbuffs; // for updating effects
 .entity buff_model; // controls effects (TODO: make csqc)
 
-const string BUFF_MODEL = "models/relics/relic.md3";
-
 const vector BUFF_MIN = ('-16 -16 -20');
 const vector BUFF_MAX = ('16 16 20');
 
index 2839ae09b6e546ee01faa1adf04be0ed0fc39e90..e4ad5ba19854f13851fb987bca87c111f189e1cf 100644 (file)
@@ -8,7 +8,7 @@
 .float campcheck_traveled_distance;
 
 MUTATOR_HOOKFUNCTION(campcheck_PlayerDies)
-{
+{SELFPARAM();
        Kill_Notification(NOTIF_ONE, self, MSG_CENTER_CPID, CPID_CAMPCHECK);
 
        return false;
@@ -28,7 +28,7 @@ MUTATOR_HOOKFUNCTION(campcheck_PlayerDamage)
 }
 
 MUTATOR_HOOKFUNCTION(campcheck_PlayerThink)
-{
+{SELFPARAM();
        if(!gameover)
        if(!warmup_stage) // don't consider it camping during warmup?
        if(time >= game_starttime)
@@ -74,7 +74,7 @@ MUTATOR_HOOKFUNCTION(campcheck_PlayerThink)
 }
 
 MUTATOR_HOOKFUNCTION(campcheck_PlayerSpawn)
-{
+{SELFPARAM();
        self.campcheck_nextcheck = time + autocvar_g_campcheck_interval * 2;
        self.campcheck_traveled_distance = 0;
 
index ab70fb217da5829ae99d1df98c8dd7c9e5dfb007..b5dc32fdfe0d924a233b099ab47f802eaceba6e3 100644 (file)
@@ -83,7 +83,7 @@
 #elif defined(SVQC)
 
 void dodging_UpdateStats()
-{
+{SELFPARAM();
        self.stat_dodging = PHYS_DODGING;
        self.stat_dodging_delay = PHYS_DODGING_DELAY;
        self.stat_dodging_horiz_speed_frozen = PHYS_DODGING_HORIZ_SPEED_FROZEN;
@@ -116,7 +116,7 @@ void dodging_Initialize()
 
 // returns 1 if the player is close to a wall
 bool check_close_to_wall(float threshold)
-{
+{SELFPARAM();
        if (PHYS_DODGING_WALL == 0) { return false; }
 
        #define X(OFFSET)                                                                                                                               \
@@ -133,12 +133,12 @@ bool check_close_to_wall(float threshold)
 }
 
 bool check_close_to_ground(float threshold)
-{
+{SELFPARAM();
        return IS_ONGROUND(self) ? true : false;
 }
 
 float PM_dodging_checkpressedkeys()
-{
+{SELFPARAM();
        if(!PHYS_DODGING)
                return false;
 
@@ -199,7 +199,7 @@ float PM_dodging_checkpressedkeys()
 }
 
 void PM_dodging()
-{
+{SELFPARAM();
        if (!PHYS_DODGING)
                return;
 
diff --git a/qcsrc/server/mutators/mutator_hook.qc b/qcsrc/server/mutators/mutator_hook.qc
new file mode 100644 (file)
index 0000000..e43848b
--- /dev/null
@@ -0,0 +1,40 @@
+AUTOCVAR(g_grappling_hook, bool, false, _("let players spawn with the grappling hook which allows them to pull themselves up"));
+#ifdef SVQC
+REGISTER_MUTATOR(hook, autocvar_g_grappling_hook) {
+    MUTATOR_ONADD {
+        g_grappling_hook = true;
+        WEP_HOOK.ammo_factor = 0;
+    }
+    MUTATOR_ONROLLBACK_OR_REMOVE {
+        g_grappling_hook = false;
+        WEP_HOOK.ammo_factor = 1;
+    }
+}
+
+MUTATOR_HOOKFUNCTION(hook, BuildMutatorsString)
+{
+    ret_string = strcat(ret_string, ":grappling_hook");
+}
+
+MUTATOR_HOOKFUNCTION(hook, BuildMutatorsPrettyString)
+{
+    ret_string = strcat(ret_string, ", Hook");
+}
+
+MUTATOR_HOOKFUNCTION(hook, BuildGameplayTipsString)
+{
+    ret_string = strcat(ret_string, "\n\n^3grappling hook^8 is enabled, press 'e' to use it\n");
+}
+
+MUTATOR_HOOKFUNCTION(hook, PlayerSpawn)
+{
+    SELFPARAM();
+    self.offhand = OFFHAND_HOOK;
+}
+
+MUTATOR_HOOKFUNCTION(hook, FilterItem)
+{
+    return self.weapon == WEP_HOOK.m_id;
+}
+
+#endif
index 2b69551e7152c98fc85921b16b99c405d6ed22bb..9f88b2b6e8d40638bf96346da31f399929dd94e6 100644 (file)
@@ -3,23 +3,33 @@
 #include "mutator.qh"
 
 #include "../cl_client.qh"
-#include "../../common/buffs.qh"
+#include "../../common/buffs/all.qh"
 
 #include "../../common/items/all.qc"
 
-void spawnfunc_item_minst_cells (void)
+spawnfunc(item_minst_cells)
 {
        if (!g_instagib) { remove(self); return; }
-       if (!self.ammo_cells)
-               self.ammo_cells = autocvar_g_instagib_ammo_drop;
+       if (!self.ammo_cells) self.ammo_cells = autocvar_g_instagib_ammo_drop;
+       StartItemA(ITEM_VaporizerCells);
+}
 
-       StartItemA (ITEM_VaporizerCells);
+void instagib_invisibility()
+{SELFPARAM();
+       self.strength_finished = autocvar_g_balance_powerup_strength_time;
+       StartItemA(ITEM_Invisibility);
 }
 
-void instagib_health_mega()
-{
+void instagib_extralife()
+{SELFPARAM();
        self.max_health = 1;
-       StartItemA (ITEM_ExtraLife);
+       StartItemA(ITEM_ExtraLife);
+}
+
+void instagib_speed()
+{SELFPARAM();
+       self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
+       StartItemA(ITEM_Speed);
 }
 
 .float instagib_nextthink;
@@ -32,7 +42,7 @@ void instagib_stop_countdown(entity e)
        e.instagib_needammo = false;
 }
 void instagib_ammocheck()
-{
+{SELFPARAM();
        if(time < self.instagib_nextthink)
                return;
        if(!IS_PLAYER(self))
@@ -130,7 +140,7 @@ MUTATOR_HOOKFUNCTION(instagib_MonsterLoot)
 }
 
 MUTATOR_HOOKFUNCTION(instagib_MonsterSpawn)
-{
+{SELFPARAM();
        // always refill ammo
        if(self.monsterid == MON_MAGE.monsterid)
                self.skin = 1;
@@ -140,20 +150,20 @@ MUTATOR_HOOKFUNCTION(instagib_MonsterSpawn)
 
 MUTATOR_HOOKFUNCTION(instagib_BotShouldAttack)
 {
-       if(checkentity.items & ITEM_Strength.m_itemid)
+       if (checkentity.items & ITEM_Invisibility.m_itemid)
                return true;
 
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(instagib_MakePlayerObserver)
-{
+{SELFPARAM();
        instagib_stop_countdown(self);
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(instagib_PlayerSpawn)
-{
+{SELFPARAM();
        self.effects |= EF_FULLBRIGHT;
        return false;
 }
@@ -171,18 +181,18 @@ MUTATOR_HOOKFUNCTION(instagib_PlayerRegen)
 }
 
 MUTATOR_HOOKFUNCTION(instagib_PlayerPowerups)
-{
+{SELFPARAM();
        if (!(self.effects & EF_FULLBRIGHT))
                self.effects |= EF_FULLBRIGHT;
 
-       if (self.items & ITEM_Strength.m_itemid)
+       if (self.items & ITEM_Invisibility.m_itemid)
        {
-               play_countdown(self.strength_finished, "misc/poweroff.wav");
+               play_countdown(self.strength_finished, SND(POWEROFF));
                if (time > self.strength_finished)
                {
                        self.alpha = default_player_alpha;
                        self.exteriorweaponentity.alpha = default_weapon_alpha;
-                       self.items &= ~ITEM_Strength.m_itemid;
+                       self.items &= ~ITEM_Invisibility.m_itemid;
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
                }
        }
@@ -192,18 +202,18 @@ MUTATOR_HOOKFUNCTION(instagib_PlayerPowerups)
                {
                        self.alpha = autocvar_g_instagib_invis_alpha;
                        self.exteriorweaponentity.alpha = autocvar_g_instagib_invis_alpha;
-                       self.items |= ITEM_Strength.m_itemid;
+                       self.items |= ITEM_Invisibility.m_itemid;
                        Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
                }
        }
 
-       if (self.items & ITEM_Shield.m_itemid)
+       if (self.items & ITEM_Speed.m_itemid)
        {
-               play_countdown(self.invincible_finished, "misc/poweroff.wav");
+               play_countdown(self.invincible_finished, SND(POWEROFF));
                if (time > self.invincible_finished)
                {
-                       self.items &= ~ITEM_Shield.m_itemid;
+                       self.items &= ~ITEM_Speed.m_itemid;
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
                }
        }
@@ -211,7 +221,7 @@ MUTATOR_HOOKFUNCTION(instagib_PlayerPowerups)
        {
                if (time < self.invincible_finished)
                {
-                       self.items |= ITEM_Shield.m_itemid;
+                       self.items |= ITEM_Speed.m_itemid;
                        Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
                }
@@ -220,8 +230,8 @@ MUTATOR_HOOKFUNCTION(instagib_PlayerPowerups)
 }
 
 MUTATOR_HOOKFUNCTION(instagib_PlayerPhysics)
-{
-       if(self.items & ITEM_Shield.m_itemid)
+{SELFPARAM();
+       if(self.items & ITEM_Speed.m_itemid)
                self.stat_sv_maxspeed = self.stat_sv_maxspeed * autocvar_g_instagib_speed_highspeed;
 
        return false;
@@ -305,7 +315,7 @@ MUTATOR_HOOKFUNCTION(instagib_PlayerDamage)
                frag_mirrordamage = 0;
        }
 
-       if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & ITEM_Strength.m_itemid))
+       if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & ITEM_Invisibility.m_itemid))
                yoda = 1;
 
        return false;
@@ -323,14 +333,14 @@ MUTATOR_HOOKFUNCTION(instagib_SetStartItems)
        start_ammo_rockets = warmup_start_ammo_rockets = 0;
        start_ammo_fuel    = warmup_start_ammo_fuel    = 0;
 
-       start_weapons = warmup_start_weapons = WEPSET_VAPORIZER;
+       start_weapons = warmup_start_weapons = WEPSET(VAPORIZER);
        start_items |= IT_UNLIMITED_SUPERWEAPONS;
 
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(instagib_FilterItem)
-{
+{SELFPARAM();
        if(self.classname == "item_cells")
                return true; // no normal cells?
 
@@ -342,15 +352,12 @@ MUTATOR_HOOKFUNCTION(instagib_FilterItem)
 
        if(self.weapon == WEP_DEVASTATOR.m_id || self.weapon == WEP_VORTEX.m_id)
        {
-               entity e = spawn(), oldself;
+               entity e = spawn();
                setorigin(e, self.origin);
-               oldself = self;
-               self = e;
-               self.noalign = oldself.noalign;
-               self.cnt = oldself.cnt;
-               self.team = oldself.team;
-               spawnfunc_item_minst_cells();
-               self = oldself;
+               e.noalign = self.noalign;
+        e.cnt = self.cnt;
+        e.team = self.team;
+               WITH(entity, self, e, spawnfunc_item_minst_cells(e));
                return true;
        }
 
@@ -367,31 +374,20 @@ MUTATOR_HOOKFUNCTION(instagib_FilterItem)
 }
 
 MUTATOR_HOOKFUNCTION(instagib_CustomizeWaypoint)
-{
+{SELFPARAM();
        entity e = WaypointSprite_getviewentity(other);
 
        // if you have the invisibility powerup, sprites ALWAYS are restricted to your team
        // but only apply this to real players, not to spectators
-       if((self.owner.flags & FL_CLIENT) && (self.owner.items & ITEM_Strength.m_itemid) && (e == other))
+       if((self.owner.flags & FL_CLIENT) && (self.owner.items & ITEM_Invisibility.m_itemid) && (e == other))
        if(DIFF_TEAM(self.owner, e))
                return true;
 
        return false;
 }
 
-MUTATOR_HOOKFUNCTION(instagib_ItemCountdown)
-{
-       switch (self.items)
-       {
-               case ITEM_Strength.m_itemid:  item_name = "item-invis";     item_color = '0 0 1'; break;
-               case ITEM_ExtraLife.m_itemid: item_name = "item-extralife"; item_color = '1 0 0'; break;
-               case ITEM_Shield.m_itemid:    item_name = "item-speed";     item_color = '1 0 1'; break;
-       }
-       return false;
-}
-
 MUTATOR_HOOKFUNCTION(instagib_PlayerDies)
-{      
+{
        if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER.m_id))
                frag_damage = 1000; // always gib if it was a vaporizer death
 
@@ -399,7 +395,7 @@ MUTATOR_HOOKFUNCTION(instagib_PlayerDies)
 }
 
 MUTATOR_HOOKFUNCTION(instagib_ItemTouch)
-{
+{SELFPARAM();
        if(self.ammo_cells)
        {
                // play some cool sounds ;)
@@ -428,19 +424,21 @@ MUTATOR_HOOKFUNCTION(instagib_ItemTouch)
 }
 
 MUTATOR_HOOKFUNCTION(instagib_OnEntityPreSpawn)
-{
+{SELFPARAM();
        if (!autocvar_g_powerups) { return false; }
-       if (!(self.classname == "item_strength" || self.classname == "item_invincible" || self.itemdef == ITEM_HealthMega))
+       // Can't use .itemdef here
+       if (!(self.classname == "item_strength" || self.classname == "item_invincible" || self.classname == "item_health_mega"))
                return false;
 
        entity e = spawn();
 
-       if(random() < 0.3)
-               e.think = spawnfunc_item_strength;
-       else if(random() < 0.6)
-               e.think = instagib_health_mega;
+       float r = random();
+       if (r < 0.3)
+               e.think = instagib_invisibility;
+       else if (r < 0.6)
+               e.think = instagib_extralife;
        else
-               e.think = spawnfunc_item_invincible;
+               e.think = instagib_speed;
 
        e.nextthink = time + 0.1;
        e.spawnflags = self.spawnflags;
@@ -482,7 +480,6 @@ MUTATOR_DEFINITION(mutator_instagib)
        MUTATOR_HOOK(ItemTouch, instagib_ItemTouch, CBC_ORDER_ANY);
        MUTATOR_HOOK(FilterItem, instagib_FilterItem, CBC_ORDER_ANY);
        MUTATOR_HOOK(CustomizeWaypoint, instagib_CustomizeWaypoint, CBC_ORDER_ANY);
-       MUTATOR_HOOK(Item_RespawnCountdown, instagib_ItemCountdown, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerDies, instagib_PlayerDies, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerDamage_SplitHealthArmor, instagib_SplitHealthArmor, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerPowerups, instagib_PlayerPowerups, CBC_ORDER_ANY);
index 339dc49aa5365f0e5f672fa520d1458acafffc79..87abd78a2c1d1a060fef72b4efd3bf35dda49683 100644 (file)
@@ -1,15 +1,18 @@
 #include "../../common/items/item.qh"
 
-#define WITH(it) this.m_##it;
-#define CONFIGURE(...) MAP(WITH, __VA_ARGS__)
-
 float instagib_respawntime_ammo = 45;
 float instagib_respawntimejitter_ammo = 0;
 GETTER(float, instagib_respawntime_ammo)
 GETTER(float, instagib_respawntimejitter_ammo)
 
+#ifndef MENUQC
+MODEL(VaporizerCells_ITEM, Item_Model("a_cells.md3"));
+#endif
+
 REGISTER_ITEM(VaporizerCells, Ammo) {
-    this.m_model                =   "a_cells.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_VaporizerCells_ITEM;
+#endif
     this.m_sound                =   "misc/itempickup.wav";
     this.m_name                 =   "Vaporizer Ammo";
     this.m_icon                 =   "ammo_supercells";
@@ -21,16 +24,53 @@ REGISTER_ITEM(VaporizerCells, Ammo) {
 #endif
 }
 
+#ifndef MENUQC
+MODEL(ExtraLife_ITEM, Item_Model("g_h100.md3"));
+#endif
+
 REGISTER_ITEM(ExtraLife, Powerup) {
-    this.m_model                =   "g_h100.md3";
+#ifndef MENUQC
+    this.m_model                =   MDL_ExtraLife_ITEM;
+#endif
     this.m_sound                =   "misc/megahealth.wav";
-    this.m_name                 =   "Extralife";
+    this.m_name                 =   "Extra life";
     this.m_icon                 =   "item_mega_health";
-#ifdef SVQC
+    this.m_color                =   '1 0 0';
+    this.m_waypoint             =   _("Extra life");
+    this.m_waypointblink        =   2;
     this.m_itemid               =   IT_NAILS;
-    this.m_botvalue             =   BOT_PICKUP_RATING_HIGH;
+}
+
+#ifndef MENUQC
+MODEL(Invisibility_ITEM, Item_Model("g_strength.md3"));
+#endif
+
+REGISTER_ITEM(Invisibility, Powerup) {
+#ifndef MENUQC
+    this.m_model            =   MDL_Invisibility_ITEM;
 #endif
+    this.m_sound            =   "misc/powerup.wav";
+    this.m_name             =   "Invisibility";
+    this.m_icon             =   "strength";
+    this.m_color            =   '0 0 1';
+    this.m_waypoint         =   _("Invisibility");
+    this.m_waypointblink    =   2;
+    this.m_itemid           =   IT_STRENGTH;
 }
 
-#undef WITH
-#undef CONFIGURE
+#ifndef MENUQC
+MODEL(Speed_ITEM, Item_Model("g_invincible.md3"));
+#endif
+
+REGISTER_ITEM(Speed, Powerup) {
+#ifndef MENUQC
+    this.m_model            =   MDL_Speed_ITEM;
+#endif
+    this.m_sound            =   "misc/powerup_shield.wav";
+    this.m_name             =   "Speed";
+    this.m_icon             =   "shield";
+    this.m_color            =   '1 0 1';
+    this.m_waypoint         =   _("Speed");
+    this.m_waypointblink    =   2;
+    this.m_itemid           =   IT_INVINCIBLE;
+}
index c77bba51630a59378bbfe02a0714d7ce32413391..fb8aac419f881c97b3e453122c36ad7ebb77de76 100644 (file)
@@ -5,7 +5,7 @@
 MUTATOR_HOOKFUNCTION(melee_SetStartItems)
 {
        start_ammo_shells = warmup_start_ammo_shells = 0;
-       start_weapons = warmup_start_weapons = WEPSET_SHOTGUN;
+       start_weapons = warmup_start_weapons = WEPSET(SHOTGUN);
 
        return false;
 }
@@ -16,7 +16,7 @@ MUTATOR_HOOKFUNCTION(melee_ForbidThrowing)
 }
 
 MUTATOR_HOOKFUNCTION(melee_FilterItem)
-{
+{SELFPARAM();
        switch (self.items)
        {
                case ITEM_HealthSmall.m_itemid:
index 686df9a567ad123316f2200c08e1e9d0c1efc4a9..3ac73031713d92d47be9d605f5472cf1bbd3ea3b 100644 (file)
@@ -5,7 +5,7 @@
 .float midair_shieldtime;
 
 MUTATOR_HOOKFUNCTION(midair_PlayerDamage)
-{
+{SELFPARAM();
        if(IS_PLAYER(frag_attacker))
        if(IS_PLAYER(frag_target))
        if(time < self.midair_shieldtime)
@@ -15,7 +15,7 @@ MUTATOR_HOOKFUNCTION(midair_PlayerDamage)
 }
 
 MUTATOR_HOOKFUNCTION(midair_PlayerPowerups)
-{
+{SELFPARAM();
        if(time >= game_starttime)
        if(self.flags & FL_ONGROUND)
        {
@@ -27,7 +27,7 @@ MUTATOR_HOOKFUNCTION(midair_PlayerPowerups)
 }
 
 MUTATOR_HOOKFUNCTION(midair_PlayerSpawn)
-{
+{SELFPARAM();
        if(IS_BOT_CLIENT(self))
                self.bot_moveskill = 0; // disable bunnyhopping
 
index a5bb70b8e2ed44b988fcf2d586841a3553db8dce..04e60bb83ec490cc6ebad1483a0642dfefff4fef 100644 (file)
@@ -32,7 +32,7 @@
 .float stat_multijump_dodging;
 
 void multijump_UpdateStats()
-{
+{SELFPARAM();
        self.stat_multijump = PHYS_MULTIJUMP;
        self.stat_multijump_speed = PHYS_MULTIJUMP_SPEED;
        self.stat_multijump_add = PHYS_MULTIJUMP_ADD;
@@ -52,7 +52,7 @@ void multijump_AddStats()
 #endif
 
 void PM_multijump()
-{
+{SELFPARAM();
        if(!PHYS_MULTIJUMP) { return; }
 
        if(IS_ONGROUND(self))
@@ -62,7 +62,7 @@ void PM_multijump()
 }
 
 bool PM_multijump_checkjump()
-{
+{SELFPARAM();
        if(!PHYS_MULTIJUMP) { return false; }
 
 #ifdef SVQC
index 0adff6068c77770b6b754c1aa053ae194b51b2b3..4fdbbd353dbf4ef70e4d9dbed1cfd3f608585215 100644 (file)
@@ -5,16 +5,16 @@
 
 #include "gamemode_keyhunt.qh"
 #include "gamemode_freezetag.qh"
-#include "../../common/nades.qh"
+#include "../../common/nades/all.qh"
 #include "../../common/monsters/spawn.qh"
 #include "../../common/monsters/sv_monsters.qh"
 
-.float lifetime;
+.float nade_time_primed;
 
 .entity nade_spawnloc;
 
 void nade_timer_think()
-{
+{SELFPARAM();
        self.skin = 8 - (self.owner.wait - time) / (autocvar_g_nades_nade_lifetime / 10);
        self.nextthink = time;
        if(!self.owner || wasfreed(self.owner))
@@ -23,13 +23,13 @@ void nade_timer_think()
 
 void nade_burn_spawn(entity _nade)
 {
-       CSQCProjectile(_nade, true, NADES[_nade.nade_type].m_projectile[true], true);
+       CSQCProjectile(_nade, true, Nades[_nade.nade_type].m_projectile[true], true);
 }
 
 void nade_spawn(entity _nade)
 {
        entity timer = spawn();
-       setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3");
+       setmodel(timer, MDL_NADE_TIMER);
        setattachment(timer, _nade, "");
        timer.classname = "nade_timer";
        timer.colormap = _nade.colormap;
@@ -42,11 +42,11 @@ void nade_spawn(entity _nade)
 
        _nade.effects |= EF_LOWPRECISION;
 
-       CSQCProjectile(_nade, true, NADES[_nade.nade_type].m_projectile[false], true);
+       CSQCProjectile(_nade, true, Nades[_nade.nade_type].m_projectile[false], true);
 }
 
 void napalm_damage(float dist, float damage, float edgedamage, float burntime)
-{
+{SELFPARAM();
        entity e;
        float d;
        vector p;
@@ -84,7 +84,7 @@ void napalm_damage(float dist, float damage, float edgedamage, float burntime)
 
 
 void napalm_ball_think()
-{
+{SELFPARAM();
        if(round_handler_IsActive())
        if(!round_handler_IsRoundStarted())
        {
@@ -117,11 +117,11 @@ void napalm_ball_think()
 
 
 void nade_napalm_ball()
-{
+{SELFPARAM();
        entity proj;
        vector kick;
 
-       spamsound(self, CH_SHOTS, W_Sound("fireball_fire"), VOL_BASE, ATTEN_NORM);
+       spamsound(self, CH_SHOTS, SND(FIREBALL_FIRE), VOL_BASE, ATTEN_NORM);
 
        proj = spawn ();
        proj.owner = self.owner;
@@ -133,7 +133,7 @@ void nade_napalm_ball()
        proj.movetype = MOVETYPE_BOUNCE;
        proj.projectiledeathtype = DEATH_NADE_NAPALM;
        PROJECTILE_MAKETRIGGER(proj);
-       setmodel(proj, "null");
+       setmodel(proj, MDL_Null);
        proj.scale = 1;//0.5;
        setsize(proj, '-4 -4 -4', '4 4 4');
        setorigin(proj, self.origin);
@@ -158,7 +158,7 @@ void nade_napalm_ball()
 
 
 void napalm_fountain_think()
-{
+{SELFPARAM();
 
        if(round_handler_IsActive())
        if(!round_handler_IsRoundStarted())
@@ -196,7 +196,7 @@ void napalm_fountain_think()
 }
 
 void nade_napalm_boom()
-{
+{SELFPARAM();
        entity fountain;
        int c;
        for (c = 0; c < autocvar_g_nades_napalm_ball_count; c++)
@@ -237,7 +237,7 @@ void nade_ice_freeze(entity freezefield, entity frost_target, float freeze_time)
 }
 
 void nade_ice_think()
-{
+{SELFPARAM();
 
        if(round_handler_IsActive())
        if(!round_handler_IsRoundStarted())
@@ -250,17 +250,9 @@ void nade_ice_think()
        {
                if ( autocvar_g_nades_ice_explode )
                {
-                       entity expef = NULL;
-                       switch(self.realowner.team)
-                       {
-                               case NUM_TEAM_1: expef = EFFECT_NADE_RED_EXPLODE; break;
-                               case NUM_TEAM_2: expef = EFFECT_NADE_BLUE_EXPLODE; break;
-                               case NUM_TEAM_3: expef = EFFECT_NADE_YELLOW_EXPLODE; break;
-                               case NUM_TEAM_4: expef = EFFECT_NADE_PINK_EXPLODE; break;
-                               default:                 expef = EFFECT_NADE_NEUTRAL_EXPLODE; break;
-                       }
+                       entity expef = EFFECT_NADE_EXPLODE(self.realowner.team);
                        Send_Effect(expef, self.origin + '0 0 1', '0 0 0', 1);
-                       sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+                       sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 
                        RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
                                autocvar_g_nades_nade_radius, self, world, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy);
@@ -310,7 +302,7 @@ void nade_ice_think()
 }
 
 void nade_ice_boom()
-{
+{SELFPARAM();
        entity fountain;
        fountain = spawn();
        fountain.owner = self.owner;
@@ -331,9 +323,9 @@ void nade_ice_boom()
 
        if ( autocvar_g_nades_ice_explode )
        {
-               setmodel(fountain, "models/grenademodel.md3");
+               setmodel(fountain, MDL_PROJECTILE_GRENADE);
                entity timer = spawn();
-               setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3");
+               setmodel(timer, MDL_NADE_TIMER);
                setattachment(timer, fountain, "");
                timer.classname = "nade_timer";
                timer.colormap = self.colormap;
@@ -345,11 +337,11 @@ void nade_ice_boom()
                timer.skin = 10;
        }
        else
-               setmodel(fountain, "null");
+               setmodel(fountain, MDL_Null);
 }
 
 void nade_translocate_boom()
-{
+{SELFPARAM();
        if(self.realowner.vehicle)
                return;
 
@@ -365,7 +357,7 @@ void nade_translocate_boom()
 }
 
 void nade_spawn_boom()
-{
+{SELFPARAM();
        entity spawnloc = spawn();
        setorigin(spawnloc, self.origin);
        setsize(spawnloc, self.realowner.mins, self.realowner.maxs);
@@ -385,7 +377,7 @@ void nade_spawn_boom()
 }
 
 void nade_heal_think()
-{
+{SELFPARAM();
        if(time >= self.ltime)
        {
                remove(self);
@@ -404,7 +396,7 @@ void nade_heal_think()
 }
 
 void nade_heal_touch()
-{
+{SELFPARAM();
        float maxhealth;
        float health_factor;
        if(IS_PLAYER(other) || IS_MONSTER(other))
@@ -446,7 +438,7 @@ void nade_heal_touch()
 }
 
 void nade_heal_boom()
-{
+{SELFPARAM();
        entity healer;
        healer = spawn();
        healer.owner = self.owner;
@@ -459,7 +451,7 @@ void nade_heal_boom()
        healer.solid = SOLID_TRIGGER;
        healer.touch = nade_heal_touch;
 
-       setmodel(healer, "models/ctf/shield.md3");
+       setmodel(healer, MDL_NADE_HEAL);
        healer.healer_radius = autocvar_g_nades_nade_radius;
        vector size = '1 1 1' * healer.healer_radius / 2;
        setsize(healer,-size,size);
@@ -472,7 +464,7 @@ void nade_heal_boom()
 }
 
 void nade_monster_boom()
-{
+{SELFPARAM();
        entity e = spawnmonster(self.pokenade_type, 0, self.realowner, self.realowner, self.origin, false, false, 1);
 
        if(autocvar_g_nades_pokenade_monster_lifetime > 0)
@@ -481,11 +473,11 @@ void nade_monster_boom()
 }
 
 void nade_boom()
-{
+{SELFPARAM();
        entity expef = NULL;
        bool nade_blast = true;
 
-       switch ( NADES[self.nade_type] )
+       switch ( Nades[self.nade_type] )
        {
                case NADE_TYPE_NAPALM:
                        nade_blast = autocvar_g_nades_napalm_blast;
@@ -517,21 +509,15 @@ void nade_boom()
 
                default:
                case NADE_TYPE_NORMAL:
-                       switch(self.realowner.team)
-                       {
-                               case NUM_TEAM_1: expef = EFFECT_NADE_RED_EXPLODE; break;
-                               case NUM_TEAM_2: expef = EFFECT_NADE_BLUE_EXPLODE; break;
-                               case NUM_TEAM_3: expef = EFFECT_NADE_YELLOW_EXPLODE; break;
-                               case NUM_TEAM_4: expef = EFFECT_NADE_PINK_EXPLODE; break;
-                               default:                 expef = EFFECT_NADE_NEUTRAL_EXPLODE; break;
-                       }
+                       expef = EFFECT_NADE_EXPLODE(self.realowner.team);
+                       break;
        }
 
        if(expef)
                Send_Effect(expef, findbetterlocation(self.origin, 8), '0 0 0', 1);
 
-       sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
-       sound(self, CH_SHOTS, W_Sound("rocket_impact"), VOL_BASE, ATTEN_NORM);
+       sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
+       sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 
        self.event_damage = func_null; // prevent somehow calling damage in the next call
 
@@ -543,7 +529,7 @@ void nade_boom()
        }
 
        if(self.takedamage)
-       switch ( NADES[self.nade_type] )
+       switch ( Nades[self.nade_type] )
        {
                case NADE_TYPE_NAPALM: nade_napalm_boom(); break;
                case NADE_TYPE_ICE: nade_ice_boom(); break;
@@ -562,7 +548,7 @@ void nade_boom()
 }
 
 void nade_touch()
-{
+{SELFPARAM();
        /*float is_weapclip = 0;
        if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODRAW)
        if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NONSOLID))
@@ -584,7 +570,7 @@ void nade_touch()
        //UpdateCSQCProjectile(self);
        if(self.health == self.max_health)
        {
-               spamsound(self, CH_SHOTS, W_Sound(strcat("grenade_bounce", ftos(1 + rint(random() * 5)))), VOL_BASE, ATTEN_NORM);
+               spamsound(self, CH_SHOTS, SND(GRENADE_BOUNCE_RANDOM()), VOL_BASE, ATTEN_NORM);
                return;
        }
 
@@ -593,14 +579,14 @@ void nade_touch()
 }
 
 void nade_beep()
-{
-       sound(self, CH_SHOTS_SINGLE, "overkill/grenadebip.ogg", VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
+{SELFPARAM();
+       sound(self, CH_SHOTS_SINGLE, SND_NADE_BEEP, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
        self.think = nade_boom;
        self.nextthink = max(self.wait, time);
 }
 
 void nade_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
        {
                self.takedamage = DAMAGE_NO;
@@ -649,7 +635,7 @@ void nade_damage(entity inflictor, entity attacker, float damage, int deathtype,
 
        if(self.health == self.max_health)
        {
-               sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
+               sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 *(ATTEN_LARGE + ATTEN_MAX));
                self.nextthink = max(time + autocvar_g_nades_nade_lifetime, time);
                self.think = nade_beep;
        }
@@ -666,7 +652,7 @@ void nade_damage(entity inflictor, entity attacker, float damage, int deathtype,
 }
 
 void toss_nade(entity e, vector _velocity, float _time)
-{
+{SELFPARAM();
        if(e.nade == world)
                return;
 
@@ -689,7 +675,7 @@ void toss_nade(entity e, vector _velocity, float _time)
                offset = '0 0 0';
 
        setorigin(_nade, w_shotorg + offset + (v_right * 25) * -1);
-       //setmodel(_nade, W_Model("v_ok_grenade.md3"));
+       //setmodel(_nade, MDL_PROJECTILE_NADE);
        //setattachment(_nade, world, "");
        PROJECTILE_MAKETRIGGER(_nade);
        setsize(_nade, '-16 -16 -16', '16 16 16');
@@ -759,7 +745,7 @@ void nades_GiveBonus(entity player, float score)
                if ( player.bonus_nade_score >= 1 )
                {
                        Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_BONUS);
-                       play2(player,"kh/alarm.wav");
+                       play2(player, SND(KH_ALARM));
                        player.bonus_nades++;
                        player.bonus_nade_score -= 1;
                }
@@ -772,7 +758,7 @@ void nades_RemoveBonus(entity player)
 }
 
 float nade_customize()
-{
+{SELFPARAM();
        //if(IS_SPEC(other)) { return false; }
        if(other == self.realowner || (IS_SPEC(other) && other.enemy == self.realowner))
        {
@@ -786,7 +772,7 @@ float nade_customize()
        {
                //self.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
                if(!self.traileffectnum)
-                       self.traileffectnum = _particleeffectnum(Nade_TrailEffect(NADES[self.nade_type].m_projectile[false], self.team));
+                       self.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades[self.nade_type].m_projectile[false], self.team).eent_eff_name);
                self.alpha = 1;
        }
 
@@ -794,7 +780,7 @@ float nade_customize()
 }
 
 void nade_prime()
-{
+{SELFPARAM();
        if(autocvar_g_nades_bonus_only)
        if(!self.bonus_nades)
                return; // only allow bonus nades
@@ -824,27 +810,27 @@ void nade_prime()
                n.pokenade_type = ((autocvar_g_nades_client_select) ? self.cvar_cl_pokenade_type : autocvar_g_nades_pokenade_monster_type);
        }
 
-       n.nade_type = bound(1, n.nade_type, NADES_COUNT);
+       n.nade_type = bound(1, n.nade_type, Nades_COUNT);
 
-       setmodel(n, W_Model("v_ok_grenade.md3"));
+       setmodel(n, MDL_PROJECTILE_NADE);
        //setattachment(n, self, "bip01 l hand");
        n.exteriormodeltoclient = self;
        n.customizeentityforclient = nade_customize;
-       n.traileffectnum = _particleeffectnum(Nade_TrailEffect(NADES[n.nade_type].m_projectile[false], self.team));
-       n.colormod = NADES[n.nade_type].m_color;
+       n.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades[n.nade_type].m_projectile[false], self.team).eent_eff_name);
+       n.colormod = Nades[n.nade_type].m_color;
        n.realowner = self;
        n.colormap = self.colormap;
        n.glowmod = self.glowmod;
        n.wait = time + autocvar_g_nades_nade_lifetime;
-       n.lifetime = time;
+       n.nade_time_primed = time;
        n.think = nade_beep;
        n.nextthink = max(n.wait - 3, time);
        n.projectiledeathtype = DEATH_NADE;
 
-       setmodel(fn, W_Model("h_ok_grenade.iqm"));
+       setmodel(fn, MDL_NADE_VIEW);
        setattachment(fn, self.weaponentity, "");
        fn.realowner = fn.owner = self;
-       fn.colormod = NADES[n.nade_type].m_color;
+       fn.colormod = Nades[n.nade_type].m_color;
        fn.colormap = self.colormap;
        fn.glowmod = self.glowmod;
        fn.think = SUB_Remove;
@@ -855,7 +841,7 @@ void nade_prime()
 }
 
 float CanThrowNade()
-{
+{SELFPARAM();
        if(self.vehicle)
                return false;
 
@@ -877,14 +863,18 @@ float CanThrowNade()
        return true;
 }
 
+.bool nade_altbutton;
+
 void nades_CheckThrow()
-{
+{SELFPARAM();
        if(!CanThrowNade())
                return;
 
-       if(!self.nade)
+       entity held_nade = self.nade;
+       if (!held_nade)
        {
-               if(self.nade_refire < time)
+               self.nade_altbutton = true;
+               if(time > self.nade_refire)
                {
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_NADE_THROW);
                        nade_prime();
@@ -893,10 +883,10 @@ void nades_CheckThrow()
        }
        else
        {
-               if(time - self.nade.lifetime >= 1)
-               {
+               self.nade_altbutton = false;
+               if (time >= held_nade.nade_time_primed + 1) {
                        makevectors(self.v_angle);
-                       float _force = time - self.nade.lifetime;
+                       float _force = time - held_nade.nade_time_primed;
                        _force /= autocvar_g_nades_nade_lifetime;
                        _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
                        toss_nade(self, (v_forward * 0.75 + v_up * 0.2 + v_right * 0.05) * _force, 0);
@@ -915,12 +905,6 @@ void nades_Clear(entity player)
        player.nade_timer = 0;
 }
 
-MUTATOR_HOOKFUNCTION(nades_CheckThrow)
-{
-       if(MUTATOR_RETURNVALUE) { nades_CheckThrow(); }
-       return false;
-}
-
 MUTATOR_HOOKFUNCTION(nades_VehicleEnter)
 {
        if(vh_player.nade)
@@ -929,51 +913,57 @@ MUTATOR_HOOKFUNCTION(nades_VehicleEnter)
        return false;
 }
 
-MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
-{
-       if(!IS_PLAYER(self)) { return false; }
-
-       float key_pressed = self.BUTTON_HOOK;
-       float time_score;
-
-       if(g_grappling_hook || client_hasweapon(self, WEP_HOOK.m_id, false, false) || (weaponsInMap & WEPSET_HOOK))
-               key_pressed = self.button16; // if hook is enabled, use an alternate key
-
-       if(self.nade)
-       {
-               self.nade_timer = bound(0, (time - self.nade.lifetime) / autocvar_g_nades_nade_lifetime, 1);
-               //print(sprintf("%d %d\n", self.nade_timer, time - self.nade.lifetime));
-               makevectors(self.angles);
-               self.nade.velocity = self.velocity;
-
-               setorigin(self.nade, self.origin + self.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
-               self.nade.angles_y = self.angles.y;
-       }
-
-       if(self.nade)
-       if(self.nade.wait - 0.1 <= time)
-               toss_nade(self, '0 0 0', time + 0.05);
-
-       if(CanThrowNade())
-       if(self.nade_refire < time)
-       {
-               if(key_pressed)
+CLASS(NadeOffhand, OffhandWeapon)
+    METHOD(NadeOffhand, offhand_think, void(NadeOffhand this, entity player, bool key_pressed))
+    {
+       entity held_nade = player.nade;
+               if (held_nade)
                {
-                       if(!self.nade)
-                               nade_prime();
+                       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);
+                       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);
+                       held_nade.angles_y = player.angles.y;
+
+                       if (time + 0.1 >= held_nade.wait)
+                               toss_nade(player, '0 0 0', time + 0.05);
                }
-               else if(time - self.nade.lifetime >= 1)
-               {
-                       if(self.nade)
-                       {
-                               makevectors(self.v_angle);
-                               float _force = time - self.nade.lifetime;
+
+        if (!CanThrowNade()) return;
+        if (!(time > player.nade_refire)) return;
+               if (key_pressed) {
+                       if (!held_nade) {
+                               nade_prime();
+                               held_nade = player.nade;
+                       }
+               } else if (time >= held_nade.nade_time_primed + 1) {
+                       if (held_nade) {
+                               makevectors(player.v_angle);
+                               float _force = time - held_nade.nade_time_primed;
                                _force /= autocvar_g_nades_nade_lifetime;
                                _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
-                               toss_nade(self, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
+                               toss_nade(player, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
                        }
                }
+    }
+ENDCLASS(NadeOffhand)
+NadeOffhand OFFHAND_NADE; STATIC_INIT(OFFHAND_NADE) { OFFHAND_NADE = NEW(NadeOffhand); }
+
+MUTATOR_HOOKFUNCTION(nades_CheckThrow)
+{
+       if (self.offhand != OFFHAND_NADE || (self.weapons & WEPSET(HOOK)) || autocvar_g_nades_override_dropweapon) {
+               nades_CheckThrow();
+               return true;
        }
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
+{SELFPARAM();
+       if (!IS_PLAYER(self)) { return false; }
+
+       if (self.nade && self.offhand != OFFHAND_NADE) OFFHAND_NADE.offhand_think(OFFHAND_NADE, self, self.nade_altbutton);
 
        if(IS_PLAYER(self))
        {
@@ -983,6 +973,7 @@ MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
                        float key_count = 0;
                        FOR_EACH_KH_KEY(key) if(key.owner == self) { ++key_count; }
 
+                       float time_score;
                        if(self.flagcarried || self.ballcarried) // this player is important
                                time_score = autocvar_g_nades_bonus_score_time_flagcarrier;
                        else
@@ -1002,7 +993,7 @@ MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
                                self.pokenade_type = autocvar_g_nades_pokenade_monster_type;
                        }
 
-                       self.nade_type = bound(1, self.nade_type, NADES_COUNT);
+                       self.nade_type = bound(1, self.nade_type, Nades_COUNT);
 
                        if(self.bonus_nade_score >= 0 && autocvar_g_nades_bonus_score_max)
                                nades_GiveBonus(self, time_score / autocvar_g_nades_bonus_score_max);
@@ -1061,7 +1052,7 @@ MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
 }
 
 MUTATOR_HOOKFUNCTION(nades_PlayerSpawn)
-{
+{SELFPARAM();
        if(autocvar_g_nades_spawn)
                self.nade_refire = time + autocvar_g_spawnshieldtime;
        else
@@ -1072,6 +1063,8 @@ MUTATOR_HOOKFUNCTION(nades_PlayerSpawn)
 
        self.nade_timer = 0;
 
+       if (!self.offhand) self.offhand = OFFHAND_NADE;
+
        if(self.nade_spawnloc)
        {
                setorigin(self, self.nade_spawnloc.origin);
@@ -1142,7 +1135,7 @@ MUTATOR_HOOKFUNCTION(nades_PlayerDamage)
 }
 
 MUTATOR_HOOKFUNCTION(nades_MonsterDies)
-{
+{SELFPARAM();
        if(IS_PLAYER(frag_attacker))
        if(DIFF_TEAM(frag_attacker, self))
        if(!(self.spawnflags & MONSTERFLAG_SPAWNED))
@@ -1152,14 +1145,14 @@ MUTATOR_HOOKFUNCTION(nades_MonsterDies)
 }
 
 MUTATOR_HOOKFUNCTION(nades_RemovePlayer)
-{
+{SELFPARAM();
        nades_Clear(self);
        nades_RemoveBonus(self);
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(nades_SpectateCopy)
-{
+{SELFPARAM();
        self.nade_timer = other.nade_timer;
        self.nade_type = other.nade_type;
        self.pokenade_type = other.pokenade_type;
@@ -1198,20 +1191,6 @@ void nades_Initialize()
        addstat(STAT_NADE_BONUS_SCORE, AS_FLOAT, bonus_nade_score);
        addstat(STAT_HEALING_ORB, AS_FLOAT, stat_healing_orb);
        addstat(STAT_HEALING_ORB_ALPHA, AS_FLOAT, stat_healing_orb_alpha);
-
-       precache_model("models/ok_nade_counter/ok_nade_counter.md3");
-       precache_model(W_Model("h_ok_grenade.iqm"));
-       precache_model(W_Model("v_ok_grenade.md3"));
-       precache_model("models/ctf/shield.md3");
-
-       precache_sound(W_Sound("rocket_impact"));
-       precache_sound(W_Sound("grenade_bounce1"));
-       precache_sound(W_Sound("grenade_bounce2"));
-       precache_sound(W_Sound("grenade_bounce3"));
-       precache_sound(W_Sound("grenade_bounce4"));
-       precache_sound(W_Sound("grenade_bounce5"));
-       precache_sound(W_Sound("grenade_bounce6"));
-       precache_sound("overkill/grenadebip.ogg");
 }
 
 MUTATOR_DEFINITION(mutator_nades)
index 1d4beda65d4dfa27efd1bed57031c84d7d0efa4c..9b51d9abb8640fbcaf4f3bbcf5ef83d5f652f760 100644 (file)
@@ -169,7 +169,7 @@ MUTATOR_HOOKFUNCTION(nt_SetStartItems)
 }
 
 MUTATOR_HOOKFUNCTION(nt_SetWeaponreplace)
-{
+{SELFPARAM();
        // otherwise, we do replace
        if(self.new_toys)
        {
@@ -189,9 +189,11 @@ MUTATOR_HOOKFUNCTION(nt_SetWeaponreplace)
 }
 
 MUTATOR_HOOKFUNCTION(nt_FilterItem)
-{
-       if(nt_IsNewToy(self.weapon) && autocvar_g_new_toys_use_pickupsound)
-               self.item_pickupsound = W_Sound("weaponpickup_new_toys");
+{SELFPARAM();
+       if(nt_IsNewToy(self.weapon) && autocvar_g_new_toys_use_pickupsound) {
+               self.item_pickupsound = string_null;
+               self.item_pickupsound_ent = SND_WEAPONPICKUP_NEW_TOYS;
+       }
        return 0;
 }
 
@@ -207,8 +209,6 @@ MUTATOR_DEFINITION(mutator_new_toys)
                if(time > 1) // game loads at time 1
                        error("This cannot be added at runtime\n");
 
-               precache_sound(W_Sound("weaponpickup_new_toys"));
-
                // mark the guns as ok to use by e.g. impulse 99
                float i;
                for(i = WEP_FIRST; i <= WEP_LAST; ++i)
index f239dbbf635d17623c2e2d20fcdb164a932a3914..5339d319ec558c63aab46f745fe68dcb7bdd0031 100644 (file)
@@ -44,7 +44,7 @@ void NIX_ChooseNextWeapon()
 }
 
 void NIX_GiveCurrentWeapon()
-{
+{SELFPARAM();
        float dt;
 
        if(!nix_nextweapon)
@@ -60,7 +60,8 @@ void NIX_GiveCurrentWeapon()
                        nix_nextchange = time; // start the first round now!
                else
                        nix_nextchange = time + autocvar_g_balance_nix_roundtime;
-               //WEP_ACTION(nix_weapon, WR_INIT); // forget it, too slow
+               // Weapon w = get_weaponinfo(nix_weapon);
+               // w.wr_init(w); // forget it, too slow
        }
 
        // get weapon info
@@ -101,7 +102,8 @@ void NIX_GiveCurrentWeapon()
                else
                        Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
 
-               WEP_ACTION(nix_weapon, WR_RESETPLAYER);
+               Weapon w = get_weaponinfo(nix_weapon);
+               w.wr_resetplayer(w);
 
                // all weapons must be fully loaded when we spawn
                if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
@@ -142,7 +144,7 @@ void NIX_GiveCurrentWeapon()
 
        self.weapons = '0 0 0';
        if(g_nix_with_blaster)
-               self.weapons |= WEPSET_BLASTER;
+               self.weapons |= WEPSET(BLASTER);
        self.weapons |= WepSet_FromWeapon(nix_weapon);
 
        if(self.switchweapon != nix_weapon)
@@ -155,8 +157,10 @@ void NIX_precache()
 {
        float i;
        for (i = WEP_FIRST; i <= WEP_LAST; ++i)
-               if (NIX_CanChooseWeapon(i))
-                       WEP_ACTION(i, WR_INIT);
+               if (NIX_CanChooseWeapon(i)) {
+                       Weapon w = get_weaponinfo(i);
+                       w.wr_init(w);
+               }
 }
 
 MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
@@ -177,7 +181,7 @@ MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
 }
 
 MUTATOR_HOOKFUNCTION(nix_FilterItem)
-{
+{SELFPARAM();
        switch (self.items)
        {
                case ITEM_HealthSmall.m_itemid:
@@ -202,14 +206,14 @@ MUTATOR_HOOKFUNCTION(nix_FilterItem)
 }
 
 MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
-{
+{SELFPARAM();
        if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
                return 1;
        return 0;
 }
 
 MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
-{
+{SELFPARAM();
        if(!intermission_running)
        if(self.deadflag == DEAD_NO)
        if(IS_PLAYER(self))
@@ -218,7 +222,7 @@ MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
 }
 
 MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
-{
+{SELFPARAM();
        self.nix_lastchange_id = -1;
        NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
        self.items |= IT_UNLIMITED_SUPERWEAPONS;
@@ -232,7 +236,7 @@ MUTATOR_HOOKFUNCTION(nix_SetModname)
 }
 
 MUTATOR_DEFINITION(mutator_nix)
-{
+{SELFPARAM();
        entity e;
 
        MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
index 9247dffacaf1317ab1fbccb4157fdaa9de7fbf89..d2086215f931dc94143c9c1e71958e8932d14a0b 100644 (file)
@@ -3,9 +3,9 @@
 
 #include "mutator.qh"
 
-void W_Blaster_Attack(float, float, float, float, float, float, float, float, float, float);
-void spawnfunc_weapon_hmg();
-void spawnfunc_weapon_rpc();
+void W_Blaster_Attack(entity, float, float, float, float, float, float, float, float, float, float);
+spawnfunc(weapon_hmg);
+spawnfunc(weapon_rpc);
 
 void ok_DecreaseCharge(entity ent, int wep)
 {
@@ -64,15 +64,14 @@ MUTATOR_HOOKFUNCTION(ok_PlayerDamage_Calculate)
 }
 
 MUTATOR_HOOKFUNCTION(ok_PlayerDamage_SplitHealthArmor)
-{
+{SELFPARAM();
        if(damage_take)
                self.ok_pauseregen_finished = max(self.ok_pauseregen_finished, time + 2);
        return false;
 }
 
 MUTATOR_HOOKFUNCTION(ok_PlayerDies)
-{
-       entity oldself = self;
+{SELFPARAM();
        entity targ = ((frag_attacker) ? frag_attacker : frag_target);
 
        if(IS_MONSTER(self))
@@ -81,11 +80,11 @@ MUTATOR_HOOKFUNCTION(ok_PlayerDies)
                other = world;
        }
 
-       self = spawn();
+       setself(spawn());
        self.ok_item = true;
        self.noalign = true;
        self.pickup_anyway = true;
-       spawnfunc_item_armor_small();
+       spawnfunc_item_armor_small(this);
        self.movetype = MOVETYPE_TOSS;
        self.gravity = 1;
        self.reset = SUB_Remove;
@@ -93,7 +92,7 @@ MUTATOR_HOOKFUNCTION(ok_PlayerDies)
        self.velocity = '0 0 200' + normalize(targ.origin - self.origin) * 500;
        self.classname = "droppedweapon"; // hax
        SUB_SetFade(self, time + 5, 1);
-       self = oldself;
+       setself(this);
 
        self.ok_lastwep = self.switchweapon;
 
@@ -101,7 +100,7 @@ MUTATOR_HOOKFUNCTION(ok_PlayerDies)
 }
 
 MUTATOR_HOOKFUNCTION(ok_PlayerRegen)
-{
+{SELFPARAM();
        // overkill's values are different, so use custom regen
        if(!self.frozen)
        {
@@ -125,7 +124,7 @@ MUTATOR_HOOKFUNCTION(ok_ForbidThrowCurrentWeapon)
 }
 
 MUTATOR_HOOKFUNCTION(ok_PlayerPreThink)
-{
+{SELFPARAM();
        if(intermission_running || gameover)
                return false;
 
@@ -150,6 +149,7 @@ MUTATOR_HOOKFUNCTION(ok_PlayerPreThink)
                int oldwep = self.weapon;
                self.weapon = WEP_BLASTER.m_id;
                W_Blaster_Attack(
+                       self,
                        WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                        WEP_CVAR_SEC(vaporizer, shotangle),
                        WEP_CVAR_SEC(vaporizer, damage),
@@ -175,10 +175,11 @@ MUTATOR_HOOKFUNCTION(ok_PlayerPreThink)
                {
                        //Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_OVERKILL_CHARGE);
                        self.ok_notice_time = time + 2;
-                       play2(self, W_Sound("dryfire"));
+                       play2(self, SND(DRYFIRE));
                }
+               Weapon wpn = get_weaponinfo(self.weapon);
                if(self.weaponentity.state != WS_CLEAR)
-                       w_ready();
+                       w_ready(wpn, self, self.BUTTON_ATCK, self.BUTTON_ATCK2);
 
                self.weapon_blocked = true;
        }
@@ -189,7 +190,7 @@ MUTATOR_HOOKFUNCTION(ok_PlayerPreThink)
 }
 
 MUTATOR_HOOKFUNCTION(ok_PlayerSpawn)
-{
+{SELFPARAM();
        if(autocvar_g_overkill_ammo_charge)
        {
                for(int i = WEP_FIRST; i <= WEP_LAST; ++i)
@@ -206,8 +207,11 @@ MUTATOR_HOOKFUNCTION(ok_PlayerSpawn)
        return false;
 }
 
+void _spawnfunc_weapon_hmg() { SELFPARAM(); spawnfunc_weapon_hmg(this); }
+void _spawnfunc_weapon_rpc() { SELFPARAM(); spawnfunc_weapon_rpc(this); }
+
 MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn)
-{
+{SELFPARAM();
        if(autocvar_g_powerups)
        if(autocvar_g_overkill_powerups_replace)
        {
@@ -215,7 +219,7 @@ MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn)
                {
                        entity wep = spawn();
                        setorigin(wep, self.origin);
-                       setmodel(wep, W_Model("g_ok_hmg.md3"));
+                       setmodel(wep, MDL_OK_HMG);
                        wep.classname = "weapon_hmg";
                        wep.ok_item = true;
                        wep.noalign = self.noalign;
@@ -223,7 +227,7 @@ MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn)
                        wep.team = self.team;
                        wep.respawntime = autocvar_g_overkill_superguns_respawn_time;
                        wep.pickup_anyway = true;
-                       wep.think = spawnfunc_weapon_hmg;
+                       wep.think = _spawnfunc_weapon_hmg;
                        wep.nextthink = time + 0.1;
                        return true;
                }
@@ -232,7 +236,7 @@ MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn)
                {
                        entity wep = spawn();
                        setorigin(wep, self.origin);
-                       setmodel(wep, W_Model("g_ok_rl.md3"));
+                       setmodel(wep, MDL_OK_RPC);
                        wep.classname = "weapon_rpc";
                        wep.ok_item = true;
                        wep.noalign = self.noalign;
@@ -240,7 +244,7 @@ MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn)
                        wep.team = self.team;
                        wep.respawntime = autocvar_g_overkill_superguns_respawn_time;
                        wep.pickup_anyway = true;
-                       wep.think = spawnfunc_weapon_rpc;
+                       wep.think = _spawnfunc_weapon_rpc;
                        wep.nextthink = time + 0.1;
                        return true;
                }
@@ -250,7 +254,7 @@ MUTATOR_HOOKFUNCTION(ok_OnEntityPreSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(ok_ItemRemove)
-{
+{SELFPARAM();
        if(self.ok_item)
                return false;
 
@@ -264,7 +268,7 @@ MUTATOR_HOOKFUNCTION(ok_ItemRemove)
 }
 
 MUTATOR_HOOKFUNCTION(ok_SpectateCopy)
-{
+{SELFPARAM();
        self.ammo_charge[self.weapon] = other.ammo_charge[other.weapon];
        self.ok_use_ammocharge = other.ok_use_ammocharge;
 
@@ -273,10 +277,10 @@ MUTATOR_HOOKFUNCTION(ok_SpectateCopy)
 
 MUTATOR_HOOKFUNCTION(ok_StartItems)
 {
-       WepSet ok_start_items = (WEPSET_MACHINEGUN | WEPSET_VORTEX | WEPSET_SHOTGUN);
+       WepSet ok_start_items = (WEPSET(MACHINEGUN) | WEPSET(VORTEX) | WEPSET(SHOTGUN));
 
-       if(WEP_RPC.weaponstart > 0) { ok_start_items |= WEPSET_RPC; }
-       if(WEP_HMG.weaponstart > 0) { ok_start_items |= WEPSET_HMG; }
+       if(WEP_RPC.weaponstart > 0) { ok_start_items |= WEPSET(RPC); }
+       if(WEP_HMG.weaponstart > 0) { ok_start_items |= WEPSET(HMG); }
 
        start_items |= IT_UNLIMITED_WEAPON_AMMO;
        start_weapons = warmup_start_weapons = ok_start_items;
@@ -317,20 +321,6 @@ void ok_Initialize()
 
        precache_all_playermodels("models/ok_player/*.dpm");
 
-       precache_model(W_Model("h_ok_mg.iqm"));
-       precache_model(W_Model("v_ok_mg.md3"));
-       precache_model(W_Model("g_ok_mg.md3"));
-
-       precache_model(W_Model("h_ok_shotgun.iqm"));
-       precache_model(W_Model("v_ok_shotgun.md3"));
-       precache_model(W_Model("g_ok_shotgun.md3"));
-
-       precache_model(W_Model("h_ok_sniper.iqm"));
-       precache_model(W_Model("v_ok_sniper.md3"));
-       precache_model(W_Model("g_ok_sniper.md3"));
-
-       precache_sound(W_Sound("dryfire"));
-
        addstat(STAT_OK_AMMO_CHARGE, AS_FLOAT, ok_use_ammocharge);
        addstat(STAT_OK_AMMO_CHARGEPOOL, AS_FLOAT, ok_ammo_charge);
 
index 0b418be40b0b71f07f46c53b952c790b42b0eb86..10f89c08e0978a2993e2a009e81ea1148ff5cdda 100644 (file)
@@ -7,7 +7,7 @@
 .float ok_item;
 
 .float ok_notice_time;
-.float ammo_charge[WEP_MAXCOUNT];
+.float ammo_charge[Weapons_MAX];
 .float ok_use_ammocharge;
 .float ok_ammo_charge;
 
index 0ee697d261f2d4425cdd4eb37b68a634cc7da734..144a8d2eaa099871a0ff8b62431463cd68045896 100644 (file)
@@ -5,7 +5,7 @@
 .vector spawn_origin, spawn_angles;
 
 void physical_item_think()
-{
+{SELFPARAM();
        self.nextthink = time;
 
        self.alpha = self.owner.alpha; // apply fading and ghosting
@@ -42,7 +42,7 @@ void physical_item_think()
 }
 
 void physical_item_touch()
-{
+{SELFPARAM();
        if(!self.cnt) // not for dropped items
        if (ITEM_TOUCH_NEEDKILL())
        {
@@ -52,7 +52,7 @@ void physical_item_touch()
 }
 
 void physical_item_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(!self.cnt) // not for dropped items
        if(ITEM_DAMAGE_NEEDKILL(deathtype))
        {
@@ -62,7 +62,7 @@ void physical_item_damage(entity inflictor, entity attacker, float damage, int d
 }
 
 MUTATOR_HOOKFUNCTION(item_spawning)
-{
+{SELFPARAM();
        if(self.owner == world && autocvar_g_physical_items <= 1)
                return false;
        if (self.spawnflags & 1) // floating item
@@ -72,7 +72,7 @@ MUTATOR_HOOKFUNCTION(item_spawning)
        // Ugly hack, but unless SOLID_TRIGGER is gotten to work with MOVETYPE_PHYSICS in the engine it can't be fixed.
        entity wep;
        wep = spawn();
-       setmodel(wep, self.model);
+       _setmodel(wep, self.model);
        setsize(wep, self.mins, self.maxs);
        setorigin(wep, self.origin);
        wep.angles = self.angles;
@@ -100,9 +100,7 @@ MUTATOR_HOOKFUNCTION(item_spawning)
                setorigin(wep, wep.origin + '0 0 1');
                entity oldself;
                oldself = self;
-               self = wep;
-               builtin_droptofloor();
-               self = oldself;
+               WITH(entity, self, wep, builtin_droptofloor());
        }
 
        wep.spawn_origin = wep.origin;
index 5dd6aa92e46e90b02aae2e1277f70460b9243db7..71262b923df8ca18e4ff4a6b36ab7d18cb46f30f 100644 (file)
@@ -3,7 +3,7 @@
 #include "mutator.qh"
 
 MUTATOR_HOOKFUNCTION(pinata_PlayerDies)
-{
+{SELFPARAM();
        float j;
        for(j = WEP_FIRST; j <= WEP_LAST; ++j)
        if(self.weapons & WepSet_FromWeapon(j))
index 1464870916ebaa23b06be4fe3992fb60a9b58ed0..e3178b338874f9892eb174afdffa6800e2c3c8a7 100644 (file)
@@ -10,7 +10,7 @@
 .float cvar_cl_spawn_near_teammate;
 
 MUTATOR_HOOKFUNCTION(msnt_Spawn_Score)
-{
+{SELFPARAM();
        if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && self.cvar_cl_spawn_near_teammate))
                return 0;
 
@@ -46,7 +46,7 @@ MUTATOR_HOOKFUNCTION(msnt_Spawn_Score)
 }
 
 MUTATOR_HOOKFUNCTION(msnt_PlayerSpawn)
-{
+{SELFPARAM();
        // Note: when entering this, fixangle is already set.
        if(autocvar_g_spawn_near_teammate_ignore_spawnpoint == 1 || (autocvar_g_spawn_near_teammate_ignore_spawnpoint == 2 && self.cvar_cl_spawn_near_teammate))
        {
@@ -155,7 +155,7 @@ MUTATOR_HOOKFUNCTION(msnt_PlayerSpawn)
 }
 
 MUTATOR_HOOKFUNCTION(msnt_PlayerDies)
-{
+{SELFPARAM();
        self.msnt_deathloc = self.origin;
        return 0;
 }
index b75e5d424c8638c4038aad900e500314d952ed13..32e81319dfe87dda5d6eeaa680aed00836bd77ae 100644 (file)
@@ -25,7 +25,7 @@ const float SSF_ITEMMSG = 4;
 .string superspec_itemfilter; //"classname1 classname2 ..."
 
 float _spectate(entity _player)
-{
+{SELFPARAM();
        if(Spectate(_player) == 1)
                self.classname = "spectator";
 
@@ -33,7 +33,7 @@ float _spectate(entity _player)
 }
 
 void superspec_save_client_conf()
-{
+{SELFPARAM();
        string fn = "superspec-local.options";
        float fh;
 
@@ -99,12 +99,13 @@ float superspec_filteritem(entity _for, entity _item)
 }
 
 MUTATOR_HOOKFUNCTION(superspec_ItemTouch)
-{
-       entity _oldself = self;
+{SELFPARAM();
        entity _item = self;
 
-       FOR_EACH_SPEC(self)
+       entity e;
+       FOR_EACH_SPEC(e)
        {
+               setself(e);
                if(self.superspec_flags & SSF_ITEMMSG)
                        if(superspec_filteritem(self, _item))
                        {
@@ -116,7 +117,7 @@ MUTATOR_HOOKFUNCTION(superspec_ItemTouch)
                                {
                                        _spectate(other);
 
-                                       self = _oldself;
+                                       setself(this);
                                        return MUT_ITEMTOUCH_CONTINUE;
                                }
                        }
@@ -146,13 +147,13 @@ MUTATOR_HOOKFUNCTION(superspec_ItemTouch)
                }
        }
 
-       self = _oldself;
+       setself(this);
 
        return MUT_ITEMTOUCH_CONTINUE;
 }
 
 MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
-{
+{SELFPARAM();
 #define OPTIONINFO(flag,var,test,text,long,short) \
     var = strcat(var, ((flag & test) ? "^2[ON]  ^7" : "^1[OFF] ^7")); \
     var = strcat(var, text," ^7(^3 ", long, "^7 | ^3", short, " ^7)\n")
@@ -434,7 +435,7 @@ MUTATOR_HOOKFUNCTION(superspec_BuildMutatorsPrettyString)
 }
 
 void superspec_hello()
-{
+{SELFPARAM();
        if(self.enemy.crypto_idfp == "")
                Send_Notification(NOTIF_ONE_ONLY, self.enemy, MSG_INFO, INFO_SUPERSPEC_MISSING_UID);
 
@@ -442,7 +443,7 @@ void superspec_hello()
 }
 
 MUTATOR_HOOKFUNCTION(superspec_ClientConnect)
-{
+{SELFPARAM();
        if(!IS_REAL_CLIENT(self))
                return false;
 
@@ -490,12 +491,12 @@ MUTATOR_HOOKFUNCTION(superspec_ClientConnect)
 }
 
 MUTATOR_HOOKFUNCTION(superspec_PlayerDies)
-{
-       entity _old_self = self;
-
-       FOR_EACH_SPEC(self)
+{SELFPARAM();
+       entity e;
+       FOR_EACH_SPEC(e)
        {
-               if(self.autospec_flags & ASF_FOLLOWKILLER && IS_PLAYER(frag_attacker) && self.enemy == _old_self)
+               setself(e);
+               if(self.autospec_flags & ASF_FOLLOWKILLER && IS_PLAYER(frag_attacker) && self.enemy == this)
                {
                        if(self.autospec_flags & ASF_SHOWWHAT)
                                superspec_msg("", "", self, sprintf("^7Following %s^7 due to followkiller\n", frag_attacker.netname), 2);
@@ -504,7 +505,7 @@ MUTATOR_HOOKFUNCTION(superspec_PlayerDies)
                }
        }
 
-       self = _old_self;
+       setself(this);
        return false;
 }
 
index 3c0e2706f8d8f52c16406de17ff03e86b16604ee..faa74bb1dcf74e989eeb50311e1b83c82bd1fba6 100644 (file)
@@ -5,12 +5,12 @@
 .float touchexplode_time;
 
 void PlayerTouchExplode(entity p1, entity p2)
-{
+{SELFPARAM();
        vector org;
        org = (p1.origin + p2.origin) * 0.5;
        org.z += (p1.mins.z + p2.mins.z) * 0.5;
 
-       sound(self, CH_TRIGGER, W_Sound("grenade_impact"), VOL_BASE, ATTEN_NORM);
+       sound(self, CH_TRIGGER, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
        Send_Effect(EFFECT_EXPLOSION_SMALL, org, '0 0 0', 1);
 
        entity e;
@@ -21,7 +21,7 @@ void PlayerTouchExplode(entity p1, entity p2)
 }
 
 MUTATOR_HOOKFUNCTION(touchexplode_PlayerThink)
-{
+{SELFPARAM();
        if(time > self.touchexplode_time)
        if(!gameover)
        if(!self.frozen)
index 85ff7b0586ef328978631a8bb3f2ce986bc05e21..3d88a901571a13ca8c77beaa274b41dc7be40c9f 100644 (file)
@@ -8,7 +8,7 @@ float autocvar_g_vampirehook_health_steal;
 .float last_dmg;
 
 MUTATOR_HOOKFUNCTION(vh, GrappleHookThink)
-{      
+{SELFPARAM();
        entity dmgent = ((SAME_TEAM(self.owner, self.aiment) && autocvar_g_vampirehook_teamheal) ? self.owner : self.aiment);
 
        if(IS_PLAYER(self.aiment))
index 7f238b88e425351c5ca82e73286d8a92a7475888..8564d34c59cb2a0b06e31df6bc93a78dd84f0d69 100644 (file)
@@ -11,8 +11,8 @@
     #include "../../common/stats.qh"
     #include "../../common/teams.qh"
     #include "../../common/util.qh"
-    #include "../../common/nades.qh"
-    #include "../../common/buffs.qh"
+    #include "../../common/nades/all.qh"
+    #include "../../common/buffs/all.qh"
     #include "../../common/command/markup.qh"
     #include "../../common/command/rpn.qh"
     #include "../../common/command/generic.qh"
 #endif
 
 #include "../../common/mutators/base.qh"
+
 #include "gamemode_assault.qc"
 #include "gamemode_ca.qc"
 #include "gamemode_ctf.qc"
+#include "gamemode_cts.qc"
+#include "gamemode_deathmatch.qc"
 #include "gamemode_domination.qc"
 #include "gamemode_freezetag.qc"
-#include "gamemode_keyhunt.qc"
+#include "gamemode_invasion.qc"
 #include "gamemode_keepaway.qc"
+#include "gamemode_keyhunt.qc"
+#include "gamemode_lms.qc"
 #include "gamemode_nexball.qc"
 #include "gamemode_onslaught.qc"
-#include "gamemode_lms.qc"
-#include "gamemode_invasion.qc"
 #include "gamemode_race.qc"
-#include "gamemode_cts.qc"
 #include "gamemode_tdm.qc"
-#include "gamemode_deathmatch.qc"
 
+#include "mutator_bloodloss.qc"
+#include "mutator_breakablehook.qc"
+#include "mutator_buffs.qc"
+#include "mutator_campcheck.qc"
+#include "mutator_dodging.qc"
+#include "mutator_hook.qc"
+#include "mutator_instagib.qc"
 #include "mutator_invincibleproj.qc"
+#include "mutator_melee_only.qc"
+#include "mutator_midair.qc"
+#include "mutator_multijump.qc"
+#include "mutator_nades.qc"
 #include "mutator_new_toys.qc"
 #include "mutator_nix.qc"
-#include "mutator_dodging.qc"
-#include "mutator_rocketflying.qc"
-#include "mutator_vampire.qc"
-#include "mutator_spawn_near_teammate.qc"
-#include "mutator_physical_items.qc"
-#include "sandbox.qc"
-#include "mutator_superspec.qc"
 #include "mutator_overkill.qc"
-#include "mutator_instagib.qc"
-#include "mutator_touchexplode.qc"
+#include "mutator_physical_items.qc"
 #include "mutator_pinata.qc"
-#include "mutator_midair.qc"
-#include "mutator_bloodloss.qc"
 #include "mutator_random_gravity.qc"
-#include "mutator_multijump.qc"
-#include "mutator_melee_only.qc"
-#include "mutator_nades.qc"
-#include "mutator_campcheck.qc"
-#include "mutator_buffs.qc"
+#include "mutator_rocketflying.qc"
 #include "mutator_rocketminsta.qc"
+#include "mutator_spawn_near_teammate.qc"
+#include "mutator_superspec.qc"
+#include "mutator_touchexplode.qc"
 #include "mutator_vampirehook.qc"
-#include "mutator_breakablehook.qc"
+#include "mutator_vampire.qc"
+
+#include "sandbox.qc"
index 2d1c3b4502830d86b27c9dab515d3b2ece1762a8..dcd29447637062b42eb156c2de525bf5f934b29c 100644 (file)
@@ -3,21 +3,22 @@
 
 #include "../../common/mutators/base.qh"
 #include "mutators.qh"
+
 #include "gamemode_assault.qh"
 #include "gamemode_ca.qh"
 #include "gamemode_ctf.qh"
+#include "gamemode_cts.qh"
 #include "gamemode_domination.qh"
-#include "gamemode_keyhunt.qh"
+#include "gamemode_invasion.qh"
 #include "gamemode_keepaway.qh"
-#include "gamemode_nexball.qh"
+#include "gamemode_keyhunt.qh"
 #include "gamemode_lms.qh"
-#include "gamemode_invasion.qh"
-#include "gamemode_race.qh"
-#include "gamemode_cts.qh"
+#include "gamemode_nexball.qh"
 #include "gamemode_onslaught.qh"
+#include "gamemode_race.qh"
 
+#include "mutator_buffs.qh"
 #include "mutator_dodging.qh"
-#include "mutator_overkill.qh"
 #include "mutator_nades.qh"
-#include "mutator_buffs.qh"
+#include "mutator_overkill.qh"
 #endif
index 273e25e3f959df6da6bb578f1c921035aef79a5b..ed3ffc5e77dfe6c3cd90afdcdad0e8bf2475a3d4 100644 (file)
@@ -10,7 +10,7 @@ float object_count;
 
 .float touch_timer;
 void sandbox_ObjectFunction_Touch()
-{
+{SELFPARAM();
        // apply material impact effects
 
        if(!self.material)
@@ -30,12 +30,12 @@ void sandbox_ObjectFunction_Touch()
        intensity -= autocvar_g_sandbox_object_material_velocity_min; // start from minimum velocity, not actual velocity
        intensity = bound(0, intensity * autocvar_g_sandbox_object_material_velocity_factor, 1);
 
-       sound(self, CH_TRIGGER, strcat("object/impact_", self.material, "_", ftos(ceil(random() * 5)) , ".wav"), VOL_BASE * intensity, ATTEN_NORM);
+       _sound(self, CH_TRIGGER, strcat("object/impact_", self.material, "_", ftos(ceil(random() * 5)) , ".wav"), VOL_BASE * intensity, ATTEN_NORM);
        Send_Effect_(strcat("impact_", self.material), self.origin, '0 0 0', ceil(intensity * 10)); // allow a count from 1 to 10
 }
 
 void sandbox_ObjectFunction_Think()
-{
+{SELFPARAM();
        entity e;
 
        // decide if and how this object can be grabbed
@@ -61,12 +61,12 @@ void sandbox_ObjectFunction_Think()
 
        self.nextthink = time;
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 .float old_solid, old_movetype;
 entity sandbox_ObjectEdit_Get(float permissions)
-{
+{SELFPARAM();
        // Returns the traced entity if the player can edit it, and world if not.
        // If permissions if false, the object is returned regardless of editing rights.
        // Attached objects are SOLID_NOT and do not get traced.
@@ -91,7 +91,7 @@ void sandbox_ObjectEdit_Scale(entity e, float f)
        if(e.scale)
        {
                e.scale = bound(autocvar_g_sandbox_object_scale_min, e.scale, autocvar_g_sandbox_object_scale_max);
-               setmodel(e, e.model); // reset mins and maxs based on mesh
+               _setmodel(e, e.model); // reset mins and maxs based on mesh
                setsize(e, e.mins * e.scale, e.maxs * e.scale); // adapt bounding box size to model size
        }
 }
@@ -140,11 +140,10 @@ void sandbox_ObjectAttach_Remove(entity e)
 }
 
 entity sandbox_ObjectSpawn(float database)
-{
+{SELFPARAM();
        // spawn a new object with default properties
 
-       entity e, oldself;
-       e = spawn();
+       entity e = spawn();
        e.classname = "object";
        e.takedamage = DAMAGE_AIM;
        e.damageforcescale = 1;
@@ -179,10 +178,7 @@ entity sandbox_ObjectSpawn(float database)
                e.angles_y = self.v_angle.y;
        }
 
-       oldself = self;
-       self = e;
-       CSQCMODEL_AUTOINIT();
-       self = oldself;
+       WITH(entity, self, e, CSQCMODEL_AUTOINIT(e));
 
        object_count += 1;
        return e;
@@ -327,7 +323,7 @@ entity sandbox_ObjectPort_Load(string s, float database)
                        parent = e; // mark parent objects as such
                }
                // properties stored for all objects
-               setmodel(e, argv(argv_num));    ++argv_num;
+               _setmodel(e, argv(argv_num));   ++argv_num;
                e.skin = stof(argv(argv_num));  ++argv_num;
                e.alpha = stof(argv(argv_num)); ++argv_num;
                e.colormod = stov(argv(argv_num));      ++argv_num;
@@ -424,7 +420,7 @@ void sandbox_Database_Load()
 }
 
 MUTATOR_HOOKFUNCTION(sandbox_PlayerCommand)
-{
+{SELFPARAM();
        if(MUTATOR_RETURNVALUE) // command was already handled?
                return false;
        if(cmd_name == "g_sandbox")
@@ -502,7 +498,7 @@ MUTATOR_HOOKFUNCTION(sandbox_PlayerCommand)
                                }
 
                                e = sandbox_ObjectSpawn(false);
-                               setmodel(e, argv(2));
+                               _setmodel(e, argv(2));
 
                                if(autocvar_g_sandbox_info > 0)
                                        LOG_INFO(strcat("^3SANDBOX - SERVER: ^7", self.netname, " spawned an object at origin ^3", vtos(e.origin), "\n"));
diff --git a/qcsrc/server/pathlib.qc b/qcsrc/server/pathlib.qc
deleted file mode 100644 (file)
index a563a02..0000000
+++ /dev/null
@@ -1,973 +0,0 @@
-#include "pathlib.qh"
-#include "_all.qh"
-
-#define medium spawnshieldtime
-
-//#define DEBUGPATHING
-#ifdef DEBUGPATHING
-float edge_show(vector point,float fsize);
-void mark_error(vector where,float lifetime);
-void mark_info(vector where,float lifetime);
-entity mark_misc(vector where,float lifetime);
-
-void pathlib_showpath(entity start)
-{
-    entity e;
-    e = start;
-    while(e.path_next)
-    {
-        te_lightning1(e,e.origin,e.path_next.origin);
-        e = e.path_next;
-    }
-}
-
-void path_dbg_think()
-{
-    pathlib_showpath(self);
-    self.nextthink = time + 1;
-}
-
-void __showpath2_think()
-{
-    mark_info(self.origin,1);
-    if(self.path_next)
-    {
-        self.path_next.think     = __showpath2_think;
-        self.path_next.nextthink = time + 0.15;
-    }
-    else
-    {
-        self.owner.think     = __showpath2_think;
-        self.owner.nextthink = time + 0.15;
-    }
-}
-
-void pathlib_showpath2(entity path)
-{
-    path.think     = __showpath2_think;
-    path.nextthink = time;
-}
-
-#endif
-
-void pathlib_deletepath(entity start)
-{
-    entity e;
-
-    e = findchainentity(owner, start);
-    while(e)
-    {
-        e.think = SUB_Remove;
-        e.nextthink = time;
-        e = e.chain;
-    }
-}
-
-float  walknode_stepsize;
-vector walknode_stepup;
-vector walknode_maxdrop;
-vector walknode_boxup;
-vector walknode_boxmax;
-vector walknode_boxmin;
-float  pathlib_movenode_goodnode;
-
-float floor_ok(vector point)
-{
-    float pc;
-
-    if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
-        return 0;
-
-    pc = pointcontents(point);
-
-    switch(pc)
-    {
-        case CONTENT_SOLID:
-        case CONTENT_SLIME:
-        case CONTENT_LAVA:
-        case CONTENT_SKY:
-            return 0;
-        case CONTENT_EMPTY:
-            if(pointcontents(point - '0 0 1') != CONTENT_SOLID)
-                return 0;
-            break;
-        case CONTENT_WATER:
-            return 1;
-    }
-    if(pointcontents(point - '0 0 1') == CONTENT_SOLID)
-        return 1;
-
-    return 0;
-}
-
-#define _pcheck(p) traceline(p+z_up,p-z_down,MOVE_WORLDONLY,self); if (!floor_ok(trace_endpos)) return 1
-float edge_check(vector point,float fsize)
-{
-    vector z_up,z_down;
-
-    z_up   = '0 0 1' * fsize;
-    z_down = '0 0 1' * fsize;
-
-    _pcheck(point + ('1 1 0'  * fsize));
-    _pcheck(point + ('1 -1 0'  * fsize));
-    _pcheck(point + ('1 0 0' * fsize));
-
-    _pcheck(point + ('0 1 0'  * fsize));
-    _pcheck(point + ('0 -1 0' * fsize));
-
-    _pcheck(point + ('-1 0 0'  * fsize));
-    _pcheck(point + ('-1 1 0'  * fsize));
-    _pcheck(point + ('-1 -1 0' * fsize));
-
-    return 0;
-}
-
-#ifdef DEBUGPATHING
-#define _pshow(p) mark_error(p,10)
-float edge_show(vector point,float fsize)
-{
-
-    _pshow(point + ('1 1 0'  * fsize));
-    _pshow(point + ('1 -1 0' * fsize));
-    _pshow(point + ('1 0 0'  * fsize));
-
-    _pshow(point + ('0 1 0'  * fsize));
-    _pshow(point + ('0 -1 0' * fsize));
-
-    _pshow(point + ('-1 0 0'  * fsize));
-    _pshow(point + ('-1 1 0'  * fsize));
-    _pshow(point + ('-1 -1 0' * fsize));
-
-    return 0;
-}
-#endif
-
-var vector pathlib_movenode(vector start,vector end,float doedge);
-vector pathlib_wateroutnode(vector start,vector end,float doedge)
-{
-    vector surface;
-
-    pathlib_movenode_goodnode = 0;
-
-    end.x = fsnap(end.x, pathlib_gridsize);
-    end.y = fsnap(end.y, pathlib_gridsize);
-
-    traceline(end + ('0 0 0.25' * pathlib_gridsize),end - ('0 0 1' * pathlib_gridsize),MOVE_WORLDONLY,self);
-    end = trace_endpos;
-
-    if(pointcontents(end - '0 0 1') != CONTENT_SOLID)
-        return end;
-
-    for(surface = start ; surface.z < (end.z + 32); ++surface.z)
-    {
-        if(pointcontents(surface) == CONTENT_EMPTY)
-            break;
-    }
-
-    if(pointcontents(surface + '0 0 1') != CONTENT_EMPTY)
-        return end;
-
-    tracebox(start + '0 0 64', walknode_boxmin,walknode_boxmax, end + '0 0 64', MOVE_WORLDONLY, self);
-    if(trace_fraction == 1)
-        pathlib_movenode_goodnode = 1;
-
-    if(fabs(surface.z - end.z) > 32)
-        pathlib_movenode_goodnode = 0;
-
-    return end;
-}
-
-vector pathlib_swimnode(vector start,vector end,float doedge)
-{
-    pathlib_movenode_goodnode = 0;
-
-    if(pointcontents(start) != CONTENT_WATER)
-        return end;
-
-    end.x = fsnap(end.x, pathlib_gridsize);
-    end.y = fsnap(end.y, pathlib_gridsize);
-
-    if(pointcontents(end) == CONTENT_EMPTY)
-        return pathlib_wateroutnode( start, end, doedge);
-
-    tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
-    if(trace_fraction == 1)
-        pathlib_movenode_goodnode = 1;
-
-    return end;
-}
-
-vector pathlib_flynode(vector start,vector end)
-{
-    pathlib_movenode_goodnode = 0;
-
-    end.x = fsnap(end.x, pathlib_gridsize);
-    end.y = fsnap(end.y, pathlib_gridsize);
-
-    tracebox(start, walknode_boxmin,walknode_boxmax, end, MOVE_WORLDONLY, self);
-    if(trace_fraction == 1)
-        pathlib_movenode_goodnode = 1;
-
-    return end;
-}
-
-vector pathlib_walknode(vector start,vector end,float doedge)
-{
-    vector direction,point,last_point,s,e;
-    float steps, distance, i,laststep;
-
-    pathlib_movenode_goodnode = 0;
-
-    s   = start;
-    e   = end;
-    e.z = 0;
-    s.z = 0;
-    direction  = normalize(s - e);
-
-    distance    = vlen(start - end);
-    laststep    = distance / walknode_stepsize;
-    steps       = floor(laststep);
-    laststep    = laststep - steps;
-
-    point = start;
-    s     = point + walknode_stepup;
-    e     = point - walknode_maxdrop;
-
-    traceline(s, e,MOVE_WORLDONLY,self);
-    if(trace_fraction == 1.0)
-        return trace_endpos;
-
-    if (floor_ok(trace_endpos) == 0)
-        return trace_endpos;
-
-    last_point = trace_endpos;
-
-    for(i = 0; i < steps; ++i)
-    {
-        point = last_point + direction * walknode_stepsize;
-
-        s = point + walknode_stepup;
-        e = point - walknode_maxdrop;
-        traceline(s, e,MOVE_WORLDONLY,self);
-        if(trace_fraction == 1.0)
-            return trace_endpos;
-
-        point = trace_endpos;
-        if (!floor_ok(trace_endpos))
-            return trace_endpos;
-
-        tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
-        if(trace_fraction != 1.0)
-            return trace_endpos;
-
-        if(doedge)
-        if(edge_check(point,pathlib_edge_check_size))
-            return trace_endpos;
-
-        last_point = point;
-    }
-
-    point = last_point + direction * walknode_stepsize * laststep;
-
-    point.x = fsnap(point.x, pathlib_gridsize);
-    point.y = fsnap(point.y, pathlib_gridsize);
-
-    s = point + walknode_stepup;
-    e = point - walknode_maxdrop;
-    traceline(s, e,MOVE_WORLDONLY,self);
-
-    if(trace_fraction == 1.0)
-        return trace_endpos;
-
-    point = trace_endpos;
-
-    if (!floor_ok(trace_endpos))
-        return trace_endpos;
-
-    tracebox(last_point + walknode_boxup, walknode_boxmin,walknode_boxmax, point + walknode_boxup, MOVE_WORLDONLY, self);
-    if(trace_fraction != 1.0)
-        return trace_endpos;
-
-    pathlib_movenode_goodnode = 1;
-    return point;
-}
-
-var float pathlib_cost(entity parent,vector to, float static_cost);
-float pathlib_g_static(entity parent,vector to, float static_cost)
-{
-    if(inwater(to))
-        return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
-    else
-        return parent.pathlib_node_g + static_cost;
-}
-
-float pathlib_g_static_water(entity parent,vector to, float static_cost)
-{
-    if(inwater(to))
-        return parent.pathlib_node_g + static_cost * pathlib_movecost_waterfactor;
-    else
-        return parent.pathlib_node_g + static_cost;
-}
-
-float pathlib_g_euclidean(entity parent,vector to, float static_cost)
-{
-    return parent.pathlib_node_g + vlen(parent.origin - to);
-}
-float pathlib_g_euclidean_water(entity parent,vector to, float static_cost)
-{
-    if(inwater(to))
-        return parent.pathlib_node_g + vlen(parent.origin - to) * pathlib_movecost_waterfactor;
-    else
-        return parent.pathlib_node_g + vlen(parent.origin - to);
-}
-
-var float(vector from,vector to) pathlib_heuristic;
-
-/**
-    Manhattan Menas we expect to move up,down left or right
-    No diagonal moves espected. (like moving bewteen city blocks)
-**/
-float pathlib_h_manhattan(vector a,vector b)
-{
-    //h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
-
-    float h;
-    h  = fabs(a.x - b.x);
-    h += fabs(a.y - b.y);
-    h *= pathlib_gridsize;
-
-    return h;
-}
-
-/**
-    This heuristic consider both stright and disagonal moves
-    to have teh same cost.
-**/
-float pathlib_h_diagonal(vector a,vector b)
-{
-    //h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
-    float h,x,y;
-
-    x = fabs(a.x - b.x);
-    y = fabs(a.y - b.y);
-    h = pathlib_movecost * max(x,y);
-
-    return h;
-}
-
-/**
-    This heuristic only considers the stright line distance.
-    Will usualy mean a lower H then G meaning A* Will speand more
-    and run slower.
-**/
-float pathlib_h_euclidean(vector a,vector b)
-{
-    return vlen(a - b);
-}
-
-/**
-    This heuristic consider both stright and disagonal moves,
-    But has a separate cost for diagonal moves.
-**/
-float pathlib_h_diagonal2(vector a,vector b)
-{
-    float h_diag,h_str,h,x,y;
-
-    /*
-    h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
-    h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
-    h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
-    */
-
-    x = fabs(a.x - b.x);
-    y = fabs(a.y - b.y);
-
-    h_diag = min(x,y);
-    h_str = x + y;
-
-    h =  pathlib_movecost_diag * h_diag;
-    h += pathlib_movecost * (h_str - 2 * h_diag);
-
-    return h;
-}
-
-/**
-    This heuristic consider both stright and disagonal moves,
-    But has a separate cost for diagonal moves.
-
-
-**/
-float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
-{
-    float h_diag,h_str,h,x,y,z;
-
-    //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
-    //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
-    //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
-
-    x = fabs(point.x - end.x);
-    y = fabs(point.y - end.y);
-    z = fabs(point.z - end.z);
-
-    h_diag = min3(x,y,z);
-    h_str = x + y + z;
-
-    h =  pathlib_movecost_diag * h_diag;
-    h += pathlib_movecost * (h_str - 2 * h_diag);
-
-    float m;
-    vector d1,d2;
-
-    d1 = normalize(preprev - point);
-    d2 = normalize(prev    - point);
-    m = vlen(d1-d2);
-    //bprint("pathlib_h_diagonal2sdp-M = ",ftos(m),"\n");
-
-    return h * m;
-}
-
-
-float pathlib_h_diagonal3(vector a,vector b)
-{
-    float h_diag,h_str,h,x,y,z;
-
-    //h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
-    //h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
-    //h(n) = D2 * h_diagonal(n) + D * (h_straight(n) - 2*h_diagonal(n)))
-
-    x = fabs(a.x - b.x);
-    y = fabs(a.y - b.y);
-    z = fabs(a.z - b.z);
-
-    h_diag = min3(x,y,z);
-    h_str = x + y + z;
-
-    h =  pathlib_movecost_diag * h_diag;
-    h += pathlib_movecost * (h_str - 2 * h_diag);
-
-    return h;
-}
-
-const float PATHLIB_NODEEXPIRE = 0.05;
-float pathlib_scraplist_cnt;
-entity newnode()
-{
-    entity n;
-#ifdef PATHLIB_USE_NODESCRAP
-    if(pathlib_scraplist_cnt)
-    {
-        n = findentity(world,owner,scraplist);
-        if(n)
-        {
-            --pathlib_scraplist_cnt;
-            ++pathlib_recycle_cnt;
-            return n;
-        }
-        else
-            pathlib_scraplist_cnt = 0;
-    }
-#endif
-    ++pathlib_made_cnt;
-    n = spawn();
-    n.think      = SUB_Remove;
-    n.nextthink  = time + PATHLIB_NODEEXPIRE;
-    return n;
-}
-
-void dumpnode(entity n)
-{
-#ifdef PATHLIB_USE_NODESCRAP
-    ++pathlib_scraplist_cnt;
-
-    n.path_next    = world;
-    n.path_prev    = world;
-    n.is_path_node = false;
-    n.owner        = scraplist;
-#else
-    //n.is_path_node = false;
-    n.think        = SUB_Remove;
-    n.nextthink    = time;
-#endif
-}
-
-entity pathlib_mknode(vector where,entity parent)
-{
-    entity node;
-
-    node              = newnode();
-    node.is_path_node = true;
-    node.owner        = openlist;
-    node.path_prev    = parent;
-
-    setorigin(node, where);
-
-    ++pathlib_open_cnt;
-
-    node.medium = pointcontents(where);
-
-    return node;
-}
-
-var float pathlib_expandnode(entity node, vector start, vector goal);
-float pathlib_expandnode_star(entity node, vector start, vector goal);
-float pathlib_expandnode_box(entity node, vector start, vector goal);
-
-var float pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
-float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector goal,float cost)
-{
-    entity node;
-    float h,g,f,doedge;
-    vector where;
-
-    ++pathlib_searched_cnt;
-
-    if(inwater(parent.origin))
-    {
-        pathlib_expandnode = pathlib_expandnode_box;
-        pathlib_movenode   = pathlib_swimnode;
-       doedge = 0;
-    }
-    else
-    {
-        if(inwater(to))
-        {
-            pathlib_expandnode = pathlib_expandnode_box;
-            pathlib_movenode   = pathlib_swimnode;
-           doedge = 0;
-        }
-        else
-        {
-
-            pathlib_expandnode = pathlib_expandnode_star;
-            pathlib_movenode   = pathlib_walknode;
-            doedge = 1;
-        }
-    }
-
-    where = pathlib_movenode(parent.origin,to,0);
-    if (!pathlib_movenode_goodnode)
-        return 0;
-
-    if(doedge)
-    if(edge_check(where,pathlib_edge_check_size))
-        return 0;
-
-    if(parent.path_prev)
-        pathlib_h_diagonal2sdp(parent.path_prev.origin,parent.origin,where,goal);
-
-    h = pathlib_heuristic(where,goal);
-    g = pathlib_cost(parent,where,cost);
-    f = g + h;
-
-    node = findradius(where,pathlib_gridsize * 0.75);
-    while(node)
-    {
-        if(node.is_path_node == true)
-        {
-            ++pathlib_merge_cnt;
-            if(node.owner == openlist)
-            {
-                if(node.pathlib_node_g > g)
-                {
-                    node.pathlib_node_h = h;
-                    node.pathlib_node_g = g;
-                    node.pathlib_node_f = f;
-                    node.path_prev = parent;
-                }
-
-                if (!best_open_node)
-                    best_open_node = node;
-                else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
-                    best_open_node = node;
-            }
-
-            return 1;
-        }
-        node = node.chain;
-    }
-
-    node = pathlib_mknode(where,parent);
-    node.pathlib_node_h = h;
-    node.pathlib_node_g = g;
-    node.pathlib_node_f = f;
-
-    if (!best_open_node)
-        best_open_node = node;
-    else if(best_open_node.pathlib_node_f > node.pathlib_node_f)
-        best_open_node = node;
-
-    return 1;
-}
-
-entity pathlib_getbestopen()
-{
-    entity node;
-    entity bestnode;
-
-    if(best_open_node)
-    {
-        ++pathlib_bestcash_hits;
-        pathlib_bestcash_saved += pathlib_open_cnt;
-
-        return best_open_node;
-    }
-
-    node = findchainentity(owner,openlist);
-    if(!node)
-        return world;
-
-    bestnode = node;
-    while(node)
-    {
-        ++pathlib_bestopen_seached;
-        if(node.pathlib_node_f < bestnode.pathlib_node_f)
-            bestnode = node;
-
-        node = node.chain;
-    }
-
-    return bestnode;
-}
-
-void pathlib_close_node(entity node,vector goal)
-{
-
-    if(node.owner == closedlist)
-    {
-        LOG_TRACE("Pathlib: Tried to close a closed node!\n");
-        return;
-    }
-
-    if(node == best_open_node)
-        best_open_node = world;
-
-    ++pathlib_closed_cnt;
-    --pathlib_open_cnt;
-
-    node.owner = closedlist;
-
-    if(vlen(node.origin - goal) <= pathlib_gridsize)
-    {
-        vector goalmove;
-
-        goalmove = pathlib_walknode(node.origin,goal,1);
-        if(pathlib_movenode_goodnode)
-        {
-            goal_node         = node;
-            pathlib_foundgoal = true;
-        }
-    }
-}
-
-float pathlib_expandnode_star(entity node, vector start, vector goal)
-{
-    vector point;
-    vector where;
-    float nodecnt = 0;
-
-    where = node.origin;
-
-    v_forward = '1 0 0';
-    v_right   = '0 1 0';
-
-    // Forward
-    point = where + v_forward * pathlib_gridsize;
-    nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
-    // Back
-    point = where - v_forward * pathlib_gridsize;
-    nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
-    // Right
-    point = where + v_right * pathlib_gridsize;
-    nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
-    // Left
-    point = where - v_right * pathlib_gridsize;
-    nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost);
-
-    // Forward-right
-    point = where + v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
-    nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
-    // Forward-left
-    point = where + v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
-    nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
-    // Back-right
-    point = where - v_forward * pathlib_gridsize + v_right * pathlib_gridsize;
-    nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
-    // Back-left
-    point = where - v_forward * pathlib_gridsize - v_right * pathlib_gridsize;
-    nodecnt += pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
-
-    return pathlib_open_cnt;
-}
-
-float pathlib_expandnode_box(entity node, vector start, vector goal)
-{
-    vector v;
-
-    for(v.z = node.origin.z - pathlib_gridsize; v.z <= node.origin.z + pathlib_gridsize; v.z += pathlib_gridsize)
-    for(v.y = node.origin.y - pathlib_gridsize; v.y <= node.origin.y + pathlib_gridsize; v.y += pathlib_gridsize)
-    for(v.x = node.origin.x - pathlib_gridsize; v.x <= node.origin.x + pathlib_gridsize; v.x += pathlib_gridsize)
-    {
-        if(vlen(v - node.origin))
-            pathlib_makenode(node,start,v,goal,pathlib_movecost);
-    }
-
-    return pathlib_open_cnt;
-}
-
-void pathlib_cleanup()
-{
-    entity node;
-
-    node = findfloat(world,is_path_node, true);
-    while(node)
-    {
-        dumpnode(node);
-        node = findfloat(node,is_path_node, true);
-    }
-
-    if(openlist)
-        remove(openlist);
-
-    if(closedlist)
-        remove(closedlist);
-
-    best_open_node = world;
-    openlist       = world;
-    closedlist     = world;
-}
-
-var float buildpath_nodefilter(vector n,vector c,vector p);
-float buildpath_nodefilter_directional(vector n,vector c,vector p)
-{
-    vector d1,d2;
-
-    d2 = normalize(p - c);
-    d1 = normalize(c - n);
-
-    if(vlen(d1-d2) < 0.25)
-        return 1;
-
-    return 0;
-}
-
-float buildpath_nodefilter_moveskip(vector n,vector c,vector p)
-{
-    pathlib_walknode(p,n,1);
-    if(pathlib_movenode_goodnode)
-        return 1;
-
-    return 0;
-}
-
-entity path_build(entity next, vector where, entity prev, entity start)
-{
-    entity path;
-
-    if(prev && next)
-        if(buildpath_nodefilter)
-            if(buildpath_nodefilter(next.origin,where,prev.origin))
-                return next;
-
-
-    path           = spawn();
-    path.owner     = start;
-    path.path_next = next;
-
-    setorigin(path,where);
-
-    if(!next)
-        path.classname = "path_end";
-    else
-    {
-        if(!prev)
-            path.classname = "path_start";
-        else
-            path.classname = "path_node";
-    }
-
-    return path;
-}
-
-entity pathlib_astar(vector from,vector to)
-{
-    entity path, start, end, open, n, ln;
-    float ptime, ftime, ctime;
-
-    ptime = gettime(GETTIME_REALTIME);
-
-    pathlib_cleanup();
-
-    // Select water<->land capable node make/link
-    pathlib_makenode     = pathlib_makenode_adaptive;
-    // Select XYZ cost estimate
-    pathlib_heuristic    = pathlib_h_diagonal3;
-    // Select distance + waterfactor cost
-    pathlib_cost         = pathlib_g_euclidean_water;
-    // Select star expander
-    pathlib_expandnode   = pathlib_expandnode_star;
-    // Select walk simulation movement test
-    pathlib_movenode     = pathlib_walknode;
-    // Filter final nodes by direction
-    buildpath_nodefilter = buildpath_nodefilter_directional;
-
-    // If the start is in water we need diffrent settings
-    if(inwater(from))
-    {
-        // Select volumetric node expaner
-        pathlib_expandnode = pathlib_expandnode_box;
-
-        // Water movement test
-        pathlib_movenode   = pathlib_swimnode;
-    }
-
-    if (!openlist)
-        openlist       = spawn();
-
-    if (!closedlist)
-        closedlist     = spawn();
-
-    if (!scraplist)
-        scraplist      = spawn();
-
-    pathlib_closed_cnt       = 0;
-    pathlib_open_cnt         = 0;
-    pathlib_made_cnt         = 0;
-    pathlib_merge_cnt        = 0;
-    pathlib_searched_cnt     = 0;
-    pathlib_bestopen_seached = 0;
-    pathlib_bestcash_hits    = 0;
-    pathlib_bestcash_saved   = 0;
-    pathlib_recycle_cnt      = 0;
-
-    pathlib_gridsize       = 128;
-    pathlib_movecost       = pathlib_gridsize;
-    pathlib_movecost_diag  = vlen(('1 1 0' * pathlib_gridsize));
-    pathlib_movecost_waterfactor = 1.1;
-    pathlib_foundgoal      = 0;
-
-    walknode_boxmax   = self.maxs * 1.5;
-    walknode_boxmin   = self.mins * 1.5;
-
-    pathlib_edge_check_size = (vlen(walknode_boxmin - walknode_boxmax) * 0.5);
-
-    walknode_boxup    = '0 0 2' * self.maxs.z;
-    walknode_stepsize = 32;
-    walknode_stepup   = '0 0 1' * walknode_stepsize;
-    walknode_maxdrop  = '0 0 3' * walknode_stepsize;
-
-    from.x = fsnap(from.x,pathlib_gridsize);
-    from.y = fsnap(from.y,pathlib_gridsize);
-
-    to.x = fsnap(to.x,pathlib_gridsize);
-    to.y = fsnap(to.y,pathlib_gridsize);
-
-    LOG_TRACE("AStar init. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n");
-    path = pathlib_mknode(from,world);
-    pathlib_close_node(path,to);
-    if(pathlib_foundgoal)
-    {
-        LOG_TRACE("AStar: Goal found on first node!\n");
-
-        open           = spawn();
-        open.owner     = open;
-        open.classname = "path_end";
-        setorigin(open,path.origin);
-
-        pathlib_cleanup();
-
-        return open;
-    }
-
-    if(pathlib_expandnode(path,from,to) <= 0)
-    {
-        LOG_TRACE("AStar path fail.\n");
-        pathlib_cleanup();
-
-        return world;
-    }
-
-    best_open_node = pathlib_getbestopen();
-    n = best_open_node;
-    pathlib_close_node(best_open_node,to);
-    if(inwater(n.origin))
-        pathlib_expandnode_box(n,from,to);
-    else
-        pathlib_expandnode_star(n,from,to);
-
-    while(pathlib_open_cnt)
-    {
-        best_open_node = pathlib_getbestopen();
-        n = best_open_node;
-        pathlib_close_node(best_open_node,to);
-
-        if(inwater(n.origin))
-            pathlib_expandnode_box(n,from,to);
-        else
-            pathlib_expandnode(n,from,to);
-
-        if(pathlib_foundgoal)
-        {
-            LOG_TRACE("Target found. Rebuilding and filtering path...\n");
-            ftime = gettime(GETTIME_REALTIME);
-            ptime = ftime - ptime;
-
-            start = path_build(world,path.origin,world,world);
-            end   = path_build(world,goal_node.origin,world,start);
-            ln    = end;
-
-            open = goal_node;
-            for(open = goal_node; open.path_prev != path; open = open.path_prev)
-            {
-                n    = path_build(ln,open.origin,open.path_prev,start);
-                ln.path_prev = n;
-                ln = n;
-            }
-            start.path_next = n;
-            n.path_prev = start;
-            ftime = gettime(GETTIME_REALTIME) - ftime;
-
-            ctime = gettime(GETTIME_REALTIME);
-            pathlib_cleanup();
-            ctime = gettime(GETTIME_REALTIME) - ctime;
-
-
-#ifdef 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");
-
-        if(pathlib_recycle_cnt)
-            LOG_TRACE("Nodes -      make/reuse: ", ftos(pathlib_made_cnt / pathlib_recycle_cnt),"\n");
-        if(pathlib_recycle_cnt)
-            LOG_TRACE("Nodes -          reused: ", ftos(pathlib_recycle_cnt),"\n");
-
-            LOG_TRACE("Nodes bestopen searched: ", ftos(pathlib_bestopen_seached),"\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. ", ftos(pathlib_scraplist_cnt), " nodes on scrap\n\n");
-#endif
-            return start;
-        }
-    }
-
-    LOG_TRACE("A* Faild to find a path! Try a smaller gridsize.\n");
-
-    pathlib_cleanup();
-
-    return world;
-}
diff --git a/qcsrc/server/pathlib.qh b/qcsrc/server/pathlib.qh
deleted file mode 100644 (file)
index da4ae0c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef PATHLIB_H
-#define PATHLIB_H
-
-//#define PATHLIB_RDFIELDS
-#ifdef PATHLIB_RDFIELDS
-    #define path_next swampslug
-    #define path_prev lasertarget
-#else
-    .entity path_next;
-    .entity path_prev;
-#endif
-
-entity openlist;
-entity closedlist;
-entity scraplist;
-
-.float pathlib_node_g;
-.float pathlib_node_h;
-.float pathlib_node_f;
-
-float pathlib_open_cnt;
-float pathlib_closed_cnt;
-float pathlib_made_cnt;
-float pathlib_merge_cnt;
-float pathlib_recycle_cnt;
-float pathlib_searched_cnt;
-
-float pathlib_bestopen_seached;
-float pathlib_bestcash_hits;
-float pathlib_bestcash_saved;
-
-float pathlib_gridsize;
-
-float pathlib_movecost;
-float pathlib_movecost_diag;
-float pathlib_movecost_waterfactor;
-
-float pathlib_edge_check_size;
-
-float pathlib_foundgoal;
-entity goal_node;
-
-entity best_open_node;
-.float is_path_node;
-
-#define inwater(point) (pointcontents(point) == CONTENT_WATER)
-
-#endif
index 878e8fd5b113fda6f8e03a6fb6f2b04521999d85..3e452f66e7dc02dbf2937410c44e08ba8684f95d 100644 (file)
@@ -1,4 +1,4 @@
-#include "../pathlib.qh"
+#include "pathlib.qh"
 
 float pathlib_g_static(entity parent,vector to, float static_cost)
 {
index 5c97cf7ac41575adba77f604d88399f000597d95..37e167aae71064e0b87c927aaf8f730058b92e0b 100644 (file)
@@ -1,4 +1,9 @@
-#include "../pathlib.qh"
+#include "pathlib.qh"
+
+MODEL(SQUARE,       "models/pathlib/square.md3");
+MODEL(SQUARE_GOOD,  "models/pathlib/goodsquare.md3");
+MODEL(SQUARE_BAD,   "models/pathlib/badsquare.md3");
+MODEL(EDGE,         "models/pathlib/edge.md3");
 
 #ifdef TURRET_DEBUG
 void mark_error(vector where,float lifetime);
@@ -18,13 +23,13 @@ void pathlib_showpath(entity start)
 }
 
 void path_dbg_think()
-{
+{SELFPARAM();
     pathlib_showpath(self);
     self.nextthink = time + 1;
 }
 
 void __showpath2_think()
-{
+{SELFPARAM();
     #ifdef TURRET_DEBUG
        mark_info(self.origin,1);
        #endif
@@ -54,7 +59,7 @@ void pathlib_showsquare2(entity node ,vector ncolor,float align)
     node.scale     = pathlib_gridsize / 512.001;
     node.solid     = SOLID_NOT;
 
-    setmodel(node,"models/pathlib/square.md3");
+    setmodel(node, MDL_SQUARE);
     setorigin(node,node.origin);
     node.colormod = ncolor;
 
@@ -84,12 +89,7 @@ void pathlib_showsquare(vector where,float goodsquare,float _lifetime)
     s.scale     = pathlib_gridsize / 512.001;
     s.solid     = SOLID_NOT;
 
-    if(goodsquare)
-        setmodel(s,"models/pathlib/goodsquare.md3");
-    else
-        setmodel(s,"models/pathlib/badsquare.md3");
-
-
+    setmodel(s, goodsquare ? MDL_SQUARE_GOOD : MDL_SQUARE_BAD);
 
     traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,s);
 
@@ -114,7 +114,7 @@ void pathlib_showedge(vector where,float _lifetime,float rot)
     e.scale     = pathlib_gridsize / 512;
     e.solid     = SOLID_NOT;
     setorigin(e,where);
-    setmodel(e,"models/pathlib/edge.md3");
+    setmodel(e, MDL_EDGE);
     //traceline(where + '0 0 32',where - '0 0 128',MOVE_WORLDONLY,e);
     //e.angles = vectoangles(trace_plane_normal);
     e.angles_y = rot;
index 39847f635d220661cf60c9caa56f57f87b06169f..f097e8a0fec8199dabff0c0501307ab768bfe703 100644 (file)
@@ -370,7 +370,7 @@ entity path_build(entity next, vector where, entity prev, entity start)
 }
 
 entity pathlib_astar(vector from,vector to)
-{
+{SELFPARAM();
     entity path, start, end, open, n, ln;
     float ptime, ftime, ctime;
 
index 8720eca8b7fdf4198ffededf425784cce73de41e..6645d712661d9a08e5c95be125f41073d526f783 100644 (file)
@@ -4,7 +4,7 @@
 #include "utility.qh"
 
 vector pathlib_wateroutnode(vector start,vector end, float doedge)
-{
+{SELFPARAM();
     vector surface;
 
     pathlib_movenode_goodnode = 0;
@@ -38,7 +38,7 @@ vector pathlib_wateroutnode(vector start,vector end, float doedge)
 }
 
 vector pathlib_swimnode(vector start,vector end, float doedge)
-{
+{SELFPARAM();
     pathlib_movenode_goodnode = 0;
 
     if(pointcontents(start) != CONTENT_WATER)
@@ -58,7 +58,7 @@ vector pathlib_swimnode(vector start,vector end, float doedge)
 }
 
 vector pathlib_flynode(vector start,vector end, float doedge)
-{
+{SELFPARAM();
     pathlib_movenode_goodnode = 0;
 
     end.x = fsnap(end.x, pathlib_gridsize);
@@ -72,7 +72,7 @@ vector pathlib_flynode(vector start,vector end, float doedge)
 }
 
 void a_think()
-{
+{SELFPARAM();
     te_lightning1(self,self.origin, self.pos1);
     if(self.cnt < time)
         remove(self);
@@ -81,7 +81,7 @@ void a_think()
 }
 
 vector pathlib_walknode(vector start,vector end,float doedge)
-{
+{SELFPARAM();
     vector direction,point,last_point,s,e;
     float steps, distance, i;
 
index 7dee3e80f6154d6980061635f280b50b34c2dcf4..4c3a7a1aadb70153b8918a330851467e74d19b1c 100644 (file)
@@ -234,7 +234,7 @@ entity pathlib_waypointpath_step()
     return world;
 }
 void plas_think()
-{
+{SELFPARAM();
     pathlib_waypointpath_step();
     if(pathlib_foundgoal)
         return;
index ce12c1c631fed9bf994d4ace53a176cf776d540a..9028f85e4f8be3ab4d65a21656634151522ecb4f 100644 (file)
@@ -72,7 +72,7 @@ entity pathlib_nodeatpoint(vector where)
 }
 
 float tile_check_cross(vector where)
-{
+{SELFPARAM();
     vector p,f,r;
 
     f = PLIB_FORWARD * tile_check_size;
@@ -107,7 +107,7 @@ float tile_check_cross(vector where)
 }
 
 float tile_check_plus(vector where)
-{
+{SELFPARAM();
     vector p,f,r;
 
     f = PLIB_FORWARD * tile_check_size;
@@ -142,7 +142,7 @@ float tile_check_plus(vector where)
 }
 
 float tile_check_plus2(vector where)
-{
+{SELFPARAM();
     vector p,f,r;
     float i = 0, e = 0;
 
index 2450d5865108112767fc15caebd10e8dd9102c0a..b21ed2ea37ef988c03ca9363462ad38738ee84b2 100644 (file)
@@ -15,11 +15,11 @@ const float PLAYERDEMO_MODE_OFF = 0;
 const float PLAYERDEMO_MODE_READING = 1;
 const float PLAYERDEMO_MODE_WRITING = 2;
 void playerdemo_init()
-{
+{SELFPARAM();
        self.playerdemo_mode = PLAYERDEMO_MODE_OFF;
 }
 void playerdemo_shutdown()
-{
+{SELFPARAM();
        if(self.playerdemo_mode != PLAYERDEMO_MODE_OFF)
        {
                LOG_INFO("playerdemo: ", self.netname, " closed\n");
@@ -28,7 +28,7 @@ void playerdemo_shutdown()
        self.playerdemo_mode = 0;
 }
 void playerdemo_open_read(string f)
-{
+{SELFPARAM();
        playerdemo_shutdown();
        self.playerdemo_mode = PLAYERDEMO_MODE_READING;
        self.playerdemo_fh = fopen(f, FILE_READ);
@@ -39,7 +39,7 @@ void playerdemo_open_read(string f)
        LOG_INFO("playerdemo: ", self.netname, " reading from ", f, "\n");
 }
 void playerdemo_open_write(string f)
-{
+{SELFPARAM();
        playerdemo_shutdown();
        self.playerdemo_mode = PLAYERDEMO_MODE_WRITING;
        self.playerdemo_fh = fopen(f, FILE_WRITE);
@@ -70,51 +70,51 @@ void playerdemo_open_write(string f)
        // end of list
 
 void playerdemo_write_originvector(.vector f, string name)
-{
+{SELFPARAM();
        fputs(self.playerdemo_fh, strcat(vtos(self.(f)), "\n"));
 }
 void playerdemo_write_sizevector(.vector f, string name)
-{
+{SELFPARAM();
        fputs(self.playerdemo_fh, strcat(vtos(self.(f)), "\n"));
 }
 void playerdemo_write_vector(.vector f, string name)
-{
+{SELFPARAM();
        fputs(self.playerdemo_fh, strcat(vtos(self.(f)), "\n"));
 }
 void playerdemo_write_string(.string f, string name)
-{
+{SELFPARAM();
        fputs(self.playerdemo_fh, strcat(self.(f), "\n"));
 }
 void playerdemo_write_modelstring(.string f, string name)
-{
+{SELFPARAM();
        fputs(self.playerdemo_fh, strcat(self.(f), "\n"));
 }
 void playerdemo_write_float(.float f, string name)
-{
+{SELFPARAM();
        fputs(self.playerdemo_fh, strcat(ftos(self.(f)), "\n"));
 }
 void playerdemo_write()
-{
+{SELFPARAM();
        if(self.playerdemo_mode != PLAYERDEMO_MODE_WRITING)
                return;
        fputs(self.playerdemo_fh, strcat(ftos(time - self.playerdemo_starttime), "\n"));
        PLAYERDEMO_FIELDS(playerdemo_write_)
 }
 void playerdemo_read_originvector(.vector f, string name)
-{
+{SELFPARAM();
        setorigin(self, stov(fgets(self.playerdemo_fh)));
 }
 void playerdemo_read_sizevector(.vector f, string name)
-{
+{SELFPARAM();
        self.(f) = stov(fgets(self.playerdemo_fh));
        setsize(self, self.mins, self.maxs);
 }
 void playerdemo_read_vector(.vector f, string name)
-{
+{SELFPARAM();
        self.(f) = stov(fgets(self.playerdemo_fh));
 }
 void playerdemo_read_string(.string f, string name)
-{
+{SELFPARAM();
        string s = fgets(self.playerdemo_fh);
        if (s != self.(f))
        {
@@ -126,17 +126,17 @@ void playerdemo_read_string(.string f, string name)
        }
 }
 void playerdemo_read_modelstring(.string f, string name)
-{
+{SELFPARAM();
        string s = fgets(self.playerdemo_fh);
        if (s != self.(f))
-               setmodel(self, s);
+               _setmodel(self, s);
 }
 void playerdemo_read_float(.float f, string name)
-{
+{SELFPARAM();
        self.(f) = stof(fgets(self.playerdemo_fh));
 }
 float playerdemo_read()
-{
+{SELFPARAM();
        if(self.playerdemo_mode != PLAYERDEMO_MODE_READING)
                return 0;
        if(self.playerdemo_time < 0)
index 09cd6e9d20810481f2adb9dceb18d16271ee5927..30fa073849d9f9b5827a050a5b269ce1b7269b03 100644 (file)
@@ -248,7 +248,7 @@ float Portal_WillHitPlane(vector eorg, vector emins, vector emaxs, vector evel,
 }
 
 void Portal_Touch()
-{
+{SELFPARAM();
        vector g;
 
 #ifdef PORTALS_ARE_NOT_SOLID
@@ -414,20 +414,20 @@ void Portal_Remove(entity portal, float killed)
        if(killed)
        {
                fixedmakevectors(portal.mangle);
-               sound(portal, CH_SHOTS, "porto/explode.wav", VOL_BASE, ATTEN_NORM);
+               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);
        }
        else
        {
                Portal_MakeBrokenPortal(portal);
-               sound(portal, CH_SHOTS, "porto/expire.wav", VOL_BASE, ATTEN_NORM);
+               sound(portal, CH_SHOTS, SND_PORTO_EXPIRE, VOL_BASE, ATTEN_NORM);
                SUB_SetFade(portal, time, 0.5);
        }
 }
 
 void Portal_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{
+{SELFPARAM();
        if(deathtype == DEATH_TELEFRAG)
                return;
        if(attacker != self.aiment)
@@ -439,7 +439,7 @@ void Portal_Damage(entity inflictor, entity attacker, float damage, int deathtyp
 }
 
 void Portal_Think_TryTeleportPlayer(entity e, vector g)
-{
+{SELFPARAM();
        if(!Portal_WillHitPlane(e.origin, e.mins, e.maxs, e.velocity + g, self.origin, v_forward, self.maxs.x))
                return;
 
@@ -451,7 +451,7 @@ void Portal_Think_TryTeleportPlayer(entity e, vector g)
 }
 
 void Portal_Think()
-{
+{SELFPARAM();
        entity e, o;
        vector g;
 
@@ -494,7 +494,7 @@ void Portal_Think()
 }
 
 float Portal_Customize()
-{
+{SELFPARAM();
        if(IS_SPEC(other))
                other = other.enemy;
        if(other == self.aiment)
@@ -574,7 +574,7 @@ void Portal_ClearAll(entity own)
        W_Porto_Remove(own);
 }
 void Portal_RemoveLater_Think()
-{
+{SELFPARAM();
        Portal_Remove(self, self.cnt);
 }
 void Portal_RemoveLater(entity portal, float kill)
@@ -636,7 +636,7 @@ entity Portal_Spawn(entity own, vector org, vector ang)
        portal.event_damage = Portal_Damage;
        portal.fade_time = time + autocvar_g_balance_portal_lifetime;
        portal.health = autocvar_g_balance_portal_health;
-       setmodel(portal, "models/portal.md3");
+       setmodel(portal, MDL_PORTAL);
        portal.savemodelindex = portal.modelindex;
        portal.customizeentityforclient = Portal_Customize;
 
diff --git a/qcsrc/server/progs.inc b/qcsrc/server/progs.inc
new file mode 100644 (file)
index 0000000..adb8cf6
--- /dev/null
@@ -0,0 +1,125 @@
+#include "../common/util-pre.qh"
+#include "sys-pre.qh"
+#include "../dpdefs/progsdefs.qh"
+#include "../dpdefs/dpextensions.qh"
+#include "sys-post.qh"
+#include "../common/util-post.qh"
+
+#include "../lib/_all.inc"
+
+#include "anticheat.qc"
+#include "antilag.qc"
+#include "campaign.qc"
+#include "cheats.qc"
+#include "cl_client.qc"
+#include "cl_impulse.qc"
+#include "cl_player.qc"
+#include "controlpoint.qc"
+#include "csqceffects.qc"
+#include "ent_cs.qc"
+#include "g_damage.qc"
+#include "g_hook.qc"
+// #include "g_lights.qc" // TODO: was never used
+#include "g_models.qc"
+#include "g_subs.qc"
+#include "g_violence.qc"
+#include "g_world.qc"
+#include "generator.qc"
+#include "ipban.qc"
+#include "item_key.qc"
+#include "mapvoting.qc"
+#include "miscfunctions.qc"
+#include "movelib.qc"
+#include "playerdemo.qc"
+#include "portals.qc"
+#include "race.qc"
+#include "round_handler.qc"
+#include "scores.qc"
+#include "scores_rules.qc"
+#include "spawnpoints.qc"
+#include "steerlib.qc"
+#include "sv_main.qc"
+#include "teamplay.qc"
+#include "t_halflife.qc"
+#include "t_items.qc"
+#include "t_quake3.qc"
+#include "t_quake.qc"
+
+#include "bot/aim.qc"
+#include "bot/bot.qc"
+#include "bot/navigation.qc"
+#include "bot/scripting.qc"
+#include "bot/waypoints.qc"
+
+#include "bot/havocbot/havocbot.qc"
+#include "bot/havocbot/role_keyhunt.qc"
+#include "bot/havocbot/roles.qc"
+
+#include "command/all.qc"
+
+#include "mutators/mutators_include.qc"
+#include "mutators/mutators.qc"
+
+#include "pathlib/costs.qc"
+#include "pathlib/expandnode.qc"
+#include "pathlib/main.qc"
+#include "pathlib/movenode.qc"
+#include "pathlib/path_waypoint.qc"
+#include "pathlib/utility.qc"
+
+#include "weapons/accuracy.qc"
+#include "weapons/common.qc"
+#include "weapons/csqcprojectile.qc" // TODO
+#include "weapons/hitplot.qc"
+#include "weapons/selection.qc"
+#include "weapons/spawning.qc"
+#include "weapons/throwing.qc"
+#include "weapons/tracing.qc"
+#include "weapons/weaponstats.qc"
+#include "weapons/weaponsystem.qc"
+
+#include "../common/animdecide.qc"
+#include "../common/campaign_file.qc"
+#include "../common/campaign_setup.qc"
+#include "../common/effects/effects.qc"
+#include "../common/effects/effectinfo.qc"
+#include "../common/mapinfo.qc"
+#include "../common/monsters/spawn.qc"
+#include "../common/monsters/sv_monsters.qc"
+#include "../common/minigames/minigames.qc"
+#include "../common/minigames/sv_minigames.qc"
+#include "../common/movetypes/include.qc"
+#include "../common/net_notice.qc"
+#include "../common/notifications.qc"
+#include "../common/physics.qc"
+#include "../common/playerstats.qc"
+#include "../common/viewloc.qc"
+#include "../common/triggers/include.qc"
+#include "../common/util.qc"
+
+#include "../common/buffs/all.qc"
+#include "../common/items/all.qc"
+#include "../common/monsters/all.qc"
+#include "../common/mutators/all.qc"
+#include "../common/nades/all.qc"
+#include "../common/turrets/all.qc"
+#include "../common/vehicles/all.qc"
+#include "../common/weapons/all.qc"
+
+#include "../common/turrets/sv_turrets.qc"
+#include "../common/turrets/config.qc"
+#include "../common/turrets/util.qc"
+#include "../common/turrets/checkpoint.qc"
+#include "../common/turrets/targettrigger.qc"
+#include "../common/weapons/config.qc"
+
+#include "../csqcmodellib/sv_model.qc"
+
+#include "../warpzonelib/anglestransform.qc"
+#include "../warpzonelib/common.qc"
+#include "../warpzonelib/server.qc"
+#include "../warpzonelib/util_server.qc"
+
+#if BUILD_MOD
+#include "../../mod/server/progs.inc"
+#endif
index 22afdf4115d0f2b980107de653309720e4a68da5..9ba92b46ff271a9a2b86228b21f3dbe018b084aa 100644 (file)
@@ -1,125 +1,2 @@
 ../../progs.dat
-
-../common/util-pre.qh
-sys-pre.qh
-../dpdefs/progsdefs.qh
-../dpdefs/dpextensions.qh
-sys-post.qh
-../common/util-post.qh
-
-../lib/_all.inc
-
-anticheat.qc
-antilag.qc
-campaign.qc
-cheats.qc
-cl_client.qc
-cl_impulse.qc
-cl_player.qc
-controlpoint.qc
-csqceffects.qc
-ent_cs.qc
-g_damage.qc
-g_hook.qc
-// g_lights.qc // TODO: was never used
-g_models.qc
-g_subs.qc
-g_violence.qc
-g_world.qc
-generator.qc
-ipban.qc
-item_key.qc
-mapvoting.qc
-miscfunctions.qc
-movelib.qc
-// pathlib.qc // TODO: was never used. Seems to duplicate `pathlib/`
-playerdemo.qc
-portals.qc
-race.qc
-round_handler.qc
-scores.qc
-scores_rules.qc
-spawnpoints.qc
-steerlib.qc
-sv_main.qc
-teamplay.qc
-t_halflife.qc
-t_items.qc
-t_quake3.qc
-t_quake.qc
-
-bot/aim.qc
-bot/bot.qc
-bot/navigation.qc
-bot/scripting.qc
-bot/waypoints.qc
-
-bot/havocbot/havocbot.qc
-bot/havocbot/role_keyhunt.qc
-bot/havocbot/roles.qc
-
-command/all.qc
-
-mutators/mutators_include.qc
-mutators/mutators.qc
-
-pathlib/costs.qc
-pathlib/expandnode.qc
-pathlib/main.qc
-pathlib/movenode.qc
-pathlib/path_waypoint.qc
-pathlib/utility.qc
-
-weapons/accuracy.qc
-weapons/common.qc
-weapons/csqcprojectile.qc // TODO
-weapons/hitplot.qc
-weapons/selection.qc
-weapons/spawning.qc
-weapons/throwing.qc
-weapons/tracing.qc
-weapons/weaponstats.qc
-weapons/weaponsystem.qc
-
-../common/animdecide.qc
-../common/buffs.qc
-../common/campaign_file.qc
-../common/campaign_setup.qc
-../common/effects.qc
-../common/mapinfo.qc
-../common/monsters/spawn.qc
-../common/monsters/sv_monsters.qc
-../common/minigames/minigames.qc
-../common/minigames/sv_minigames.qc
-../common/movetypes/include.qc
-../common/nades.qc
-../common/net_notice.qc
-../common/notifications.qc
-../common/physics.qc
-../common/playerstats.qc
-../common/viewloc.qc
-../common/triggers/include.qc
-../common/util.qc
-
-../common/items/all.qc
-../common/monsters/all.qc
-../common/mutators/all.qc
-../common/vehicles/all.qc
-../common/weapons/all.qc // TODO
-
-../common/turrets/sv_turrets.qc
-../common/turrets/config.qc
-../common/turrets/util.qc
-../common/turrets/turrets.qc
-../common/turrets/checkpoint.qc
-../common/turrets/targettrigger.qc
-../common/weapons/config.qc
-
-../csqcmodellib/sv_model.qc
-
-../warpzonelib/anglestransform.qc
-../warpzonelib/common.qc
-../warpzonelib/server.qc
-../warpzonelib/util_server.qc
-
-../../mod/server/progs.inc
+progs.inc
index bffb221a24287bd4671ca615b7a12d2cd69b68e8..fbf1eaa185af29a2b6a5d3ab61b72410e6763e6c 100644 (file)
@@ -86,7 +86,7 @@ string race_readName(string map, float pos)
 
 const float MAX_CHECKPOINTS = 255;
 
-void spawnfunc_target_checkpoint();
+spawnfunc(target_checkpoint);
 
 .float race_penalty;
 .float race_penalty_accumulator;
@@ -569,7 +569,7 @@ void dumpsurface(entity e)
 }
 
 void checkpoint_passed()
-{
+{SELFPARAM();
        string oldmsg;
        entity cp;
 
@@ -577,7 +577,7 @@ void checkpoint_passed()
        {
                // do not allow portalling through checkpoints
                trace_plane_normal = normalize(-1 * other.velocity);
-               self = other;
+               setself(other);
                W_Porto_Fail(0);
                return;
        }
@@ -724,7 +724,7 @@ void checkpoint_use()
 }
 
 float race_waypointsprite_visible_for_player(entity e)
-{
+{SELFPARAM();
        if(e.race_checkpoint == -1 || self.owner.race_checkpoint == -2)
                return true;
        else if(e.race_checkpoint == self.owner.race_checkpoint)
@@ -735,8 +735,8 @@ float race_waypointsprite_visible_for_player(entity e)
 
 float have_verified;
 void trigger_race_checkpoint_verify()
-{
-       entity oldself, cp;
+{SELFPARAM();
+       entity cp;
        float i, p;
        float qual;
 
@@ -746,8 +746,7 @@ void trigger_race_checkpoint_verify()
 
        qual = g_race_qualifying;
 
-       oldself = self;
-       self = spawn();
+       setself(spawn());
        self.classname = "player";
 
        if(g_race)
@@ -895,11 +894,11 @@ void trigger_race_checkpoint_verify()
                                }
        }
        remove(self);
-       self = oldself;
+       setself(this);
 }
 
 vector trigger_race_checkpoint_spawn_evalfunc(entity player, entity spot, vector current)
-{
+{SELFPARAM();
        if(g_race_qualifying)
        {
                // spawn at first
@@ -930,7 +929,7 @@ vector trigger_race_checkpoint_spawn_evalfunc(entity player, entity spot, vector
        return current;
 }
 
-void spawnfunc_trigger_race_checkpoint()
+spawnfunc(trigger_race_checkpoint)
 {
        vector o;
        if(!g_race && !g_cts) { remove(self); return; }
@@ -978,7 +977,7 @@ void spawnfunc_trigger_race_checkpoint()
        InitializeEntity(self, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
 }
 
-void spawnfunc_target_checkpoint() // defrag entity
+spawnfunc(target_checkpoint) // defrag entity
 {
        vector o;
        if(!g_race && !g_cts) { remove(self); return; }
@@ -1019,8 +1018,8 @@ void spawnfunc_target_checkpoint() // defrag entity
        InitializeEntity(self, trigger_race_checkpoint_verify, INITPRIO_FINDTARGET);
 }
 
-void spawnfunc_target_startTimer() { spawnfunc_target_checkpoint(); }
-void spawnfunc_target_stopTimer() { spawnfunc_target_checkpoint(); }
+spawnfunc(target_startTimer) { spawnfunc_target_checkpoint(this); }
+spawnfunc(target_stopTimer) { spawnfunc_target_checkpoint(this); }
 
 void race_AbandonRaceCheck(entity p)
 {
@@ -1043,7 +1042,7 @@ void race_StartCompleting()
 }
 
 void race_PreparePlayer()
-{
+{SELFPARAM();
        race_ClearTime(self);
        self.race_place = 0;
        self.race_started = 0;
@@ -1052,7 +1051,7 @@ void race_PreparePlayer()
 }
 
 void race_RetractPlayer()
-{
+{SELFPARAM();
        if(!g_race && !g_cts)
                return;
        if(self.race_respawn_checkpoint == 0 || self.race_respawn_checkpoint == race_timed_checkpoint)
@@ -1060,11 +1059,11 @@ void race_RetractPlayer()
        self.race_checkpoint = self.race_respawn_checkpoint;
 }
 
-void spawnfunc_info_player_race (void)
+spawnfunc(info_player_race)
 {
        if(!g_race && !g_cts) { remove(self); return; }
        ++race_spawns;
-       spawnfunc_info_player_deathmatch();
+       spawnfunc_info_player_deathmatch(this);
 
        if(self.race_place > race_highest_place_spawn)
                race_highest_place_spawn = self.race_place;
@@ -1073,9 +1072,8 @@ void spawnfunc_info_player_race (void)
 }
 
 void race_ClearRecords()
-{
+{SELFPARAM();
        float i;
-       entity e;
 
        for(i = 0; i < MAX_CHECKPOINTS; ++i)
        {
@@ -1085,15 +1083,13 @@ void race_ClearRecords()
                race_checkpoint_recordholders[i] = string_null;
        }
 
-       e = self;
-       FOR_EACH_CLIENT(self)
+       entity e;
+       FOR_EACH_CLIENT(e)
        {
-               float p;
-               p = self.race_place;
-               race_PreparePlayer();
-               self.race_place = p;
+               float p = e.race_place;
+               WITH(entity, self, e, race_PreparePlayer());
+               e.race_place = p;
        }
-       self = e;
 }
 
 void race_ImposePenaltyTime(entity pl, float penalty, string reason)
@@ -1131,7 +1127,7 @@ void race_ImposePenaltyTime(entity pl, float penalty, string reason)
 }
 
 void penalty_touch()
-{
+{SELFPARAM();
        EXACTTRIGGER_TOUCH;
        if(other.race_lastpenalty != self)
        {
@@ -1141,11 +1137,11 @@ void penalty_touch()
 }
 
 void penalty_use()
-{
+{SELFPARAM();
        race_ImposePenaltyTime(activator, self.race_penalty, self.race_penalty_reason);
 }
 
-void spawnfunc_trigger_race_penalty()
+spawnfunc(trigger_race_penalty)
 {
        EXACTTRIGGER_INIT;
 
index d5b0281338ac22f1999db48338432feb482f0af2..0d608f9af76268de54d415746ca813e2b965453c 100644 (file)
@@ -5,7 +5,7 @@
 #include "../common/util.qh"
 
 void round_handler_Think()
-{
+{SELFPARAM();
        float f;
 
        if(time < game_starttime)
index 57f5e95f8fd6878951ac9d42e5ce79c7ba1dcbd2..14893b12d8a9d3140da373415fc4b35871fdf56d 100644 (file)
@@ -55,7 +55,7 @@ vector ScoreField_Compare(entity t1, entity t2, .float field, float fieldflags,
  * teamscore entities
  */
 
-float TeamScore_SendEntity(entity to, float sendflags)
+bool TeamScore_SendEntity(entity this, entity to, float sendflags)
 {
        float i, p, longflags;
 
@@ -186,7 +186,7 @@ void ScoreInfo_SetLabel_TeamScore(float i, string label, float scoreflags)
        }
 }
 
-float ScoreInfo_SendEntity(entity to, int sf)
+bool ScoreInfo_SendEntity(entity this, entity to, int sf)
 {
        float i;
        WriteByte(MSG_ENTITY, ENT_CLIENT_SCORES_INFO);
@@ -230,7 +230,7 @@ void ScoreInfo_Init(float teams)
  * per-player score entities
  */
 
-float PlayerScore_SendEntity(entity to, float sendflags)
+bool PlayerScore_SendEntity(entity this, entity to, float sendflags)
 {
        float i, p, longflags;
 
index b8045b4691a5398222a050a5ed31e2517f7932f6..09d914a3c86751b7f0d6bbc97e49c8277575e560 100644 (file)
@@ -9,7 +9,7 @@
 #include "../common/util.qh"
 #include "../warpzonelib/util_server.qh"
 
-float SpawnPoint_Send(entity to, int sf)
+bool SpawnPoint_Send(entity this, entity to, int sf)
 {
        WriteByte(MSG_ENTITY, ENT_CLIENT_SPAWNPOINT);
 
@@ -21,7 +21,7 @@ float SpawnPoint_Send(entity to, int sf)
        return true;
 }
 
-float SpawnEvent_Send(entity to, int sf)
+bool SpawnEvent_Send(entity this, entity to, int sf)
 {
        float send;
 
@@ -46,7 +46,7 @@ float SpawnEvent_Send(entity to, int sf)
 }
 
 void spawnpoint_use()
-{
+{SELFPARAM();
        if(teamplay)
        if(have_team_spawns > 0)
        {
@@ -57,7 +57,7 @@ void spawnpoint_use()
 }
 
 void relocate_spawnpoint()
-{
+{SELFPARAM();
     // nudge off the floor
     setorigin(self, self.origin + '0 0 1');
 
@@ -141,17 +141,17 @@ void relocate_spawnpoint()
        { Net_LinkEntity(self, false, 0, SpawnPoint_Send); }
 }
 
-void spawnfunc_info_player_survivor (void)
+spawnfunc(info_player_survivor)
 {
-       spawnfunc_info_player_deathmatch();
+       spawnfunc_info_player_deathmatch(this);
 }
 
-void spawnfunc_info_player_start (void)
+spawnfunc(info_player_start)
 {
-       spawnfunc_info_player_deathmatch();
+       spawnfunc_info_player_deathmatch(this);
 }
 
-void spawnfunc_info_player_deathmatch (void)
+spawnfunc(info_player_deathmatch)
 {
        self.classname = "info_player_deathmatch";
        relocate_spawnpoint();
@@ -160,54 +160,54 @@ void spawnfunc_info_player_deathmatch (void)
 /*QUAKED spawnfunc_info_player_team1 (1 0 0) (-16 -16 -24) (16 16 24)
 Starting point for a player in team one (Red).
 Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team1()
+spawnfunc(info_player_team1)
 {
-       if(g_assault) { remove(self); return; }
+       if(g_assault) { remove(this); return; }
 
-       self.team = NUM_TEAM_1; // red
-       spawnfunc_info_player_deathmatch();
+       this.team = NUM_TEAM_1; // red
+       spawnfunc_info_player_deathmatch(this);
 }
 
 
 /*QUAKED spawnfunc_info_player_team2 (1 0 0) (-16 -16 -24) (16 16 24)
 Starting point for a player in team two (Blue).
 Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team2()
+spawnfunc(info_player_team2)
 {
-       if(g_assault) { remove(self); return; }
+       if(g_assault) { remove(this); return; }
 
-       self.team = NUM_TEAM_2; // blue
-       spawnfunc_info_player_deathmatch();
+       this.team = NUM_TEAM_2; // blue
+       spawnfunc_info_player_deathmatch(this);
 }
 
 /*QUAKED spawnfunc_info_player_team3 (1 0 0) (-16 -16 -24) (16 16 24)
 Starting point for a player in team three (Yellow).
 Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team3()
+spawnfunc(info_player_team3)
 {
-       if(g_assault) { remove(self); return; }
+       if(g_assault) { remove(this); return; }
 
-       self.team = NUM_TEAM_3; // yellow
-       spawnfunc_info_player_deathmatch();
+       this.team = NUM_TEAM_3; // yellow
+       spawnfunc_info_player_deathmatch(this);
 }
 
 
 /*QUAKED spawnfunc_info_player_team4 (1 0 0) (-16 -16 -24) (16 16 24)
 Starting point for a player in team four (Purple).
 Keys: "angle" viewing angle when spawning. */
-void spawnfunc_info_player_team4()
+spawnfunc(info_player_team4)
 {
-       if(g_assault) { remove(self); return; }
+       if(g_assault) { remove(this); return; }
 
-       self.team = NUM_TEAM_4; // purple
-       spawnfunc_info_player_deathmatch();
+       this.team = NUM_TEAM_4; // purple
+       spawnfunc_info_player_deathmatch(this);
 }
 
 // Returns:
 //   _x: prio (-1 if unusable)
 //   _y: weight
 vector Spawn_Score(entity spot, float mindist, float teamcheck)
-{
+{SELFPARAM();
        float shortest, thisdist;
        float prio;
        entity player;
@@ -258,10 +258,9 @@ vector Spawn_Score(entity spot, float mindist, float teamcheck)
                        ++found;
                        if(ent.spawn_evalfunc)
                        {
-                               entity oldself = self;
-                               self = ent;
-                               spawn_score = ent.spawn_evalfunc(oldself, spot, spawn_score);
-                               self = oldself;
+                               WITH(entity, self, ent, {
+                                       spawn_score = ent.spawn_evalfunc(this, spot, spawn_score);
+                               });
                                if(spawn_score.x < 0)
                                        return spawn_score;
                        }
@@ -332,7 +331,7 @@ Finds a point to respawn
 =============
 */
 entity SelectSpawnPoint (float anypoint)
-{
+{SELFPARAM();
        float teamcheck;
        entity spot, firstspot;
 
index e697001c18145e96233de28a8bfba1e436f59503..ef2ab6687800227d3caa022fa3b8b09761346081 100644 (file)
@@ -3,9 +3,9 @@
 
 .vector spawnpoint_score;
 float spawnpoint_nag;
-float SpawnEvent_Send(entity to, int sf);
+bool SpawnEvent_Send(entity this, entity to, int sf);
 entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck);
 entity SelectSpawnPoint (float anypoint);
-void spawnfunc_info_player_deathmatch();
+spawnfunc(info_player_deathmatch);
 void spawnpoint_use();
 #endif
index e57d56dd169be0022cd881bc00d32e581f8e5842..fbf84da32be0b06fb2a16d0ae2f790bdc5fcb9da 100644 (file)
@@ -9,7 +9,7 @@
     Uniform pull towards a point
 **/
 vector steerlib_pull(vector point)
-{
+{SELFPARAM();
     return normalize(point - self.origin);
 }
 
@@ -27,7 +27,7 @@ vector steerlib_push(vector point)
     Pull toward a point, The further away, the stronger the pull.
 **/
 vector steerlib_arrive(vector point,float maximal_distance)
-{
+{SELFPARAM();
     float distance;
     vector direction;
 
@@ -40,7 +40,7 @@ vector steerlib_arrive(vector point,float maximal_distance)
     Pull toward a point increasing the pull the closer we get
 **/
 vector steerlib_attract(vector point, float maximal_distance)
-{
+{SELFPARAM();
     float distance;
     vector direction;
 
@@ -51,7 +51,7 @@ vector steerlib_attract(vector point, float maximal_distance)
 }
 
 vector steerlib_attract2(vector point, float min_influense,float max_distance,float max_influense)
-{
+{SELFPARAM();
     float distance;
     vector direction;
     float influense;
@@ -99,7 +99,7 @@ vector steerlib_attract2(vector point, float maximal_distance,float min_influens
     Move away from a point.
 **/
 vector steerlib_repell(vector point,float maximal_distance)
-{
+{SELFPARAM();
     float distance;
     vector direction;
 
@@ -113,7 +113,7 @@ vector steerlib_repell(vector point,float maximal_distance)
     Try to keep at ideal_distance away from point
 **/
 vector steerlib_standoff(vector point,float ideal_distance)
-{
+{SELFPARAM();
     float distance;
     vector direction;
 
@@ -140,7 +140,7 @@ vector steerlib_standoff(vector point,float ideal_distance)
     where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
 **/
 vector steerlib_wander(float range,float tresh,vector oldpoint)
-{
+{SELFPARAM();
     vector wander_point;
     wander_point = v_forward - oldpoint;
 
@@ -159,7 +159,7 @@ vector steerlib_wander(float range,float tresh,vector oldpoint)
     Dodge a point. dont work to well.
 **/
 vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
-{
+{SELFPARAM();
     float distance;
 
     distance = max(vlen(self.origin - point),min_distance);
@@ -175,7 +175,7 @@ vector steerlib_dodge(vector point,vector dodge_dir,float min_distance)
 **/
 .float flock_id;
 vector steerlib_flock(float _radius, float standoff,float separation_force,float flock_force)
-{
+{SELFPARAM();
     entity flock_member;
     vector push = '0 0 0', pull = '0 0 0';
     float ccount = 0;
@@ -201,7 +201,7 @@ vector steerlib_flock(float _radius, float standoff,float separation_force,float
     xy only version (for ground movers).
 **/
 vector steerlib_flock2d(float _radius, float standoff,float separation_force,float flock_force)
-{
+{SELFPARAM();
     entity flock_member;
     vector push = '0 0 0', pull = '0 0 0';
     float ccount = 0;
@@ -232,7 +232,7 @@ vector steerlib_flock2d(float _radius, float standoff,float separation_force,flo
     This results in a aligned movement (?!) much like flocking.
 **/
 vector steerlib_swarm(float _radius, float standoff,float separation_force,float swarm_force)
-{
+{SELFPARAM();
     entity swarm_member;
     vector force = '0 0 0', center = '0 0 0';
     float ccount = 0;
@@ -262,7 +262,7 @@ vector steerlib_swarm(float _radius, float standoff,float separation_force,float
     You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
 **/
 vector steerlib_traceavoid(float pitch,float length)
-{
+{SELFPARAM();
     vector vup_left,vup_right,vdown_left,vdown_right;
     float fup_left,fup_right,fdown_left,fdown_right;
     vector upwish,downwish,leftwish,rightwish;
@@ -309,7 +309,7 @@ vector steerlib_traceavoid(float pitch,float length)
     Run tracelines in a forward trident, bias each direction negative if something is found there.
 **/
 vector steerlib_traceavoid_flat(float pitch, float length, vector vofs)
-{
+{SELFPARAM();
     vector vt_left, vt_right,vt_front;
     float f_left, f_right,f_front;
     vector leftwish, rightwish,frontwish, v_left;
@@ -381,7 +381,7 @@ float beamsweep_badpoint(vector point,float waterok)
 
 //#define BEAMSTEER_VISUAL
 float beamsweep(vector from, vector dir,float length, float step,float step_up, float step_down)
-{
+{SELFPARAM();
     float i;
     vector a,b,u,d;
 
@@ -421,7 +421,7 @@ float beamsweep(vector from, vector dir,float length, float step,float step_up,
 }
 
 vector steerlib_beamsteer(vector dir, float length, float step, float step_up, float step_down)
-{
+{SELFPARAM();
     float bm_forward, bm_right, bm_left,p;
     vector vr,vl;
 
@@ -497,7 +497,7 @@ vector steerlib_beamsteer(vector dir, float length, float step, float step_up, f
 //#define TLIBS_TETSLIBS
 #ifdef TLIBS_TETSLIBS
 void flocker_die()
-{
+{SELFPARAM();
        Send_Effect(EFFECT_ROCKET_EXPLODE, self.origin, '0 0 0', 1);
 
     self.owner.cnt += 1;
@@ -509,7 +509,7 @@ void flocker_die()
 
 
 void flocker_think()
-{
+{SELFPARAM();
     vector dodgemove,swarmmove;
     vector reprellmove,wandermove,newmove;
 
@@ -545,15 +545,16 @@ void flocker_think()
         self.nextthink = time + 0.1;
 }
 
+MODEL(FLOCKER, "models/turrets/rocket.md3");
 
 void spawn_flocker()
-{
+{SELFPARAM();
     entity flocker;
 
     flocker = spawn ();
 
     setorigin(flocker, self.origin + '0 0 32');
-    setmodel (flocker, "models/turrets/rocket.md3");
+    setmodel (flocker, MDL_FLOCKER);
     setsize (flocker, '-3 -3 -3', '3 3 3');
 
     flocker.flock_id   = self.flock_id;
@@ -574,7 +575,7 @@ void spawn_flocker()
 }
 
 void flockerspawn_think()
-{
+{SELFPARAM();
 
 
     if(self.cnt > 0)
@@ -585,7 +586,7 @@ void flockerspawn_think()
 }
 
 void flocker_hunter_think()
-{
+{SELFPARAM();
     vector dodgemove,attractmove,newmove;
     entity e,ee;
     float d,bd;
@@ -639,10 +640,8 @@ void flocker_hunter_think()
 
 
 float globflockcnt;
-void spawnfunc_flockerspawn()
-{
-    precache_model ( "models/turrets/rocket.md3");
-    precache_model("models/turrets/c512.md3");
+spawnfunc(flockerspawn)
+{SELFPARAM();
     ++globflockcnt;
 
     if(!self.cnt)      self.cnt = 20;
@@ -654,7 +653,7 @@ void spawnfunc_flockerspawn()
 
     self.enemy = spawn();
 
-    setmodel(self.enemy, "models/turrets/rocket.md3");
+    setmodel(self.enemy, MDL_FLOCKER);
     setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128));
 
     self.enemy.classname = "FLock Hunter";
index 1f629af5cfe06eb0e5815127c9d8bd75fb6d3c78..138051827bcad56fac48d9ed1f993596a8f405cc 100644 (file)
 .float lastground;
 
 void CreatureFrame (void)
-{
-       entity oldself;
+{SELFPARAM();
        float dm;
 
-       oldself = self;
-       for(self = world; (self = findfloat(self, damagedbycontents, true)); )
+       for(entity e = world; (e = findfloat(e, damagedbycontents, true)); )
        {
+               setself(e);
                if (self.movetype == MOVETYPE_NOCLIP) { continue; }
 
                float vehic = IS_VEHICLE(self);
@@ -91,7 +90,7 @@ void CreatureFrame (void)
                                                if (self.watersound_finished < time)
                                                {
                                                        self.watersound_finished = time + 0.5;
-                                                       sound (self, CH_PLAYER_SINGLE, "player/lava.wav", VOL_BASE, ATTEN_NORM);
+                                                       sound (self, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
                                                }
                                                Damage (self, world, world, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0');
                                        }
@@ -100,7 +99,7 @@ void CreatureFrame (void)
                                                if (self.watersound_finished < time)
                                                {
                                                        self.watersound_finished = time + 0.5;
-                                                       sound (self, CH_PLAYER_SINGLE, "player/slime.wav", VOL_BASE, ATTEN_NORM);
+                                                       sound (self, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
                                                }
                                                Damage (self, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
                                        }
@@ -169,7 +168,7 @@ void CreatureFrame (void)
 
         self.oldvelocity = self.velocity;
        }
-       self = oldself;
+       setself(this);
 }
 
 
@@ -186,7 +185,7 @@ float game_delay_last;
 
 float RedirectionThink();
 void StartFrame (void)
-{
+{SELFPARAM();
        execute_next_frame();
 
        remove = remove_unsafely; // not during spawning!
@@ -218,8 +217,7 @@ void StartFrame (void)
        }
 #endif
 
-       entity e;
-       for(e = world; (e = findfloat(e, csqcprojectile_clientanimate, 1)); )
+       for(entity e = world; (e = findfloat(e, csqcprojectile_clientanimate, 1)); )
                CSQCProjectile_Check(e);
 
        if(RedirectionThink())
@@ -264,8 +262,9 @@ void StartFrame (void)
 
        bot_serverframe();
 
-       FOR_EACH_PLAYER(self)
-               self.porto_forbidden = max(0, self.porto_forbidden - 1);
+       entity e;
+       FOR_EACH_PLAYER(e)
+               e.porto_forbidden = max(0, e.porto_forbidden - 1);
 
        anticheat_startframe();
 
@@ -279,7 +278,7 @@ void StartFrame (void)
 .string cvarfilter;
 float DoesQ3ARemoveThisEntity();
 void SV_OnEntityPreSpawnFunction()
-{
+{SELFPARAM();
        if (self)
        if (self.gametypefilter != "")
        if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, self.gametypefilter))
index bfdcdb860e267fff7a385d17fa76cd4c6fa4c3ab..067e0140976fb18399e1f71ec32247933d6cbac5 100644 (file)
@@ -3,7 +3,6 @@
 
 #define objerror builtin_objerror
 #define droptofloor builtin_droptofloor
-#define sound builtin_sound
 #define remove builtin_remove
 #define cvar_set builtin_cvar_set
 #define cvar_string builtin_cvar_string
index f041dd39659aebd31a8b375b6e14d1fd51820f1c..0438282006c22a072255fb75142b4ee63eaf8b9f 100644 (file)
@@ -5,30 +5,30 @@
 .float  rendermode;
 .vector rendercolor;
 
-void spawnfunc_weapon_crossbow() {}
-void spawnfunc_weapon_handgrenade() {}
-void spawnfunc_ammo_crossbow() {}
-void spawnfunc_ammo_9mmclip() {}
-void spawnfunc_ammo_gaussclip() {}
-void spawnfunc_weapon_rpg() {}
-void spawnfunc_weapon_357() {}
+spawnfunc(weapon_crossbow) {}
+spawnfunc(weapon_handgrenade) {}
+spawnfunc(ammo_crossbow) {}
+spawnfunc(ammo_9mmclip) {}
+spawnfunc(ammo_gaussclip) {}
+spawnfunc(weapon_rpg) {}
+spawnfunc(weapon_357) {}
 void ammo_ARgrenades() {}
-void spawnfunc_item_battery() {}
-void spawnfunc_ammo_rpgclip() {}
+spawnfunc(item_battery) {}
+spawnfunc(ammo_rpgclip) {}
 void weapon_9mmAR() {}
-void spawnfunc_weapon_tripmine() {}
-void spawnfunc_weapon_snark() {}
-void spawnfunc_ammo_buckshot() {}
+spawnfunc(weapon_tripmine) {}
+spawnfunc(weapon_snark) {}
+spawnfunc(ammo_buckshot) {}
 void ammo_9mmAR() {}
-void spawnfunc_ammo_357() {}
-void spawnfunc_weapon_gauss() {}
-void spawnfunc_weapon_hornetgun() {}
-//void spawnfunc_weapon_shotgun() {}
-void spawnfunc_item_healthkit() {}
-void spawnfunc_item_longjump() {}
-void spawnfunc_item_antidote() {}
-void spawnfunc_func_recharge() {}
-void spawnfunc_info_node() {}
-void spawnfunc_env_sound() {}
-void spawnfunc_light_spot() {}
-void spawnfunc_func_healthcharger() {}
+spawnfunc(ammo_357) {}
+spawnfunc(weapon_gauss) {}
+spawnfunc(weapon_hornetgun) {}
+//spawnfunc(weapon_shotgun) {}
+spawnfunc(item_healthkit) {}
+spawnfunc(item_longjump) {}
+spawnfunc(item_antidote) {}
+spawnfunc(func_recharge) {}
+spawnfunc(info_node) {}
+spawnfunc(env_sound) {}
+spawnfunc(light_spot) {}
+spawnfunc(func_healthcharger) {}
index 5d392fd84a24c8fc64a025fc4d2f1ae0aa2c2f4e..0a5785037f0223df12170535d348786cdb431d4b 100644 (file)
@@ -28,7 +28,7 @@
 #endif
 
 #ifdef CSQC
-void ItemDraw()
+void ItemDraw(entity self)
 {
     if(self.gravity)
     {
@@ -64,7 +64,7 @@ void ItemDraw()
     }
 }
 
-void ItemDrawSimple()
+void ItemDrawSimple(entity this)
 {
     if(self.gravity)
     {
@@ -76,7 +76,7 @@ void ItemDrawSimple()
 }
 
 void Item_PreDraw()
-{
+{SELFPARAM();
        vector org;
        float alph;
        org = getpropertyvec(VF_ORIGIN);
@@ -96,7 +96,7 @@ void Item_PreDraw()
 }
 
 void ItemRead(float _IsNew)
-{
+{SELFPARAM();
     int sf = ReadByte();
 
     if(sf & ISF_LOCATION)
@@ -207,7 +207,7 @@ void ItemRead(float _IsNew)
             LOG_TRACE("^1WARNING!^7 self.mdl is unset for item ", self.classname, " tell tZork aboute this!\n");
 
         precache_model(self.mdl);
-        setmodel(self, self.mdl);
+        _setmodel(self, self.mdl);
     }
 
     if(sf & ISF_COLORMAP)
@@ -246,7 +246,7 @@ void ItemRead(float _IsNew)
 #endif
 
 #ifdef SVQC
-bool ItemSend(entity to, int sf)
+bool ItemSend(entity this, entity to, int sf)
 {
        if(self.gravity)
                sf |= ISF_DROP;
@@ -310,7 +310,7 @@ void ItemUpdate(entity item)
 }
 
 float have_pickup_item(void)
-{
+{SELFPARAM();
        if(self.flags & FL_POWERUP)
        {
                if(autocvar_g_powerups > 0)
@@ -416,7 +416,7 @@ void Item_Show (entity e, float mode)
 }
 
 void Item_Think()
-{
+{SELFPARAM();
        self.nextthink = time;
        if(self.origin != self.oldorigin)
        {
@@ -432,15 +432,15 @@ void Item_ItemsTime_SetTime(entity e, float t);
 void Item_ItemsTime_SetTimesForAllPlayers();
 
 void Item_Respawn (void)
-{
+{SELFPARAM();
        Item_Show(self, 1);
        // this is ugly...
        if(self.items == ITEM_Strength.m_itemid)
-               sound (self, CH_TRIGGER, "misc/strength_respawn.wav", VOL_BASE, ATTEN_NORM);    // play respawn sound
+               sound (self, CH_TRIGGER, SND_STRENGTH_RESPAWN, VOL_BASE, ATTEN_NORM);   // play respawn sound
        else if(self.items == ITEM_Shield.m_itemid)
-               sound (self, CH_TRIGGER, "misc/shield_respawn.wav", VOL_BASE, ATTEN_NORM);      // play respawn sound
+               sound (self, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTEN_NORM);     // play respawn sound
        else
-               sound (self, CH_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+               sound (self, CH_TRIGGER, SND_ITEMRESPAWN, VOL_BASE, ATTEN_NORM);        // play respawn sound
        setorigin (self, self.origin);
 
     if (Item_ItemsTime_Allow(self.itemdef, self.weapons))
@@ -458,7 +458,7 @@ void Item_Respawn (void)
 }
 
 void Item_RespawnCountdown (void)
-{
+{SELFPARAM();
        if(self.count >= ITEM_RESPAWN_TICKS)
        {
                if(self.waypointsprite_attached)
@@ -472,15 +472,24 @@ void Item_RespawnCountdown (void)
                if(self.count == 1)
                {
                        MUTATOR_CALLHOOK(Item_RespawnCountdown, string_null, '0 0 0');
-                       int wpextra = 0;
-            entity e = self.itemdef;
-            if (e) wpextra = e.m_id;
-                       if (self.flags & FL_WEAPON) {
-                               entity wi = get_weaponinfo(self.weapon);
-                               if (wi) wpextra = wi.m_id;
-                       }
-            entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_POWERUP);
-            wp.wp_extra = wpextra;
+                       do {
+                               {
+                                       entity wi = get_weaponinfo(self.weapon);
+                                       if (wi.m_id) {
+                                               entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Weapon);
+                                               wp.wp_extra = wi.m_id;
+                                               break;
+                                       }
+                               }
+                               {
+                                       entity ii = self.itemdef;
+                                       if (ii.m_id) {
+                                               entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, true, RADARICON_Item);
+                                               wp.wp_extra = ii.m_id;
+                                               break;
+                                       }
+                               }
+                       } while (0);
             if(self.waypointsprite_attached)
             {
                 GameItem def = self.itemdef;
@@ -492,27 +501,26 @@ void Item_RespawnCountdown (void)
 
                if(self.waypointsprite_attached)
                {
+                       setself(self.waypointsprite_attached);
                        entity e;
-                       entity it = self;
-                       self = self.waypointsprite_attached;
                        FOR_EACH_REALCLIENT(e)
                                if(self.waypointsprite_visible_for_player(e))
                                {
                                        msg_entity = e;
-                                       soundto(MSG_ONE, it, CH_TRIGGER, "misc/itemrespawncountdown.wav", VOL_BASE, ATTEN_NORM);        // play respawn sound
+                                       soundto(MSG_ONE, this, CH_TRIGGER, SND(ITEMRESPAWNCOUNTDOWN), VOL_BASE, ATTEN_NORM);    // play respawn sound
                                }
-                       self = it;
+                       setself(this);
 
                        WaypointSprite_Ping(self.waypointsprite_attached);
                        //WaypointSprite_UpdateHealth(self.waypointsprite_attached, self.count);
                }
                else
-                       sound(self, CH_TRIGGER, "misc/itemrespawncountdown.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+                       sound(self, CH_TRIGGER, SND_ITEMRESPAWNCOUNTDOWN, VOL_BASE, ATTEN_NORM);        // play respawn sound
        }
 }
 
 void Item_RespawnThink()
-{
+{SELFPARAM();
        self.nextthink = time;
        if(self.origin != self.oldorigin)
        {
@@ -646,7 +654,7 @@ float Item_GiveTo(entity item, entity player)
                        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                        if(it & WepSet_FromWeapon(i))
                        {
-                               W_DropEvent(WR_PICKUP, player, i, item);
+                               W_DropEvent(wr_pickup, player, i, item);
                                W_GiveWeapon(player, i);
                        }
                }
@@ -699,7 +707,7 @@ float Item_GiveTo(entity item, entity player)
 }
 
 void Item_Touch (void)
-{
+{SELFPARAM();
        entity e, head;
 
        // remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
@@ -751,7 +759,7 @@ void Item_Touch (void)
        other.last_pickup = time;
 
        Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(self), '0 0 0', 1);
-       sound (other, CH_TRIGGER, self.item_pickupsound, VOL_BASE, ATTEN_NORM);
+       _sound (other, CH_TRIGGER, (self.item_pickupsound ? self.item_pickupsound : self.item_pickupsound_ent.sound_str()), VOL_BASE, ATTEN_NORM);
 
        if (self.classname == "droppedweapon")
                remove (self);
@@ -779,7 +787,7 @@ void Item_Touch (void)
 }
 
 void Item_Reset()
-{
+{SELFPARAM();
        Item_Show(self, !self.state);
        setorigin (self, self.origin);
 
@@ -797,7 +805,7 @@ void Item_Reset()
 }
 
 void Item_FindTeam()
-{
+{SELFPARAM();
        entity head, e;
 
        if(self.effects & EF_NODRAW)
@@ -833,7 +841,7 @@ void Item_FindTeam()
 // Savage: used for item garbage-collection
 // TODO: perhaps nice special effect?
 void RemoveItem(void)
-{
+{SELFPARAM();
        if(wasfreed(self) || !self) { return; }
        Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(self), '0 0 0', 1);
        remove(self);
@@ -967,7 +975,7 @@ void Item_Damage(entity inflictor, entity attacker, float damage, int deathtype,
 }
 
 void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, float defaultrespawntimejitter, string itemname, float itemid, float weaponid, float itemflags, float(entity player, entity item) pickupevalfunc, float pickupbasevalue)
-{
+{SELFPARAM();
        startitem_failed = false;
 
        if(self.model == "")
@@ -1120,14 +1128,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                precache_model (self.model);
                precache_sound (self.item_pickupsound);
 
-               precache_sound ("misc/itemrespawncountdown.wav");
-               if(itemid == ITEM_Strength.m_itemid)
-                       precache_sound ("misc/strength_respawn.wav");
-               else if(itemid == ITEM_Shield.m_itemid)
-                       precache_sound ("misc/shield_respawn.wav");
-               else
-                       precache_sound ("misc/itemrespawn.wav");
-
                if((itemflags & (FL_POWERUP | FL_WEAPON)) || (itemid & (IT_HEALTH | IT_ARMOR | IT_KEY1 | IT_KEY2)))
                        self.target = "###item###"; // for finding the nearest item using find()
 
@@ -1140,7 +1140,7 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
        self.mdl = self.model;
        self.netname = itemname;
        self.touch = Item_Touch;
-       setmodel(self, "null"); // precision set below
+       setmodel(self, MDL_Null); // precision set below
        //self.effects |= EF_LOWPRECISION;
 
        if((itemflags & FL_POWERUP) || self.health || self.armorvalue)
@@ -1197,20 +1197,14 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
        }
 }
 
-string Item_Model(string item_mdl)
-{
-       string output = strcat("models/items/", item_mdl);
-       MUTATOR_CALLHOOK(ItemModel, item_mdl, output);
-       return strzone(item_model_output);
-}
-
 void StartItemA (entity a)
-{
+{SELFPARAM();
     self.itemdef = a;
-    StartItem(Item_Model(a.m_model), a.m_sound, a.m_respawntime(), a.m_respawntimejitter(), a.m_name, a.m_itemid, 0, a.m_itemflags, a.m_pickupevalfunc, a.m_botvalue);
+    StartItem(strzone(a.m_model.model_str()), a.m_sound, a.m_respawntime(), a.m_respawntimejitter(), a.m_name, a.m_itemid, 0, a.m_itemflags, a.m_pickupevalfunc, a.m_botvalue);
 }
 
-void spawnfunc_item_rockets (void) {
+spawnfunc(item_rockets)
+{
        if(!self.ammo_rockets)
                self.ammo_rockets = g_pickup_rockets;
        if(!self.pickup_anyway)
@@ -1218,13 +1212,14 @@ void spawnfunc_item_rockets (void) {
     StartItemA (ITEM_Rockets);
 }
 
-void spawnfunc_item_bullets (void) {
+spawnfunc(item_bullets)
+{
        if(!weaponswapping)
        if(autocvar_sv_q3acompat_machineshotgunswap)
        if(self.classname != "droppedweapon")
        {
                weaponswapping = true;
-               spawnfunc_item_shells();
+               spawnfunc_item_shells(this);
                weaponswapping = false;
                return;
        }
@@ -1236,7 +1231,8 @@ void spawnfunc_item_bullets (void) {
     StartItemA (ITEM_Bullets);
 }
 
-void spawnfunc_item_cells (void) {
+spawnfunc(item_cells)
+{
        if(!self.ammo_cells)
                self.ammo_cells = g_pickup_cells;
        if(!self.pickup_anyway)
@@ -1244,7 +1240,7 @@ void spawnfunc_item_cells (void) {
        StartItemA (ITEM_Cells);
 }
 
-void spawnfunc_item_plasma()
+spawnfunc(item_plasma)
 {
        if(!self.ammo_plasma)
                self.ammo_plasma = g_pickup_plasma;
@@ -1253,13 +1249,14 @@ void spawnfunc_item_plasma()
        StartItemA (ITEM_Plasma);
 }
 
-void spawnfunc_item_shells (void) {
+spawnfunc(item_shells)
+{
        if(!weaponswapping)
        if(autocvar_sv_q3acompat_machineshotgunswap)
        if(self.classname != "droppedweapon")
        {
                weaponswapping = true;
-               spawnfunc_item_bullets();
+               spawnfunc_item_bullets(this);
                weaponswapping = false;
                return;
        }
@@ -1271,7 +1268,8 @@ void spawnfunc_item_shells (void) {
        StartItemA (ITEM_Shells);
 }
 
-void spawnfunc_item_armor_small (void) {
+spawnfunc(item_armor_small)
+{
        if(!self.armorvalue)
                self.armorvalue = g_pickup_armorsmall;
        if(!self.max_armorvalue)
@@ -1281,7 +1279,8 @@ void spawnfunc_item_armor_small (void) {
        StartItemA (ITEM_ArmorSmall);
 }
 
-void spawnfunc_item_armor_medium (void) {
+spawnfunc(item_armor_medium)
+{
        if(!self.armorvalue)
                self.armorvalue = g_pickup_armormedium;
        if(!self.max_armorvalue)
@@ -1291,7 +1290,8 @@ void spawnfunc_item_armor_medium (void) {
        StartItemA (ITEM_ArmorMedium);
 }
 
-void spawnfunc_item_armor_big (void) {
+spawnfunc(item_armor_big)
+{
        if(!self.armorvalue)
                self.armorvalue = g_pickup_armorbig;
        if(!self.max_armorvalue)
@@ -1301,7 +1301,8 @@ void spawnfunc_item_armor_big (void) {
        StartItemA (ITEM_ArmorLarge);
 }
 
-void spawnfunc_item_armor_large (void) {
+spawnfunc(item_armor_large)
+{
        if(!self.armorvalue)
                self.armorvalue = g_pickup_armorlarge;
        if(!self.max_armorvalue)
@@ -1311,7 +1312,8 @@ void spawnfunc_item_armor_large (void) {
        StartItemA (ITEM_ArmorMega);
 }
 
-void spawnfunc_item_health_small (void) {
+spawnfunc(item_health_small)
+{
        if(!self.max_health)
                self.max_health = g_pickup_healthsmall_max;
        if(!self.health)
@@ -1321,7 +1323,8 @@ void spawnfunc_item_health_small (void) {
        StartItemA (ITEM_HealthSmall);
 }
 
-void spawnfunc_item_health_medium (void) {
+spawnfunc(item_health_medium)
+{
        if(!self.max_health)
                self.max_health = g_pickup_healthmedium_max;
        if(!self.health)
@@ -1331,7 +1334,8 @@ void spawnfunc_item_health_medium (void) {
     StartItemA (ITEM_HealthMedium);
 }
 
-void spawnfunc_item_health_large (void) {
+spawnfunc(item_health_large)
+{
        if(!self.max_health)
                self.max_health = g_pickup_healthlarge_max;
        if(!self.health)
@@ -1341,7 +1345,8 @@ void spawnfunc_item_health_large (void) {
        StartItemA (ITEM_HealthLarge);
 }
 
-void spawnfunc_item_health_mega (void) {
+spawnfunc(item_health_mega)
+{
     if(!self.max_health)
         self.max_health = g_pickup_healthmega_max;
     if(!self.health)
@@ -1352,30 +1357,31 @@ void spawnfunc_item_health_mega (void) {
 }
 
 // support old misnamed entities
-void spawnfunc_item_armor1() { spawnfunc_item_armor_small(); }  // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
-void spawnfunc_item_armor25() { spawnfunc_item_armor_large(); }
-void spawnfunc_item_health1() { spawnfunc_item_health_small(); }
-void spawnfunc_item_health25() { spawnfunc_item_health_medium(); }
-void spawnfunc_item_health100() { spawnfunc_item_health_mega(); }
-
-void spawnfunc_item_strength (void) {
-               precache_sound("weapons/strength_fire.wav");
+spawnfunc(item_armor1) { spawnfunc_item_armor_small(this); }  // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
+spawnfunc(item_armor25) { spawnfunc_item_armor_large(this); }
+spawnfunc(item_health1) { spawnfunc_item_health_small(this); }
+spawnfunc(item_health25) { spawnfunc_item_health_medium(this); }
+spawnfunc(item_health100) { spawnfunc_item_health_mega(this); }
+
+spawnfunc(item_strength)
+{
                if(!self.strength_finished)
                        self.strength_finished = autocvar_g_balance_powerup_strength_time;
                StartItemA (ITEM_Strength);
 }
 
-void spawnfunc_item_invincible (void) {
+spawnfunc(item_invincible)
+{
                if(!self.invincible_finished)
                        self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
                StartItemA (ITEM_Shield);
 }
 
 // compatibility:
-void spawnfunc_item_quad (void) {self.classname = "item_strength";spawnfunc_item_strength();}
+spawnfunc(item_quad) { self.classname = "item_strength";spawnfunc_item_strength(this);}
 
-void target_items_use (void)
-{
+void target_items_use()
+{SELFPARAM();
        if(activator.classname == "droppedweapon")
        {
                EXACTTRIGGER_TOUCH;
@@ -1398,7 +1404,7 @@ void target_items_use (void)
                centerprint(activator, self.message);
 }
 
-void spawnfunc_target_items (void)
+spawnfunc(target_items)
 {
        float n, i, j;
        entity e;
@@ -1412,13 +1418,6 @@ void spawnfunc_target_items (void)
        if(!self.superweapons_finished)
                self.superweapons_finished = autocvar_g_balance_superweapons_time;
 
-       precache_sound("misc/itempickup.wav");
-       precache_sound("misc/megahealth.wav");
-       precache_sound("misc/armor25.wav");
-       precache_sound("misc/powerup.wav");
-       precache_sound("misc/poweroff.wav");
-       precache_sound(W_Sound("weaponpickup"));
-
        n = tokenize_console(self.netname);
        if(argv(0) == "give")
        {
@@ -1445,8 +1444,10 @@ void spawnfunc_target_items (void)
                                        if(s == e.netname)
                                        {
                                                self.weapons |= WepSet_FromWeapon(j);
-                                               if(self.spawnflags == 0 || self.spawnflags == 2)
-                                                       WEP_ACTION(e.weapon, WR_INIT);
+                                               if(self.spawnflags == 0 || self.spawnflags == 2) {
+                                                       Weapon w = get_weaponinfo(e.weapon);
+                                                       w.wr_init(w);
+                                               }
                                                break;
                                        }
                                }
@@ -1516,14 +1517,15 @@ void spawnfunc_target_items (void)
                        e = get_weaponinfo(j);
                        if(argv(i) == e.netname)
                        {
-                               WEP_ACTION(e.weapon, WR_INIT);
+                               Weapon w = get_weaponinfo(e.weapon);
+                               w.wr_init(w);
                                break;
                        }
                }
        }
 }
 
-void spawnfunc_item_fuel(void)
+spawnfunc(item_fuel)
 {
        if(!self.ammo_fuel)
                self.ammo_fuel = g_pickup_fuel;
@@ -1532,23 +1534,23 @@ void spawnfunc_item_fuel(void)
        StartItemA (ITEM_JetpackFuel);
 }
 
-void spawnfunc_item_fuel_regen(void)
+spawnfunc(item_fuel_regen)
 {
        if(start_items & ITEM_JetpackRegen.m_itemid)
        {
-               spawnfunc_item_fuel();
+               spawnfunc_item_fuel(this);
                return;
        }
        StartItemA (ITEM_JetpackRegen);
 }
 
-void spawnfunc_item_jetpack(void)
+spawnfunc(item_jetpack)
 {
        if(!self.ammo_fuel)
                self.ammo_fuel = g_pickup_fuel_jetpack;
        if(start_items & ITEM_Jetpack.m_itemid)
        {
-               spawnfunc_item_fuel();
+               spawnfunc_item_fuel(this);
                return;
        }
        StartItemA (ITEM_Jetpack);
@@ -1647,12 +1649,12 @@ void GiveSound(entity e, float v0, float v1, float t, string snd_incr, string sn
        if(v1 <= v0 - t)
        {
                if(snd_decr != "")
-                       sound (e, CH_TRIGGER, snd_decr, VOL_BASE, ATTEN_NORM);
+                       _sound (e, CH_TRIGGER, snd_decr, VOL_BASE, ATTEN_NORM);
        }
        else if(v0 >= v0 + t)
        {
                if(snd_incr != "")
-                       sound (e, CH_TRIGGER, snd_incr, VOL_BASE, ATTEN_NORM);
+                       _sound (e, CH_TRIGGER, snd_incr, VOL_BASE, ATTEN_NORM);
        }
 }
 
@@ -1664,7 +1666,7 @@ void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .floa
                e.(regenfield) = max(e.(regenfield), time + regentime);
 }
 float GiveItems(entity e, float beginarg, float endarg)
-{
+{SELFPARAM();
        float got, i, j, val, op;
        float _switchweapon;
        entity wi;
@@ -1818,31 +1820,33 @@ float GiveItems(entity e, float beginarg, float endarg)
                op = OP_SET;
        }
 
-       POSTGIVE_BIT(e, items, ITEM_JetpackRegen.m_itemid, "misc/itempickup.wav", string_null);
-       POSTGIVE_BIT(e, items, IT_UNLIMITED_SUPERWEAPONS, "misc/powerup.wav", "misc/poweroff.wav");
-       POSTGIVE_BIT(e, items, IT_UNLIMITED_WEAPON_AMMO, "misc/powerup.wav", "misc/poweroff.wav");
-       POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, "misc/itempickup.wav", string_null);
+       POSTGIVE_BIT(e, items, ITEM_JetpackRegen.m_itemid, SND(ITEMPICKUP), string_null);
+       POSTGIVE_BIT(e, items, IT_UNLIMITED_SUPERWEAPONS, SND(POWERUP), SND(POWEROFF));
+       POSTGIVE_BIT(e, items, IT_UNLIMITED_WEAPON_AMMO, SND(POWERUP), SND(POWEROFF));
+       POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, SND(ITEMPICKUP), string_null);
        for(j = WEP_FIRST; j <= WEP_LAST; ++j)
        {
                wi = get_weaponinfo(j);
                if(wi.weapon)
                {
-                       POSTGIVE_WEAPON(e, j, W_Sound("weaponpickup"), string_null);
+                       POSTGIVE_WEAPON(e, j, SND(WEAPONPICKUP), string_null);
                        if (!(save_weapons & WepSet_FromWeapon(j)))
-                               if(e.weapons & WepSet_FromWeapon(j))
-                                       WEP_ACTION(wi.weapon, WR_INIT);
+                               if(e.weapons & WepSet_FromWeapon(j)) {
+                                       Weapon w = get_weaponinfo(wi.weapon);
+                                       w.wr_init(w);
+                               }
                }
        }
-       POSTGIVE_VALUE(e, strength_finished, 1, "misc/powerup.wav", "misc/poweroff.wav");
-       POSTGIVE_VALUE(e, invincible_finished, 1, "misc/powerup_shield.wav", "misc/poweroff.wav");
-       POSTGIVE_VALUE(e, ammo_nails, 0, "misc/itempickup.wav", string_null);
-       POSTGIVE_VALUE(e, ammo_cells, 0, "misc/itempickup.wav", string_null);
-       POSTGIVE_VALUE(e, ammo_plasma, 0, "misc/itempickup.wav", string_null);
-       POSTGIVE_VALUE(e, ammo_shells, 0, "misc/itempickup.wav", string_null);
-       POSTGIVE_VALUE(e, ammo_rockets, 0, "misc/itempickup.wav", string_null);
-       POSTGIVE_VALUE_ROT(e, ammo_fuel, 1, pauserotfuel_finished, autocvar_g_balance_pause_fuel_rot, pauseregen_finished, autocvar_g_balance_pause_fuel_regen, "misc/itempickup.wav", string_null);
-       POSTGIVE_VALUE_ROT(e, armorvalue, 1, pauserotarmor_finished, autocvar_g_balance_pause_armor_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, "misc/armor25.wav", string_null);
-       POSTGIVE_VALUE_ROT(e, health, 1, pauserothealth_finished, autocvar_g_balance_pause_health_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, "misc/megahealth.wav", string_null);
+       POSTGIVE_VALUE(e, strength_finished, 1, SND(POWERUP), SND(POWEROFF));
+       POSTGIVE_VALUE(e, invincible_finished, 1, "misc/powerup_shield.wav", SND(POWEROFF));
+       POSTGIVE_VALUE(e, ammo_nails, 0, SND(ITEMPICKUP), string_null);
+       POSTGIVE_VALUE(e, ammo_cells, 0, SND(ITEMPICKUP), string_null);
+       POSTGIVE_VALUE(e, ammo_plasma, 0, SND(ITEMPICKUP), string_null);
+       POSTGIVE_VALUE(e, ammo_shells, 0, SND(ITEMPICKUP), string_null);
+       POSTGIVE_VALUE(e, ammo_rockets, 0, SND(ITEMPICKUP), string_null);
+       POSTGIVE_VALUE_ROT(e, ammo_fuel, 1, pauserotfuel_finished, autocvar_g_balance_pause_fuel_rot, pauseregen_finished, autocvar_g_balance_pause_fuel_regen, SND(ITEMPICKUP), string_null);
+       POSTGIVE_VALUE_ROT(e, armorvalue, 1, pauserotarmor_finished, autocvar_g_balance_pause_armor_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND(ARMOR25), string_null);
+       POSTGIVE_VALUE_ROT(e, health, 1, pauserothealth_finished, autocvar_g_balance_pause_health_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND(MEGAHEALTH), string_null);
 
        if(e.superweapons_finished <= 0)
                if(self.weapons & WEPSET_SUPERWEAPONS)
index d93e28bb611053773784fb08612df1f16ba83fdb..dd79b1788f2b14fbf451b5b4ee01f16d1f2ea3c6 100644 (file)
@@ -78,23 +78,23 @@ string autocvar_cl_simpleitems_postfix = "_simple";
 .float  spawntime;
 .float  gravity;
 .vector colormod;
-void ItemDraw();
 
-void ItemDrawSimple();
+void ItemDraw(entity this);
+void ItemDrawSimple(entity this);
 
 void ItemRead(float _IsNew);
 
 #endif
 #ifdef SVQC
-void spawnfunc_item_strength();
-void spawnfunc_item_invincible();
-void spawnfunc_item_armor_small();
-void spawnfunc_item_shells();
-void spawnfunc_item_bullets();
-void spawnfunc_item_rockets();
+spawnfunc(item_strength);
+spawnfunc(item_invincible);
+spawnfunc(item_armor_small);
+spawnfunc(item_shells);
+spawnfunc(item_bullets);
+spawnfunc(item_rockets);
 
 float autocvar_sv_simple_items;
-bool ItemSend(entity to, int sf);
+bool ItemSend(entity this, entity to, int sf);
 
 
 float have_pickup_item(void);
@@ -135,7 +135,7 @@ void Item_FindTeam();
 // Savage: used for item garbage-collection
 // TODO: perhaps nice special effect?
 
-bool ItemSend(entity to, int sf);
+bool ItemSend(entity this, entity to, int sf);
 void ItemUpdate(entity item);
 
 // pickup evaluation functions
index 517b8808225f50773e2e9b303af7ff717ac33f3c..9e22b8d06542ddf2236c4cb2a5ba57dbbbe9e546 100644 (file)
@@ -2,27 +2,27 @@
 
 #include "../common/weapons/all.qh"
 
-void spawnfunc_weapon_electro();
-void spawnfunc_weapon_hagar();
-void spawnfunc_weapon_machinegun();
-void spawnfunc_item_bullets();
-void spawnfunc_item_armor_large();
-void spawnfunc_item_armor_large();
-void spawnfunc_item_health_mega();
-void spawnfunc_item_health_medium();
+spawnfunc(weapon_electro);
+spawnfunc(weapon_hagar);
+spawnfunc(weapon_machinegun);
+spawnfunc(item_bullets);
+spawnfunc(item_armor_large);
+spawnfunc(item_armor_large);
+spawnfunc(item_health_mega);
+spawnfunc(item_health_medium);
 
 //***********************
 //QUAKE 1 ENTITIES - So people can play quake1 maps with the xonotic weapons
 //***********************
-void spawnfunc_weapon_nailgun (void) {spawnfunc_weapon_electro();}
-void spawnfunc_weapon_supernailgun (void) {spawnfunc_weapon_hagar();}
-void spawnfunc_weapon_supershotgun (void) {spawnfunc_weapon_machinegun();}
-
-void spawnfunc_item_spikes (void) {spawnfunc_item_bullets();}
-//void spawnfunc_item_armor1 (void) {spawnfunc_item_armor_medium;}  // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
-void spawnfunc_item_armor2 (void) {spawnfunc_item_armor_large();}
-void item_armorInv (void) {spawnfunc_item_armor_large();}
-void spawnfunc_item_health (void) {if (self.spawnflags & 2) spawnfunc_item_health_mega();else spawnfunc_item_health_medium();}
+spawnfunc(weapon_nailgun) {spawnfunc_weapon_electro(this);}
+spawnfunc(weapon_supernailgun) {spawnfunc_weapon_hagar(this);}
+spawnfunc(weapon_supershotgun) {spawnfunc_weapon_machinegun(this);}
+
+spawnfunc(item_spikes) {spawnfunc_item_bullets(this);}
+//spawnfunc(item_armor1) {spawnfunc_item_armor_medium(this);}  // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
+spawnfunc(item_armor2) {spawnfunc_item_armor_large(this);}
+void item_armorInv() {SELFPARAM();spawnfunc_item_armor_large(self);}
+spawnfunc(item_health) {if (self.spawnflags & 2) spawnfunc_item_health_mega(this);else spawnfunc_item_health_medium(this);}
 
 //spawnfunc_item_spikes
 //spawnfunc_item_health
index 6908b6dbf18500f2927971f6441f2cbd04602831..c8f595761d0b6e03ad911b66cb6f1c7080f1b82a 100644 (file)
@@ -1,29 +1,29 @@
 #include "_all.qh"
 
 #include "../common/weapons/all.qh"
-#include "../common/buffs.qh"
+#include "../common/buffs/all.qh"
 
-void spawnfunc_weapon_crylink();
-void spawnfunc_weapon_electro();
-void spawnfunc_weapon_hagar();
-void spawnfunc_weapon_machinegun();
-void spawnfunc_weapon_vortex();
+spawnfunc(weapon_crylink);
+spawnfunc(weapon_electro);
+spawnfunc(weapon_hagar);
+spawnfunc(weapon_machinegun);
+spawnfunc(weapon_vortex);
 
-void spawnfunc_target_items();
+spawnfunc(target_items);
 
-void spawnfunc_item_bullets();
-void spawnfunc_item_cells();
-void spawnfunc_item_rockets();
-void spawnfunc_item_shells();
+spawnfunc(item_bullets);
+spawnfunc(item_cells);
+spawnfunc(item_rockets);
+spawnfunc(item_shells);
 
-void spawnfunc_item_jetpack();
+spawnfunc(item_jetpack);
 
-void spawnfunc_item_armor_big();
-void spawnfunc_item_armor_large();
-void spawnfunc_item_armor_small();
+spawnfunc(item_armor_big);
+spawnfunc(item_armor_large);
+spawnfunc(item_armor_small);
 
-void spawnfunc_item_health_medium();
-void spawnfunc_item_health_mega();
+spawnfunc(item_health_medium);
+spawnfunc(item_health_mega);
 
 //***********************
 //QUAKE 3 ENTITIES - So people can play quake3 maps with the xonotic weapons
@@ -32,38 +32,38 @@ void spawnfunc_item_health_mega();
 // NOTE: for best experience, you need to swap MGs with SGs in the map or it won't have a MG
 
 // SG -> SG
-void spawnfunc_ammo_shells()         { spawnfunc_item_shells();         }
+spawnfunc(ammo_shells)         { spawnfunc_item_shells(this);         }
 
 // MG -> MG
-void spawnfunc_ammo_bullets()        { spawnfunc_item_bullets();        }
+spawnfunc(ammo_bullets)        { spawnfunc_item_bullets(this);        }
 
 // GL -> Mortar
-void spawnfunc_ammo_grenades()       { spawnfunc_item_rockets();        }
+spawnfunc(ammo_grenades)       { spawnfunc_item_rockets(this);        }
 
 // LG -> Lightning
-void spawnfunc_weapon_lightning()    { spawnfunc_weapon_electro();      }
-void spawnfunc_ammo_lightning()      { spawnfunc_item_cells();          }
+spawnfunc(weapon_lightning)    { spawnfunc_weapon_electro(this);      }
+spawnfunc(ammo_lightning)      { spawnfunc_item_cells(this);          }
 
 // Plasma -> Hagar
-void spawnfunc_weapon_plasmagun()    { spawnfunc_weapon_hagar();        }
-void spawnfunc_ammo_cells()          { spawnfunc_item_rockets();        }
+spawnfunc(weapon_plasmagun)    { spawnfunc_weapon_hagar(this);        }
+spawnfunc(ammo_cells)          { spawnfunc_item_rockets(this);        }
 
 // Rail -> Vortex
-void spawnfunc_weapon_railgun()      { spawnfunc_weapon_vortex();          }
-void spawnfunc_ammo_slugs()          { spawnfunc_item_cells();          }
+spawnfunc(weapon_railgun)      { spawnfunc_weapon_vortex(this);          }
+spawnfunc(ammo_slugs)          { spawnfunc_item_cells(this);          }
 
 // BFG -> Crylink
-void spawnfunc_weapon_bfg()          { spawnfunc_weapon_crylink();      }
-void spawnfunc_ammo_bfg()            { spawnfunc_item_cells();          }
+spawnfunc(weapon_bfg)          { spawnfunc_weapon_crylink(this);      }
+spawnfunc(ammo_bfg)            { spawnfunc_item_cells(this);          }
 
 // RL -> RL
-void spawnfunc_ammo_rockets()        { spawnfunc_item_rockets();        }
+spawnfunc(ammo_rockets)        { spawnfunc_item_rockets(this);        }
 
 // Armor
-void spawnfunc_item_armor_body()     { spawnfunc_item_armor_large();    }
-void spawnfunc_item_armor_combat()   { spawnfunc_item_armor_big();      }
-void spawnfunc_item_armor_shard()    { spawnfunc_item_armor_small();    }
-void spawnfunc_item_enviro()         { spawnfunc_item_invincible();     }
+spawnfunc(item_armor_body)     { spawnfunc_item_armor_large(this);    }
+spawnfunc(item_armor_combat)   { spawnfunc_item_armor_big(this);      }
+spawnfunc(item_armor_shard)    { spawnfunc_item_armor_small(this);    }
+spawnfunc(item_enviro)         { spawnfunc_item_invincible(this);     }
 
 // weapon remove ent from df
 void target_init_verify()
@@ -84,17 +84,17 @@ void target_init_verify()
                        }
 }
 
-void spawnfunc_target_init()
+spawnfunc(target_init)
 {
        self.spawnflags = 0; // remove all weapons except the ones listed below
        self.netname = "shotgun"; // keep these weapons through the remove trigger
-       spawnfunc_target_items();
+       spawnfunc_target_items(this);
        InitializeEntity(self, target_init_verify, INITPRIO_FINDTARGET);
 }
 
 // weapon give ent from defrag
 void target_give_init()
-{
+{SELFPARAM();
        entity targ;
        for (targ = world; (targ = find(targ, targetname, self.target)); ) {
                if (targ.classname == "weapon_rocketlauncher" || targ.classname == "weapon_devastator") {
@@ -131,30 +131,30 @@ void target_give_init()
         targ.nextthink = time;
        }
        self.spawnflags = 2;
-       spawnfunc_target_items();
+       spawnfunc_target_items(this);
        InitializeEntity(self, target_init_verify, INITPRIO_FINDTARGET);
 }
 
-void spawnfunc_target_give()
+spawnfunc(target_give)
 {
        InitializeEntity(self, target_give_init, INITPRIO_FINDTARGET);
 }
 
-//void spawnfunc_item_flight()       /* handled by buffs mutator or jetpack */
-//void spawnfunc_item_haste()        /* handled by buffs mutator */
-//void spawnfunc_item_health()       /* handled in t_quake.qc */
-//void spawnfunc_item_health_large() /* handled in t_items.qc */
-//void spawnfunc_item_health_small() /* handled in t_items.qc */
-//void spawnfunc_item_health_mega()  /* handled in t_items.qc */
-//void spawnfunc_item_invis()        /* handled by buffs mutator */
-//void spawnfunc_item_regen()        /* handled by buffs mutator */
+//spawnfunc(item_flight)       /* handled by buffs mutator or jetpack */
+//spawnfunc(item_haste)        /* handled by buffs mutator */
+//spawnfunc(item_health)       /* handled in t_quake.qc */
+//spawnfunc(item_health_large) /* handled in t_items.qc */
+//spawnfunc(item_health_small) /* handled in t_items.qc */
+//spawnfunc(item_health_mega)  /* handled in t_items.qc */
+//spawnfunc(item_invis)        /* handled by buffs mutator */
+//spawnfunc(item_regen)        /* handled by buffs mutator */
 
 // CTF spawnfuncs handled in mutators/gamemode_ctf.qc now
 
-void spawnfunc_item_flight()
+spawnfunc(item_flight)
 {
        if(!cvar("g_buffs") || !cvar("g_buffs_flight"))
-               spawnfunc_item_jetpack();
+               spawnfunc_item_jetpack(this);
        else
                buff_Init_Compat(self, BUFF_FLIGHT);
 }
@@ -166,7 +166,7 @@ void spawnfunc_item_flight()
 .float notta;
 .string gametype;
 float DoesQ3ARemoveThisEntity()
-{
+{SELFPARAM();
        // Q3 style filters (DO NOT USE, THIS IS COMPAT ONLY)
 
        if(self.notq3a)
index b41ebaca9f6c4b3606808dc58394a53ff9b8d279..2fbbd50b32e3c9dc78b214ae0dcda2c6a9f817e3 100644 (file)
@@ -247,9 +247,6 @@ void InitGameplayMode()
                MUTATOR_ADD(gamemode_invasion);
        }
 
-       if(teamplay)
-               entcs_init();
-
        cache_mutatormsg = strzone("");
        cache_lastmutatormsg = strzone("");
 
@@ -269,7 +266,8 @@ void InitGameplayMode()
        InitializeEntity(world, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK);
 }
 
-string GetClientVersionMessage() {
+string GetClientVersionMessage()
+{SELFPARAM();
        string versionmsg;
        if (self.version_mismatch) {
                if(self.version < autocvar_gameversion) {
@@ -303,8 +301,6 @@ string getwelcomemessage(void)
                modifications = strcat(modifications, ", Low gravity");
        if(g_cloaked && !g_cts)
                modifications = strcat(modifications, ", Cloaked");
-       if(g_grappling_hook)
-               modifications = strcat(modifications, ", Hook");
        if(g_weapon_stay && !g_cts)
                modifications = strcat(modifications, ", Weapons stay");
        if(g_jetpack)
@@ -324,9 +320,6 @@ string getwelcomemessage(void)
        if(modifications != "")
                s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
 
-       if (g_grappling_hook)
-               s = strcat(s, "\n\n^3grappling hook^8 is enabled, press 'e' to use it\n");
-
        if (cvar("g_nades"))
                s = strcat(s, "\n\n^3nades^8 are enabled, press 'g' to use them\n");
 
@@ -404,7 +397,7 @@ void SetPlayerTeam(entity pl, float t, float s, float noprint)
 
 // set c1...c4 to show what teams are allowed
 void CheckAllowedTeams (entity for_whom)
-{
+{SELFPARAM();
        float dm;
        entity head;
        string teament_name;
@@ -710,7 +703,7 @@ float FindSmallestTeam(entity pl, float ignore_pl)
 }
 
 float JoinBestTeam(entity pl, float only_return_best, float forcebestteam)
-{
+{SELFPARAM();
        float smallest, selectedteam;
 
        // don't join a team if we're not playing a team game
@@ -787,7 +780,7 @@ float JoinBestTeam(entity pl, float only_return_best, float forcebestteam)
 
 //void() ctf_playerchanged;
 void SV_ChangeTeam(float _color)
-{
+{SELFPARAM();
        float scolor, dcolor, steam, dteam; //, dbotcount, scount, dcount;
 
        // in normal deathmatch we can just apply the color and we're done
index 8ce6eae61b79e4377bfe3da50122c707e0e68527..3ce05ac2a66c2d24ab50dc74b91a94c61d6d156a 100644 (file)
@@ -13,8 +13,6 @@ float cb1, cb2, cb3, cb4;
 
 void TeamchangeFrags(entity e);
 
-void entcs_init();
-
 void LogTeamchange(float player_id, float team_number, float type);
 
 void default_delayedinit();
index d0dda35af10cc979ca3296adc0b6883d8ac6c746..09f155ecbd7ea68052a953e1f713c560f0d829b4 100644 (file)
@@ -17,7 +17,7 @@ float accuracy_byte(float n, float d)
        return 1 + rint(n * 100.0 / d);
 }
 
-float accuracy_send(entity to, int sf)
+bool accuracy_send(entity this, entity to, int sf)
 {
        int w, f;
        entity a;
index 03f002f6a9fd59d8576de2050ab60c0dc2aa96d0..e8d22d98b19db76ac1f14935aee31b2f3ce2c96d 100644 (file)
@@ -5,12 +5,12 @@
 .float cvar_cl_accuracy_data_receive;
 
 .entity accuracy;
-.float accuracy_frags[WEP_MAXCOUNT];
+.float accuracy_frags[Weapons_MAX];
 
-.float accuracy_hit[WEP_MAXCOUNT];
-.float accuracy_fired[WEP_MAXCOUNT];
-.float accuracy_cnt_hit[WEP_MAXCOUNT];
-.float accuracy_cnt_fired[WEP_MAXCOUNT];
+.float accuracy_hit[Weapons_MAX];
+.float accuracy_fired[Weapons_MAX];
+.float accuracy_cnt_hit[Weapons_MAX];
+.float accuracy_cnt_fired[Weapons_MAX];
 
 
 // init/free
index 8c3c883815e80816849267c47e37180769432d79..f1720757f6607564db7f1a89083570178afac39b 100644 (file)
@@ -9,21 +9,19 @@
 #include "../../common/weapons/all.qh"
 
 void W_GiveWeapon (entity e, float wep)
-{
-       entity oldself;
+{SELFPARAM();
 
        if (!wep)
                return;
 
        e.weapons |= WepSet_FromWeapon(wep);
 
-       oldself = self;
-       self = e;
+       setself(e);
 
        if(IS_PLAYER(other))
                { Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_WEAPON_GOT, wep); }
 
-       self = oldself;
+       setself(this);
 }
 
 void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound
@@ -32,7 +30,7 @@ void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound
                && ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam
                || (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold)))
                {
-                       sound(player, CH_TRIGGER, W_Sound("strength_fire"), VOL_BASE, ATTEN_NORM);
+                       sound(player, CH_TRIGGER, SND_STRENGTH_FIRE, VOL_BASE, ATTEN_NORM);
                        player.prevstrengthsound = time;
                }
                player.prevstrengthsoundattempt = time;
@@ -81,7 +79,7 @@ float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype,
 }
 
 void W_PrepareExplosionByDamage(entity attacker, void() explode)
-{
+{SELFPARAM();
        self.takedamage = DAMAGE_NO;
        self.event_damage = func_null;
 
index 507fc4a413b792d6d5450d3591c6442c6d438036..ca98ad10b8bc3837d29651542795ec1ba20e4a7f 100644 (file)
@@ -10,7 +10,7 @@
 
 .float csqcprojectile_type;
 
-bool CSQCProjectile_SendEntity(entity to, int sf)
+bool CSQCProjectile_SendEntity(entity this, entity to, int sf)
 {
        float ft, fr;
 
@@ -99,13 +99,13 @@ void CSQCProjectile(entity e, float clientanimate, int type, float docull)
 
 void UpdateCSQCProjectile(entity e)
 {
-       if(e.SendEntity == CSQCProjectile_SendEntity)
+       if(e.SendEntity3 == CSQCProjectile_SendEntity)
        {
                // send new origin data
                e.SendFlags |= 0x01;
        }
 // FIXME HACK
-       else if(e.SendEntity == ItemSend)
+       else if(e.SendEntity3 == ItemSend)
        {
                ItemUpdate(e);
        }
@@ -114,7 +114,7 @@ void UpdateCSQCProjectile(entity e)
 
 void UpdateCSQCProjectileAfterTeleport(entity e)
 {
-       if(e.SendEntity == CSQCProjectile_SendEntity)
+       if(e.SendEntity3 == CSQCProjectile_SendEntity)
        {
                // send new origin data
                e.SendFlags |= 0x01;
index d563ac2d84eb3cd01ebf85e8ac8a054c53432b5e..ce2a671c4584f9290ea9a67d93b985c102f11179 100644 (file)
@@ -18,15 +18,16 @@ void Send_WeaponComplain(entity e, float wpn, float type)
 }
 
 float client_hasweapon(entity cl, float wpn, float andammo, float complain)
-{
+{SELFPARAM();
        float f;
-       entity oldself;
 
        if(time < self.hasweapon_complain_spam)
                complain = 0;
 
-       if(wpn == WEP_HOOK.m_id && !g_grappling_hook && autocvar_g_nades && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn)))
-               complain = 0;
+       // ignore hook button when using other offhand equipment
+       if (cl.offhand != OFFHAND_HOOK)
+       if (wpn == WEP_HOOK.m_id && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn)))
+           complain = 0;
 
        if(complain)
                self.hasweapon_complain_spam = time + 0.2;
@@ -47,10 +48,9 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                        }
                        else
                        {
-                               oldself = self;
-                               self = cl;
-                               f = WEP_ACTION(wpn, WR_CHECKAMMO1);
-                               f = f + WEP_ACTION(wpn, WR_CHECKAMMO2);
+                               setself(cl);
+                               Weapon w = get_weaponinfo(wpn);
+                               f = w.wr_checkammo1(w) + w.wr_checkammo2(w);
 
                                // always allow selecting the Mine Layer if we placed mines, so that we can detonate them
                                entity mine;
@@ -58,14 +58,14 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                                for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
                                        f = 1;
 
-                               self = oldself;
+                               setself(this);
                        }
                        if (!f)
                        {
                                if (complain)
                                if(IS_REAL_CLIENT(cl))
                                {
-                                       play2(cl, W_Sound("unavailable"));
+                                       play2(cl, SND(UNAVAILABLE));
                                        Send_WeaponComplain (cl, wpn, 0);
                                }
                                return false;
@@ -109,13 +109,13 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                        Send_WeaponComplain (cl, wpn, 2);
                }
 
-               play2(cl, W_Sound("unavailable"));
+               play2(cl, SND(UNAVAILABLE));
        }
        return false;
 }
 
 float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing)
-{
+{SELFPARAM();
        // We cannot tokenize in this function, as GiveItems calls this
        // function. Thus we must use car/cdr.
        float weaponwant, first_valid, prev_valid, switchtonext, switchtolast;
@@ -254,7 +254,7 @@ void W_SwitchToOtherWeapon(entity pl)
 }
 
 void W_SwitchWeapon(float imp)
-{
+{SELFPARAM();
        if (self.switchweapon != imp)
        {
                if (client_hasweapon(self, imp, true, true))
@@ -262,11 +262,14 @@ void W_SwitchWeapon(float imp)
                else
                        self.selectweapon = imp; // update selectweapon ANYWAY
        }
-       else if(!forbidWeaponUse(self)) { WEP_ACTION(self.weapon, WR_RELOAD); }
+       else if(!forbidWeaponUse(self)) {
+               Weapon w = get_weaponinfo(self.weapon);
+               w.wr_reload(w);
+       }
 }
 
 void W_CycleWeapon(string weaponorder, float dir)
-{
+{SELFPARAM();
        float w;
        w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, true);
        if(w > 0)
@@ -274,7 +277,7 @@ void W_CycleWeapon(string weaponorder, float dir)
 }
 
 void W_NextWeaponOnImpulse(float imp)
-{
+{SELFPARAM();
        float w;
        w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0));
        if(w > 0)
@@ -283,7 +286,7 @@ void W_NextWeaponOnImpulse(float imp)
 
 // next weapon
 void W_NextWeapon(float list)
-{
+{SELFPARAM();
        if(list == 0)
                W_CycleWeapon(weaponorder_byid, -1);
        else if(list == 1)
@@ -294,7 +297,7 @@ void W_NextWeapon(float list)
 
 // prev weapon
 void W_PreviousWeapon(float list)
-{
+{SELFPARAM();
        if(list == 0)
                W_CycleWeapon(weaponorder_byid, +1);
        else if(list == 1)
@@ -305,7 +308,7 @@ void W_PreviousWeapon(float list)
 
 // previously used if exists and has ammo, (second) best otherwise
 void W_LastWeapon(void)
-{
+{SELFPARAM();
        if(client_hasweapon(self, self.cnt, true, false))
                W_SwitchWeapon(self.cnt);
        else
index 3c3c9d80695fde47bfb984a548919eb643cc19d2..b011bb1fffd3e9c1fd5d3318d0765edd1bc26da7 100644 (file)
@@ -35,11 +35,10 @@ string W_Apply_Weaponreplace(string in)
 }
 
 void weapon_defaultspawnfunc(float wpn)
-{
+{SELFPARAM();
        entity e;
        float t;
        string s;
-       entity oldself;
        float i, j;
        int f;
 
@@ -67,7 +66,6 @@ void weapon_defaultspawnfunc(float wpn)
                if(t >= 2)
                {
                        self.team = --internalteam;
-                       oldself = self;
                        for(i = 1; i < t; ++i)
                        {
                                s = argv(i);
@@ -76,8 +74,8 @@ void weapon_defaultspawnfunc(float wpn)
                                        e = get_weaponinfo(j);
                                        if(e.netname == s)
                                        {
-                                               self = spawn();
-                                               copyentity(oldself, self);
+                                               setself(spawn());
+                                               copyentity(this, self);
                                                self.classname = "replacedweapon";
                                                weapon_defaultspawnfunc(j);
                                                break;
@@ -85,10 +83,10 @@ void weapon_defaultspawnfunc(float wpn)
                                }
                                if(j > WEP_LAST)
                                {
-                                       LOG_INFO("The weapon replace list for ", oldself.classname, " contains an unknown weapon ", s, ". Skipped.\n");
+                                       LOG_INFO("The weapon replace list for ", this.classname, " contains an unknown weapon ", s, ". Skipped.\n");
                                }
                        }
-                       self = oldself;
+                       setself(this);
                }
                if(t >= 1) // always the case!
                {
@@ -179,9 +177,12 @@ void weapon_defaultspawnfunc(float wpn)
        if(self.team)
                f |= FL_NO_WEAPON_STAY;
 
-       StartItem(e.model, "weapons/weaponpickup.wav", self.respawntime, self.respawntimejitter, e.message, 0, e.weapon, f, weapon_pickupevalfunc, e.bot_pickupbasevalue);
+       StartItem(strzone(e.m_model.model_str()), string_null, self.respawntime, self.respawntimejitter, e.message, 0, e.weapon, f, weapon_pickupevalfunc, e.bot_pickupbasevalue);
+       self.item_pickupsound_ent = SND_WEAPONPICKUP;
        #if 0 // WEAPONTODO
-       if (self.modelindex) // don't precache if self was removed
-               WEP_ACTION(e.weapon, WR_INIT);
+       if (self.modelindex) { // don't precache if self was removed
+               Weapon w = get_weaponinfo(e.weapon);
+               w.wr_init(w);
+       }
        #endif
 }
index 89ec52f2179f5114230addfe9eb567aa6909c55a..a649cf75b9858ee2d84ce74ce6e1b857e021a522 100644 (file)
@@ -11,7 +11,7 @@
 #include "../../common/weapons/all.qh"
 
 void thrown_wep_think()
-{
+{SELFPARAM();
        self.nextthink = time;
        if(self.oldorigin != self.origin)
        {
@@ -30,13 +30,12 @@ void thrown_wep_think()
 
 // returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
 string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo)
-{
-       entity oldself, wep;
+{SELFPARAM();
        float thisammo, i;
        string s;
        var .int ammotype = (get_weaponinfo(wpn)).ammo_field;
 
-       wep = spawn();
+       entity wep = spawn();
 
        setorigin(wep, org);
        wep.classname = "droppedweapon";
@@ -45,7 +44,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
        wep.flags |= FL_TOSSED;
        wep.colormap = own.colormap;
 
-       W_DropEvent(WR_DROP,own,wpn,wep);
+       W_DropEvent(wr_drop,own,wpn,wep);
 
        if(WepSet_FromWeapon(wpn) & WEPSET_SUPERWEAPONS)
        {
@@ -75,10 +74,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                }
        }
 
-       oldself = self;
-       self = wep;
-       weapon_defaultspawnfunc(wpn);
-       self = oldself;
+       WITH(entity, self, wep, weapon_defaultspawnfunc(wpn));
        if(startitem_failed)
                return string_null;
        wep.glowmod = own.weaponentity_glowmod;
@@ -166,7 +162,7 @@ float W_IsWeaponThrowable(float w)
 
 // toss current weapon
 void W_ThrowWeapon(vector velo, vector delta, float doreduce)
-{
+{SELFPARAM();
        float w;
        string a;
 
@@ -194,7 +190,7 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce)
 }
 
 void SpawnThrownWeapon(vector org, float w)
-{
+{SELFPARAM();
        if(self.weapons & WepSet_FromWeapon(self.weapon))
                if(W_IsWeaponThrowable(self.weapon))
                        W_ThrowNewWeapon(self, self.weapon, false, org, randomvec() * 125 + '0 0 200');
index eec32a3e51ac0339bf9c764d992b15aa3b942b90..69821aaaf6d84f42f79055407747e6f521e14d8c 100644 (file)
@@ -131,7 +131,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector m
 
        if (snd != "")
        {
-               sound (ent, chan, snd, VOL_BASE, ATTN_NORM);
+               _sound (ent, chan, snd, VOL_BASE, ATTN_NORM);
                W_PlayStrengthSound(ent);
        }
 
@@ -194,7 +194,7 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p
 // ====================
 
 void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
-{
+{SELFPARAM();
        vector hitloc, force, endpoint, dir;
        entity ent, endent;
        float endq3surfaceflags;
@@ -287,7 +287,7 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f
                        if(f <= 0)
                                continue;
 
-                       snd = W_Sound(strcat("nexwhoosh", ftos(floor(random() * 3) + 1)));
+                       snd = SND(NEXWHOOSH_RANDOM());
 
                        if(!pseudoprojectile)
                                pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume
@@ -345,7 +345,7 @@ void fireBullet_trace_callback(vector start, vector hit, vector end)
 }
 
 void fireBullet(vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects)
-{
+{SELFPARAM();
        vector  end;
 
        dir = normalize(dir + randomvec() * spread);
index f53e3c53d09119c21b6c5542d640197dc9cf0b37..ae76b36b662901661a8cdb172126bfd4c21f015d 100644 (file)
@@ -47,10 +47,10 @@ float W_WeaponSpeedFactor()
 }
 
 
-void(float fr, float t, void() func) weapon_thinkf;
+void weapon_thinkf(entity actor, float fr, float t, void(Weapon thiswep, entity actor, bool fire1, bool fire2) func);
 
 float CL_Weaponentity_CustomizeEntityForClient()
-{
+{SELFPARAM();
        self.viewmodelforclient = self.owner;
        if(IS_SPEC(other))
                if(other.enemy == self.owner)
@@ -110,19 +110,19 @@ float CL_Weaponentity_CustomizeEntityForClient()
 //   call again with ""
 //   remove the ent
 void CL_WeaponEntity_SetModel(string name)
-{
+{SELFPARAM();
        float v_shot_idx;
        if (name != "")
        {
                // if there is a child entity, hide it until we're sure we use it
                if (self.weaponentity)
                        self.weaponentity.model = "";
-               setmodel(self, W_Model(strcat("v_", name, ".md3")));
+               _setmodel(self, W_Model(strcat("v_", name, ".md3")));
                v_shot_idx = gettagindex(self, "shot"); // used later
                if(!v_shot_idx)
                        v_shot_idx = gettagindex(self, "tag_shot");
 
-               setmodel(self, W_Model(strcat("h_", name, ".iqm")));
+               _setmodel(self, W_Model(strcat("h_", name, ".iqm")));
                // preset some defaults that work great for renamed zym files (which don't need an animinfo)
                self.anim_fire1  = animfixfps(self, '0 1 0.01', '0 0 0');
                self.anim_fire2  = animfixfps(self, '1 1 0.01', '0 0 0');
@@ -135,14 +135,14 @@ void CL_WeaponEntity_SetModel(string name)
                {
                        if (!self.weaponentity)
                                self.weaponentity = spawn();
-                       setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
+                       _setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
                        setattachment(self.weaponentity, self, "weapon");
                }
                else if(gettagindex(self, "tag_weapon"))
                {
                        if (!self.weaponentity)
                                self.weaponentity = spawn();
-                       setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
+                       _setmodel(self.weaponentity, W_Model(strcat("v_", name, ".md3")));
                        setattachment(self.weaponentity, self, "tag_weapon");
                }
                else
@@ -269,22 +269,19 @@ void CL_WeaponEntity_SetModel(string name)
 }
 
 vector CL_Weapon_GetShotOrg(float wpn)
-{
-       entity wi, oldself;
-       vector ret;
-       wi = get_weaponinfo(wpn);
-       oldself = self;
-       self = spawn();
+{SELFPARAM();
+       entity wi = get_weaponinfo(wpn);
+       setself(spawn());
        CL_WeaponEntity_SetModel(wi.mdl);
-       ret = self.movedir;
+       vector ret = self.movedir;
        CL_WeaponEntity_SetModel("");
        remove(self);
-       self = oldself;
+       setself(this);
        return ret;
 }
 
 void CL_Weaponentity_Think()
-{
+{SELFPARAM();
        int tb;
        self.nextthink = time;
        if (intermission_running)
@@ -360,7 +357,7 @@ void CL_Weaponentity_Think()
 }
 
 void CL_ExteriorWeaponentity_Think()
-{
+{SELFPARAM();
        float tag_found;
        self.nextthink = time;
        if (self.owner.exteriorweaponentity != self)
@@ -379,7 +376,7 @@ void CL_ExteriorWeaponentity_Think()
                self.dmg = self.owner.modelindex;
                self.deadflag = self.owner.deadflag;
                if (self.owner.weaponname != "")
-                       setmodel(self, W_Model(strcat("v_", self.owner.weaponname, ".md3")));
+                       _setmodel(self, W_Model(strcat("v_", self.owner.weaponname, ".md3")));
                else
                        self.model = "";
 
@@ -404,122 +401,127 @@ void CL_ExteriorWeaponentity_Think()
        self.glowmod = self.owner.weaponentity_glowmod;
        self.colormap = self.owner.colormap;
 
-       CSQCMODEL_AUTOUPDATE();
+       CSQCMODEL_AUTOUPDATE(self);
 }
 
 // spawning weaponentity for client
-void CL_SpawnWeaponentity()
+void CL_SpawnWeaponentity(entity e)
 {
-       self.weaponentity = spawn();
-       self.weaponentity.classname = "weaponentity";
-       self.weaponentity.solid = SOLID_NOT;
-       self.weaponentity.owner = self;
-       setmodel(self.weaponentity, ""); // precision set when changed
-       setorigin(self.weaponentity, '0 0 0');
-       self.weaponentity.angles = '0 0 0';
-       self.weaponentity.viewmodelforclient = self;
-       self.weaponentity.flags = 0;
-       self.weaponentity.think = CL_Weaponentity_Think;
-       self.weaponentity.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
-       self.weaponentity.nextthink = time;
-
-       self.exteriorweaponentity = spawn();
-       self.exteriorweaponentity.classname = "exteriorweaponentity";
-       self.exteriorweaponentity.solid = SOLID_NOT;
-       self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity;
-       self.exteriorweaponentity.owner = self;
-       setorigin(self.exteriorweaponentity, '0 0 0');
-       self.exteriorweaponentity.angles = '0 0 0';
-       self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;
-       self.exteriorweaponentity.nextthink = time;
-
-       {
-               entity oldself = self;
-               self = self.exteriorweaponentity;
-               CSQCMODEL_AUTOINIT();
-               self = oldself;
-       }
+       entity view = e.weaponentity = spawn();
+       view.classname = "weaponentity";
+       view.solid = SOLID_NOT;
+       view.owner = e;
+       setmodel(view, MDL_Null); // precision set when changed
+       setorigin(view, '0 0 0');
+       view.angles = '0 0 0';
+       view.viewmodelforclient = e;
+       view.flags = 0;
+       view.think = CL_Weaponentity_Think;
+       view.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
+       view.nextthink = time;
+
+       entity exterior = e.exteriorweaponentity = spawn();
+       exterior.classname = "exteriorweaponentity";
+       exterior.solid = SOLID_NOT;
+       exterior.exteriorweaponentity = exterior;
+       exterior.owner = e;
+       setorigin(exterior, '0 0 0');
+       exterior.angles = '0 0 0';
+       exterior.think = CL_ExteriorWeaponentity_Think;
+       exterior.nextthink = time;
+
+       CSQCMODEL_AUTOINIT(exterior);
 }
 
 // Weapon subs
-void w_clear()
+void w_clear(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       if (self.weapon != -1)
+       if (actor.weapon != -1)
        {
-               self.weapon = 0;
-               self.switchingweapon = 0;
+               actor.weapon = 0;
+               actor.switchingweapon = 0;
        }
-       if (self.weaponentity)
+       if (actor.weaponentity)
        {
-               self.weaponentity.state = WS_CLEAR;
-               self.weaponentity.effects = 0;
+               actor.weaponentity.state = WS_CLEAR;
+               actor.weaponentity.effects = 0;
        }
 }
 
-void w_ready()
+void w_ready(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
-       if (self.weaponentity)
-               self.weaponentity.state = WS_READY;
-       weapon_thinkf(WFRAME_IDLE, 1000000, w_ready);
+       if (actor.weaponentity)
+               actor.weaponentity.state = WS_READY;
+       weapon_thinkf(actor, WFRAME_IDLE, 1000000, w_ready);
 }
 
 .float prevdryfire;
 .float prevwarntime;
-float weapon_prepareattack_checkammo(float secondary)
+bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, float secondary)
 {
-       if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-       if (!WEP_ACTION(self.weapon, WR_CHECKAMMO1 + secondary))
-       {
-               // always keep the Mine Layer if we placed mines, so that we can detonate them
-               entity mine;
-               if(self.weapon == WEP_MINE_LAYER.m_id)
-               for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
-                       return false;
+       if ((actor.items & IT_UNLIMITED_WEAPON_AMMO)) return true;
+       bool ammo = false;
+       if (secondary) {
+               WITH(entity, self, actor, ammo = thiswep.wr_checkammo2(thiswep));
+       } else {
+               WITH(entity, self, actor, ammo = thiswep.wr_checkammo1(thiswep));
+       }
+       if (ammo) return true;
+       // always keep the Mine Layer if we placed mines, so that we can detonate them
+       entity mine;
+       if(actor.weapon == WEP_MINE_LAYER.m_id)
+       for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == actor)
+               return false;
 
-               if(self.weapon == WEP_SHOTGUN.m_id)
-               if(!secondary && WEP_CVAR(shotgun, secondary) == 1)
-                       return false; // no clicking, just allow
+       if(actor.weapon == WEP_SHOTGUN.m_id)
+       if(!secondary && WEP_CVAR(shotgun, secondary) == 1)
+               return false; // no clicking, just allow
 
-               if(self.weapon == self.switchweapon && time - self.prevdryfire > 1) // only play once BEFORE starting to switch weapons
-               {
-                       sound (self, CH_WEAPON_A, W_Sound("dryfire"), VOL_BASE, ATTEN_NORM);
-                       self.prevdryfire = time;
-               }
+       if(actor.weapon == actor.switchweapon && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
+       {
+               sound (actor, CH_WEAPON_A, SND_DRYFIRE, VOL_BASE, ATTEN_NORM);
+               actor.prevdryfire = time;
+       }
 
-               if(WEP_ACTION(self.weapon, WR_CHECKAMMO2 - secondary)) // check if the other firing mode has enough ammo
-               {
-                       if(time - self.prevwarntime > 1)
-                       {
-                               Send_Notification(
-                                       NOTIF_ONE,
-                                       self,
-                                       MSG_MULTI,
-                                       ITEM_WEAPON_PRIMORSEC,
-                                       self.weapon,
-                                       secondary,
-                                       (1 - secondary)
-                               );
-                       }
-                       self.prevwarntime = time;
-               }
-               else // this weapon is totally unable to fire, switch to another one
+       // check if the other firing mode has enough ammo
+       bool ammo_other = false;
+       if (secondary) {
+               WITH(entity, self, actor, ammo = thiswep.wr_checkammo1(thiswep));
+       } else {
+               WITH(entity, self, actor, ammo = thiswep.wr_checkammo2(thiswep));
+       }
+       if (ammo_other)
+       {
+               if (time - actor.prevwarntime > 1)
                {
-                       W_SwitchToOtherWeapon(self);
+                       Send_Notification(
+                               NOTIF_ONE,
+                               actor,
+                               MSG_MULTI,
+                               ITEM_WEAPON_PRIMORSEC,
+                               actor.weapon,
+                               secondary,
+                               (1 - secondary)
+                       );
                }
-
-               return false;
+               actor.prevwarntime = time;
        }
-       return true;
+       else // this weapon is totally unable to fire, switch to another one
+       {
+               W_SwitchToOtherWeapon(actor);
+       }
+
+       return false;
 }
 .float race_penalty;
-float weapon_prepareattack_check(float secondary, float attacktime)
+bool weapon_prepareattack_check(Weapon thiswep, entity actor, bool secondary, float attacktime)
 {
-       if(!weapon_prepareattack_checkammo(secondary))
+       if(!weapon_prepareattack_checkammo(thiswep, actor, secondary))
                return false;
 
        //if sv_ready_restart_after_countdown is set, don't allow the player to shoot
        //if all players readied up and the countdown is running
-       if(time < game_starttime || time < self.race_penalty) {
+       if(time < game_starttime || time < actor.race_penalty) {
                return false;
        }
 
@@ -527,53 +529,49 @@ float weapon_prepareattack_check(float secondary, float attacktime)
                return false;
 
        // do not even think about shooting if switching
-       if(self.switchweapon != self.weapon)
+       if(actor.switchweapon != actor.weapon)
                return false;
 
        if(attacktime >= 0)
        {
                // don't fire if previous attack is not finished
-               if (ATTACK_FINISHED(self) > time + self.weapon_frametime * 0.5)
+               if (ATTACK_FINISHED(actor) > time + actor.weapon_frametime * 0.5)
                        return false;
                // don't fire while changing weapon
-               if (self.weaponentity.state != WS_READY)
+               if (actor.weaponentity.state != WS_READY)
                        return false;
        }
-
        return true;
 }
-float weapon_prepareattack_do(float secondary, float attacktime)
+void weapon_prepareattack_do(entity actor, bool secondary, float attacktime)
 {
-       self.weaponentity.state = WS_INUSE;
+       actor.weaponentity.state = WS_INUSE;
 
-       self.spawnshieldtime = min(self.spawnshieldtime, time); // kill spawn shield when you fire
+       actor.spawnshieldtime = min(actor.spawnshieldtime, time); // kill spawn shield when you fire
 
        // if the weapon hasn't been firing continuously, reset the timer
        if(attacktime >= 0)
        {
-               if (ATTACK_FINISHED(self) < time - self.weapon_frametime * 1.5)
+               if (ATTACK_FINISHED(actor) < time - actor.weapon_frametime * 1.5)
                {
-                       ATTACK_FINISHED(self) = time;
+                       ATTACK_FINISHED(actor) = time;
                        //dprint("resetting attack finished to ", ftos(time), "\n");
                }
-               ATTACK_FINISHED(self) = ATTACK_FINISHED(self) + attacktime * W_WeaponRateFactor();
+               ATTACK_FINISHED(actor) = ATTACK_FINISHED(actor) + attacktime * W_WeaponRateFactor();
        }
-       self.bulletcounter += 1;
-       //dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n");
-       return true;
+       actor.bulletcounter += 1;
+       //dprint("attack finished ", ftos(ATTACK_FINISHED(actor)), "\n");
 }
-float weapon_prepareattack(float secondary, float attacktime)
+bool weapon_prepareattack(Weapon thiswep, entity actor, bool secondary, float attacktime)
 {
-       if(weapon_prepareattack_check(secondary, attacktime))
-       {
-               weapon_prepareattack_do(secondary, attacktime);
+       if (weapon_prepareattack_check(thiswep, actor, secondary, attacktime)) {
+               weapon_prepareattack_do(actor, secondary, attacktime);
                return true;
        }
-       else
-               return false;
+       return false;
 }
 
-void weapon_thinkf(float fr, float t, void() func)
+void weapon_thinkf(entity actor, float fr, float t, void(Weapon thiswep, entity actor, bool fire1, bool fire2) func)
 {
        vector a;
        vector of, or, ou;
@@ -581,7 +579,7 @@ void weapon_thinkf(float fr, float t, void() func)
 
        if(fr == WFRAME_DONTCHANGE)
        {
-               fr = self.weaponentity.wframe;
+               fr = actor.weaponentity.wframe;
                restartanim = false;
        }
        else if (fr == WFRAME_IDLE)
@@ -593,27 +591,27 @@ void weapon_thinkf(float fr, float t, void() func)
        or = v_right;
        ou = v_up;
 
-       if (self.weaponentity)
+       if (actor.weaponentity)
        {
-               self.weaponentity.wframe = fr;
+               actor.weaponentity.wframe = fr;
                a = '0 0 0';
                if (fr == WFRAME_IDLE)
-                       a = self.weaponentity.anim_idle;
+                       a = actor.weaponentity.anim_idle;
                else if (fr == WFRAME_FIRE1)
-                       a = self.weaponentity.anim_fire1;
+                       a = actor.weaponentity.anim_fire1;
                else if (fr == WFRAME_FIRE2)
-                       a = self.weaponentity.anim_fire2;
+                       a = actor.weaponentity.anim_fire2;
                else // if (fr == WFRAME_RELOAD)
-                       a = self.weaponentity.anim_reload;
+                       a = actor.weaponentity.anim_reload;
                a.z *= g_weaponratefactor;
-               setanim(self.weaponentity, a, restartanim == false, restartanim, restartanim);
+               setanim(actor.weaponentity, a, restartanim == false, restartanim, restartanim);
        }
 
        v_forward = of;
        v_right = or;
        v_up = ou;
 
-       if(self.weapon_think == w_ready && func != w_ready && self.weaponentity.state == WS_RAISE)
+       if(actor.weapon_think == w_ready && func != w_ready && actor.weaponentity.state == WS_RAISE)
        {
                backtrace("Tried to override initial weapon think function - should this really happen?");
        }
@@ -621,31 +619,31 @@ void weapon_thinkf(float fr, float t, void() func)
        t *= W_WeaponRateFactor();
 
        // VorteX: haste can be added here
-       if (self.weapon_think == w_ready)
+       if (actor.weapon_think == w_ready)
        {
-               self.weapon_nextthink = time;
+               actor.weapon_nextthink = time;
                //dprint("started firing at ", ftos(time), "\n");
        }
-       if (self.weapon_nextthink < time - self.weapon_frametime * 1.5 || self.weapon_nextthink > time + self.weapon_frametime * 1.5)
+       if (actor.weapon_nextthink < time - actor.weapon_frametime * 1.5 || actor.weapon_nextthink > time + actor.weapon_frametime * 1.5)
        {
-               self.weapon_nextthink = time;
+               actor.weapon_nextthink = time;
                //dprint("reset weapon animation timer at ", ftos(time), "\n");
        }
-       self.weapon_nextthink = self.weapon_nextthink + t;
-       self.weapon_think = func;
-       //dprint("next ", ftos(self.weapon_nextthink), "\n");
+       actor.weapon_nextthink = actor.weapon_nextthink + t;
+       actor.weapon_think = func;
+       //dprint("next ", ftos(actor.weapon_nextthink), "\n");
 
        if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
        {
-               if((self.weapon == WEP_SHOCKWAVE.m_id || self.weapon == WEP_SHOTGUN.m_id) && fr == WFRAME_FIRE2)
-                       animdecide_setaction(self, ANIMACTION_MELEE, restartanim);
+               if((actor.weapon == WEP_SHOCKWAVE.m_id || actor.weapon == WEP_SHOTGUN.m_id) && fr == WFRAME_FIRE2)
+                       animdecide_setaction(actor, ANIMACTION_MELEE, restartanim);
                else
-                       animdecide_setaction(self, ANIMACTION_SHOOT, restartanim);
+                       animdecide_setaction(actor, ANIMACTION_SHOOT, restartanim);
        }
        else
        {
-               if(self.anim_upper_action == ANIMACTION_SHOOT || self.anim_upper_action == ANIMACTION_MELEE)
-                       self.anim_upper_action = 0;
+               if(actor.anim_upper_action == ANIMACTION_SHOOT || actor.anim_upper_action == ANIMACTION_MELEE)
+                       actor.anim_upper_action = 0;
        }
 }
 
@@ -664,85 +662,89 @@ float forbidWeaponUse(entity player)
        return 0;
 }
 
-void W_WeaponFrame()
+.bool hook_switchweapon;
+
+void W_WeaponFrame(entity actor)
 {
        vector fo, ri, up;
 
        if (frametime)
-               self.weapon_frametime = frametime;
+               actor.weapon_frametime = frametime;
 
-       if (!self.weaponentity || self.health < 1)
+       if (!actor.weaponentity || actor.health < 1)
                return; // Dead player can't use weapons and injure impulse commands
 
-       if(forbidWeaponUse(self))
-       if(self.weaponentity.state != WS_CLEAR)
+       if(forbidWeaponUse(actor))
+       if(actor.weaponentity.state != WS_CLEAR)
        {
-               w_ready();
+               Weapon wpn = get_weaponinfo(actor.weapon);
+               w_ready(wpn, actor, actor.BUTTON_ATCK, actor.BUTTON_ATCK2);
                return;
        }
 
-       if(!self.switchweapon)
+       if(!actor.switchweapon)
        {
-               self.weapon = 0;
-               self.switchingweapon = 0;
-               self.weaponentity.state = WS_CLEAR;
-               self.weaponname = "";
-               //self.items &= ~IT_AMMO;
+               actor.weapon = 0;
+               actor.switchingweapon = 0;
+               actor.weaponentity.state = WS_CLEAR;
+               actor.weaponname = "";
+               //actor.items &= ~IT_AMMO;
                return;
        }
 
-       makevectors(self.v_angle);
+       makevectors(actor.v_angle);
        fo = v_forward; // save them in case the weapon think functions change it
        ri = v_right;
        up = v_up;
 
        // Change weapon
-       if (self.weapon != self.switchweapon)
+       if (actor.weapon != actor.switchweapon)
        {
-               if (self.weaponentity.state == WS_CLEAR)
+               if (actor.weaponentity.state == WS_CLEAR)
                {
                        // end switching!
-                       self.switchingweapon = self.switchweapon;
-                       entity newwep = get_weaponinfo(self.switchweapon);
+                       actor.switchingweapon = actor.switchweapon;
+                       entity newwep = get_weaponinfo(actor.switchweapon);
 
                        // the two weapon entities will notice this has changed and update their models
-                       self.weapon = self.switchweapon;
-                       self.weaponname = newwep.mdl;
-                       self.bulletcounter = 0;
-                       self.ammo_field = newwep.ammo_field;
-                       WEP_ACTION(self.switchweapon, WR_SETUP);
-                       self.weaponentity.state = WS_RAISE;
+                       actor.weapon = actor.switchweapon;
+                       actor.weaponname = newwep.mdl;
+                       actor.bulletcounter = 0;
+                       actor.ammo_field = newwep.ammo_field;
+                       Weapon w = get_weaponinfo(actor.switchweapon);
+                       w.wr_setup(w);
+                       actor.weaponentity.state = WS_RAISE;
 
                        // set our clip load to the load of the weapon we switched to, if it's reloadable
                        if(newwep.spawnflags & WEP_FLAG_RELOADABLE && newwep.reloading_ammo) // prevent accessing undefined cvars
                        {
-                               self.clip_load = self.(weapon_load[self.switchweapon]);
-                               self.clip_size = newwep.reloading_ammo;
+                               actor.clip_load = actor.(weapon_load[actor.switchweapon]);
+                               actor.clip_size = newwep.reloading_ammo;
                        }
                        else
-                               self.clip_load = self.clip_size = 0;
+                               actor.clip_load = actor.clip_size = 0;
 
-                       weapon_thinkf(WFRAME_IDLE, newwep.switchdelay_raise, w_ready);
+                       weapon_thinkf(actor, WFRAME_IDLE, newwep.switchdelay_raise, w_ready);
                }
-               else if (self.weaponentity.state == WS_DROP)
+               else if (actor.weaponentity.state == WS_DROP)
                {
                        // in dropping phase we can switch at any time
-                       self.switchingweapon = self.switchweapon;
+                       actor.switchingweapon = actor.switchweapon;
                }
-               else if (self.weaponentity.state == WS_READY)
+               else if (actor.weaponentity.state == WS_READY)
                {
                        // start switching!
-                       self.switchingweapon = self.switchweapon;
-                       entity oldwep = get_weaponinfo(self.weapon);
+                       actor.switchingweapon = actor.switchweapon;
+                       entity oldwep = get_weaponinfo(actor.weapon);
 
                        // set up weapon switch think in the future, and start drop anim
                        #ifndef INDEPENDENT_ATTACK_FINISHED
-                       if(ATTACK_FINISHED(self) <= time + self.weapon_frametime * 0.5)
+                       if(ATTACK_FINISHED(actor) <= time + actor.weapon_frametime * 0.5)
                        {
                        #endif
-                               sound(self, CH_WEAPON_SINGLE, W_Sound("weapon_switch"), VOL_BASE, ATTN_NORM);
-                               self.weaponentity.state = WS_DROP;
-                               weapon_thinkf(WFRAME_DONTCHANGE, oldwep.switchdelay_drop, w_clear);
+                               sound(actor, CH_WEAPON_SINGLE, SND_WEAPON_SWITCH, VOL_BASE, ATTN_NORM);
+                               actor.weaponentity.state = WS_DROP;
+                               weapon_thinkf(actor, WFRAME_DONTCHANGE, oldwep.switchdelay_drop, w_clear);
                        #ifndef INDEPENDENT_ATTACK_FINISHED
                        }
                        #endif
@@ -750,11 +752,11 @@ void W_WeaponFrame()
        }
 
        // LordHavoc: network timing test code
-       //if (self.button0)
-       //      print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(self)), " >= ", ftos(self.weapon_nextthink), "\n");
+       //if (actor.button0)
+       //      print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(actor)), " >= ", ftos(actor.weapon_nextthink), "\n");
 
        float w;
-       w = self.weapon;
+       w = actor.weapon;
 
        // call the think code which may fire the weapon
        // and do so multiple times to resolve framerate dependency issues if the
@@ -764,10 +766,10 @@ void W_WeaponFrame()
        while (c < W_TICSPERFRAME)
        {
                c = c + 1;
-               if(w && !(self.weapons & WepSet_FromWeapon(w)))
+               if(w && !(actor.weapons & WepSet_FromWeapon(w)))
                {
-                       if(self.weapon == self.switchweapon)
-                               W_SwitchWeapon_Force(self, w_getbestweapon(self));
+                       if(actor.weapon == actor.switchweapon)
+                               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
                        w = 0;
                }
 
@@ -775,82 +777,103 @@ void W_WeaponFrame()
                v_right = ri;
                v_up = up;
 
-               if(w)
-                       WEP_ACTION(self.weapon, WR_THINK);
-               else
-                       WEP_ACTION(self.weapon, WR_GONETHINK);
+               bool block_weapon = false;
+               {
+                       bool key_pressed = actor.BUTTON_HOOK && !actor.vehicle;
+               Weapon off = actor.offhand;
+               if (off && !(actor.weapons & WEPSET(HOOK))) {
+                       if (off.offhand_think) off.offhand_think(off, actor, key_pressed);
+               } else {
+                       if (key_pressed && actor.switchweapon != WEP_HOOK.m_id && !actor.hook_switchweapon) {
+                                       W_SwitchWeapon(WEP_HOOK.m_id);
+                               }
+                               actor.hook_switchweapon = key_pressed;
+                               Weapon h = WEP_HOOK;
+                               block_weapon = (actor.weapon == h.m_id && (actor.BUTTON_ATCK || key_pressed));
+                               h.wr_think(h, actor, block_weapon, false);
+               }
+        }
+
+               if (!block_weapon)
+               if (w) {
+                       Weapon e = get_weaponinfo(actor.weapon);
+                       e.wr_think(e, actor, actor.BUTTON_ATCK, actor.BUTTON_ATCK2);
+               } else {
+                       Weapon w = get_weaponinfo(actor.weapon);
+                       w.wr_gonethink(w);
+               }
 
-               if (time + self.weapon_frametime * 0.5 >= self.weapon_nextthink)
+               if (time + actor.weapon_frametime * 0.5 >= actor.weapon_nextthink)
                {
-                       if(self.weapon_think)
+                       if(actor.weapon_think)
                        {
                                v_forward = fo;
                                v_right = ri;
                                v_up = up;
-                               self.weapon_think();
+                               Weapon wpn = get_weaponinfo(actor.weapon);
+                               actor.weapon_think(wpn, actor, actor.BUTTON_ATCK, actor.BUTTON_ATCK2);
                        }
                        else
-                               bprint("\{1}^1ERROR: undefined weapon think function for ", self.netname, "\n");
+                               bprint("\{1}^1ERROR: undefined weapon think function for ", actor.netname, "\n");
                }
        }
 }
 
-void W_AttachToShotorg(entity flash, vector offset)
+void W_AttachToShotorg(entity actor, entity flash, vector offset)
 {
        entity xflash;
-       flash.owner = self;
+       flash.owner = actor;
        flash.angles_z = random() * 360;
 
-       if(gettagindex(self.weaponentity, "shot"))
-               setattachment(flash, self.weaponentity, "shot");
+       if(gettagindex(actor.weaponentity, "shot"))
+               setattachment(flash, actor.weaponentity, "shot");
        else
-               setattachment(flash, self.weaponentity, "tag_shot");
+               setattachment(flash, actor.weaponentity, "tag_shot");
        setorigin(flash, offset);
 
        xflash = spawn();
        copyentity(flash, xflash);
 
-       flash.viewmodelforclient = self;
+       flash.viewmodelforclient = actor;
 
-       if(self.weaponentity.oldorigin.x > 0)
+       if(actor.weaponentity.oldorigin.x > 0)
        {
-               setattachment(xflash, self.exteriorweaponentity, "");
-               setorigin(xflash, self.weaponentity.oldorigin + offset);
+               setattachment(xflash, actor.exteriorweaponentity, "");
+               setorigin(xflash, actor.weaponentity.oldorigin + offset);
        }
        else
        {
-               if(gettagindex(self.exteriorweaponentity, "shot"))
-                       setattachment(xflash, self.exteriorweaponentity, "shot");
+               if(gettagindex(actor.exteriorweaponentity, "shot"))
+                       setattachment(xflash, actor.exteriorweaponentity, "shot");
                else
-                       setattachment(xflash, self.exteriorweaponentity, "tag_shot");
+                       setattachment(xflash, actor.exteriorweaponentity, "tag_shot");
                setorigin(xflash, offset);
        }
 }
 
-void W_DecreaseAmmo(float ammo_use)
+void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use)
 {
-       entity wep = get_weaponinfo(self.weapon);
 
        if(cvar("g_overkill"))
-       if(self.ok_use_ammocharge)
+       if(actor.ok_use_ammocharge)
        {
-               ok_DecreaseCharge(self, self.weapon);
+               ok_DecreaseCharge(actor, actor.weapon);
                return; // TODO
        }
 
-       if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo)
+       if((actor.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo)
                return;
 
        // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if(wep.reloading_ammo)
        {
-               self.clip_load -= ammo_use;
-               self.(weapon_load[self.weapon]) = self.clip_load;
+               actor.clip_load -= ammo_use;
+               actor.(weapon_load[actor.weapon]) = actor.clip_load;
        }
        else if(wep.ammo_field != ammo_none)
        {
-               self.(wep.ammo_field) -= ammo_use;
-               if(self.(wep.ammo_field) < 0)
+               actor.(wep.ammo_field) -= ammo_use;
+               if(actor.(wep.ammo_field) < 0)
                {
                        backtrace(sprintf(
                                "W_DecreaseAmmo(%.2f): '%s' subtracted too much %s from '%s', resulting with '%.2f' left... "
@@ -858,8 +881,8 @@ void W_DecreaseAmmo(float ammo_use)
                                ammo_use,
                                wep.netname,
                                GetAmmoPicture(wep.ammo_field),
-                               self.netname,
-                               self.(wep.ammo_field)
+                               actor.netname,
+                               actor.(wep.ammo_field)
                        ));
                }
        }
@@ -871,47 +894,48 @@ void W_DecreaseAmmo(float ammo_use)
 .float reload_complain;
 .string reload_sound;
 
-void W_ReloadedAndReady()
+void W_ReloadedAndReady(Weapon thiswep, entity actor, bool fire1, bool fire2)
 {
        // finish the reloading process, and do the ammo transfer
 
-       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       actor.clip_load = actor.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
 
        // if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
-       if(!self.reload_ammo_min || self.items & IT_UNLIMITED_WEAPON_AMMO || self.ammo_field == ammo_none)
-               self.clip_load = self.reload_ammo_amount;
+       if(!actor.reload_ammo_min || actor.items & IT_UNLIMITED_WEAPON_AMMO || actor.ammo_field == ammo_none)
+               actor.clip_load = actor.reload_ammo_amount;
        else
        {
                // make sure we don't add more ammo than we have
-               float load = min(self.reload_ammo_amount - self.clip_load, self.(self.ammo_field));
-        self.clip_load += load;
-        self.(self.ammo_field) -= load;
+               float load = min(actor.reload_ammo_amount - actor.clip_load, actor.(actor.ammo_field));
+        actor.clip_load += load;
+        actor.(actor.ammo_field) -= load;
        }
-       self.(weapon_load[self.weapon]) = self.clip_load;
+       actor.(weapon_load[actor.weapon]) = actor.clip_load;
 
        // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
        // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
        // so your weapon is disabled for a few seconds without reason
 
-       //ATTACK_FINISHED(self) -= self.reload_time - 1;
+       //ATTACK_FINISHED(actor) -= actor.reload_time - 1;
 
-       w_ready();
+       Weapon wpn = get_weaponinfo(actor.weapon);
+       w_ready(wpn, actor, actor.BUTTON_ATCK, actor.BUTTON_ATCK2);
 }
 
-void W_Reload(float sent_ammo_min, string sent_sound)
+void W_Reload(entity actor, float sent_ammo_min, string sent_sound)
 {
        // set global values to work with
        entity e;
-       e = get_weaponinfo(self.weapon);
+       e = get_weaponinfo(actor.weapon);
 
        if(cvar("g_overkill"))
-       if(self.ok_use_ammocharge)
+       if(actor.ok_use_ammocharge)
                return; // TODO
 
-       self.reload_ammo_min = sent_ammo_min;
-       self.reload_ammo_amount = e.reloading_ammo;
-       self.reload_time = e.reloading_time;
-       self.reload_sound = sent_sound;
+       actor.reload_ammo_min = sent_ammo_min;
+       actor.reload_ammo_amount = e.reloading_ammo;
+       actor.reload_time = e.reloading_time;
+       actor.reload_sound = sent_sound;
 
        // don't reload weapons that don't have the RELOADABLE flag
        if (!(e.spawnflags & WEP_FLAG_RELOADABLE))
@@ -921,65 +945,66 @@ void W_Reload(float sent_ammo_min, string sent_sound)
        }
 
        // return if reloading is disabled for this weapon
-       if(!self.reload_ammo_amount)
+       if(!actor.reload_ammo_amount)
                return;
 
        // our weapon is fully loaded, no need to reload
-       if (self.clip_load >= self.reload_ammo_amount)
+       if (actor.clip_load >= actor.reload_ammo_amount)
                return;
 
        // no ammo, so nothing to load
-       if(self.ammo_field != ammo_none)
-       if(!self.(self.ammo_field) && self.reload_ammo_min)
-       if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+       if(actor.ammo_field != ammo_none)
+       if(!actor.(actor.ammo_field) && actor.reload_ammo_min)
+       if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               if(IS_REAL_CLIENT(self) && self.reload_complain < time)
+               if(IS_REAL_CLIENT(actor) && actor.reload_complain < time)
                {
-                       play2(self, W_Sound("unavailable"));
-                       sprint(self, strcat("You don't have enough ammo to reload the ^2", WEP_NAME(self.weapon), "\n"));
-                       self.reload_complain = time + 1;
+                       play2(actor, SND(UNAVAILABLE));
+                       sprint(actor, strcat("You don't have enough ammo to reload the ^2", WEP_NAME(actor.weapon), "\n"));
+                       actor.reload_complain = time + 1;
                }
                // switch away if the amount of ammo is not enough to keep using this weapon
-               if (!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2)))
+               Weapon w = get_weaponinfo(actor.weapon);
+               if (!(w.wr_checkammo1(w) + w.wr_checkammo2(w)))
                {
-                       self.clip_load = -1; // reload later
-                       W_SwitchToOtherWeapon(self);
+                       actor.clip_load = -1; // reload later
+                       W_SwitchToOtherWeapon(actor);
                }
                return;
        }
 
-       if (self.weaponentity)
+       if (actor.weaponentity)
        {
-               if (self.weaponentity.wframe == WFRAME_RELOAD)
+               if (actor.weaponentity.wframe == WFRAME_RELOAD)
                        return;
 
                // allow switching away while reloading, but this will cause a new reload!
-               self.weaponentity.state = WS_READY;
+               actor.weaponentity.state = WS_READY;
        }
 
        // now begin the reloading process
 
-       sound(self, CH_WEAPON_SINGLE, self.reload_sound, VOL_BASE, ATTEN_NORM);
+       _sound(actor, CH_WEAPON_SINGLE, actor.reload_sound, VOL_BASE, ATTEN_NORM);
 
        // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
        // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
        // so your weapon is disabled for a few seconds without reason
 
-       //ATTACK_FINISHED(self) = max(time, ATTACK_FINISHED(self)) + self.reload_time + 1;
+       //ATTACK_FINISHED(actor) = max(time, ATTACK_FINISHED(actor)) + actor.reload_time + 1;
 
-       weapon_thinkf(WFRAME_RELOAD, self.reload_time, W_ReloadedAndReady);
+       weapon_thinkf(actor, WFRAME_RELOAD, actor.reload_time, W_ReloadedAndReady);
 
-       if(self.clip_load < 0)
-               self.clip_load = 0;
-       self.old_clip_load = self.clip_load;
-       self.clip_load = self.(weapon_load[self.weapon]) = -1;
+       if(actor.clip_load < 0)
+               actor.clip_load = 0;
+       actor.old_clip_load = actor.clip_load;
+       actor.clip_load = actor.(weapon_load[actor.weapon]) = -1;
 }
 
-void W_DropEvent(float event, entity player, float weapon_type, entity weapon_item)
-{
-       entity oldself = self;
-       self = player;
+void W_DropEvent(.void(Weapon) event, entity player, float weapon_type, entity weapon_item)
+{SELFPARAM();
+       setself(player);
        weapon_dropevent_item = weapon_item;
-       WEP_ACTION(weapon_type, event);
-       self = oldself;
+       Weapon w = get_weaponinfo(weapon_type);
+       w.event(w);
+       setself(this);
 }
index e466449e6e841f2d93a3fa2d86540d508652a2c6..e1fc0922d62f53d50ce4b99fbe436b82b1bd20e7 100644 (file)
@@ -14,32 +14,32 @@ const float WFRAME_FIRE2 = 1;
 const float WFRAME_IDLE = 2;
 const float WFRAME_RELOAD = 3;
 
-void CL_SpawnWeaponentity();
+void CL_SpawnWeaponentity(entity e);
 
 vector CL_Weapon_GetShotOrg(float wpn);
 
 float forbidWeaponUse(entity player);
 
-void W_AttachToShotorg(entity flash, vector offset);
+void W_AttachToShotorg(entity actor, entity flash, vector offset);
 
-void W_DecreaseAmmo(float ammo_use);
+void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use);
 
-void W_DropEvent(float event, entity player, float weapon_type, entity weapon_item);
+void W_DropEvent(.void(Weapon) event, entity player, float weapon_type, entity weapon_item);
 
-void W_Reload(float sent_ammo_min, string sent_sound);
+void W_Reload(entity actor, float sent_ammo_min, string sent_sound);
 
-void W_WeaponFrame();
+void W_WeaponFrame(entity actor);
 
 float W_WeaponRateFactor();
 
 float W_WeaponSpeedFactor();
 
-float weapon_prepareattack(float secondary, float attacktime);
+bool weapon_prepareattack(Weapon thiswep, entity actor, bool secondary, float attacktime);
 
-float weapon_prepareattack_check(float secondary, float attacktime);
+bool weapon_prepareattack_check(Weapon thiswep, entity actor, float secondary, float attacktime);
 
-float weapon_prepareattack_do(float secondary, float attacktime);
+void weapon_prepareattack_do(entity actor, float secondary, float attacktime);
 
-void weapon_thinkf(float fr, float t, void() func);
+void weapon_thinkf(entity actor, float fr, float t, void(Weapon thiswep, entity actor, bool fire1, bool fire2) func);
 
 #endif
index e0bb6434584efb034b554b9985febc3ff39a8280..85fbdd933e6e2453447d1b144f2663d92bc4a598 100644 (file)
@@ -10,7 +10,7 @@
 #endif
 
 void WarpZone_Fade_PreDraw()
-{
+{SELFPARAM();
        vector org;
        org = getpropertyvec(VF_ORIGIN);
        if(!checkpvs(org, self)) // this makes sense as long as we don't support recursive warpzones
@@ -27,7 +27,7 @@ void WarpZone_Fade_PreDraw()
 }
 
 void WarpZone_Read(float isnew)
-{
+{SELFPARAM();
        warpzone_warpzones_exist = 1;
        if (!self.enemy)
        {
@@ -92,7 +92,7 @@ void WarpZone_Read(float isnew)
 }
 
 void WarpZone_Camera_Read(float isnew)
-{
+{SELFPARAM();
        warpzone_cameras_exist = 1;
        self.classname = "func_warpzone_camera";
 
@@ -149,7 +149,7 @@ void WarpZone_Camera_Read(float isnew)
 
 void CL_RotateMoves(vector ang) = #638;
 void WarpZone_Teleported_Read(float isnew)
-{
+{SELFPARAM();
        vector v;
        self.classname = "warpzone_teleported";
        v.x = ReadCoord();
index d04b768f8810e8b3b5d2b431b54ba135cafc0fe8..0eaaac980c69a3e70cf0ba8974994741776f8507 100644 (file)
@@ -43,7 +43,7 @@ void WarpZone_Accumulator_AddInverse(entity acc, entity wz)
 .vector(vector, vector) camera_transform;
 float autocvar_cl_warpzone_usetrace = 1;
 vector WarpZone_camera_transform(vector org, vector ang)
-{
+{SELFPARAM();
        vector vf, vr, vu;
        if(self.warpzone_fadestart)
                if(vlen(org - self.origin - 0.5 * (self.mins + self.maxs)) > self.warpzone_fadeend + 400)
@@ -81,7 +81,7 @@ void WarpZone_SetUp(entity e, vector my_org, vector my_ang, vector other_org, ve
 }
 
 vector WarpZone_Camera_camera_transform(vector org, vector ang)
-{
+{SELFPARAM();
        // a fixed camera view
        if(self.warpzone_fadestart)
                if(vlen(org - self.origin - 0.5 * (self.mins + self.maxs)) > self.warpzone_fadeend + 400)
@@ -573,15 +573,13 @@ vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org)
        return nearest;
 }
 
-float WarpZoneLib_BadClassname(string myclassname)
+bool WarpZoneLib_BadEntity(entity e)
 {
+       string myclassname = e.classname;
+       if (e.instanceOfObject) return true;
        switch(myclassname)
        {
-               case "weapon_info":
-               case "monster_info":
                case "deathtype":
-               case "callback":
-               case "callbackchain":
                case "weaponentity":
                case "exteriorweaponentity":
                case "csqc_score_team":
@@ -589,8 +587,8 @@ float WarpZoneLib_BadClassname(string myclassname)
                case "ent_client_scoreinfo":
                case "saved_cvar_value":
                case "accuracy":
-               case "entcs_sender_v2":
-               case "entcs_receiver_v2":
+               case "entcs_sender":
+               case "entcs_receiver":
                case "clientinit":
                case "sprite_waypoint":
                case "waypoint":
@@ -630,7 +628,7 @@ void WarpZone_FindRadius_Recurse(vector org, float rad,        vector org0,
 
        for(e = e0; e; e = e.chain)
        {
-               if(WarpZoneLib_BadClassname(e.classname))
+               if(WarpZoneLib_BadEntity(e))
                        continue;
                p = WarpZoneLib_NearestPointOnBox(e.origin + e.mins, e.origin + e.maxs, org0);
                if(needlineofsight)
@@ -667,7 +665,7 @@ void WarpZone_FindRadius_Recurse(vector org, float rad,        vector org0,
        }
        for(e = wz; e; e = e.WarpZone_findradius_next)
        {
-               if(WarpZoneLib_BadClassname(e.classname))
+               if(WarpZoneLib_BadEntity(e))
                        continue;
 
                org0_new = WarpZone_TransformOrigin(e, org);
@@ -698,7 +696,7 @@ entity WarpZone_FindRadius(vector org, float rad, float needlineofsight)
 
 .entity WarpZone_refsys;
 void WarpZone_RefSys_GC()
-{
+{SELFPARAM();
        // garbage collect unused reference systems
        self.nextthink = time + 1;
        if(self.owner.WarpZone_refsys != self)
@@ -818,7 +816,7 @@ entity WarpZone_RefSys_SpawnSameRefSys(entity me)
 }
 
 float WarpZoneLib_ExactTrigger_Touch()
-{
+{SELFPARAM();
        return !WarpZoneLib_BoxTouchesBrush(other.absmin, other.absmax, self, other);
 }
 
index b5c6f656a44e1410514f83da79f19aa5ce23a082..d34870ec0110f5a953320a4fcbb5256d3735c82e 100644 (file)
@@ -54,7 +54,7 @@ void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector
 }
 
 bool WarpZone_Teleported_Send(entity to, int sf)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
        WriteCoord(MSG_ENTITY, self.angles.x);
        WriteCoord(MSG_ENTITY, self.angles.y);
@@ -140,7 +140,7 @@ float WarpZone_Teleport(entity wz, entity player, float f0, float f1)
                player.fixangle = false;
 
                entity ts = spawn();
-               setmodel(ts, "null");
+               setmodel(ts, MDL_Null);
                ts.SendEntity = WarpZone_Teleported_Send;
                ts.SendFlags = 0xFFFFFF;
                ts.drawonlytoclient = player;
@@ -158,9 +158,7 @@ float WarpZone_Teleport(entity wz, entity player, float f0, float f1)
 }
 
 void WarpZone_Touch (void)
-{
-       entity oldself;
-
+{SELFPARAM();
        if(other.classname == "trigger_warpzone")
                return;
 
@@ -205,14 +203,13 @@ void WarpZone_Touch (void)
                if (!self.target) self.target = save1;
                if (!self.target3) self.target3 = save2;
 
-               oldself = self;
-               self = self.enemy;
+               setself(self.enemy);
                save1 = self.target; self.target = string_null;
                save2 = self.target2; self.target2 = string_null;
                SUB_UseTargets();
                if (!self.target) self.target = save1;
                if (!self.target2) self.target2 = save2;
-               self = oldself;
+               setself(this);
        }
        else
        {
@@ -221,7 +218,7 @@ void WarpZone_Touch (void)
 }
 
 bool WarpZone_Send(entity to, int sendflags)
-{
+{SELFPARAM();
        WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE);
 
        // we must send this flag for clientside to match properly too
@@ -275,7 +272,7 @@ bool WarpZone_Send(entity to, int sendflags)
 }
 
 bool WarpZone_Camera_Send(entity to, int sendflags)
-{
+{SELFPARAM();
        int f = 0;
        WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA);
 
@@ -321,7 +318,7 @@ bool WarpZone_Camera_Send(entity to, int sendflags)
 
 #ifdef WARPZONELIB_KEEPDEBUG
 float WarpZone_CheckProjectileImpact(entity player)
-{
+{SELFPARAM();
        vector o0, v0;
 
        o0 = player.origin + player.view_ofs;
@@ -388,7 +385,7 @@ float WarpZone_CheckProjectileImpact(entity player)
 #endif
 
 float WarpZone_Projectile_Touch()
-{
+{SELFPARAM();
        if(other.classname == "trigger_warpzone")
                return true;
 
@@ -456,7 +453,7 @@ float WarpZone_Projectile_Touch()
 }
 
 void WarpZone_InitStep_FindOriginTarget()
-{
+{SELFPARAM();
        if(self.killtarget != "")
        {
                self.aiment = find(world, targetname, self.killtarget);
@@ -470,7 +467,7 @@ void WarpZone_InitStep_FindOriginTarget()
 }
 
 void WarpZonePosition_InitStep_FindTarget()
-{
+{SELFPARAM();
        if(self.target == "")
        {
                error("Warp zone position with no target");
@@ -492,7 +489,7 @@ void WarpZonePosition_InitStep_FindTarget()
 }
 
 void WarpZoneCamera_Think(void)
-{
+{SELFPARAM();
        if(self.warpzone_save_origin != self.origin
        || self.warpzone_save_angles != self.angles
        || self.warpzone_save_eorigin != self.enemy.origin
@@ -508,7 +505,7 @@ void WarpZoneCamera_Think(void)
 }
 
 void WarpZoneCamera_InitStep_FindTarget()
-{
+{SELFPARAM();
        entity e;
        float i;
        if(self.target == "")
@@ -538,7 +535,7 @@ void WarpZoneCamera_InitStep_FindTarget()
 }
 
 void WarpZone_InitStep_UpdateTransform()
-{
+{SELFPARAM();
        vector org, ang, norm, point;
        float area;
        vector tri, a, b, c, n;
@@ -619,7 +616,7 @@ void WarpZone_InitStep_UpdateTransform()
 }
 
 void WarpZone_InitStep_ClearTarget()
-{
+{SELFPARAM();
        if(self.enemy)
                self.enemy.enemy = world;
        self.enemy = world;
@@ -627,7 +624,7 @@ void WarpZone_InitStep_ClearTarget()
 
 entity warpzone_first; .entity warpzone_next;
 void WarpZone_InitStep_FindTarget()
-{
+{SELFPARAM();
        float i;
        entity e, e2;
 
@@ -658,7 +655,7 @@ void WarpZone_InitStep_FindTarget()
 
 void WarpZone_Think();
 void WarpZone_InitStep_FinalizeTransform()
-{
+{SELFPARAM();
        if(!self.enemy || self.enemy.enemy != self)
        {
                error("Invalid warp zone detected. Killed.");
@@ -683,17 +680,17 @@ float warpzone_initialized;
 entity warpzone_position_first;
 entity warpzone_camera_first;
 .entity warpzone_next;
-void spawnfunc_misc_warpzone_position(void)
+spawnfunc(misc_warpzone_position)
 {
        // "target", "angles", "origin"
        self.warpzone_next = warpzone_position_first;
        warpzone_position_first = self;
 }
-void spawnfunc_trigger_warpzone_position(void)
+spawnfunc(trigger_warpzone_position)
 {
-       spawnfunc_misc_warpzone_position();
+       spawnfunc_misc_warpzone_position(this);
 }
-void spawnfunc_trigger_warpzone(void)
+spawnfunc(trigger_warpzone)
 {
        // warp zone entities must have:
        // "killtarget" pointing to a target_position with a direction arrow
@@ -703,11 +700,6 @@ void spawnfunc_trigger_warpzone(void)
        //              the map, with another killtarget to designate its
        //              orientation
 
-#ifndef WARPZONE_USE_FIXANGLE
-       // used when teleporting
-       precache_model("null");
-#endif
-
        if(!self.scale)
                self.scale = self.modelscale;
        if(!self.scale)
@@ -718,7 +710,7 @@ void spawnfunc_trigger_warpzone(void)
        if(m != "")
        {
                precache_model(m);
-               setmodel(self, m); // no precision needed
+               _setmodel(self, m); // no precision needed
        }
        setorigin(self, self.origin);
        if(self.scale)
@@ -731,7 +723,7 @@ void spawnfunc_trigger_warpzone(void)
        self.warpzone_next = warpzone_first;
        warpzone_first = self;
 }
-void spawnfunc_func_camera(void)
+spawnfunc(func_camera)
 {
        if(!self.scale)
                self.scale = self.modelscale;
@@ -740,7 +732,7 @@ void spawnfunc_func_camera(void)
        if(self.model != "")
        {
                precache_model(self.model);
-               setmodel(self, self.model); // no precision needed
+               _setmodel(self, self.model); // no precision needed
        }
        setorigin(self, self.origin);
        if(self.scale)
@@ -757,37 +749,33 @@ void spawnfunc_func_camera(void)
        warpzone_camera_first = self;
 }
 void WarpZones_Reconnect()
-{
-       entity e;
-       e = self;
-       for(self = warpzone_first; self; self = self.warpzone_next)
+{SELFPARAM();
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
                WarpZone_InitStep_ClearTarget();
-       for(self = warpzone_first; self; self = self.warpzone_next)
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
                WarpZone_InitStep_FindTarget();
-       for(self = warpzone_camera_first; self; self = self.warpzone_next)
+       for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
                WarpZoneCamera_InitStep_FindTarget();
-       for(self = warpzone_first; self; self = self.warpzone_next)
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
                WarpZone_InitStep_FinalizeTransform();
-       self = e;
+       setself(this);
 }
 
 void WarpZone_Think()
-{
+{SELFPARAM();
        if(self.warpzone_save_origin != self.origin
        || self.warpzone_save_angles != self.angles
        || self.warpzone_save_eorigin != self.enemy.origin
        || self.warpzone_save_eangles != self.enemy.angles)
        {
-               entity oldself;
-               oldself = self;
                WarpZone_InitStep_UpdateTransform();
-               self = self.enemy;
+               setself(self.enemy);
                WarpZone_InitStep_UpdateTransform();
-               self = oldself;
+               setself(this);
                WarpZone_InitStep_FinalizeTransform();
-               self = self.enemy;
+               setself(self.enemy);
                WarpZone_InitStep_FinalizeTransform();
-               self = oldself;
+               setself(this);
                self.warpzone_save_origin = self.origin;
                self.warpzone_save_angles = self.angles;
                self.warpzone_save_eorigin = self.enemy.origin;
@@ -797,25 +785,23 @@ void WarpZone_Think()
 }
 
 void WarpZone_StartFrame()
-{
+{SELFPARAM();
        entity e;
        if(warpzone_initialized == 0)
        {
                warpzone_initialized = 1;
-               e = self;
-               for(self = warpzone_first; self; self = self.warpzone_next)
+               for(setself(warpzone_first); self; setself(self.warpzone_next))
                        WarpZone_InitStep_FindOriginTarget();
-               for(self = warpzone_position_first; self; self = self.warpzone_next)
+               for(setself(warpzone_position_first); self; setself(self.warpzone_next))
                        WarpZonePosition_InitStep_FindTarget();
-               for(self = warpzone_first; self; self = self.warpzone_next)
+               for(setself(warpzone_first); self; setself(self.warpzone_next))
                        WarpZone_InitStep_UpdateTransform();
-               self = e;
+               setself(this);
                WarpZones_Reconnect();
                WarpZone_PostInitialize_Callback();
        }
 
-       entity oldself, oldother;
-       oldself = self;
+       entity oldother;
        oldother = other;
        for(e = world; (e = nextent(e)); )
        {
@@ -830,14 +816,14 @@ void WarpZone_StartFrame()
 
                                // warpzones
                                if(warpzone_warpzones_exist) {
-                               self = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs);
+                               setself(WarpZone_Find(e.origin + e.mins, e.origin + e.maxs));
                                if(self)
                                if(!WarpZoneLib_ExactTrigger_Touch())
                                        if(WarpZone_PlaneDist(self, e.origin + e.view_ofs) <= 0)
                                                WarpZone_Teleport(self, e, -1, 0); } // NOT triggering targets by this!
 
                                // teleporters
-                               self = Teleport_Find(e.origin + e.mins, e.origin + e.maxs);
+                               setself(Teleport_Find(e.origin + e.mins, e.origin + e.maxs));
                                if(self)
                                if(!WarpZoneLib_ExactTrigger_Touch())
                                        Simple_TeleportPlayer(self, other); // NOT triggering targets by this!
@@ -852,7 +838,7 @@ void WarpZone_StartFrame()
                        break;
                }
        }
-       self = oldself;
+       setself(this);
        other = oldother;
 }
 
@@ -867,42 +853,42 @@ float visible_to_some_client(entity ent)
        return 0;
 }
 void trigger_warpzone_reconnect_use()
-{
+{SELFPARAM();
        entity e;
        e = self;
        // NOTE: this matches for target, not targetname, but of course
        // targetname must be set too on the other entities
-       for(self = warpzone_first; self; self = self.warpzone_next)
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
                self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && (visible_to_some_client(self) || visible_to_some_client(self.enemy))));
-       for(self = warpzone_camera_first; self; self = self.warpzone_next)
+       for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
                self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && visible_to_some_client(self)));
-       for(self = warpzone_first; self; self = self.warpzone_next)
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
                if(self.warpzone_reconnecting)
                        WarpZone_InitStep_ClearTarget();
-       for(self = warpzone_first; self; self = self.warpzone_next)
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
                if(self.warpzone_reconnecting)
                        WarpZone_InitStep_FindTarget();
-       for(self = warpzone_camera_first; self; self = self.warpzone_next)
+       for(setself(warpzone_camera_first); self; setself(self.warpzone_next))
                if(self.warpzone_reconnecting)
                        WarpZoneCamera_InitStep_FindTarget();
-       for(self = warpzone_first; self; self = self.warpzone_next)
+       for(setself(warpzone_first); self; setself(self.warpzone_next))
                if(self.warpzone_reconnecting || self.enemy.warpzone_reconnecting)
                        WarpZone_InitStep_FinalizeTransform();
-       self = e;
+       setself(e);
 }
 
-void spawnfunc_trigger_warpzone_reconnect()
+spawnfunc(trigger_warpzone_reconnect)
 {
        self.use = trigger_warpzone_reconnect_use;
 }
 
-void spawnfunc_target_warpzone_reconnect()
+spawnfunc(target_warpzone_reconnect)
 {
-       spawnfunc_trigger_warpzone_reconnect(); // both names make sense here :(
+       spawnfunc_trigger_warpzone_reconnect(this); // both names make sense here :(
 }
 
 void WarpZone_PlayerPhysics_FixVAngle(void)
-{
+{SELFPARAM();
 #ifndef WARPZONE_DONT_FIX_VANGLE
        if(IS_REAL_CLIENT(self))
        if(self.v_angle.z <= 360) // if not already adjusted
index 0af6d3c0dcd44dacfb266a3f3ed9f400b0ee7bf4..0b983c299c8cac5b05c69ec72ad58878137aa77d 100644 (file)
@@ -12,7 +12,7 @@
 #include "common.qh"
 
 void WarpZoneLib_ExactTrigger_Init()
-{
+{SELFPARAM();
        vector mi, ma;
        if (self.movedir == '0 0 0')
        if (self.angles != '0 0 0')
@@ -30,7 +30,7 @@ void WarpZoneLib_ExactTrigger_Init()
                mi = self.mins;
                ma = self.maxs;
                precache_model(self.model);
-               setmodel(self, self.model);
+               _setmodel(self, self.model);
                // let mapper-set mins/maxs override the model's bounds if set
                if(mi != '0 0 0' || ma != '0 0 0')
                {
index 1e42413a1b7dcdf982b369e9809aacdc60a89453..ba16fd79ef8f4ddac88686a09435a27e8ee45a95 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/env bash
 cd ${0%[\\/]*}
-find . -name .git -prune -o -type f -print0 |                                    \
+find . -name .git -prune -o -type f -print0 |               \
     xargs -0 sed -i                                         \
         `# strip trailing spaces`                           \
         -e 's/[[:space:]]*$//'                              \
index eb768df231f9023827cbffe4b55c681c366cedbd..760337d53a34bc2f38058bfc0ab3b193d456dc0a 100644 (file)
@@ -1,3 +1,4 @@
+// TODO: remove after 0.8.2. Default impulse commands for 0.8.1 servers
 alias weapon_blaster "impulse 230"
 alias weapon_shotgun "impulse 231"
 alias weapon_machinegun "impulse 232"
@@ -18,11 +19,3 @@ alias weapon_fireball "impulse 246"
 alias weapon_seeker "impulse 247"
 alias weapon_shockwave "impulse 248"
 alias weapon_arc "impulse 249"
-
-// Backwards compatibility with 0.7.0
-alias weapon_laser "weapon_blaster"
-alias weapon_uzi "weapon_machinegun"
-alias weapon_grenadelauncher "weapon_mortar"
-alias weapon_nex "weapon_vortex"
-alias weapon_rocketlauncher "weapon_devastator"
-alias weapon_minstanex "weapon_vaporizer"