Compare commits

..

No commits in common. "Develop" and "master" have entirely different histories.

163 changed files with 7297 additions and 3045 deletions

BIN
.dir.tiff

Binary file not shown.

View file

@ -1,6 +1,6 @@
ISC License
Copyright (c) 2016-2025, Marco "eukara" Cawthorne <marco@icculus.org>
Copyright (c) 2016-2021, Marco "eukara" Hladik <marco@icculus.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View file

@ -1 +0,0 @@
package_tfc.pk3

View file

@ -1 +0,0 @@
TeamEffort

View file

@ -1,5 +1,4 @@
# ![](img/te.png) Team Effort
# FreeTFC
Clean-room reimplementation of Team Fortress Classic in QuakeC.
![Preview 1](img/preview1.jpg)
@ -9,7 +8,8 @@ Clone the repository into the Nuclide-SDK:
> git clone REPOURL tfc
Then run `make game GAME=tfc`!
then either run Nuclide's ./build_game.sh shell script, or issue 'make' inside
./tfc/src!
Obviously make sure that Nuclide has fteqw and fteqcc set-up for building.
@ -29,7 +29,7 @@ We've had people ask in the oddest of places for help, please don't do that.
## License
ISC License
Copyright (c) 2016-2025 Marco Cawthorne <marco@icculus.org>
Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above

View file

@ -1,99 +0,0 @@
set sk_plr_ac1 "32"
set sk_plr_ac2 "32"
set sk_plr_ac3 "32"
set sk_plr_autorifle1 "8"
set sk_plr_autorifle2 "8"
set sk_plr_autorifle3 "8"
set sk_plr_bioweapon1 "8"
set sk_plr_bioweapon2 "8"
set sk_plr_bioweapon3 "8"
set sk_plr_bioweapon_infection1 "8"
set sk_plr_bioweapon_infection2 "8"
set sk_plr_bioweapon_infection3 "8"
set sk_plr_crowbar1 "18"
set sk_plr_crowbar2 "18"
set sk_plr_crowbar3 "18"
set sk_plr_flamethrower1 "20"
set sk_plr_flamethrower2 "20"
set sk_plr_flamethrower3 "20"
set sk_plr_flamethrower_afterburn1 "2"
set sk_plr_flamethrower_afterburn2 "2"
set sk_plr_flamethrower_afterburn3 "2"
set sk_plr_incendiarylauncher1 "80"
set sk_plr_incendiarylauncher2 "80"
set sk_plr_incendiarylauncher3 "80"
set sk_plr_incendiarylauncher_splash1 "40"
set sk_plr_incendiarylauncher_splash2 "40"
set sk_plr_incendiarylauncher_splash3 "40"
set sk_plr_knife1 "36"
set sk_plr_knife2 "36"
set sk_plr_knife3 "36"
set sk_plr_medikit_overheal1 "5"
set sk_plr_medikit_overheal2 "5"
set sk_plr_medikit_overheal3 "5"
set sk_plr_nail1 "9"
set sk_plr_nail2 "9"
set sk_plr_nail3 "9"
set sk_plr_nail_super1 "12"
set sk_plr_nail_super2 "12"
set sk_plr_nail_super3 "12"
set sk_player_arm1 "1"
set sk_player_arm2 "1"
set sk_player_arm3 "1"
set sk_player_chest1 "1"
set sk_player_chest2 "1"
set sk_player_chest3 "1"
set sk_player_head1 "3"
set sk_player_head2 "3"
set sk_player_head3 "3"
set sk_player_leg1 "1"
set sk_player_leg2 "1"
set sk_player_leg3 "1"
set sk_player_stomach1 "1"
set sk_player_stomach2 "1"
set sk_player_stomach3 "1"
set sk_plr_shotgun1 "4"
set sk_plr_shotgun2 "4"
set sk_plr_shotgun3 "4"
set sk_plr_shotgun_super1 "4"
set sk_plr_shotgun_super2 "4"
set sk_plr_shotgun_super3 "4"
set sk_plr_pipebomb1 "80"
set sk_plr_pipebomb2 "80"
set sk_plr_pipebomb3 "80"
set sk_plr_pipebomb_splash1 "40"
set sk_plr_pipebomb_splash2 "40"
set sk_plr_pipebomb_splash3 "40"
set sk_plr_railgun1 "23"
set sk_plr_railgun2 "23"
set sk_plr_railgun3 "23"
set sk_plr_railgun_charge1 "100"
set sk_plr_railgun_charge2 "100"
set sk_plr_railgun_charge3 "100"
set sk_plr_railgun_charge_splash1 "25"
set sk_plr_railgun_charge_splash2 "25"
set sk_plr_railgun_charge_splash3 "25"
set sk_plr_rpg1 "100"
set sk_plr_rpg2 "100"
set sk_plr_rpg3 "100"
set sk_plr_rpg_splash1 "25"
set sk_plr_rpg_splash2 "25"
set sk_plr_rpg_splash3 "25"
set sk_plr_sniperrifle1 "18"
set sk_plr_sniperrifle2 "18"
set sk_plr_sniperrifle3 "18"
set sk_plr_spanner1 "18"
set sk_plr_spanner2 "18"
set sk_plr_spanner3 "18"
set sk_plr_stickybomb1 "80"
set sk_plr_stickybomb2 "80"
set sk_plr_stickybomb3 "80"
set sk_plr_stickybomb_splash1 "40"
set sk_plr_stickybomb_splash2 "40"
set sk_plr_stickybomb_splash3 "40"
set sk_plr_tranq1 "18"
set sk_plr_tranq2 "18"
set sk_plr_tranq3 "18"
set sk_plr_umbrella1 "18"
set sk_plr_umbrella2 "18"
set sk_plr_umbrella3 "18"

View file

@ -1 +0,0 @@
exec "skill.cfg"

View file

@ -1,30 +0,0 @@
// these have to be defined by the game.
entityDef ammo_types {
"ammo_none" "0"
"ammo_rockets" "1"
"ammo_nails" "2"
"ammo_cells" "3"
"ammo_shells" "4"
"ammo_medkits" "5"
"ammo_detpack" "6"
}
entityDef ammo_names {
"ammo_none" "None"
"ammo_rockets" "Rockets"
"ammo_nails" "Nails"
"ammo_cells" "Cells"
"ammo_shells" "Shells"
"ammo_medkits" "Medkit"
"ammo_detpack" "Depack"
}
entityDef ammo_max {
"ammo_none" "0"
"ammo_rockets" "255"
"ammo_nails" "255"
"ammo_cells" "255"
"ammo_shells" "255"
"ammo_medkits" "255"
"ammo_detpack" "255"
}

View file

@ -1,8 +0,0 @@
entityDef item_suit
{
"spawnclass" "ncItem"
"model" "models/w_suit.mdl"
"mins" "-16 -16 0"
"maxs" "16 16 16"
"inv_carry" "1"
}

View file

@ -1,192 +0,0 @@
entityDef player
{
"spawnclass" "TFPlayer"
}
entityDef player_shared
{
"inherit" "player"
"item" "item_suit"
}
entityDef player_scout
{
"inherit" "player_shared"
"model" "models/player/scout/scout.mdl"
"health" "75"
"armor" "25"
"maxarmor" "50"
"pm_walkspeed" "400" // 450 in QWTF
"ammo_shells" "17"
"ammo_nails" "100"
"max_ammo_shells" "50"
"max_ammo_nails" "200"
"max_ammo_cells" "100"
"max_ammo_rockets" "25"
"weapon" "tf_weapon_axe,tf_weapon_shotgun,tf_weapon_ng"
"current_weapon" "1"
}
entityDef player_sniper
{
"inherit" "player_shared"
"model" "models/player/sniper/sniper.mdl"
"health" "90"
"armor" "0"
"maxarmor" "50"
"pm_walkspeed" "300"
"ammo_shells" "60"
"ammo_nails" "50"
"max_ammo_shells" "75"
"max_ammo_nails" "100"
"max_ammo_cells" "50"
"max_ammo_rockets" "25"
"weapon" "tf_weapon_axe,tf_weapon_sniperrifle,tf_weapon_autorifle,tf_weapon_ng"
"current_weapon" "1"
}
entityDef player_soldier
{
"inherit" "player_shared"
"model" "models/player/soldier/soldier.mdl"
"health" "100"
"armor" "100"
"maxarmor" "200"
"pm_walkspeed" "240"
"ammo_shells" "26"
"ammo_rockets" "6"
"max_ammo_shells" "100"
"max_ammo_nails" "100"
"max_ammo_cells" "50"
"max_ammo_rockets" "50"
"weapon" "tf_weapon_axe,tf_weapon_supershotgun,tf_weapon_shotgun,tf_weapon_rpg"
"current_weapon" "1"
}
entityDef player_demo
{
"inherit" "player_shared"
"model" "models/player/demo/demo.mdl"
"health" "90"
"armor" "50"
"maxarmor" "100"
"pm_walkspeed" "280"
"ammo_shells" "22"
"ammo_rockets" "14"
"max_ammo_shells" "75"
"max_ammo_nails" "50"
"max_ammo_cells" "50"
"max_ammo_rockets" "50"
"weapon" "tf_weapon_axe,tf_weapon_shotgun,tf_weapon_gl,tf_weapon_pl"
"current_weapon" "1"
}
entityDef player_medic
{
"inherit" "player_shared"
"model" "models/player/medic/medic.mdl"
"health" "90"
"armor" "50"
"maxarmor" "100"
"pm_walkspeed" "320"
"ammo_shells" "26"
"ammo_nails" "50"
"max_ammo_shells" "75"
"max_ammo_nails" "150"
"max_ammo_cells" "50"
"max_ammo_rockets" "25"
"weapon" "tf_weapon_medikit,tf_weapon_supershotgun,tf_weapon_shotgun,tf_weapon_superng"
"current_weapon" "1"
}
entityDef player_heavy
{
"inherit" "player_shared"
"model" "models/player/hvyweapon/hvyweapon.mdl"
"health" "100"
"armor" "150"
"maxarmor" "300"
"pm_walkspeed" "228"
"ammo_shells" "176"
"max_ammo_shells" "200"
"max_ammo_nails" "200"
"max_ammo_cells" "50"
"max_ammo_rockets" "25"
"weapon" "tf_weapon_axe,tf_weapon_supershotgun,tf_weapon_shotgun,tf_weapon_ac"
"current_weapon" "1"
}
entityDef player_pyro
{
"inherit" "player_shared"
"model" "models/player/pyro/pyro.mdl"
"health" "100"
"armor" "50"
"maxarmor" "150"
"pm_walkspeed" "300"
"ammo_shells" "12"
"ammo_cells" "120"
"ammo_rockets" "5"
"max_ammo_shells" "40"
"max_ammo_nails" "50"
"max_ammo_cells" "200"
"max_ammo_rockets" "60"
"weapon" "tf_weapon_axe,tf_weapon_shotgun,tf_weapon_flamethrower,tf_weapon_ic"
"current_weapon" "1"
}
entityDef player_spy
{
"inherit" "player_shared"
"model" "models/player/spy/spy.mdl"
"health" "90"
"armor" "25"
"maxarmor" "100"
"pm_walkspeed" "300"
"ammo_shells" "24"
"ammo_nails" "50"
"max_ammo_shells" "40"
"max_ammo_nails" "50"
"max_ammo_cells" "30"
"max_ammo_rockets" "15"
"weapon" "tf_weapon_knife,tf_weapon_tranq,tf_weapon_supershotgun,tf_weapon_ng"
"current_weapon" "1"
}
entityDef player_engineer
{
"inherit" "player_shared"
"model" "models/player/engineer/engineer.mdl"
"health" "80"
"armor" "25"
"maxarmor" "50"
"pm_walkspeed" "300"
"ammo_shells" "4"
"ammo_nails" "25"
"ammo_cells" "100"
"max_ammo_shells" "50"
"max_ammo_nails" "50"
"max_ammo_cells" "200"
"max_ammo_rockets" "30"
"weapon" "tf_weapon_spanner,tf_weapon_railgun,tf_weapon_supershotgun"
"current_weapon" "1"
}
entityDef player_civilian
{
"inherit" "player_shared"
"model" "models/player/civilian/civilian.mdl"
"health" "50"
"armor" "0"
"maxarmor" "0"
"pm_walkspeed" "300"
"ammo_shells" "0"
"ammo_nails" "0"
"ammo_cells" "0"
"max_ammo_shells" "0"
"max_ammo_nails" "0"
"max_ammo_cells" "0"
"max_ammo_rockets" "0"
"weapon" "tf_weapon_umbrella"
"current_weapon" "1"
}

View file

@ -1,19 +0,0 @@
#include "weapons/ac.def"
#include "weapons/autorifle.def"
#include "weapons/axe.def"
#include "weapons/flamethrower.def"
#include "weapons/gl.def"
#include "weapons/ic.def"
#include "weapons/knife.def"
#include "weapons/medikit.def"
#include "weapons/ng.def"
#include "weapons/pl.def"
#include "weapons/railgun.def"
#include "weapons/rpg.def"
#include "weapons/shotgun.def"
#include "weapons/sniperrifle.def"
#include "weapons/spanner.def"
#include "weapons/superng.def"
#include "weapons/supershotgun.def"
#include "weapons/tranq.def"
#include "weapons/umbrella.def"

View file

@ -1,55 +0,0 @@
entityDef tf_weapon_ac
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Assualt Cannon"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/w_tfac.mdl"
"model_view" "models/v_tfac.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfAssaultCannon"
"inv_name" "Assualt Cannon"
"ammoType" "ammo_shells"
"ammoRequired" "1"
"ammoPerShot" "2"
"punchAngle" "-2 0 0"
"actLoop" "4"
"act_holster" "6"
"act_draw" "5"
"act_fireStart" "2"
"act_fireStop" "3"
"act_idle" "0,1"
"snd_fireStart" "Weapon_Minigun.WindUp"
"snd_fireLoop" "Weapon_Minigun.Fire"
"snd_fireEnd" "Weapon_Minigun.WindDown"
"snd_empty" "Weapon_Minigun.ClipEmpty"
// HLWeapon specific
"hudSlot" "4"
"hudSlotPos" "0"
"weight" "30"
}
entityDef projectile_tfAssaultCannon
{
"inherit" "projectile_bullet_base"
"damage" "skill:plr_ac"
"hitscans" "12"
"spread" "0.08716 0.08716"
}
entityDef fireInfo_tfAssaultCannon
{
"def_onFire" "projectile_tfAssaultCannon"
"fireRate" "0.1"
"punchAngle" "-2 0 0"
"model_flash" "sprites/muzzleflash2.spr"
}

View file

@ -1,52 +0,0 @@
entityDef tf_weapon_autorifle
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Automatic Rifle"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/w_9mmhandgun.mdl"
"model_view" "models/v_tfc_sniper.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfAutoRifle"
"inv_name" "Automatic Rifle"
"inv_ammo_shells" "75"
"ammoType" "ammo_shells"
"ammoRequired" "1"
"ammoPerShot" "1"
"punchAngle" "-2 0 0"
"act_fire" "6"
"act_holster" "8"
"act_draw" "7"
"act_idle" "5"
"snd_fire" "Weapon_SMG.Single"
"snd_empty" "Weapon_SMG.ClipEmpty"
// HLWeapon specific
"hudSlot" "2"
"hudSlotPos" "0"
"weight" "10"
}
entityDef projectile_tfAutoRifleBullet
{
"inherit" "projectile_bullet_base"
"damage" "skill:plr_autorifle"
"spread" "0.025 0.025"
}
entityDef fireInfo_tfAutoRifle
{
"def_onFire" "projectile_tfAutoRifleBullet"
"ammoType" "ammo_shells"
"fireRate" "0.085"
"punchAngle" "-2 0 0"
"model_flash" "sprites/muzzleflash1.spr"
}

View file

@ -1,49 +0,0 @@
entityDef tf_weapon_axe
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Crowbar (Axe)"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/w_crowbar.mdl"
"model_view" "models/v_tfc_crowbar.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_melee" "damage_tfAxe"
"melee_distance" "32"
"inv_name" "Crowbar (Axe)"
"ammoType" ""
"ammoRequired" "0"
"clipSize" "0"
"silent_fire" "1"
"meleeRateMiss" "0.5"
"meleeRateHit" "0.5"
"act_idle" "0"
"act_draw" "1"
"act_holster" "2"
"act_fireFailed" "4,5,7"
"act_fire" "3,6,8"
// HLWeapon specific
"hudSlot" "0"
"hudSlotPos" "0"
"weight" "0"
"crosshair" "none"
"ammoIcon" "none"
}
entityDef damage_tfAxe
{
"damage" "skill:plr_crowbar"
"gib" "1"
"snd_hit" "Weapon_Crowbar.HitWorld"
"snd_hitFlesh" "Weapon_Crowbar.HitFlesh"
"snd_miss" "Weapon_Crowbar.Miss"
}

View file

@ -1,88 +0,0 @@
entityDef tf_weapon_flamethrower
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Flamethrower"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_egon.mdl"
"model_view" "models/v_flame.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfFlameThrower"
"inv_name" "Flamethrower"
"ammoType" "ammo_cells"
"ammoRequired" "1"
"act_fire" "5,6,7,8"
"act_holster" "10"
"act_draw" "9"
"act_idle" "0,1"
"snd_fire" "Weapon_FlameThrower.Fire"
"snd_empty" "Weapon_Pistol.ClipEmpty"
// HLWeapon specific
"hudSlot" "3"
"hudSlotPos" "1"
"weight" "30"
}
entityDef fireInfo_tfFlameThrower
{
"def_onFire" "projectile_tfFire"
"ammoPerShot" "2"
"fireRate" ".2"
"punchAngle" "-2 0 0"
"act_fire" "5,6"
"model_flash" "sprites/muzzleflash2.spr"
}
entityDef projectile_tfFire
{
"spawnclass" "ncProjectile"
"model" "sprites/fthrow.spr"
"def_damage" "tfFireDirect"
"health" "0"
"velocity" "250"
"angular_velocity" "0 0 200"
"fuse" "10"
"detonate_on_fuse" "0"
"detonate_on_death" "1"
"detonate_on_world" "1"
"detonate_on_actor" "1"
"impact_damage_effect" "1"
"impact_gib" "1"
"thrust" "2000"
"thrust_start" "0.1"
"thrust_end" "2"
"light_color" "1 0.8 0.4"
"light_radius" "160"
"light_offset" "0 0 0"
}
entityDef damage_tfFireDirect
{
"damage" "skill:plr_flamethrower"
}
entityDef damage_tfFireAfterburn
{
"damage" "skill:plr_flamethrower_afterburn"
}
entityDef fireInfo_tfFlameThrower
{
"def_onFire" "projectile_tfFire"
"punchAngle" "-10 0 0"
"reloadTime" "0.6"
}

View file

@ -1,78 +0,0 @@
entityDef tf_weapon_gl
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Grenade Launcher"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_glauncher.mdl"
"model_view" "models/v_tfgl.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfGrenadeLauncher"
"inv_name" "Grenade Launcher"
"clipSize" "6"
"ammoType" "ammo_rockets"
"ammoRequired" "1"
"ammoPerShot" "1"
"punchAngle" "-2 0 0"
"act_fire" "2"
"act_holster" "10"
"act_reloadStart" "4"
"act_reload" "4"
"act_reloadEnd" "5"
"act_draw" "8"
"act_idle" "0"
"snd_fire" "Weapon_GrenadeLauncher.Single"
"snd_empty" "Weapon_Pistol.ClipEmpty"
// HLWeapon specific
"hudSlot" "3"
"hudSlotPos" "0"
"weight" "10"
}
entityDef fireInfo_tfGrenadeLauncher
{
"def_onFire" "projectile_tfPipebomb"
"fireRate" "0.8"
"punchAngle" "-4 0 0"
}
entityDef projectile_tfPipebomb
{
"spawnclass" "ncProjectile"
"model" "models/pipebomb.mdl"
"skin" "1"
"frame" "1"
"fuse" "4"
"detonate_on_fuse" "1"
"bounce" "1"
"angular_velocity" "-350 0 0"
"velocity" "300 0 40"
"model_detonate" "fx_explosion.main"
"snd_explode" "Weapon_Grenade_Pipebomb.Explode"
"snd_bounce" "Weapon_Grenade_Pipebomb.Bounce"
"decal_detonate" "ExplosionScorch"
"smoke_fly" "weapon_rpg.trail"
"def_damage" "damage_tfPipebombDirect"
"def_splash_damage" "damage_tfPipebombSplash"
}
entityDef damage_tfPipebombDirect
{
"damage" "skill:plr_pipebomb"
}
entityDef damage_tfPipebombSplash
{
"damage" "skill:plr_pipebomb_splash"
"radius" "250"
}

View file

@ -1,95 +0,0 @@
entityDef tf_weapon_ic
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Incendiary Cannon"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/w_9mmhandgun.mdl"
"model_view" "models/v_tfc_rpg.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfIncendiaryCannon"
"inv_name" "Incendiary Cannon"
"ammoType" "ammo_rockets"
"ammoRequired" "1" // 3 in Quake Team Fortress
"ammoPerShot" "1"
"punchAngle" "-4 0 0"
"act_idle" "0,1"
"act_idleEmpty" "10,11"
"act_draw" "4"
"act_drawEmpty" "6"
"act_holster" "3"
"act_holsterEmpty" "5"
"act_reloadStart" "7"
"act_reload" "8"
"act_reloadEnd" "9"
"act_fire" "2"
"snd_fire" "Weapon_FlameThrower.FireRocket"
"snd_empty" "Weapon_Pistol.ClipEmpty"
// HLWeapon specific
"hudSlot" "4"
"hudSlotPos" "0"
"weight" "20"
}
entityDef projectile_tfIncendiaryRocket
{
"spawnclass" "ncProjectile"
"model" "models/rpgrocket.mdl"
"def_damage" "damage_tfIncendiaryRocketDirect"
"def_splash_damage" "damage_tfIncendiaryRocketSplash"
"health" "0"
"velocity" "250"
"angular_velocity" "0 0 200"
"fuse" "10"
"detonate_on_fuse" "0"
"detonate_on_death" "1"
"detonate_on_world" "1"
"detonate_on_actor" "1"
"impact_damage_effect" "1"
"impact_gib" "1"
"thrust" "2000"
"thrust_start" "0.1"
"thrust_end" "2"
"smoke_fly" "weapon_rpg.trail"
"decal_detonate" "ExplosionScorch"
"model_detonate" "fx_explosion.main"
"light_color" "1 0.8 0.4"
"light_radius" "160"
"light_offset" "0 0 0"
"explode_light_color" "2 1.6 0.8"
"explode_light_radius" "320"
"explode_light_fadetime" "0.5"
"snd_explode" "fx.explosion"
}
entityDef damage_tfIncendiaryRocketDirect
{
"damage" "skill:plr_incendiarylauncher"
}
entityDef damage_tfIncendiaryRocketSplash
{
"damage" "skill:plr_incendiarylauncher_splash"
"radius" "250"
}
entityDef fireInfo_tfIncendiaryCannon
{
"def_onFire" "projectile_tfIncendiaryRocket"
"punchAngle" "-10 0 0"
}

View file

@ -1,50 +0,0 @@
entityDef tf_weapon_knife
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Knife"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_knife.mdl"
"model_view" "models/v_tfc_knife.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_melee" "damage_tfKnife"
"melee_distance" "32"
"inv_name" "Knife"
"ammoType" ""
"ammoRequired" "0"
"clipSize" "0"
"silent_fire" "1"
"meleeRateMiss" "0.35"
"meleeRateHit" "0.35"
"act_idle" "0,1"
"act_draw" "4"
"act_holster" "5"
"act_fireFailed" "2"
"act_fire" "3"
// HLWeapon specific
"hudSlot" "0"
"hudSlotPos" "0"
"weight" "0"
"crosshair" "none"
"ammoIcon" "none"
}
}
entityDef damage_tfKnife
{
"damage" "skill:plr_knife"
"gib" "1"
"snd_hit" "Weapon_Knife.HitWorld"
"snd_hitFlesh" "Weapon_Knife.HitFlesh"
"snd_miss" "Weapon_Knife.Miss"
}

View file

@ -1,68 +0,0 @@
entityDef tf_weapon_medikit
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Medkit"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_medkit.mdl"
"model_view" "models/v_tfc_medkit.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_melee" "damage_tfMedikit"
"melee_distance" "32"
"inv_name" "Medikit"
"ammoType" ""
"ammoRequired" "0"
"clipSize" "0"
"silent_fire" "1"
"meleeRateMiss" "0.35"
"meleeRateHit" "0.35"
"act_idle" "0,1"
"act_draw" "5"
"act_holster" "4"
"act_fireFailed" "3"
"act_fire" "2"
// HLWeapon specific
"hudSlot" "0"
"hudSlotPos" "0"
"weight" "30"
"crosshair" "none"
"ammoIcon" "none"
}
//TODO
// Does initial damage then triggers tfInfection
entityDef damage_tfBioweapon
{
"damage" "skill:plr_bioweapon"
"snd_hitFlesh" "Weapon_Bioweapon.HitFlesh"
}
// Damages every couple seconds until death or heal
// Spreads to other players (except medic)
entityDef damage_tfBioweaponInfection
{
"damage" "skill:plr_bioweapon_infection"
}
// Initial heal will always fully heal player
entityDef damage_tfMedikit
{
"snd_hitFlesh" "Weapon_Medikit.HitFlesh"
}
// Overheal applys heal every attack, maxes at 50+
entityDef damage_tfMedikitOverheal
{
"damage" "skill:plr_medikit_overheal"
"snd_hitFlesh" "Weapon_Medikit.Overheal"
}

View file

@ -1,70 +0,0 @@
entityDef tf_weapon_ng
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Nail Gun"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_nailgun2.mdl"
"model_view" "models/v_tfc_nailgun.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfNailGun"
"inv_name" "Nail Gun"
"inv_ammo_nails" "25"
"ammoType" "ammo_nails"
"ammoRequired" "1"
"ammoPerShot" "1"
"act_idle" "0,1"
"act_draw" "4"
"act_fire" "5,6,7"
"snd_fire" "Weapon_NailGun.Single"
"snd_empty" "Weapon_NailGun.ClipEmpty"
// HLWeapon specific
"hudSlot" "3"
"hudSlotPos" "0"
"weight" "20"
}
entityDef debris_tfNail
{
"spawnclass" "ncProjectile"
"model" "models/nail.mdl"
}
entityDef projectile_tfNail
{
"spawnclass" "ncProjectile"
"model" "models/nail.mdl"
"velocity" "1000 0 0"
"angular_velocity" "0 0 20"
"mins" "0 0 0"
"maxs" "0 0 0"
"damage" "skill:plr_nail"
"snd_explode" "impact.tfNail"
"snd_hit" "impact.tfNailHitFlesh"
"detonate_on_fuse" "0"
"detonate_on_death" "1"
"detonate_on_world" "1"
"detonate_on_actor" "1"
"projectile_debris" "debris_tfNail"
"model_detonate" "impact_default.main"
"decal_detonate" "Impact.Shot"
"debris_count" "1"
"debris_stick" "1"
"debris_offset" "-2 0 0"
"offset" "0 3 -6"
}
entityDef fireInfo_tfNailGun
{
"def_onFire" "projectile_tfNail"
"fireRate" "0.1"
"punchAngle" "-4 0 0"
"model_flash" "sprites/muzzleflash2.spr"
}

View file

@ -1,75 +0,0 @@
entityDef tf_weapon_pl
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Sticky Launcher"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_glauncher.mdl"
"model_view" "models/v_tfgl.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfStickyLauncher"
"detonateOnFire" "projectile_tfStickybomb"
"inv_name" "Sticky Launcher"
"clipSize" "6"
"ammoType" "ammo_rockets"
"ammoRequired" "1"
"ammoPerShot" "1"
"punchAngle" "-2 0 0"
"act_fire" "3"
"act_holster" "11"
"act_reloadStart" "6"
"act_reload" "6"
"act_reloadEnd" "7"
"act_draw" "9"
"act_idle" "1"
"snd_fire" "Weapon_StickyBombLauncher.Single"
"snd_empty" "Weapon_Pistol.ClipEmpty"
// HLWeapon specific
"hudSlot" "4"
"hudSlotPos" "0"
"weight" "10"
}
entityDef fireInfo_tfStickyLauncher
{
"def_onFire" "projectile_tfStickybomb"
"fireRate" "0.8"
"punchAngle" "-4 0 0"
}
entityDef projectile_tfStickybomb
{
"spawnclass" "ncProjectile"
"model" "models/pipebomb.mdl"
"frame" "1"
"bounce" "1"
"angular_velocity" "-350 0 0"
"velocity" "300 0 40"
"model_detonate" "fx_explosion.main"
"snd_explode" "Weapon_Grenade_Pipebomb.Explode"
"snd_bounce" "Weapon_Grenade_Pipebomb.Bounce"
"decal_detonate" "ExplosionScorch"
"def_damage" "damage_tfStickybombDirect"
"def_splash_damage" "damage_tfStickybombSplash"
}
entityDef damage_tfStickybombDirect
{
"damage" "skill:plr_stickybomb"
}
entityDef damage_tfStickybombSplash
{
"damage" "skill:plr_stickybomb_splash"
"radius" "250"
}

View file

@ -1,138 +0,0 @@
entityDef tf_weapon_railgun
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "RailGun"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_9mmhandgun.mdl"
"model_view" "models/v_tfc_railgun.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfRailGun"
// "def_altFireInfo" "fireInfo_tfRailGunCharge" // Fortress Forever style charge attack
"inv_name" "RailGun"
"ammoType" "ammo_nails"
"ammoRequired" "1"
"ammoPerShot" "1"
"punchAngle" "-2 0 0"
"act_fire" "1"
// "actAltFire" "1"
"act_holster" "3"
"act_draw" "2"
"act_idle" "0"
"snd_fire" "Weapon_Railgun.Single"
"snd_altfire" "Weapon_Railgun.WindUp"
"snd_empty" "Weapon_Pistol.ClipEmpty"
// HLWeapon specific
"hudSlot" "1"
"hudSlotPos" "0"
"weight" "10"
}
entityDef projectile_tfRailShot
{
"spawnclass" "ncProjectile"
"model" ""
"def_damage" "damage_tfRailDirect"
"health" "0"
"velocity" "250"
"angular_velocity" "0 0 200"
"fuse" "10"
"detonate_on_fuse" "0"
"detonate_on_death" "1"
"detonate_on_world" "1"
"detonate_on_actor" "1"
"impact_damage_effect" "1"
"impact_gib" "1"
"thrust" "2000"
"thrust_start" "0.1"
"thrust_end" "2"
"smoke_fly" "weapon_railgun.trail"
"decal_detonate" "Impact.BigShot"
"model_detonate" "fx_spark.main"
"snd_explode" "fx.spark
"light_color" "0 0.5 0"
"light_radius" "160"
"light_offset" "0 0 0"
}
entityDef projectile_tfRailChargedShot
{
"spawnclass" "ncProjectile"
"model" ""
"def_damage" "damage_tfRailChargeDirect"
"def_splash_damage" "damage_tfTailChargedSplash"
"health" "0"
"velocity" "250"
"angular_velocity" "0 0 200"
"fuse" "10"
"detonate_on_fuse" "0"
"detonate_on_death" "1"
"detonate_on_world" "1"
"detonate_on_actor" "1"
"impact_damage_effect" "1"
"impact_gib" "1"
"thrust" "2000"
"thrust_start" "0.1"
"thrust_end" "2"
"smoke_fly" "weapon_railgun.trail"
"decal_detonate" "ExplosionScorch"
"model_detonate" "fx_explosion.main"
"light_color" "0 0.5 0"
"light_radius" "160"
"light_offset" "0 0 0"
"explode_light_color" "2 1.6 0.8"
"explode_light_radius" "320"
"explode_light_fadetime" "0.5"
"snd_explode" "fx.explosion"
}
entityDef damage_tfRailDirect
{
"damage" "skill:plr_railgun"
}
entityDef damage_tfRailChargeDirect
{
"damage" "skill:plr_railgun_charge"
}
entityDef damage_tfTailChargedSplash
{
"damage" "skill:plr_railgun_charge_splash"
"radius" "250"
}
entityDef fireInfo_tfRailGun
{
"def_onFire" "projectile_tfRailShot"
"ammoPerShot" "1"
"fireRate" "0.4"
"punchAngle" "-2 0 0"
}
entityDef fireInfo_tfRailGunCharge
{
"def_onFire" "projectile_tfRailChargedShot"
"ammoPerShot" "1"
"fireRate" "0.75"
"punchAngle" "-10 0 0"
}

View file

@ -1,95 +0,0 @@
entityDef tf_weapon_rpg
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Rocket Launcher"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/w_rpg.mdl"
"model_view" "models/v_tfc_rpg.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
"def_fireInfo" "fireInfo_tfRPG"
"ammoType" "ammo_rockets"
"clipSize" "4"
"ammoRequired" "1"
"ammoPerShot" "1"
"inv_ammo_rockets" "1"
"fireRate" "2.5"
"act_idle" "0,1"
"act_idleEmpty" "10,11"
"act_draw" "4"
"act_drawEmpty" "6"
"act_holster" "3"
"act_holsterEmpty" "5"
"act_reloadStart" "7"
"act_reload" "8"
"act_reloadEnd" "9"
"act_fire" "2"
"snd_fire" "Weapon_RPG.Single"
"snd_empty" "Weapon_Pistol.ClipEmpty"
// HLWeapon specific
"hudSlot" "3"
"hudSlotPos" "0"
"weight" "20"
}
entityDef projectile_tfRocket
{
"spawnclass" "ncProjectile"
"model" "models/rpgrocket.mdl"
"def_damage" "damage_tfRocketDirect"
"def_splash_damage" "damage_tfRocketSplash"
"health" "0"
"velocity" "250"
"angular_velocity" "0 0 200"
"fuse" "10"
"detonate_on_fuse" "0"
"detonate_on_death" "1"
"detonate_on_world" "1"
"detonate_on_actor" "1"
"impact_damage_effect" "1"
"impact_gib" "1"
"thrust" "2000"
"thrust_start" "0.1"
"thrust_end" "2"
"smoke_fly" "weapon_rpg.trail"
"decal_detonate" "ExplosionScorch"
"model_detonate" "fx_explosion.main"
"light_color" "1 0.8 0.4"
"light_radius" "160"
"light_offset" "0 0 0"
"explode_light_color" "2 1.6 0.8"
"explode_light_radius" "320"
"explode_light_fadetime" "0.5"
"snd_explode" "fx.explosion"
}
entityDef damage_tfRocketDirect
{
"damage" "skill:plr_rpg"
}
entityDef damage_tfRocketSplash
{
"damage" "skill:plr_rpg_splash"
"radius" "250"
}
entityDef fireInfo_tfRPG
{
"def_onFire" "projectile_tfRocket"
"punchAngle" "-10 0 0"
"reloadTime" "0.6"
}

View file

@ -1,62 +0,0 @@
entityDef tf_weapon_shotgun
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Single-Barrel Shotgun"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_shotgun.mdl"
"model_view" "models/v_tfc_12gauge.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfShotgun"
"inv_name" "Single-Barrel Shotgun"
"inv_ammo_shells" "4"
"ammoType" "ammo_shells"
"ammoRequired" "1"
"clipSize" "8"
"act_fire" "1"
"act_holster" "7"
"act_reloadStart" "5"
"act_reload" "3"
"act_reloadEnd" "4"
"act_draw" "6"
"act_idle" "0,8,9"
//TODO Fast Reload
"snd_fire" "Weapon_Shotgun.Single"
"snd_empty" "Weapon_Shotgun.Empty"
"snd_reload" "Weapon_Shotgun.Reload"
"snd_reload_end" "Weapon_Shotgun.Pump"
// HLWeapon specific
"hudSlot" "1"
"hudSlotPos" "0"
"weight" "10"
}
// TODO Damage should be 4-24
entityDef projectile_tfShotgun
{
"inherit" "projectile_bullet_base"
"damage" "skill:plr_shotgun"
"hitscans" "12"
"spread" "0.08716 0.08716"
}
entityDef fireInfo_tfShotgun
{
"def_onFire" "projectile_tfShotgun"
"ammoPerShot" "1"
"fireRate" "0.5"
"punchAngle" "-2 0 0"
"model_flash" "sprites/muzzleflash2.spr"
"reloadTime" "0.2"
}

View file

@ -1,59 +0,0 @@
entityDef tf_weapon_sniperrifle
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Sniper Rifle"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_sniper2.mdl"
"model_view" "models/v_tfc_sniper.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfSniperRifle"
"inv_name" "Sniper Rifle"
"inv_ammo_shells" "75"
"ammoType" "ammo_shells"
"ammoRequired" "1"
"ammoPerShot" "1"
"punchAngle" "-2 0 0"
"act_fire" "6"
"act_holster" "8"
"act_draw" "7"
"act_idle" "5"
"snd_fire" "Weapon_SniperRifle.Single"
"snd_empty" "Weapon_SniperRifle.ClipEmpty"
// HLWeapon specific
"hudSlot" "1"
"hudSlotPos" "0"
"weight" "20"
"zoomDuration" "0"
"zoomFov" "20"
"zoomFovStep" "5"
"zoomFovMin" "5"
"zoomFovMax" "40"
}
entityDef projectile_tfSniperRifleBullet
{
"inherit" "projectile_bullet_base"
"damage" "skill:plr_sniperrifle"
"spread" "0.025 0.025"
}
entityDef fireInfo_tfSniperRifle
{
"def_onFire" "projectile_tfSniperRifleBullet"
"ammoType" "ammo_shells"
"fireRate" "0.75"
"punchAngle" "-2 0 0"
"model_flash" "sprites/muzzleflash1.spr"
}

View file

@ -1,46 +0,0 @@
entityDef tf_weapon_spanner
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Wrench"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_spanner.mdl"
"model_view" "models/v_tfc_spanner.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_melee" "damage_tfWrench"
"melee_distance" "32"
"inv_name" "Wrench"
"ammoType" "ammo_cells"
"ammoRequired" "0"
"ammoPerShot" "0"
"punchAngle" "0 0 0"
"silent_fire" "1"
"act_idle" "0"
"act_draw" "4"
"act_holster" "5"
"act_fireFailed" "1,2"
"act_fire" "3"
// HLWeapon specific
"hudSlot" "0"
"hudSlotPos" "0"
"weight" "0"
"crosshair" "none"
"ammoIcon" "none"
}
entityDef damage_tfWrench
{
"damage" "skill:plr_spanner"
"snd_hit" "Weapon_Wrench.HitWorld"
"snd_hitFlesh" "Weapon_Wrench.HitFlesh"
"snd_miss" "Weapon_Wrench.Miss"
}

View file

@ -1,64 +0,0 @@
entityDef tf_weapon_superng
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Super Nail Gun"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_snailgun2.mdl"
"model_view" "models/v_tfc_supernailgun.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfSuperNailGun"
"inv_name" "Super Nail Gun"
"inv_ammo_nails" "50"
"ammoType" "ammo_nails"
"ammoRequired" "1"
"act_idle" "0,1"
"act_draw" "4"
"act_fire" "5,6,7"
"snd_fire" "Weapon_SyringeGun.Single"
"snd_empty" "Weapon_SyringeGun.ClipEmpty"
// HLWeapon specific
"hudSlot" "3"
"hudSlotPos" "0"
"weight" "20"
}
entityDef projectile_tfSuperNail
{
"spawnclass" "ncProjectile"
"model" "models/nail.mdl"
"velocity" "1000 0 0"
"angular_velocity" "0 0 20"
"mins" "0 0 0"
"maxs" "0 0 0"
"damage" "skill:plr_nail_super"
"snd_explode" "impact.tfNail"
"snd_hit" "impact.tfNailHitFlesh"
"detonate_on_fuse" "0"
"detonate_on_death" "1"
"detonate_on_world" "1"
"detonate_on_actor" "1"
"projectile_debris" "debris_tfNail"
"model_detonate" "impact_default.main"
"decal_detonate" "ExplosionScorch"
"debris_count" "1"
"debris_stick" "1"
"debris_offset" "-2 0 0"
}
entityDef fireInfo_tfSuperNailGun
{
"def_onFire" "projectile_tfSuperNail"
"ammoPerShot" "1"
"fireRate" "0.1"
"punchAngle" "-4 0 0"
"model_flash" "sprites/muzzleflash2.spr"
}

View file

@ -1,61 +0,0 @@
entityDef tf_weapon_supershotgun
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Double-Barrel Shotgun"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/w_shotgun.mdl"
"model_view" "models/v_tfc_shotgun.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfSuperShotgun"
"inv_name" "Double-Barrel Shotgun"
"inv_ammo_shells" "4"
"ammoType" "ammo_shells"
"ammoRequired" "2"
"clipSize" "16"
"act_fire" "1"
"act_holster" "7"
"act_reloadStart" "5"
"act_reload" "3"
"act_reloadEnd" "4"
"act_draw" "6"
"act_idle" "0,8,9"
"snd_fire" "Weapon_SuperShotgun.Single"
"snd_empty" "Weapon_Shotgun.Empty"
"snd_reload" "Weapon_Shotgun.Reload"
"snd_reload_end" "Weapon_Shotgun.Pump"
// HLWeapon specific
"hudSlot" "2"
"hudSlotPos" "1"
"weight" "20"
}
// TODO Damage should be 4-56
entityDef projectile_tfSuperShotgun
{
"inherit" "projectile_bullet_base"
"damage" "skill:plr_shotgun_super"
"hitscans" "12"
"spread" "0.08716 0.08716"
}
entityDef fireInfo_tfSuperShotgun
{
"def_onFire" "projectile_tfSuperShotgun"
"ammoPerShot" "2"
"fireRate" "0.7"
"punchAngle" "-4 0 0"
"model_flash" "sprites/muzzleflash2.spr"
"reloadTime" "0.4"
}

View file

@ -1,71 +0,0 @@
entityDef tf_weapon_tranq
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Tranquilizer Gun"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/w_9mmhandgun.mdl"
"model_view" "models/v_tfc_pistol.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_fireInfo" "fireInfo_tfTranq"
"inv_name" "Tranquilizer Gun"
"ammoType" "ammo_shells"
"ammoRequired" "1"
"ammoPerShot" "1"
"punchAngle" "-2 0 0"
"act_fire" "3"
"actAltFire" "3"
"act_fireLast" "4"
"actAltFireLast" "4"
"act_holster" "8"
"act_reload" "6"
"act_reloadEmpty" "5"
"act_draw" "7"
"act_idle" "0,1,2"
"view_geomset" "geomset 2 2\n"
"snd_fire" "Weapon_Tranq.Single"
"snd_empty" "Weapon_Tranq.ClipEmpty"
// HLWeapon specific
"hudSlot" "1"
"hudSlotPos" "0"
"weight" "10"
}
entityDef fireInfo_tfTranq
{
"def_onFire" "projectile_tfTranq"
"fireRate" "2.0"
"punchAngle" "-4 0 0"
}
entityDef projectile_tfTranq
{
"spawnclass" "ncProjectile"
"model" "models/nail.mdl"
"velocity" "1000 0 0"
"angular_velocity" "0 0 20"
"mins" "0 0 0"
"maxs" "0 0 0"
"damage" "skill:plr_tranq"
"snd_explode" "impact.tfNail"
"snd_hit" "impact.tfNailHitFlesh"
"detonate_on_fuse" "0"
"detonate_on_death" "1"
"detonate_on_world" "1"
"detonate_on_actor" "1"
"projectile_debris" "debris_tfNail"
"model_detonate" "impact_default.main"
"decal_detonate" "ExplosionScorch"
"debris_count" "1"
"debris_stick" "1"
"debris_offset" "-2 0 0"
}

View file

@ -1,49 +0,0 @@
entityDef tf_weapon_umbrella
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Umbrella"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_umbrella.mdl"
"model_view" "models/v_umbrella.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
// weapon specific
"def_melee" "damage_tfUmbrella"
"melee_distance" "32"
"inv_name" "Umbrella"
"ammoType" ""
"ammoRequired" "0"
"clipSize" "0"
"silent_fire" "1"
"meleeRateMiss" "0.5"
"meleeRateHit" "0.5"
"act_idle" "0"
"act_draw" "1"
"act_holster" "2"
"act_fireFailed" "4,5,7"
"act_fire" "3,6,8"
// HLWeapon specific
"hudSlot" "0"
"hudSlotPos" "0"
"weight" "0"
"crosshair" "none"
"ammoIcon" "none"
}
entityDef damage_tfUmbrella
{
"damage" "skill:plr_umbrella"
"gib" "1"
"snd_hit" "Weapon_Umbrella.HitWorld"
"snd_hitFlesh" "Weapon_Umbrella.HitFlesh"
"snd_miss" "Weapon_Umbrella.Miss"
}

View file

@ -1,238 +0,0 @@
Weapon_Bioweapon.HitFlesh
{
pitch 0.75
sample items/medshot4.wav
}
Weapon_Crowbar.HitWorld
{
alerts
sample weapons/cbar_hit1.wav
sample weapons/cbar_hit2.wav
}
Weapon_Crowbar.HitFlesh
{
alerts
sample weapons/cbar_hitbod1.wav
sample weapons/cbar_hitbod2.wav
sample weapons/cbar_hitbod3.wav
}
Weapon_Crowbar.Miss
{
sample weapons/cbar_miss1.wav
}
Weapon_FlameThrower.Fire
{
sample weapons/flmfire2.wav
}
Weapon_FlameThrower.FireRocket
{
sample weapons/sgun1.wav
}
Weapon_Grenade_Pipebomb.Bounce
{
sample weapons/grenade_hit1.wav
sample weapons/grenade_hit2.wav
sample weapons/grenade_hit3.wav
}
Weapon_Grenade_Pipebomb.Explode
{
sample weapons/explode3.wav
sample weapons/explode4.wav
sample weapons/explode5.wav
}
Weapon_GrenadeLauncher.Single
{
sample weapons/glauncher.wav
}
Weapon_Knife.HitWorld
{
alerts
sample weapons/cbar_hit1.wav
sample weapons/cbar_hit2.wav
}
Weapon_Knife.HitFlesh
{
alerts
sample weapons/cbar_hitbod1.wav
sample weapons/cbar_hitbod2.wav
sample weapons/cbar_hitbod3.wav
}
Weapon_Knife.Miss
{
sample weapons/cbar_miss1.wav
}
Weapon_Medikit.HitFlesh
{
sample items/medshot4.wav
}
Weapon_Minigun.Fire
{
alerts
pitch 0.75
sample weapons/asscan2.wav
}
Weapon_Minigun.ClipEmpty
{
sample weapons/dryfire1.wav
}
Weapon_Minigun.WindDown
{
alerts
sample weapons/asscan3.wav
}
Weapon_Minigun.WindUp
{
alerts
sample weapons/asscan1.wav
}
Weapon_Medikit.Overheal
{
pitch 1.5
sample items/smallmedkit1.wav
}
Weapon_Medikit.HitFlesh
{
sample items/smallmedkit1.wav
}
Weapon_NailGun.Single
{
sample weapons/airgun_1.wav
}
Weapon_NailGun.ClipEmpty
{
sample weapons/dryfire1.wav
}
Weapon_RPG.Single
{
sample weapons/rocketfire1.wav
}
Weapon_Pistol.ClipEmpty
{
sample weapons/dryfire1.wav
}
Weapon_Railgun.Single
{
sample weapons/railgun.wav
}
Weapon_Railgun.WindUp
{
pitch 0.5
sample weapons/railgun.wav
}
Weapon_Shotgun.Single
{
sample weapons/sbarrel1.wav
}
Weapon_SuperShotgun.Single
{
sample weapons/shotgn2.wav
}
Weapon_Shotgun.Pump
{
sample weapons/scock1.wav
}
Weapon_Shotgun.Reload
{
sample weapons/reload3.wav
}
Weapon_SMG.Single
{
sample weapons/sniper.wav
}
Weapon_SMG.ClipEmpty
{
sample weapons/dryfire1.wav
}
Weapon_SniperRifle.Single
{
sample ambience/rifle1.wav
}
Weapon_SniperRifle.ClipEmpty
{
sample weapons/dryfire1.wav
}
Weapon_StickyBombLauncher.Single
{
sample weapons/glauncher2.wav
}
Weapon_SyringeGun.Single
{
sample weapons/spike2.wav
}
Weapon_SyringeGun.ClipEmpty
{
sample weapons/dryfire1.wav
}
Weapon_Tranq.Single
{
sample weapons/dartgun.wav
}
Weapon_Tranq.ClipEmpty
{
sample weapons/dryfire1.wav
}
Weapon_Wrench.HitFlesh
{
sample weapons/cbar_hitbod1.wav
sample weapons/cbar_hitbod2.wav
sample weapons/cbar_hitbod3.wav
}
Weapon_Wrench.HitWorld
{
sample weapons/cbar_hit1.wav
sample weapons/cbar_hit2.wav
}
Weapon_Wrench.Miss
{
sample weapons/cbar_miss1.wav
}
engineer.build
{
sample weapons/building.wav
}
engineer.turret_set
{
sample weapons/turrset.wav
}

View file

@ -1,3 +0,0 @@
set "hostname" "Team Effort Server"
set "maxplayers" "8"
set g_gametype "default"

BIN
icon.tga

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

2
instructions.txt Normal file
View file

@ -0,0 +1,2 @@
In order to play this FreeHL addon, please move the folder this file is
in into the same place where 'valve' and 'default.fmf' reside. Thanks!

14
manifest.fmf Normal file
View file

@ -0,0 +1,14 @@
FTEMANIFEST 1
GAME tfc
NAME "Team Fortress"
BASEGAME platform
BASEGAME valve
BASEGAME tfc
// you don't really want to change these
RTCBROKER master.frag-net.com:27950
PROTOCOLNAME "Nuclide"
MAINCONFIG game.cfg
DOWNLOADSURL "http://www.frag-net.com/dl/packages"
-exec platform_default.cfg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

View file

@ -1,5 +0,0 @@
exec default_controls.cfg
exec default_cvar.cfg
exec default_video.cfg
exec default_valve.cfg
exec default_tfc.cfg

View file

@ -3,4 +3,3 @@ CC=fteqcc
all:
cd client && $(MAKE)
cd server && $(MAKE)
cd rules && $(MAKE)

View file

@ -1,4 +1,4 @@
QCC=fteqcc
CC=fteqcc
all:
$(QCC) $(CFLAGS) -I../../../src/platform/ -I../../../valve/src/shared/ progs.src
$(CC) progs.src

View file

@ -14,14 +14,11 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void VGUI_ChooseClass(int);
void VGUI_ChooseClass(void);
bool
int
ClientGame_ConsoleCommand(void)
{
int s = (int)getproperty(VF_ACTIVESEAT);
pSeatTFC = &g_seats_tfc[s];
switch(argv(0)) {
case "build":
sendevent("TFCBuild", "i", stoi(argv(1)));
@ -31,42 +28,27 @@ ClientGame_ConsoleCommand(void)
break;
case "chooseclass":
case "changeclass":
VGUI_ChooseClass(userinfo.GetInteger(pSeat->m_ePlayer, "*team"));
VGUI_ChooseClass();
break;
case "chooseteam":
case "changeteam":
VGUI_ChooseTeam();
break;
case "+gren1":
pSeatTFC->m_bInputGren1 = true;
pSeat->m_iInputExtra1 = TRUE;
break;
case "-gren1":
pSeatTFC->m_bInputGren1 = false;
pSeat->m_iInputExtra1 = FALSE;
break;
case "+gren2":
pSeatTFC->m_bInputGren2 = true;
pSeat->m_iInputExtra2 = TRUE;
break;
case "-gren2":
pSeatTFC->m_bInputGren2 = false;
break;
/* stubbed out, so they won't get forwarded to Nuclide */
case "goprone":
case "gocrouch":
case "+prone":
case "-prone":
case "+gostand":
case "-gostand":
case "+sprint":
case "-sprint":
break;
case "invnext":
pSeatLocal->weaponSelectionHUD.SelectNext(false);
break;
case "invprev":
pSeatLocal->weaponSelectionHUD.SelectPrevious(false);
pSeat->m_iInputExtra2 = FALSE;
break;
default:
return (false);
return (0);
}
return (true);
return (1);
}

View file

@ -15,7 +15,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "../../../valve/src/shared/defs.h"
#define MAX_A_CELLS 200
var string g_dmsg_spr;
@ -29,10 +28,5 @@ var string g_tfchud7_spr;
var int MUZZLE_ROUND;
void TFCHallucination_Insert(vector, vector);
struct
{
bool m_bInputGren1;
bool m_bInputGren2;
} g_seats_tfc[4], *pSeatTFC;
void TFCHallucination_Insert(vector, vector);

View file

@ -42,7 +42,7 @@ ClientGame_PreDraw(void)
void
ClientGame_PostDraw(void)
{
TFPlayer pl = (TFPlayer)pSeat->m_ePlayer;
player pl = (player)pSeat->m_ePlayer;
if (serverkeyfloat("areadefs") == 1) {
string strArea = getplayerkeyvalue(player_localnum, "*areadef");

View file

@ -18,12 +18,6 @@ int
ClientGame_EntityUpdate(float id, float new)
{
switch (id) {
case ENT_PLAYER:
NSENTITY_READENTITY(TFPlayer, new)
break;
case ENT_WEAPON:
NSENTITY_READENTITY(HLWeapon, new)
break;
default:
return (0);
}

View file

@ -24,6 +24,20 @@ ClientGame_EventParse(float fHeader)
case EV_OBITUARY:
Obituary_Parse();
break;
case EV_BLOOD:
vector vBloodPos;
vector vBloodColor;
vBloodPos[0] = readcoord();
vBloodPos[1] = readcoord();
vBloodPos[2] = readcoord();
vBloodColor[0] = readbyte() / 255;
vBloodColor[1] = readbyte() / 255;
vBloodColor[2] = readbyte() / 255;
FX_Blood(vBloodPos, vBloodColor);
break;
case EV_CHAT:
float fSender = readbyte();
float fTeam = readbyte();
@ -41,6 +55,15 @@ ClientGame_EventParse(float fHeader)
case EV_VIEWMODEL:
View_PlayAnimation(readbyte());
break;
case EV_WEAPON_PICKUP:
int w = readbyte();
if (autocvar_cl_autoweaponswitch == 1) {
sendevent("PlayerSwitchWeapon", "i", w);
}
HUD_WeaponPickupNotify(w);
break;
default:
return (0);
}

View file

@ -1,5 +1,5 @@
class
TFCHallucination:ncEntity
TFCHallucination:NSEntity
{
};
@ -28,8 +28,7 @@ TFCHallucination_Insert(vector viewPosition, vector viewDirection)
halluPos += v_forward * random(8, 64);
halluPos += v_up * random(-64, 64);
halluPos += v_right * random(-64, 64);
#warning FIX THE BLOOD CALL!
//FX_Blood(halluPos, [1,0,0]);
FX_Blood(halluPos, [1,0,0]);
}
pointsound(viewPosition, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM);
break;
@ -68,7 +67,7 @@ TFCHallucination_Insert(vector viewPosition, vector viewDirection)
break;
case 7: /* nade thrown about */
int nadeSelection = (int)floor(random(0, 8));
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
switch (nadeSelection) {
case 1:
@ -108,7 +107,7 @@ TFCHallucination_Insert(vector viewPosition, vector viewDirection)
break;
case 8: /* nail shot around */
halluPos = viewPosition + (v_forward * -32) + (v_right * random(-64, 64));
ncRenderableEntity eNail = spawn(ncRenderableEntity);
NSRenderableEntity eNail = spawn(NSRenderableEntity);
eNail.SetModel("models/nail.mdl");
eNail.SetOrigin(halluPos);
eNail.SetMovetype(MOVETYPE_NOCLIP);

View file

@ -76,10 +76,10 @@ HUD_AmmoNotify_Insert(int type, int count)
/* called whenever we should check for pickup updates */
void
HUD_AmmoNotify_Check(ncPlayer pl)
HUD_AmmoNotify_Check(player pl)
{
HUD_AmmoNotify_Insert(0, pl.m_iAmmoTypes[1] - pl.m_iAmmoTypes_net[1]);
HUD_AmmoNotify_Insert(1, pl.m_iAmmoTypes[2] - pl.m_iAmmoTypes_net[2]);
HUD_AmmoNotify_Insert(2, pl.m_iAmmoTypes[3] - pl.m_iAmmoTypes_net[3]);
HUD_AmmoNotify_Insert(3, pl.m_iAmmoTypes[4] - pl.m_iAmmoTypes_net[4]);
}
HUD_AmmoNotify_Insert(0, pl.m_iAmmoRockets - pl.m_iAmmoRockets_net);
HUD_AmmoNotify_Insert(1, pl.m_iAmmoNails - pl.m_iAmmoNails_net);
HUD_AmmoNotify_Insert(2, pl.m_iAmmoCells - pl.m_iAmmoCells_net);
HUD_AmmoNotify_Insert(3, pl.m_iAmmoShells - pl.m_iAmmoShells_net);
}

View file

@ -76,7 +76,7 @@ HUD_ItemNotify_Insert(int type, int count)
/* called whenever we should check for pickup updates */
void
HUD_ItemNotify_Check(ncPlayer pl)
HUD_ItemNotify_Check(player pl)
{
int healthdiff = bound(0, pl.health - pl.health_net, 100);
int armordiff = bound(0, pl.armor - pl.armor_net, 100);

View file

@ -30,19 +30,11 @@ ClientGame_Init(float apilevel, string enginename, float engineversion)
registercommand("-gren1");
registercommand("+gren2");
registercommand("-gren2");
registercommand("chooseclass");
registercommand("changeclass");
registercommand("changeteam");
registercommand("chooseteam");
registercommand("lastinv");
registercommand("invnext");
registercommand("invprev");
registercommand("changeteam");
Obituary_Init();
pSeatTFC = &g_seats_tfc[0];
pSeatLocal->weaponSelectionHUD = spawn(HLWeaponSelect);
}
void VGUI_ChooseTeam(void);
@ -58,6 +50,8 @@ ClientGame_RendererRestart(string rstr)
Obituary_Precache();
Damage_Precache();
FX_Blood_Init();
/* HUD selection icons */
g_dmsg_spr = spriteframe("sprites/tfc_dmsg.spr", 0, 0.0f);
g_tfchud1_spr = spriteframe("sprites/tfchud01.spr", 0, 0.0f);
@ -73,5 +67,4 @@ ClientGame_RendererRestart(string rstr)
MUZZLE_SMALL = (int)getmodelindex("sprites/muzzleflash2.spr");
MUZZLE_WEIRD = (int)getmodelindex("sprites/muzzleflash3.spr");
MUZZLE_ROUND = (int)getmodelindex("sprites/muzzleflash.spr");
HLSprite_Init();
}

View file

@ -1,7 +1,6 @@
#pragma target fte_5768
//#pragma flag enable assumeint
#pragma progs_dat "../../csprogs.dat"
#pragma forcecrc 54730
#define CSQC
#define CLIENT
@ -21,6 +20,8 @@ defs.h
../../../src/gs-entbase/shared.src
../shared/include.src
vox.qc
../../../valve/src/client/damage.qc
draw.qc
init.qc
@ -37,13 +38,11 @@ hud_itemnotify.qc
hud_ammonotify.qc
../../../valve/src/client/hud_sprite.qc
../../../valve/src/client/hud.qc
../../../valve/src/client/HLWeaponSelect.qc
../../../valve/src/client/hud_weaponselect.qc
../../../valve/src/client/scoreboard.qc
../../../src/client/include.src
../../../valve/src/client/vgui_chooseteam.qc
../../../valve/src/client/vgui_changeclass.qc
vgui_chooseteam.qc
vgui_changeclass.qc
../../../src/shared/include.src
#endlist

View file

@ -0,0 +1,232 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
static string g_classDescrScout;
static string g_classDescrSniper;
static string g_classDescrSoldier;
static string g_classDescrDemoman;
static string g_classDescrMedic;
static string g_classDescrHWGuy;
static string g_classDescrPyro;
static string g_classDescrSpy;
static string g_classDescrEngineer;
static string g_classDescrRandomPC;
static void
TFCClass_Init(void)
{
g_classDescrScout = textfile_to_string("classes/short_scout.txt");
g_classDescrSniper = textfile_to_string("classes/short_sniper.txt");
g_classDescrSoldier = textfile_to_string("classes/short_soldier.txt");
g_classDescrDemoman = textfile_to_string("classes/short_demoman.txt");
g_classDescrMedic = textfile_to_string("classes/short_medic.txt");
g_classDescrHWGuy = textfile_to_string("classes/short_hwguy.txt");
g_classDescrPyro = textfile_to_string("classes/short_pyro.txt");
g_classDescrSpy = textfile_to_string("classes/short_spy.txt");
g_classDescrEngineer = textfile_to_string("classes/short_engineer.txt");
g_classDescrRandomPC = textfile_to_string("classes/short_randompc.txt");
}
static VGUIWindow winClassSelection;
static VGUIPic imgClassPreview;
static VGUILabel lblClassTitle;
static VGUILabel lblClassDescription;
static VGUILabel lblClassCounter;
class TFClassButton:VGUIButton
{
void TFClassButton(void);
virtual void OnMouseUp(void);
virtual void OnMouseEntered(void);
};
void
TFClassButton::TFClassButton(void)
{
}
void
TFClassButton::OnMouseUp(void)
{
int classSelection = GetTag();
sendevent("ClassJoin", "f", (float)classSelection);
winClassSelection.Hide();
}
void
TFClassButton::OnMouseEntered(void)
{
int classSelection = GetTag();
string teamName = "blue";
switch (getplayerkeyfloat(player_localnum, "*team")) {
case 1:
teamName = "blue";
break;
case 2:
teamName = "red";
break;
case 3:
teamName = "blue"; /* TFC doesn't ship with a real green. */
break;
case 4:
teamName = "red"; /* TFC doesn't ship with a real yellow either. */
break;
}
switch (classSelection) {
case 1:
lblClassTitle.SetTitle(Titles_GetTextBody("Title_scout"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_scout", teamName));
lblClassDescription.SetTitle(g_classDescrScout);
break;
case 2:
lblClassTitle.SetTitle(Titles_GetTextBody("Title_sniper"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_sniper", teamName));
lblClassDescription.SetTitle(g_classDescrSniper);
break;
case 3:
lblClassTitle.SetTitle(Titles_GetTextBody("Title_soldier"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_soldier", teamName));
lblClassDescription.SetTitle(g_classDescrSoldier);
break;
case 4:
lblClassTitle.SetTitle(Titles_GetTextBody("Title_demoman"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_demoman", teamName));
lblClassDescription.SetTitle(g_classDescrDemoman);
break;
case 5:
lblClassTitle.SetTitle(Titles_GetTextBody("Title_medic"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_medic", teamName));
lblClassDescription.SetTitle(g_classDescrMedic);
break;
case 6:
lblClassTitle.SetTitle(Titles_GetTextBody("Title_hwguy"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_hwguy", teamName));
lblClassDescription.SetTitle(g_classDescrHWGuy);
break;
case 7:
lblClassTitle.SetTitle(Titles_GetTextBody("Title_pyro"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_pyro", teamName));
lblClassDescription.SetTitle(g_classDescrPyro);
break;
case 8:
lblClassTitle.SetTitle(Titles_GetTextBody("Title_spy"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_spy", teamName));
lblClassDescription.SetTitle(g_classDescrSpy);
break;
case 9:
lblClassTitle.SetTitle(Titles_GetTextBody("Title_engineer"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_engineer", teamName));
lblClassDescription.SetTitle(g_classDescrEngineer);
break;
case 0:
lblClassTitle.SetTitle(Titles_GetTextBody("RandomPC"));
imgClassPreview.SetImage(strcat("gfx/vgui/640_randompc", teamName));
lblClassDescription.SetTitle(g_classDescrRandomPC);
break;
}
}
string g_classnames [] = {
"Scout",
"Sniper",
"Soldier",
"Demoman",
"Medic",
"HWGuy",
"Pyro",
"Spy",
"Engineer",
"Random"
};
void
VGUI_ChooseClass(void)
{
static int initialized;
static TFClassButton *btns;
static VGUILabel lblSelectClass;
static VGUIFrame frmClassInfo;
if (!initialized) {
vector btnpos = [40,80];
initialized = TRUE;
TFCClass_Init();
winClassSelection = spawn(VGUIWindow);
winClassSelection.SetSize([640, 480]);
winClassSelection.SetStyleMask(VGUIWindowBorderless | VGUIWindowFullscreen);
lblSelectClass = spawn(VGUILabel);
lblSelectClass.SetTitle(Titles_GetTextBody("Title_SelectYourClass"));
lblSelectClass.SetTextSize(19);
lblSelectClass.SetPos([40, 38]);
lblSelectClass.SetSize([400, 24]);
frmClassInfo = spawn(VGUIFrame);
frmClassInfo.SetPos([176, 80]);
frmClassInfo.SetSize([424, 312]);
imgClassPreview = spawn(VGUIPic);
imgClassPreview.SetPos([190, 90]);
lblClassTitle = spawn(VGUILabel);
lblClassTitle.SetPos([338, 90]);
lblClassTitle.SetTextSize(19);
lblClassTitle.SetSize([320, 24]);
lblClassCounter = spawn(VGUILabel);
lblClassCounter.SetPos([338, 90 + 32]);
lblClassCounter.SetSize([320, 18]);
lblClassDescription = spawn(VGUILabel);
lblClassDescription.SetPos([338, 90 + 32 + 32]);
lblClassDescription.SetSize([250, 240]);
g_uiDesktop.Add(winClassSelection);
winClassSelection.Add(lblSelectClass);
winClassSelection.Add(frmClassInfo);
winClassSelection.Add(imgClassPreview);
winClassSelection.Add(lblClassTitle);
winClassSelection.Add(lblClassCounter);
winClassSelection.Add(lblClassDescription);
btns = memalloc(sizeof(TFClassButton) * g_classnames.length);
for (int i = 0; i < g_classnames.length; i++) {
btns[i] = spawn(TFClassButton);
btns[i].SetTitle(Titles_GetTextBody(g_classnames[i]));
btns[i].SetSize([124, 24]);
btns[i].SetPos(btnpos);
if (i == 9) {
btns[i].SetKeyEquivalent("0");
btns[i].SetTag(0);
} else {
btns[i].SetKeyEquivalent(ftos((float)i+1));
btns[i].SetTag(i+1i);
}
winClassSelection.Add(btns[i]);
btnpos[1] += 32;
}
}
winClassSelection.Show();
winClassSelection.SetPos((video_res / 2) - (winClassSelection.GetSize() / 2));
}

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
static VGUIWindow winChooseTeam;
class TFTeamButton:VGUIButton
{
void TFTeamButton(void);
virtual void OnMouseUp(void);
};
void
TFTeamButton::TFTeamButton(void)
{
}
void
TFTeamButton::OnMouseUp(void)
{
int tag = GetTag();
localcmd("changeclass\n");
sendevent("TeamJoin", "f", (float)tag);
winChooseTeam.Hide();
}
string
VGUI_ChooseTeam_MapInfo(void)
{
static string mapinfo = __NULL__;
if (mapinfo != __NULL__)
return mapinfo;
filestream fileMap = fopen(strcat("maps/", mapname, ".txt"), FILE_READ);
string temp;
if (fileMap != -1) {
while ((temp = fgets(fileMap))) {
mapinfo = strcat(mapinfo, temp, "\n");
}
} else {
mapinfo = Titles_GetTextBody("Map_Description_not_available");
}
return mapinfo;
}
void
VGUI_ChooseTeam(void)
{
static int initialized;
static VGUIButton btnAutoAssign;
static VGUIButton btnGoSpectator;
static VGUIFrame frmMapInfo;
static VGUILabel lblSelectTeam;
static VGUILabel lblMapName;
static VGUILabel lblMapInfo;
if (!initialized) {
vector btnpos = [40,80];
initialized = TRUE;
winChooseTeam = spawn(VGUIWindow);
winChooseTeam.SetSize('640 480');
winChooseTeam.SetStyleMask(VGUIWindowBorderless | VGUIWindowFullscreen);
lblSelectTeam = spawn(VGUILabel);
lblSelectTeam.SetTitle(Titles_GetTextBody("Title_SelectYourTeam"));
lblSelectTeam.SetTextSize(19);
lblSelectTeam.SetPos([40, 38]);
lblSelectTeam.SetSize('400 24');
frmMapInfo = spawn(VGUIFrame);
frmMapInfo.SetPos('176 80');
frmMapInfo.SetSize('424 312');
lblMapName = spawn(VGUILabel);
lblMapName.SetTitle(mapname);
lblMapName.SetTextSize(19);
lblMapName.SetPos('194 105');
lblMapName.SetSize('250 312');
lblMapInfo = spawn(VGUILabel);
lblMapInfo.SetTitle(VGUI_ChooseTeam_MapInfo());
lblMapInfo.SetPos('194 129');
lblMapInfo.SetSize('375 250');
for (int t = 1; t <= serverkeyfloat("teams"); t++) {
TFTeamButton btnForTeam;
string team_name = serverkey(sprintf("team_%i", t));
btnForTeam = spawn(TFTeamButton);
btnForTeam.SetTitle(strtoupper(team_name));
btnForTeam.SetPos(btnpos);
btnForTeam.SetKeyEquivalent(ftos((float)t));
btnForTeam.SetSize('124 24');
switch (team_name) {
case "Blue":
btnForTeam.SetTag(1);
break;
case "Red":
btnForTeam.SetTag(2);
break;
case "Green":
btnForTeam.SetTag(3);
break;
case "Yellow":
btnForTeam.SetTag(4);
break;
}
winChooseTeam.Add(btnForTeam);
btnpos[1] += 32;
}
btnAutoAssign = spawn(VGUIButton);
btnAutoAssign.SetTitle(Titles_GetTextBody("Team_AutoAssign"));
btnAutoAssign.SetPos(btnpos);
btnAutoAssign.SetSize('124 24');
btnAutoAssign.SetKeyEquivalent("5");
//btnAutoAssign.SetFunc(VGUI_AutoAssign);
btnpos[1] += 32;
btnGoSpectator = spawn(VGUIButton);
btnGoSpectator.SetTitle(Titles_GetTextBody("Menu_Spectate"));
btnGoSpectator.SetPos(btnpos);
btnGoSpectator.SetSize('124 24');
btnGoSpectator.SetKeyEquivalent("6");
//btnGoSpectator.SetFunc(VGUI_GoSpectator);
g_uiDesktop.Add(winChooseTeam);
winChooseTeam.Add(frmMapInfo);
winChooseTeam.Add(lblSelectTeam);
winChooseTeam.Add(lblMapName);
winChooseTeam.Add(lblMapInfo);
winChooseTeam.Add(btnAutoAssign);
winChooseTeam.Add(btnGoSpectator);
}
winChooseTeam.Show();
winChooseTeam.SetPos((video_res / 2) - (winChooseTeam.GetSize() / 2));
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2025 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -14,65 +14,35 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CLIENT
class
VOX:ncTalkMonster
TFCVox:NSTalkMonster
{
public:
void(void) VOX;
void(void) TFCVox;
virtual void(string) SentenceSample;
};
TFCVox g_vox;
void
VOX::SentenceSample(string sample)
TFCVox::SentenceSample(string sample)
{
sound(this, CHAN_VOICE, sample, 1.0, ATTN_NONE, 100, SOUNDFLAG_FOLLOW | SOUNDFLAG_NOSPACIALISE);
}
void
VOX:: VOX(void)
TFCVox::TFCVox(void)
{
}
void
Vox_Parse(void)
{
static VOX voxDelegate;
string msg = readstring();
if (!voxDelegate) {
voxDelegate = spawn(VOX);
}
if (!g_vox)
g_vox = spawn(TFCVox);
voxDelegate.Sentence(msg);
print(msg);
print("\n");
g_vox.Sentence(msg);
}
#endif
#ifdef SERVER
void
Vox_Sentence_Broadcast(string wordsToBroadcast)
{
if (!STRING_SET(wordsToBroadcast)) {
return;
}
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_TFC_VOXMSG);
WriteString(MSG_MULTICAST, wordsToBroadcast);
multicast(g_vec_null, MULTICAST_ALL_R);
}
void
Vox_Sentence_Single(entity targetClient, string wordsToVOX)
{
if (!STRING_SET(wordsToVOX)) {
return;
}
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_TFC_VOXMSG);
WriteString(MSG_MULTICAST, wordsToVOX);
msg_entity = targetClient;
multicast(g_vec_null, MULTICAST_ONE_R);
}
#endif

View file

@ -1,64 +0,0 @@
63
1 cfg/skill.cfg
1 cfg/skill_manifest.cfg
1 data/avanti.way
1 data/badlands.way
1 data/casbah.way
1 data/crossover2.way
1 data/cz2.way
1 data/dustbowl.way
1 data/epicenter.way
1 data/flagrun.way
1 data/hunted.way
1 data/push.way
1 data/rock2.way
1 data/warpath.way
1 data/well.way
1 decls/def/ammo.def
1 decls/def/armor.def
1 decls/def/items.def
1 decls/def/monsters.def
1 decls/def/player.def
1 decls/def/weapons.def
1 decls/def/weapons/ac.def
1 decls/def/weapons/autorifle.def
1 decls/def/weapons/axe.def
1 decls/def/weapons/flamethrower.def
1 decls/def/weapons/gl.def
1 decls/def/weapons/ic.def
1 decls/def/weapons/knife.def
1 decls/def/weapons/medikit.def
1 decls/def/weapons/ng.def
1 decls/def/weapons/pl.def
1 decls/def/weapons/railgun.def
1 decls/def/weapons/rpg.def
1 decls/def/weapons/shotgun.def
1 decls/def/weapons/sniperrifle.def
1 decls/def/weapons/spanner.def
1 decls/def/weapons/superng.def
1 decls/def/weapons/supershotgun.def
1 decls/def/weapons/tranq.def
1 decls/def/weapons/umbrella.def
1 decls/sound/items_tfc.sndshd
1 decls/sound/player_tfc.sndshd
1 decls/sound/turret_tfc.sndshd
1 decls/sound/weapons_tfc.sndshd
1 default_tfc.cfg
1 maps/2fort.jpg
1 maps/avanti.jpg
1 maps/badlands.jpg
1 maps/casbah.jpg
1 maps/crossover2.jpg
1 maps/cz2.jpg
1 maps/dustbowl.jpg
1 maps/epicenter.jpg
1 maps/flagrun.jpg
1 maps/hunted.jpg
1 maps/push.jpg
1 maps/rock2.jpg
1 maps/warpath.jpg
1 maps/well.jpg
1 particles/weapon_railgun.cfg
1 progs/default.dat
1 quake.rc
1 scripts/constants.txt

View file

@ -1,3 +1,2 @@
#pragma sourcefile client/progs.src
#pragma sourcefile server/progs.src
#pragma sourcefile rules/default.qc

View file

@ -1,5 +0,0 @@
QCC=fteqcc
all:
mkdir -pv ../../progs/
$(QCC) $(CFLAGS) -I../../../src/server default.qc

View file

@ -1,204 +0,0 @@
/*
* Copyright (c) 2024-2025 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma PROGS_DAT "../../progs/default.dat"
#include "../../../src/server/api.h"
static string g_tfClasses[] = {
"player_scout",
"player_sniper",
"player_soldier",
"player_demo",
"player_medic",
"player_heavy",
"player_pyro",
"player_spy",
"player_engineer",
};
static string g_tfHelp[] = {
"HELP_SCOUT",
"HELP_SNIPER",
"HELP_SOLDIER",
"HELP_DEMO",
"HELP_MEDIC",
"HELP_HEAVY",
"HELP_PYRO",
"HELP_SPY",
"HELP_ENGINEER",
};
static string g_tfPlayerColor[5] = {
"0xffffff",
"0x9aff",
"0xff1800"
"0xffca00",
"0x3bff00"
};
bool
AllowFlashlight(void)
{
return cvars.GetBool("mp_flashlight");
}
void
TF_SwitchClass(entity targetPlayer, int classID)
{
ents.ChangeToClass(targetPlayer, g_tfClasses[classID]);
game.TeleportToSpawn(targetPlayer);
ents.Input(targetPlayer, "Message", g_tfHelp[classID], targetPlayer);
userinfo.SetString(targetPlayer, "topcolor", g_tfPlayerColor[targetPlayer.team]);
userinfo.SetString(targetPlayer, "bottomcolor", g_tfPlayerColor[targetPlayer.team]);
}
void
TF_GoSpectator(entity targetPlayer)
{
if (!targetPlayer) {
return;
}
ents.ChangeToClass(targetPlayer, "spectator");
game.TeleportToSpawn(targetPlayer);
}
void
CodeCallback_Precache(void)
{
for (int i = 0i; i < g_tfClasses.length; i++) {
precache.Entity(g_tfClasses[i]);
}
}
void
CodeCallback_StartGameType(void)
{
motd.LoadDefault();
}
void
CodeCallback_PlayerSpawn(entity playerEntity)
{
/* first course of action is to kick players into spectator cam */
TF_GoSpectator(playerEntity);
}
void
CodeCallback_PlayerDisconnect(void)
{
}
bool
CodeCallback_PlayerRequestRespawn(entity playerEntity)
{
CodeCallback_PlayerSpawn(playerEntity);
return (true);
}
void
CodeCallback_PlayerDamage(entity inflictor, entity attacker)
{
}
void
CodeCallback_PlayerKilled(entity playerEntity, entity inflictor, entity attacker, string weapon)
{
combat.Obituary(playerEntity.netname, attacker.netname, weapon, "");
/* death-counter */
playerEntity.deaths++;
/* update score-counter */
if (ents.isPlayer(attacker)) {
if (self == attacker) {
attacker.frags--;
} else {
attacker.frags++;
}
}
}
bool
CodeCallback_CallRequestTeam(entity playerEntity, int teamNum)
{
ents.Input(playerEntity, "SetTeam", itos(teamNum), playerEntity);
return (true);
}
bool
CodeCallback_ClientCommand(entity targetPlayer, string command)
{
float commandArgs = tokenize(command);
switch (argv(0)) {
case "random":
int classID = (int)floor(random(0, g_tfClasses.length));
TF_SwitchClass(targetPlayer, classID);
break;
case "scout":
TF_SwitchClass(targetPlayer, 0);
break;
case "sniper":
TF_SwitchClass(targetPlayer, 1);
break;
case "soldier":
TF_SwitchClass(targetPlayer, 2);
break;
case "demo":
TF_SwitchClass(targetPlayer, 3);
break;
case "medic":
TF_SwitchClass(targetPlayer, 4);
break;
case "heavy":
TF_SwitchClass(targetPlayer, 5);
break;
case "pyro":
TF_SwitchClass(targetPlayer, 6);
break;
case "spy":
TF_SwitchClass(targetPlayer, 7);
break;
case "engineer":
TF_SwitchClass(targetPlayer, 8);
break;
default:
return (false);
}
return (true);
}
bool
CodeCallback_ImpulseCommand(entity clientEntity, float impulseNum)
{
switch (impulseNum) {
case 100:
if (AllowFlashlight() == true) {
ents.Input(clientEntity, "UseItem", "item_suit", clientEntity);
}
break;
default:
return (false);
}
return (true);
}

View file

@ -1,4 +1,4 @@
QCC=fteqcc
CC=fteqcc
all:
$(QCC) $(CFLAGS) -I../../../valve/src/shared/ progs.src
$(CC) progs.src

25
src/server/bot.qc Normal file
View file

@ -0,0 +1,25 @@
class
TFCBot:NSBot
{
void TFCBot(void);
//virtual void CreateObjective(void);
};
void CSEv_TeamJoin_f(float f);
void CSEv_ClassJoin_f(float f);
void
TFCBot::TFCBot(void)
{
CSEv_TeamJoin_f(0);
CSEv_ClassJoin_f(0);
}
#if 0
void
TFCBot::CreateObjective(void)
{
super:: CreateObjective();
}
#endif

48
src/server/client.qc Normal file
View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* called every input frame */
void
Game_RunClientCommand(void)
{
player pl = (player)self;
/* clear map triggers */
pl.gflags &= ~GF_NOBUILDZONE;
pl.gflags &= ~GF_NOGRENADEZONE;
pl.Physics_Run();
}
/* client cmd overrides happen here */
void
Game_ParseClientCommand(string cmd)
{
tokenize(cmd);
if (argv(1) == "timeleft") {
string msg;
string timestring;
float timeleft;
timeleft = cvar("timelimit") - (time / 60);
timestring = Util_TimeToString(timeleft);
msg = sprintf("we have %s minutes remaining", timestring);
bprint(PRINT_CHAT, msg);
return;
}
clientcommand(self, cmd);
}

View file

@ -14,7 +14,9 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "../../../valve/src/shared/defs.h"
#include "gamerules.h"
#include "../../../valve/src/server/items.h"
#include "../../../valve/src/server/flashlight.h"
#include "sentry.h"
var bool g_tfcHasBlueTeam = false;
@ -47,7 +49,7 @@ TFC_DetonateTypeForPlayer(entity pl, string cname)
if (e.real_owner != pl)
continue;
ncSurfacePropEntity targ = (ncSurfacePropEntity)e;
NSSurfacePropEntity targ = (NSSurfacePropEntity)e;
targ.Destroy();
}
}

View file

@ -19,7 +19,7 @@
/* The unit has 150 health and can hold up to 400 shells, 600 nails, 300 rockets, 400 cells, and 500 armor points. */
class
TFCDispenser:ncSurfacePropEntity
TFCDispenser:NSSurfacePropEntity
{
float m_flNextDispense;
@ -28,28 +28,28 @@ TFCDispenser:ncSurfacePropEntity
int m_iRockets;
int m_iCells;
int m_iArmor;
void(void) TFCDispenser;
void TFCDispenser(void);
virtual void(player) Place;
virtual void(void) FinishPlacing;
virtual void Place(TFPlayer);
virtual void FinishPlacing(void);
virtual void(entity) Touch;
virtual void Touch(entity);
virtual void(void) Replenish;
virtual void(void) ClampValues;
virtual void Replenish(void);
virtual void ClampValues(void);
virtual int(void) GrabShells;
virtual int(void) GrabNails;
virtual int(void) GrabRockets;
virtual int(void) GrabCells;
virtual int(void) GrabArmor;
virtual int GrabShells(void);
virtual int GrabNails(void);
virtual int GrabRockets(void);
virtual int GrabCells(void);
virtual int GrabArmor(void);
virtual void Death(entity, entity, int, vector, vector, int);
virtual void(void) Death;
};
void
TFCDispenser::Death(entity inflictor, entity attacker, int damage, vector dir, vector absImpactPos, int hitBody)
TFCDispenser::Death(void)
{
env_message_single(real_owner, "#Dispenser_destroyed");
pointparticles(particleeffectnum("fx_explosion.main"), origin, [0,0,0], 1);
@ -171,25 +171,21 @@ TFCDispenser::Touch(entity eToucher)
if (m_flNextDispense > time)
return;
TFPlayer pl = (TFPlayer)eToucher;
int rocketType = ammoNumForName("ammo_rockets");
int nailType = ammoNumForName("ammo_nails");
int cellType = ammoNumForName("ammo_cells");
int shellType = ammoNumForName("ammo_shells");
player pl = (player)eToucher;
int r, n, c, s, a, sum;
r = n = c = s = a = sum = 0;
/* only subtract what if we need anything */
if (pl.GetReserveAmmo(rocketType) < pl.MaxAmmo(rocketType))
if (pl.m_iAmmoRockets < pl.m_iMaxRockets)
r = GrabRockets();
if (pl.GetReserveAmmo(nailType) < pl.MaxAmmo(nailType))
if (pl.m_iAmmoNails < pl.m_iMaxNails)
n = GrabNails();
if (pl.GetReserveAmmo(cellType) < pl.MaxAmmo(cellType))
if (pl.m_iAmmoCells < pl.m_iMaxCells)
c = GrabCells();
if (pl.GetReserveAmmo(shellType) < pl.MaxAmmo(shellType))
if (pl.m_iAmmoShells < pl.m_iMaxShells)
s = GrabShells();
if (pl.armor < pl.GetMaxArmor())
if (pl.armor < pl.m_iMaxArmor)
a = GrabArmor();
/* see the sum of what we picked up to determine if we'll register as a pickup */
@ -202,20 +198,29 @@ TFCDispenser::Touch(entity eToucher)
sound(this, CHAN_ITEM, "weapons/scock1.wav", 1.0, ATTN_NORM);
/* add whatever it is we can get */
pl.GiveAmmo(rocketType, r);
pl.GiveAmmo(nailType, n);
pl.GiveAmmo(cellType, c);
pl.GiveAmmo(shellType, s);
pl.m_iAmmoRockets += r;
pl.m_iAmmoNails += n;
pl.m_iAmmoCells += c;
pl.m_iAmmoShells += s;
pl.armor += a;
if (pl.armor > pl.GetMaxArmor())
pl.armor = pl.GetMaxArmor();
/* clamp player values */
if (pl.m_iAmmoRockets > pl.m_iMaxRockets)
pl.m_iAmmoRockets = pl.m_iMaxRockets;
if (pl.m_iAmmoNails > pl.m_iMaxNails)
pl.m_iAmmoNails = pl.m_iMaxNails;
if (pl.m_iAmmoCells > pl.m_iMaxCells)
pl.m_iAmmoCells = pl.m_iMaxCells;
if (pl.m_iAmmoShells > pl.m_iMaxShells)
pl.m_iAmmoShells = pl.m_iMaxShells;
if (pl.armor > pl.m_iMaxArmor)
pl.armor = pl. m_iMaxArmor;
m_flNextDispense = time + 2.0f;
}
void
TFCDispenser::Place(TFPlayer pl)
TFCDispenser::Place(player pl)
{
vector newAngles = pl.GetAngles();
newAngles[0] = newAngles[2] = 0;
@ -249,21 +254,20 @@ TFCDispenser::TFCDispenser(void)
SetMovetype(MOVETYPE_NONE);
SetSize([-16,-16,0], [16,16,48]);
SetHealth(150);
MakeVulnerable();
SetTakedamage(DAMAGE_YES);
}
void
TFCDispenser_Build(void)
{
TFPlayer pl = (TFPlayer)self;
int cellType = ammoNumForName("ammo_cells");
player pl = (player)self;
/* only engineers can do this */
if (pl.classtype != CLASS_ENGINEER)
return;
/* it costs cells to build these things */
if (pl.UseAmmo(cellType, TFC_DISPENSER_COST) == false) {
/* it costs */
if (pl.m_iAmmoCells < TFC_DISPENSER_COST) {
env_message_single(pl, "#Build_nometal");
return;
}
@ -279,6 +283,8 @@ TFCDispenser_Build(void)
return;
}
pl.m_iAmmoCells -= TFC_DISPENSER_COST;
/* deploy */
TFCDispenser dispenser = spawn(TFCDispenser);
dispenser.Place(pl);
@ -287,5 +293,5 @@ TFCDispenser_Build(void)
void
TFCDispenser_Dismantle(void)
{
TFC_DetonateTypeForPlayer((TFPlayer)self, "TFCDispenser");
TFC_DetonateTypeForPlayer((player)self, "TFCDispenser");
}

View file

@ -1,15 +0,0 @@
#includelist
dispenser.qc
sentry.qc
teleporter.qc
func_nobuild.qc
func_nogrenades.qc
info_player_teamspawn.qc
item_tfgoal.qc
info_tfgoal.qc
info_areadef.qc
info_tfdetect.qc
item_armor.qc
item_healthkit.qc
#endlist

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2025 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -23,20 +23,24 @@ Brush volume that when entered, will not allow you to deploy anything as an engi
-------- KEYS --------
"targetname" Name
*/
class
func_nobuild:ncBrushTrigger
{
public:
void func_nobuild(void);
virtual void Respawn(void);
virtual void Touch(entity);
class
func_nobuild:NSBrushTrigger
{
void(void) func_nobuild;
virtual void(void) Respawn;
virtual void(entity) Touch;
};
void
func_nobuild::func_nobuild(void)
func_nobuild::Touch(entity eToucher)
{
player pl = (player)eToucher;
if (!(eToucher.flags & FL_CLIENT))
return;
pl.gflags |= GF_NOBUILDZONE;
}
void
@ -46,13 +50,7 @@ func_nobuild::Respawn(void)
}
void
func_nobuild::Touch(entity eToucher)
func_nobuild::func_nobuild(void)
{
TFPlayer pl = (TFPlayer)eToucher;
if (isPlayer(eToucher) == false) {
return;
}
pl.gflags |= GF_NOBUILDZONE;
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2025 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -23,20 +23,24 @@ Brush volume that when entered, will not allow you to deploy any grenades.
-------- KEYS --------
"targetname" Name
*/
class
func_nogrenades:ncBrushTrigger
{
public:
void func_nogrenades(void);
virtual void Respawn(void);
virtual void Touch(entity);
class
func_nogrenades:NSBrushTrigger
{
void(void) func_nogrenades;
virtual void(void) Respawn;
virtual void(entity) Touch;
};
void
func_nogrenades::func_nogrenades(void)
func_nogrenades::Touch(entity eToucher)
{
player pl = (player)eToucher;
if (!(eToucher.flags & FL_CLIENT))
return;
pl.gflags |= GF_NOGRENADEZONE;
}
void
@ -46,13 +50,7 @@ func_nogrenades::Respawn(void)
}
void
func_nogrenades::Touch(entity eToucher)
func_nogrenades::func_nogrenades(void)
{
TFPlayer pl = (TFPlayer)eToucher;
if (isPlayer(eToucher) == false) {
return;
}
pl.gflags |= GF_NOGRENADEZONE;
}
}

35
src/server/gamerules.h Normal file
View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class TFCGameRules:CGameRules
{
void(void) TFCGameRules;
virtual bool ConsoleCommand(NSClientPlayer, string);
virtual bool IsTeamplay(void);
virtual void PlayerConnect(NSClientPlayer);
virtual void PlayerDisconnect(NSClientPlayer);
virtual void PlayerPostFrame(NSClientPlayer);
virtual void PlayerSpawn(NSClientPlayer);
virtual void PlayerKill(NSClientPlayer);
virtual void PlayerRespawn(NSClientPlayer);
virtual void PlayerDeath(NSClientPlayer);
virtual void DropGoalItem(NSClientPlayer);
virtual float ImpulseCommand(NSClient, float);
virtual void LevelNewParms(void);
virtual void InitPostEnts(void);
};

207
src/server/gamerules.qc Normal file
View file

@ -0,0 +1,207 @@
/*
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
TFCGameRules::TFCGameRules(void)
{
/* wipe the serverinfo clean */
forceinfokey(world, "teams", "0");
forceinfokey(world, "team_1", "");
forceinfokey(world, "team_2", "");
forceinfokey(world, "team_3", "");
forceinfokey(world, "team_4", "");
forceinfokey(world, "teamscore_1", "");
forceinfokey(world, "teamscore_2", "");
forceinfokey(world, "teamscore_3", "");
forceinfokey(world, "teamscore_4", "");
}
bool
TFCGameRules::ConsoleCommand(NSClientPlayer pp, string cmd)
{
tokenize(cmd);
switch (argv(0)) {
default:
return (false);
}
return (true);
}
bool
TFCGameRules::IsTeamplay(void)
{
return TRUE;
}
void
TFCGameRules::DropGoalItem(NSClientPlayer pp)
{
/* skip normal players */
if (!(pp.g_items & ITEM_GOALITEM))
return;
item_tfgoal target;
for (entity e = world; (e = find(e, ::classname, "item_tfgoal"));) {
target = (item_tfgoal)e;
/* item is still pick-upable */
if (target.solid != SOLID_NOT) {
print("the item is not picked up. \n");
continue;
}
/* that's us, yup */
if (target.m_eActivator == pp) {
target.DropReturnable(pp);
return;
}
}
print("^1WARNING: ^7Player marked as having impossible goal-item\n");
}
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
TFCGameRules::PlayerPostFrame(NSClientPlayer pp)
{
}
void
TFCGameRules::LevelNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm64 = FL_CLIENT;
}
void
TFCGameRules::PlayerConnect(NSClientPlayer pl)
{
if (Plugin_PlayerConnect(pl) == FALSE)
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname));
}
void
TFCGameRules::PlayerDisconnect(NSClientPlayer pl)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = PLAYER_MODELINDEX;
}
void
TFCGameRules_PlayerRespawn(void)
{
TFCGameRules rule = (TFCGameRules)g_grMode;
rule.PlayerRespawn((NSClientPlayer)self);
}
void
TFCGameRules::PlayerDeath(NSClientPlayer pp)
{
player pl = (player)pp;
DropGoalItem(pp);
pl.SetSolid(SOLID_NOT);
pl.SetMovetype(MOVETYPE_NONE);
pl.ScheduleThink(TFCGameRules_PlayerRespawn, 4.0f);
/* play the iconic death sound */
Sound_Play(pl, CHAN_VOICE, "player_tfc.death");
}
void
TFCGameRules::PlayerKill(NSClientPlayer pp)
{
player pl = (player)pp;
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}
void
TFCGameRules::PlayerRespawn(NSClientPlayer pp)
{
player pl = (player)pp;
pl.MakeClass(pl.classtype);
pl.SpawnIntoGame();
}
void
TFCGameRules::PlayerSpawn(NSClientPlayer pp)
{
player pl = (player)pp;
pl.MakeTempSpectator(); /* replace this with a non-spectator ghost */
Spawn_ObserverCam(pl);
}
bool
TFCGameRules::ImpulseCommand(NSClient bp, float num)
{
switch (num) {
case 101:
player pl = (player)bp;
if (cvar("sv_cheats") > 0) {
Weapons_AddItem(pl, WEAPON_CROWBAR, -1);
Weapons_AddItem(pl, WEAPON_MEDKIT, -1);
Weapons_AddItem(pl, WEAPON_KNIFE, -1);
Weapons_AddItem(pl, WEAPON_WRENCH, -1);
Weapons_AddItem(pl, WEAPON_UMBRELLA, -1);
Weapons_AddItem(pl, WEAPON_SBS, -1);
Weapons_AddItem(pl, WEAPON_SNIPER, -1);
Weapons_AddItem(pl, WEAPON_TRANQUIL, -1);
Weapons_AddItem(pl, WEAPON_RAILGUN, -1);
Weapons_AddItem(pl, WEAPON_AUTORIFLE, -1);
Weapons_AddItem(pl, WEAPON_DBS, -1);
Weapons_AddItem(pl, WEAPON_NAILGUN, -1);
Weapons_AddItem(pl, WEAPON_GLAUNCHER, -1);
Weapons_AddItem(pl, WEAPON_SUPERNAIL, -1);
Weapons_AddItem(pl, WEAPON_FLAMER, -1);
Weapons_AddItem(pl, WEAPON_RPG, -1);
Weapons_AddItem(pl, WEAPON_PIPEBOMB, -1);
Weapons_AddItem(pl, WEAPON_ASSCAN, -1);
Weapons_AddItem(pl, WEAPON_INCENDIARY, -1);
Weapons_AddItem(pl, WEAPON_GRAPPLE, -1);
}
break;
default:
return super::ImpulseCommand(bp, num);
}
return true;
}
void
TFCGameRules::InitPostEnts(void)
{
super::InitPostEnts();
/* rename the team spawns. */
info_player_teamspawn::RenameTeamSpawns();
info_tfdetect::Setup();
}

View file

@ -28,33 +28,26 @@ Describes an area's bounds and description/name.
*/
class
info_areadef:ncPointTrigger
info_areadef:NSPointTrigger
{
public:
void info_areadef(void);
virtual void Respawn(void);
virtual void SpawnKey(string,string);
virtual void Touch(entity);
private:
string m_strDescription;
vector m_vecMins;
vector m_vecMaxs;
void(void) info_areadef;
virtual void(void) Respawn;
virtual void(string,string) SpawnKey;
virtual void(entity) Touch;
};
void
info_areadef::info_areadef(void)
info_areadef::Touch(entity eToucher)
{
serverinfo.SetBool("areadefs", true);
}
void
info_areadef::Touch(entity touchingEntity)
{
if (isPlayer(touchingEntity) == false) {
if (!(eToucher.flags & FL_CLIENT))
return;
}
userinfo.SetString(touchingEntity, "*areadef", m_strDescription);
forceinfokey(eToucher, "*areadef", m_strDescription);
}
void
@ -68,6 +61,12 @@ info_areadef::SpawnKey(string strKey, string strValue)
m_strDescription = strreplace("GREEN", "^x4F4GREEN^7", m_strDescription);
m_strDescription = strreplace("YELLOW", "^xFF4YELLOW^7", m_strDescription);
break;
case "mins":
m_vecMins = stov(strValue);
break;
case "maxs":
m_vecMaxs = stov(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
}
@ -76,9 +75,15 @@ info_areadef::SpawnKey(string strKey, string strValue)
void
info_areadef::Respawn(void)
{
super::Respawn();
/* set up our volume */
SetSolid(SOLID_TRIGGER);
SetSize(GetSpawnFloat("mins"), GetSpawnFloat("maxs"));
SetMovetype(MOVETYPE_NONE);
SetOrigin(GetSpawnOrigin());
SetSize(m_vecMins, m_vecMaxs);
}
void
info_areadef::info_areadef(void)
{
forceinfokey(world, "areadefs", "1");
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2025 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -14,38 +14,53 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class
info_player_teamspawn:ncSpawnPoint
class info_player_teamspawn:NSSpawnPoint
{
public:
void(void) info_player_teamspawn;
virtual void Spawned(void);
virtual void SpawnKey(string, string);
nonvirtual void RenameTeamSpawns(void);
};
void
info_player_teamspawn::info_player_teamspawn(void)
{
}
void
info_player_teamspawn::Spawned(void)
info_player_teamspawn::SpawnKey(string keyName, string setValue)
{
team = GetSpawnInt ("team_no");
switch (keyName) {
case "team_no":
team = ReadInt(setValue);
break;
default:
super::SpawnKey(keyName, setValue);
}
}
switch (team) {
case 1:
classname = "info_teamspawn_blue";
break;
case 2:
classname = "info_teamspawn_red";
break;
case 4:
classname = "info_teamspawn_yellow";
break;
case 3:
classname = "info_teamspawn_green";
break;
void
info_player_teamspawn::RenameTeamSpawns(void)
{
for (entity e = world; (e = find(e, ::classname, "info_player_teamspawn"));) {
info_player_teamspawn findSpawn = (info_player_teamspawn)e;
switch (findSpawn.team) {
case 1:
e.classname = "info_teamspawn_blue";
break;
case 2:
e.classname = "info_teamspawn_red";
break;
case 3:
e.classname = "info_teamspawn_yellow";
break;
case 4:
e.classname = "info_teamspawn_green";
break;
}
}
botinfo = BOTINFO_SPAWNPOINT;

View file

@ -57,35 +57,20 @@ typedef enum
# NOTES
The `maxammo_` keys sets the limits regarding available team classes.
The following flags can be combined:
- ONLY_CIVILLIAN (-1) : Not a bitflag, but when set this team only allows the civillian class.
- SCOUT (1) : No Scout class.
- SNIPER (2) : No Sniper class.
- SOLDIER (4) : No Soldier class.
- DEMO (8) : No Demoman class.
- MEDIC (16) : No Medic class.
- HEAVY (32) : No Heavy Weapons Guy class.
- PYRO (64) : No Pyro class.
- NO_RANDOM_CLASS (128) : No random class in menus.
- SPY (256) : No Spy class.
- ENGINEER (512) : No Engineer class.
# TRIVIA
This entity was introduced in Team Fortress (1996).
*/
class
info_tfdetect:ncPointTrigger
info_tfdetect:NSPointTrigger
{
public:
void info_tfdetect(void);
virtual void SpawnKey(string, string);
virtual void Spawned(void);
virtual void Respawn(void);
nonvirtual void Setup(void);
nonvirtual void SetupClass(int teamID, tfdetectTeamFlags_t classFlags);
private:
string m_strTeam1Name;
@ -151,99 +136,74 @@ info_tfdetect::SpawnKey(string keyName, string setValue)
}
void
info_tfdetect::Spawned(void)
info_tfdetect::Respawn(void)
{
super::Spawned();
ScheduleThink(Setup, 0.0f);
}
void
info_tfdetect::SetupClass(int teamID, tfdetectTeamFlags_t classFlags)
{
if (classFlags == TFDFL_CIVILIANONLY) {
teams.AddClass(teamID, "civilian");
return;
}
if (!(classFlags & TFDFL_NOSCOUNT)) {
teams.AddClass(teamID, "scout");
}
if (!(classFlags & TFDFL_NOSNIPER)) {
teams.AddClass(teamID, "sniper");
}
if (!(classFlags & TFDFL_NOSOLDIER)) {
teams.AddClass(teamID, "soldier");
}
if (!(classFlags & TFDFL_NODEMOMAN)) {
teams.AddClass(teamID, "demo");
}
if (!(classFlags & TFDFL_NOMEDIC)) {
teams.AddClass(teamID, "medic");
}
if (!(classFlags & TFDFL_NOHEAVY)) {
teams.AddClass(teamID, "heavy");
}
if (!(classFlags & TFDFL_NOPYRO)) {
teams.AddClass(teamID, "pyro");
}
if (!(classFlags & TFDFL_NOSPY)) {
teams.AddClass(teamID, "spy");
}
if (!(classFlags & TFDFL_NOENGINEER)) {
teams.AddClass(teamID, "engineer");
}
if (!(classFlags & TFDFL_NORANDOM)) {
teams.AddClass(teamID, "random");
}
}
void
info_tfdetect::Setup(void)
{
int team_count = 0i;
entity e = __NULL__;
info_tfdetect globalTFD = (info_tfdetect)find(world, ::classname, "info_tfdetect");
/* populate the serverinfo field with the teams we have on the map */
if (exists.InMap("info_teamspawn_blue")) {
teams.SetUp(1, m_strTeam1Name, [153, 204, 255], true);
SetupClass(1, m_bfTeam1Flags);
teams.SetSpawnPoint(1, "info_teamspawn_blue");
e = find(world, ::classname, "info_teamspawn_blue");
if (e) {
team_count += 1;
forceinfokey(world, sprintf("team_%i", team_count), "Blue");
forceinfokey(world, sprintf("teamscore_%i", team_count), "0");
g_tfcHasBlueTeam = true;
}
if (exists.InMap("info_teamspawn_red")) {
teams.SetUp(2, m_strTeam2Name, [255, 63, 63], true);
SetupClass(2, m_bfTeam2Flags);
teams.SetSpawnPoint(2, "info_teamspawn_red");
e = find(world, ::classname, "info_teamspawn_red");
if (e) {
team_count += 1;
forceinfokey(world, sprintf("team_%i", team_count), "Red");
forceinfokey(world, sprintf("teamscore_%i", team_count), "0");
g_tfcHasRedTeam = true;
}
if (exists.InMap("info_teamspawn_green")) {
teams.SetUp(3, m_strTeam3Name, [153, 255, 204], true);
SetupClass(3, m_bfTeam3Flags);
teams.SetSpawnPoint(3, "info_teamspawn_green");
e = find(world, ::classname, "info_teamspawn_green");
if (e) {
team_count += 1;
forceinfokey(world, sprintf("team_%i", team_count), "Green");
forceinfokey(world, sprintf("teamscore_%i", team_count), "0");
g_tfcHasGreenTeam = true;
}
if (exists.InMap("info_teamspawn_yellow")) {
teams.SetUp(4, m_strTeam4Name, [255, 255, 153], true);
SetupClass(4, m_bfTeam4Flags);
teams.SetSpawnPoint(4, "info_teamspawn_yellow");
e = find(world, ::classname, "info_teamspawn_yellow");
if (e) {
team_count += 1;
forceinfokey(world, sprintf("team_%i", team_count), "Yellow");
forceinfokey(world, sprintf("teamscore_%i", team_count), "0");
g_tfcHasYellowTeam = true;
}
forceinfokey(world, "teams", itos(team_count));
if (!globalTFD) {
NSLog("No info_tfdetect in level.");
forceinfokey(world, "teamflags_1", "0");
forceinfokey(world, "teamflags_2", "0");
forceinfokey(world, "teamflags_3", "0");
forceinfokey(world, "teamflags_4", "0");
return;
}
forceinfokey(world, "team_1", globalTFD.m_strTeam1Name);
forceinfokey(world, "team_2", globalTFD.m_strTeam2Name);
forceinfokey(world, "team_3", globalTFD.m_strTeam3Name);
forceinfokey(world, "team_4", globalTFD.m_strTeam4Name);
forceinfokey(world, "teamflags_1", ftos(globalTFD.m_bfTeam1Flags));
forceinfokey(world, "teamflags_2", ftos(globalTFD.m_bfTeam1Flags));
forceinfokey(world, "teamflags_3", ftos(globalTFD.m_bfTeam1Flags));
forceinfokey(world, "teamflags_4", ftos(globalTFD.m_bfTeam1Flags));
/* the evil localcmd feature of this entity. */
if (STRING_SET(m_strLocalCommand)) {
if (m_strLocalCommand) {
localcmd(m_strLocalCommand);
localcmd("\n");
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2025 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -59,16 +59,8 @@ typedef enumflags
} tfgoal_result;
/* point entity version */
class info_tfgoal:ncRenderableEntity
class info_tfgoal:NSRenderableEntity
{
public:
void(void) info_tfgoal;
virtual void(entity) Touch;
virtual void(void) Respawn;
virtual void(string, string) SpawnKey;
virtual void Spawned(void);
private:
string m_strName;
string m_strActivatedSound;
@ -79,7 +71,7 @@ private:
tfgoal_activation m_tfgActivation;
tfgoal_effects m_tfgEffects;
tfgoal_result m_tfgResult;
TFPlayer m_Activator;
player m_Activator;
float m_dMustCarry; /* player must carry item of this ID */
float m_dRespawn; /* respawn after num seconds on TFRESULT_REMOVE */
@ -116,80 +108,33 @@ private:
string m_voxOwnerTeam; /* owner team */
string m_voxNonOwnerTeams; /* non-owner team */
string m_strSpawnModel; /* because we mangle it */
void(void) info_tfgoal;
virtual void(entity) Touch;
virtual void(void) Respawn;
virtual void(string, string) SpawnKey;
virtual void Spawned(void);
};
void
info_tfgoal::info_tfgoal(void)
{
m_tfgState = TFGOAL_INACTIVE;
m_tfgResult = TFRESULT_REMOVE;
m_strName = __NULL__;
m_strActivatedSound = __NULL__;
m_iGoalID = 0i;
m_iGoalGroupID = 0i;
m_tfgActivation = 0;
m_tfgEffects = 0;
m_Activator = __NULL__;
m_dMustCarry = 0.0f;
m_dRespawn = 0.0f;
m_dTeamBlueGain = 0.0f;
m_dTeamRedGain = 0.0f;
m_dTeamYellowGain = 0.0f;
m_dTeamGreenGain = 0.0f;
m_dScore = 0.0f;
m_iTeamUses = 0i;
m_iTeamOwner = 0i;
m_iHealth = 0i;
m_iArmor = 0i;
m_iShells = 0i;
m_iNails = 0i;
m_iCells = 0i;
m_iMedikit = 0i;
m_iRockets = 0i;
m_iDetpack = 0i;
m_msgAll = __NULL__;
m_msgActivator = __NULL__;
m_msgActTeam = __NULL__;
m_msgNonActTeam = __NULL__;
m_msgOwnerTeam = __NULL__;
m_msgNonOwnerTeams = __NULL__;
m_voxAll = __NULL__;
m_voxActivator = __NULL__;
m_voxActTeam = __NULL__;
m_voxNonActTeam = __NULL__;
m_voxOwnerTeam = __NULL__;
m_voxNonOwnerTeams = __NULL__;
m_strSpawnModel = __NULL__;
}
void
info_tfgoal::Spawned(void)
{
super::Spawned();
/* HACK: goals without a targetname and TFGOAL_REMOVED can't work */
if (m_tfgState == TFGOAL_REMOVED && HasTargetname() == false) {
if (m_tfgState == TFGOAL_REMOVED && !targetname) {
m_tfgState = TFGOAL_INACTIVE;
}
}
void
info_tfgoal::Touch(entity touchingEntity)
info_tfgoal::Touch(entity eToucher)
{
item_tfgoal findme = __NULL__;
int rocketType = ammoNumForName("ammo_rockets");
int nailType = ammoNumForName("ammo_nails");
int cellType = ammoNumForName("ammo_cells");
int shellType = ammoNumForName("ammo_shells");
int medikitType = ammoNumForName("ammo_medkit");
int detpackType = ammoNumForName("ammo_detpack");
if (isPlayer(touchingEntity) == false) {
if (eToucher.classname != "player") {
return;
}
TFPlayer pl = (TFPlayer)touchingEntity;
player pl = (player)eToucher;
/* check for state */
if (m_tfgState != TFGOAL_INACTIVE) {
@ -199,7 +144,7 @@ info_tfgoal::Touch(entity touchingEntity)
/* check for team eligibility */
if (m_iTeamUses)
if (touchingEntity.team != m_iTeamUses) {
if (eToucher.team != m_iTeamUses) {
print("not eligble\n");
return;
}
@ -210,9 +155,8 @@ info_tfgoal::Touch(entity touchingEntity)
for (entity e = world; (e = find(e, ::classname, "item_tfgoal"));) {
item_tfgoal a = (item_tfgoal)e;
if (a.m_dItemID == m_dMustCarry) {
if (a.m_dItemID == m_dMustCarry)
findme = a;
}
}
if (!findme) {
@ -235,53 +179,57 @@ info_tfgoal::Touch(entity touchingEntity)
/* mark as removed on the player end, too. */
pl.g_items &= ~ITEM_GOALITEM;
pl.RemoveVFlags(VFL_GOALITEM);
pl.flags &= ~FL_GOALITEM;
forceinfokey(pl, "*goalitem_t", "");
}
sound(this, CHAN_ITEM, m_strActivatedSound, 1.0f, ATTN_NORM);
Logging_Pickup(touchingEntity, this, m_strName);
Logging_Pickup(eToucher, this, m_strName);
/* here we increase/decrease funstuff */
pl.health += m_iHealth;
pl.armor += m_iArmor;
pl.GiveAmmo(rocketType, m_iRockets);
pl.GiveAmmo(nailType, m_iNails);
pl.GiveAmmo(cellType, m_iCells);
pl.GiveAmmo(shellType, m_iShells);
pl.GiveAmmo(medikitType, m_iMedikit);
pl.GiveAmmo(detpackType, m_iDetpack);
pl.m_iAmmoShells += m_iShells;
pl.m_iAmmoNails += m_iNails;
pl.m_iAmmoCells += m_iCells;
pl.m_iAmmoRockets += m_iRockets;
pl.m_iAmmoMedikit += m_iMedikit;
pl.m_iAmmoDetpack += m_iDetpack;
/* clamp */
pl.SetHealth(bound(0, pl.GetHealth(), pl.GetMaxHealth()));
pl.SetArmor(bound(0, pl.GetArmor(), pl.GetMaxArmor()));
pl.health = bound(0, pl.health, pl.m_iMaxHealth);
pl.armor = bound(0, pl.armor, pl.m_iMaxArmor);
pl.m_iAmmoShells = bound(0, pl.m_iAmmoShells, pl.m_iMaxShells);
pl.m_iAmmoNails = bound(0, pl.m_iAmmoNails, pl.m_iMaxNails);
pl.m_iAmmoCells = bound(0, pl.m_iAmmoCells, pl.m_iMaxCells);
pl.m_iAmmoRockets = bound(0, pl.m_iAmmoRockets, pl.m_iMaxRockets);
pl.frags += frags;
string ts;
if (m_dScore) {
ts = sprintf("teamscore_%i", m_iTeamUses);
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dScore);
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dScore));
}
if (m_dTeamBlueGain) {
ts = "teamscore_1";
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dTeamBlueGain);
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dTeamBlueGain));
}
if (m_dTeamRedGain) {
ts = "teamscore_2";
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dTeamRedGain);
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dTeamRedGain));
}
if (m_dTeamYellowGain) {
ts = "teamscore_3";
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dTeamYellowGain);
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dTeamYellowGain));
}
if (m_dTeamGreenGain) {
ts = "teamscore_4";
serverinfo.SetFloat(ts, serverkeyfloat(ts) + m_dTeamGreenGain);
forceinfokey(world, ts, sprintf("%d", serverkeyfloat(ts) + m_dTeamGreenGain));
}
/* message broadcaster */
if (STRING_SET(m_msgAll)) {
if (m_msgAll) {
env_message_broadcast(m_msgAll);
} else {
for (entity e = world; (e = find(e, ::classname, "player")); ) {
@ -290,21 +238,20 @@ info_tfgoal::Touch(entity touchingEntity)
} else if (e.team == pl.team ) {
env_message_single(e, m_msgActTeam);
} else if (e.team != pl.team) {
if (e.team == m_iTeamOwner && STRING_SET(m_msgOwnerTeam)) {
if (e.team == m_iTeamOwner && m_msgOwnerTeam)
env_message_single(e, m_msgOwnerTeam);
} else {
if (STRING_SET(m_msgNonOwnerTeams)) {
else {
if (m_msgNonOwnerTeams)
env_message_single(e, m_msgNonOwnerTeams);
} else {
else
env_message_single(e, m_msgNonActTeam);
}
}
}
}
}
/* vox speaker */
if (STRING_SET(m_voxAll)) {
if (m_voxAll) {
Vox_Sentence_Broadcast(m_voxAll);
} else {
for (entity e = world; (e = find(e, ::classname, "player")); ) {
@ -313,14 +260,13 @@ info_tfgoal::Touch(entity touchingEntity)
} else if (e.team == pl.team ) {
Vox_Sentence_Single(e, m_voxActTeam);
} else if (e.team != pl.team) {
if (e.team == m_iTeamOwner && m_voxOwnerTeam) {
if (e.team == m_iTeamOwner && m_voxOwnerTeam)
Vox_Sentence_Single(e, m_voxOwnerTeam);
} else {
if (STRING_SET(m_voxNonOwnerTeams)) {
else {
if (m_voxNonOwnerTeams)
Vox_Sentence_Single(e, m_voxNonOwnerTeams);
} else {
else
Vox_Sentence_Single(e, m_voxNonActTeam);
}
}
}
}
@ -338,172 +284,193 @@ info_tfgoal::Respawn(void)
{
SetSolid(SOLID_TRIGGER);
SetMovetype(MOVETYPE_NONE);
SetModel(m_strSpawnModel);
SetModel(GetSpawnModel());
SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
SetOrigin(GetSpawnVector("origin"));
SetOrigin(GetSpawnOrigin());
team = m_iTeamUses;
if (frags > 0) {
if (frags > 0)
botinfo = BOTINFO_TEAM_GOALCAPTURE;
}
void
info_tfgoal::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "netname":
netname = strValue;
break;
case "noise":
m_strActivatedSound = strValue;
break;
case "mdl":
model = strValue;
if (serverkeyfloat("*bspversion") == 0) {
model = strreplace("progs", "models", model);
model = strreplace("tf_stan", "flag", model);
}
break;
case "goal_state":
m_tfgState = stof(strValue);
break;
case "g_a":
m_tfgActivation = stof(strValue);
break;
case "g_e":
m_tfgEffects = stof(strValue);
break;
case "goal_result":
m_tfgResult = stof(strValue);
break;
case "items_allowed":
m_dMustCarry = stof(strValue);
break;
case "team_no":
m_iTeamUses = stoi(strValue);
break;
case "owned_by":
m_iTeamOwner = stoi(strValue);
break;
case "count":
m_dScore = stof(strValue);
break;
case "wait":
m_dRespawn = stof(strValue);
break;
case "increase_team1":
m_dTeamBlueGain = stof(strValue);
break;
case "increase_team2":
m_dTeamRedGain = stof(strValue);
break;
case "increase_team3":
m_dTeamYellowGain = stof(strValue);
break;
case "increase_team4":
m_dTeamGreenGain = stof(strValue);
break;
/* messages that get sent */
case "b_b":
m_msgAll = strValue; /* global */
break;
case "message":
m_msgActivator = strValue; /* AP */
break;
case "b_t":
case "team_broadcast":
m_msgActTeam = strValue; /* AP team */
break;
case "b_n":
case "netname_non_team_broadcast":
m_msgNonActTeam = strValue; /* non-AP team */
break;
case "b_o":
case "owners_team_broadcast":
m_msgOwnerTeam = strValue; /* owner team */
break;
case "non_owners_team_broadcast":
m_msgNonOwnerTeams = strValue; /* non-owner team */
break;
/* sentences that get played */
case "speak":
m_voxAll = strValue; /* global */
break;
case "AP_speak":
m_voxActivator = strValue; /* AP */
break;
case "team_speak":
m_voxActTeam = strValue; /* AP team */
break;
case "non_team_speak":
m_voxNonActTeam = strValue; /* non-AP team */
break;
case "owners_team_speak":
m_voxOwnerTeam = strValue; /* owner team */
break;
case "non_owners_team_speak":
m_voxNonOwnerTeams = strValue; /* non-owner team */
break;
/* AP manipulators */
case "health":
m_iHealth = stoi(strValue);
break;
case "armor":
m_iArmor = stoi(strValue);
break;
case "ammo_shells":
m_iShells = stoi(strValue);
break;
case "ammo_nails":
m_iNails = stoi(strValue);
break;
case "ammo_rockets":
m_iRockets = stoi(strValue);
break;
case "ammo_cells":
m_iCells = stoi(strValue);
break;
case "ammo_medikit":
m_iMedikit = stoi(strValue);
break;
default:
super::SpawnKey(strKey, strValue);
break;
}
}
void
info_tfgoal::SpawnKey(string keyName, string setValue)
info_tfgoal::info_tfgoal(void)
{
switch (keyName) {
case "netname":
netname = ReadString(setValue);
break;
case "noise":
m_strActivatedSound = ReadString(setValue);
break;
case "model":
case "mdl":
m_strSpawnModel = ReadString(setValue);
m_tfgState = TFGOAL_INACTIVE;
m_tfgResult = TFRESULT_REMOVE;
if (serverinfo.GetInteger("*bspversion") == 0i) {
m_strSpawnModel = strreplace("progs", "models", model);
m_strSpawnModel = strreplace("tf_stan", "flag", model);
}
break;
case "goal_state":
m_tfgState = ReadFloat(setValue);
break;
case "g_a":
m_tfgActivation = ReadFloat(setValue);
break;
case "g_e":
m_tfgEffects = ReadFloat(setValue);
break;
case "goal_result":
m_tfgResult = ReadFloat(setValue);
break;
case "items_allowed":
m_dMustCarry = ReadFloat(setValue);
break;
case "team_no":
m_iTeamUses = ReadInt(setValue);
break;
case "owned_by":
m_iTeamOwner = ReadInt(setValue);
break;
case "count":
m_dScore = ReadFloat(setValue);
break;
case "wait":
m_dRespawn = ReadFloat(setValue);
break;
case "increase_team1":
m_dTeamBlueGain = ReadFloat(setValue);
break;
case "increase_team2":
m_dTeamRedGain = ReadFloat(setValue);
break;
case "increase_team3":
m_dTeamYellowGain = ReadFloat(setValue);
break;
case "increase_team4":
m_dTeamGreenGain = ReadFloat(setValue);
break;
/* messages that get sent */
case "b_b":
m_msgAll = ReadString(setValue); /* global */
break;
case "message":
m_msgActivator = ReadString(setValue); /* AP */
break;
case "b_t":
case "team_broadcast":
m_msgActTeam = ReadString(setValue); /* AP team */
break;
case "b_n":
case "netname_non_team_broadcast":
m_msgNonActTeam = ReadString(setValue); /* non-AP team */
break;
case "b_o":
case "owners_team_broadcast":
m_msgOwnerTeam = ReadString(setValue); /* owner team */
break;
case "non_owners_team_broadcast":
m_msgNonOwnerTeams = ReadString(setValue); /* non-owner team */
break;
/* sentences that get played */
case "speak":
m_voxAll = ReadString(setValue); /* global */
break;
case "AP_speak":
m_voxActivator = ReadString(setValue); /* AP */
break;
case "team_speak":
m_voxActTeam = ReadString(setValue); /* AP team */
break;
case "non_team_speak":
m_voxNonActTeam = ReadString(setValue); /* non-AP team */
break;
case "owners_team_speak":
m_voxOwnerTeam = ReadString(setValue); /* owner team */
break;
case "non_owners_team_speak":
m_voxNonOwnerTeams = ReadString(setValue); /* non-owner team */
break;
/* AP manipulators */
case "health":
m_iHealth = ReadInt(setValue);
break;
case "armor":
m_iArmor = ReadInt(setValue);
break;
case "ammo_shells":
m_iShells = ReadInt(setValue);
break;
case "ammo_nails":
m_iNails = ReadInt(setValue);
break;
case "ammo_rockets":
m_iRockets = ReadInt(setValue);
break;
case "ammo_cells":
m_iCells = ReadInt(setValue);
break;
case "ammo_medikit":
m_iMedikit = ReadInt(setValue);
break;
default:
super::SpawnKey(keyName, setValue);
break;
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
SpawnKey(argv(i), argv(i+1));
}
precache_sound(m_strActivatedSound);
super::NSRenderableEntity();
info_tfgoal::Respawn();
}
/* the brush based version of tfgoal */
class i_t_g:info_tfgoal
{
public:
void(void) i_t_g;
virtual void(void) Respawn;
};
void
i_t_g::i_t_g(void)
{
classname = "info_tfgoal";
m_tfgState = TFGOAL_INACTIVE;
m_tfgResult = TFRESULT_NONE;
}
void
i_t_g::Respawn(void)
{
SetSolid(SOLID_BSPTRIGGER);
SetMovetype(MOVETYPE_NONE);
SetModel(m_strSpawnModel);
SetOrigin(GetSpawnVector("origin"));
SetModel(GetSpawnModel());
SetOrigin(GetSpawnOrigin());
Hide();
team = m_iTeamUses;
if (frags > 0) {
if (frags > 0)
botinfo = BOTINFO_TEAM_GOALCAPTURE;
}
}
void
i_t_g::i_t_g(void)
{
classname = "info_tfgoal";
m_tfgState = TFGOAL_INACTIVE;
m_tfgResult = TFRESULT_NONE;
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
SpawnKey(argv(i), argv(i+1));
}
super::NSRenderableEntity();
precache_sound(m_strActivatedSound);
Respawn();
}

View file

@ -15,7 +15,7 @@
*/
class
TFCArmor:ncRenderableEntity
TFCArmor:NSRenderableEntity
{
float m_flRespawnDelay;
int m_iTeamUses;
@ -65,10 +65,10 @@ TFCArmor::Spawned(void)
void
TFCArmor::Respawn(void)
{
SetModel(GetSpawnString("model"));
SetModel(GetSpawnModel());
SetSize([-16,-16,0], [16,16,56]);
SetSolid(SOLID_TRIGGER);
SetOrigin(GetSpawnVector("origin"));
SetOrigin(GetSpawnOrigin());
DropToFloor();
botinfo = BOTINFO_ARMOR;
}
@ -79,9 +79,7 @@ TFCArmor::Touch(entity eToucher)
if (eToucher.classname != "player") {
return;
}
TFPlayer pl = (TFPlayer)eToucher;
int cellType = ammoNumForName("ammo_cells");
player pl = (player)eToucher;
/* check for team eligibility */
if (m_iTeamUses)
@ -89,14 +87,14 @@ TFCArmor::Touch(entity eToucher)
return;
/* if we can't add anything, don't bother */
if (pl.armor >= pl.GetMaxArmor() && pl.GetReserveAmmo(cellType) >= pl.MaxAmmo(cellType))
if (pl.armor >= pl.m_iMaxArmor && pl.m_iAmmoCells >= pl.m_iMaxCells)
return;
int ap;
int tp = 0;
/* get remaining points */
ap = pl.GetMaxArmor() - pl.armor;
ap = pl.m_iMaxArmor - pl.armor;
tp = m_iArmorValue;
/* if that's all we can give... */
@ -108,7 +106,7 @@ TFCArmor::Touch(entity eToucher)
/* give the remaining as metal... engineers only!*/
if (pl.classtype == CLASS_ENGINEER) {
pl.GiveAmmo(cellType, (tp - ap));
pl. m_iAmmoCells = bound(0, pl.m_iAmmoCells + (tp - ap), pl.m_iMaxCells);
}
}

View file

@ -29,7 +29,7 @@ Health pickup. Unlike Team Fortress, this is the only one and it provides
*/
class
item_healthkit:ncRenderableEntity
item_healthkit:NSRenderableEntity
{
int m_iTeamUses;
float m_flRespawnDelay;
@ -47,7 +47,7 @@ item_healthkit::Touch(entity eToucher)
if (eToucher.classname != "player") {
return;
}
TFPlayer pl = (TFPlayer)eToucher;
player pl = (player)eToucher;
/* check for team eligibility */
if (m_iTeamUses)
@ -55,10 +55,10 @@ item_healthkit::Touch(entity eToucher)
return;
/* leave when full */
if (pl.health >= pl.GetMaxHealth())
if (pl.health >= pl.m_iMaxHealth)
return;
pl.SetHealth(bound(0, pl.GetHealth() + 25, pl.GetMaxHealth()));
pl.health = bound(0, pl.health + 25, pl.m_iMaxHealth);
Sound_Play(this, CHAN_ITEM, "item_healthkit_tfc.pickup");
@ -88,7 +88,7 @@ item_healthkit::Respawn(void)
SetModel("models/w_medkit.mdl");
SetSize([-16,-16,0], [16,16,56]);
SetSolid(SOLID_TRIGGER);
SetOrigin(GetSpawnVector("origin"));
SetOrigin(GetSpawnOrigin());
DropToFloor();
botinfo = BOTINFO_HEALTH;
}
@ -98,4 +98,4 @@ item_healthkit::item_healthkit(void)
{
Sound_Precache("item_healthkit_tfc.pickup");
m_flRespawnDelay = 30.0f;
}
}

View file

@ -54,29 +54,19 @@ Duplicate keys:
typedef enum
{
GISTATUS_HOME, /*<< The item is at its home base. */
GISTATUS_DROPPED /*<< The item is at neither on a player, nor at its base. */
GISTATUS_HOME,
GISTATUS_DROPPED
} goalitem_status_e;
class item_tfgoal:ncRenderableEntity
class item_tfgoal:NSRenderableEntity
{
public:
void(void) item_tfgoal;
virtual void(entity) Touch;
virtual void(void) Respawn;
virtual void(string, string) SpawnKey;
virtual void(ncPlayer) DropReturnable;
virtual void(void) TeamOwnerReturns;
virtual void(void) Spawned;
private:
float m_dItemID;
int m_iTeamUses;
int m_iTeamOwner;
string m_strSound;
TFPlayer m_eActivator;
player m_eActivator;
goalitem_status_e m_status;
@ -99,28 +89,20 @@ private:
string m_returnOwner;
float m_flPausetime;
string m_strSpawnModel; /* because we mangle it */
void(void) item_tfgoal;
virtual void(entity) Touch;
virtual void(void) Respawn;
virtual void(string, string) SpawnKey;
virtual void(NSClientPlayer) DropReturnable;
virtual void(void) TeamOwnerReturns;
virtual void(void) Spawned;
};
void
item_tfgoal::item_tfgoal(void)
item_tfgoal::DropReturnable(NSClientPlayer pp)
{
m_status = GISTATUS_HOME;
m_returnOwner = m_returnTeam = __NULL__;
m_flPausetime = 0;
}
void
item_tfgoal::Spawned(void)
{
super::Spawned();
precache_sound(m_strSound);
}
void
item_tfgoal::DropReturnable(ncPlayer pp)
{
TFPlayer pl = (TFPlayer)pp;
player pl = (player)pp;
/* make it available again, put it exactly where we died */
Respawn();
@ -141,22 +123,21 @@ item_tfgoal::TeamOwnerReturns(void)
Respawn();
for (entity e = world; (e = find(e, ::classname, "player")); ) {
if (e.team == m_iTeamUses) {
if (e.team == m_iTeamUses)
env_message_single(e, m_returnTeam);
} else if (e.team == m_iTeamOwner) {
else if (e.team == m_iTeamOwner)
env_message_single(e, m_returnOwner);
}
}
}
void
item_tfgoal::Touch(entity touchingEntity)
item_tfgoal::Touch(entity eToucher)
{
if (isPlayer(touchingEntity) == false) {
if (eToucher.classname != "player") {
return;
}
TFPlayer pl = (TFPlayer)touchingEntity;
player pl = (player)eToucher;
/* not in standard TFC, make cvar? */
#if 0
@ -177,7 +158,7 @@ item_tfgoal::Touch(entity touchingEntity)
Disappear();
pl.g_items |= ITEM_GOALITEM;
pl.AddVFlags(VFL_GOALITEM);
pl.flags |= FL_GOALITEM;
forceinfokey(pl, "*goalitem_t", itos(m_iTeamOwner));
m_eActivator = pl;
@ -186,7 +167,7 @@ item_tfgoal::Touch(entity touchingEntity)
sound(this, CHAN_ITEM, m_strSound, 1.0f, ATTN_NONE);
/* message broadcaster */
if (STRING_SET(m_msgAll)) {
if (m_msgAll) {
env_message_broadcast(m_msgAll);
} else {
for (entity e = world; (e = find(e, ::classname, "player")); ) {
@ -208,7 +189,7 @@ item_tfgoal::Touch(entity touchingEntity)
}
/* vox speaker */
if (STRING_SET(m_voxAll)) {
if (m_voxAll) {
Vox_Sentence_Broadcast(m_voxAll);
} else {
for (entity e = world; (e = find(e, ::classname, "player")); ) {
@ -217,14 +198,13 @@ item_tfgoal::Touch(entity touchingEntity)
} else if (e.team == pl.team ) {
Vox_Sentence_Single(e, m_voxActTeam);
} else if (e.team != pl.team) {
if (e.team == m_iTeamOwner && STRING_SET(m_voxOwnerTeam)) {
if (e.team == m_iTeamOwner && m_voxOwnerTeam)
Vox_Sentence_Single(e, m_voxOwnerTeam);
} else {
if (STRING_SET(m_voxNonOwnerTeams)) {
else {
if (m_voxNonOwnerTeams)
Vox_Sentence_Single(e, m_voxNonOwnerTeams);
} else {
else
Vox_Sentence_Single(e, m_voxNonActTeam);
}
}
}
}
@ -234,14 +214,13 @@ item_tfgoal::Touch(entity touchingEntity)
void
item_tfgoal::Respawn(void)
{
SetModel(m_strSpawnModel);
SetModel(GetSpawnModel());
SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
SetSolid(SOLID_TRIGGER);
SetOrigin(GetSpawnVector("origin"));
SetOrigin(GetSpawnOrigin());
m_eActivator = __NULL__;
ReleaseThink();
m_status = GISTATUS_HOME;
SetRenderMode(RM_NORMAL);
/* helps with bots */
team = m_iTeamOwner;
@ -254,25 +233,24 @@ item_tfgoal::Respawn(void)
}
if (m_iTeamOwner) {
SetRenderAmt(1);
SetRenderAmt(1.0f);
SetRenderFX(RFX_GLOWSHELL);
} else {
} else
return;
}
/* spawn into the world */
switch (m_iTeamOwner) {
case 1:
SetRenderColor([0,0,255]);
SetRenderColor([0,0,1]);
break;
case 2:
SetRenderColor([255,0,0]);
SetRenderColor([1,0,0]);
break;
case 3:
SetRenderColor([255, 255,0]);
SetRenderColor([1,1,0]);
break;
case 4:
SetRenderColor([0,255,0]);
SetRenderColor([0,1,0]);
break;
}
}
@ -284,15 +262,13 @@ item_tfgoal::SpawnKey(string strKey, string strValue)
case "noise":
m_strSound = strValue;
break;
case "model":
case "mdl":
m_strSpawnModel = strValue;
model = strValue;
if (serverkeyfloat("*bspversion") == 0) {
m_strSpawnModel = strreplace("progs", "models", model);
m_strSpawnModel = strreplace("tf_stan", "flag", model);
if (serverkeyfloat("*bspversion") == BSPVER_Q1) {
model = strreplace("progs", "models", model);
model = strreplace("tf_stan", "flag", model);
}
break;
case "goal_no":
m_dItemID = stof(strValue);
@ -358,3 +334,18 @@ item_tfgoal::SpawnKey(string strKey, string strValue)
break;
}
}
void
item_tfgoal::Spawned(void)
{
super::Spawned();
precache_sound(m_strSound);
}
void
item_tfgoal::item_tfgoal(void)
{
m_status = GISTATUS_HOME;
m_returnOwner = m_returnTeam = __NULL__;
m_flPausetime = 0;
}

View file

@ -1,7 +1,6 @@
void
TFCNade_ThrowCaltrop(TFPlayer pl)
TFCNade_ThrowCaltrop(player pl)
{
#if 0
vector vecNadeVelocity;
static void TFCNade_ThrowHandGrenade_Touch(void) {
@ -15,14 +14,14 @@ TFCNade_ThrowCaltrop(TFPlayer pl)
pointparticles(particleeffectnum("fx_explosion.main"), self.origin, [0,0,0], 1);
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_GLAUNCHER);
sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
ncEntity::Destroy();
NSEntity::Destroy();
}
for (int i = 0; i < 6; i++) {
makevectors([0, random() * 360, 0]);
vecNadeVelocity = v_forward * 50 + v_up * 150 + crandom() * v_right * 10 + crandom() * v_up * 10;
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/caltrop.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
@ -35,13 +34,11 @@ TFCNade_ThrowCaltrop(TFPlayer pl)
eNade.touch = TFCNade_ThrowHandGrenade_Touch;
}
#endif
}
void
TFCNade_ThrowHandGrenade(TFPlayer pl)
TFCNade_ThrowHandGrenade(player pl)
{
#if 0
vector vecNadeVelocity;
float flTimer;
@ -57,14 +54,14 @@ TFCNade_ThrowHandGrenade(TFPlayer pl)
pointparticles(particleeffectnum("fx_explosion.main"), self.origin, [0,0,0], 1);
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_GLAUNCHER);
sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
ncEntity::Destroy();
NSEntity::Destroy();
}
Weapons_MakeVectors(pl);
vecNadeVelocity = v_forward * 600 + v_up * 200 + crandom() * v_right * 10 + crandom() * v_up * 10;
flTimer = max(0.0, pl. gren1.GetNextThinkTime() - time);
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/w_grenade.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
@ -77,13 +74,11 @@ TFCNade_ThrowHandGrenade(TFPlayer pl)
eNade.touch = TFCNade_ThrowHandGrenade_Touch;
eNade.ScheduleThink(TFCNade_ThrowHandGrenade_Explode, flTimer);
#endif
}
void
TFCNade_ThrowConcussion(TFPlayer pl)
TFCNade_ThrowConcussion(player pl)
{
#if 0
vector vecNadeVelocity;
float flTimer;
@ -95,7 +90,7 @@ TFCNade_ThrowConcussion(TFPlayer pl)
}
static void TFCNade_ThrowConcussion_Explode(void) {
for (TFPlayer f = world; (f = (TFPlayer)find(f, ::classname, "player"));) {
for (player f = world; (f = (player)find(f, ::classname, "player"));) {
float dist = vlen(f.origin - self.origin);
if (dist < 256) {
@ -130,14 +125,14 @@ TFCNade_ThrowConcussion(TFPlayer pl)
msg_entity = self;
multicast(self.origin, MULTICAST_PVS);
ncEntity::Destroy();
NSEntity::Destroy();
}
Weapons_MakeVectors(pl);
vecNadeVelocity = v_forward * 600 + v_up * 200 + crandom() * v_right * 10 + crandom() * v_up * 10;
flTimer = max(0.0, pl.gren2.GetNextThinkTime() - time);
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/conc_grenade.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
@ -149,13 +144,11 @@ TFCNade_ThrowConcussion(TFPlayer pl)
eNade.touch = TFCNade_ThrowConcussion_Touch;
eNade.ScheduleThink(TFCNade_ThrowConcussion_Explode, flTimer);
#endif
}
void
TFCNade_ThrowNail(TFPlayer pl)
TFCNade_ThrowNail(player pl)
{
#if 0
vector vecNadeVelocity;
float flTimer;
@ -170,7 +163,7 @@ TFCNade_ThrowNail(TFPlayer pl)
pointparticles(particleeffectnum("fx_explosion.main"), self.origin, [0,0,0], 1);
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_GLAUNCHER);
sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
ncEntity::Destroy();
NSEntity::Destroy();
}
static void TFCNade_ThrowNail_Shoot(entity source, vector euler_dir) {
@ -229,7 +222,7 @@ TFCNade_ThrowNail(TFPlayer pl)
vecNadeVelocity = v_forward * 600 + v_up * 200 + crandom() * v_right * 10 + crandom() * v_up * 10;
flTimer = max(0.0, pl.gren2.GetNextThinkTime() - time);
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/ngrenade.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
@ -242,13 +235,11 @@ TFCNade_ThrowNail(TFPlayer pl)
eNade.touch = TFCNade_ThrowNail_Touch;
eNade.ScheduleThink(TFCNade_ThrowNail_Deploy, flTimer);
#endif
}
void
TFCNade_ThrowMIRVBomblet(ncEntity bomb)
TFCNade_ThrowMIRVBomblet(NSEntity bomb)
{
#if 0
vector vecNadeVelocity;
static void TFCNade_ThrowMIRVBomblet_Touch(void) {
@ -262,15 +253,15 @@ TFCNade_ThrowMIRVBomblet(ncEntity bomb)
pointparticles(particleeffectnum("fx_explosion.main"), self.origin, [0,0,0], 1);
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_GLAUNCHER);
sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
ncEntity::Destroy();
NSEntity::Destroy();
}
TFPlayer pl = (TFPlayer)bomb.owner;
player pl = (player)bomb.owner;
makevectors([0, random() * 360, 0]);
vecNadeVelocity = v_forward * 100 + v_up * 350 + crandom() * v_right * 10 + crandom() * v_up * 10;
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/bomblet.mdl");
eNade.SetOrigin(bomb.origin + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
@ -284,13 +275,11 @@ TFCNade_ThrowMIRVBomblet(ncEntity bomb)
eNade.touch = TFCNade_ThrowMIRVBomblet_Touch;
eNade.ScheduleThink(TFCNade_ThrowMIRVBomblet_Explode, 1.5f + random());
#endif
}
void
TFCNade_ThrowMIRV(TFPlayer pl)
TFCNade_ThrowMIRV(player pl)
{
#if 0
vector vecNadeVelocity;
float flTimer;
@ -308,10 +297,10 @@ TFCNade_ThrowMIRV(TFPlayer pl)
sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
for (int i = 0; i < 4; i++) {
TFCNade_ThrowMIRVBomblet((ncEntity)self);
TFCNade_ThrowMIRVBomblet((NSEntity)self);
}
ncEntity::Destroy();
NSEntity::Destroy();
}
Weapons_MakeVectors(pl);
@ -319,7 +308,7 @@ TFCNade_ThrowMIRV(TFPlayer pl)
vecNadeVelocity = v_forward * 600 + v_up * 200 + crandom() * v_right * 10 + crandom() * v_up * 10;
flTimer = max(0.0, pl. gren2.GetNextThinkTime() - time);
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/mirv_grenade.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
@ -330,13 +319,11 @@ TFCNade_ThrowMIRV(TFPlayer pl)
eNade.SetSkin(1);
eNade.ScheduleThink(TFCNade_ThrowMIRV_Explode, flTimer);
eNade.touch = TFCNade_ThrowMIRV_Touch;
#endif
}
void
TFCNade_ThrowNapalm(TFPlayer pl)
TFCNade_ThrowNapalm(player pl)
{
#if 0
vector vecNadeVelocity;
float flTimer;
@ -348,14 +335,14 @@ TFCNade_ThrowNapalm(TFPlayer pl)
}
static void TFCNade_ThrowConcussion_Explode(void) {
ncEntity::Destroy();
NSEntity::Destroy();
}
Weapons_MakeVectors(pl);
vecNadeVelocity = v_forward * 600 + v_up * 200 + crandom() * v_right * 10 + crandom() * v_up * 10;
flTimer = max(0.0, pl.gren2.GetNextThinkTime() - time);
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/napalm.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
@ -367,13 +354,11 @@ TFCNade_ThrowNapalm(TFPlayer pl)
eNade.touch = TFCNade_ThrowConcussion_Touch;
eNade.ScheduleThink(TFCNade_ThrowConcussion_Explode, flTimer);
#endif
}
void
TFCNade_ThrowHallucination(TFPlayer pl)
TFCNade_ThrowHallucination(player pl)
{
#if 0
vector vecNadeVelocity;
float flTimer;
@ -385,21 +370,21 @@ TFCNade_ThrowHallucination(TFPlayer pl)
}
static void TFCNade_ThrowConcussion_Explode(void) {
for (TFPlayer f = world; (f = (TFPlayer)find(f, ::classname, "player"));) {
for (player f = world; (f = (player)find(f, ::classname, "player"));) {
float dist = vlen(f.origin - self.origin);
if (dist < 192) {
f.m_flHallucination = 15.0f;
}
}
ncEntity::Destroy();
NSEntity::Destroy();
}
Weapons_MakeVectors(pl);
vecNadeVelocity = v_forward * 600 + v_up * 200 + crandom() * v_right * 10 + crandom() * v_up * 10;
flTimer = max(0.0, pl.gren2.GetNextThinkTime() - time);
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/spy_grenade.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
@ -411,13 +396,11 @@ TFCNade_ThrowHallucination(TFPlayer pl)
eNade.touch = TFCNade_ThrowConcussion_Touch;
eNade.ScheduleThink(TFCNade_ThrowConcussion_Explode, flTimer);
#endif
}
void
TFCNade_ThrowEMP(TFPlayer pl)
TFCNade_ThrowEMP(player pl)
{
#if 0
vector vecNadeVelocity;
float flTimer;
@ -429,14 +412,14 @@ TFCNade_ThrowEMP(TFPlayer pl)
}
static void TFCNade_ThrowEMP_Explode(void) {
ncEntity::Destroy();
NSEntity::Destroy();
}
Weapons_MakeVectors(pl);
vecNadeVelocity = v_forward * 600 + v_up * 200 + crandom() * v_right * 10 + crandom() * v_up * 10;
flTimer = max(0.0, pl.gren2.GetNextThinkTime() - time);
ncRenderableEntity eNade = spawn(ncRenderableEntity);
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/emp_grenade.mdl");
eNade.SetOrigin(Weapons_GetCameraPos(pl) + (v_forward * 14) + (v_up * -4) + (v_right * 2));
eNade.SetOwner(pl);
@ -448,11 +431,10 @@ TFCNade_ThrowEMP(TFPlayer pl)
eNade.touch = TFCNade_ThrowEMP_Touch;
eNade.ScheduleThink(TFCNade_ThrowEMP_Explode, flTimer);
#endif
}
void
TFCNade_ThrowSecondary(TFPlayer pl)
TFCNade_ThrowSecondary(player pl)
{
switch (pl.classtype) {
case CLASS_SCOUT:
@ -482,10 +464,10 @@ TFCNade_ThrowSecondary(TFPlayer pl)
}
void
TFCNade_SelfExplode(TFPlayer pl)
TFCNade_SelfExplode(player pl)
{
float dmg = 100;
pointparticles(particleeffectnum("fx_explosion.main"), pl.origin, [0,0,0], 1);
//Damage_Radius(pl.origin, pl, dmg, dmg * 2.5f, TRUE, WEAPON_GLAUNCHER);
Damage_Radius(pl.origin, pl, dmg, dmg * 2.5f, TRUE, WEAPON_GLAUNCHER);
sound(pl, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
}

View file

@ -1,7 +1,6 @@
#pragma target fte_5768
//#pragma flag enable assumeint
#pragma progs_dat "../../progs.dat"
#pragma forcecrc 54730
#define QWSSQC
#define SERVER
@ -13,14 +12,46 @@
../../../src/shared/defs.h
../../../src/server/defs.h
../../../src/botlib/botinfo.h
../../../src/gs-entbase/server.src
../../../src/gs-entbase/shared.src
defs.h
../shared/include.src
entities.src
../../../valve/src/server/player.qc
dispenser.qc
sentry.qc
teleporter.qc
func_nobuild.qc
func_nogrenades.qc
vox.qc
../../../valve/src/server/items.qc
../../../src/botlib/include.src
bot.qc
info_player_teamspawn.qc
item_tfgoal.qc
info_tfgoal.qc
info_areadef.qc
info_tfdetect.qc
item_armor.qc
item_healthkit.qc
nades.qc
gamerules.qc
client.qc
server.qc
../../../valve/src/server/damage.qc
../../../valve/src/server/flashlight.qc
../../../valve/src/server/modelevent.qc
spawn.qc
../../../src/server/include.src
../../../src/shared/include.src
#endlist

View file

@ -25,9 +25,9 @@ typedef enum
} sentrystate_e;
class
TFCSentry:ncSurfacePropEntity
TFCSentry:NSSurfacePropEntity
{
ncSurfacePropEntity m_eHead;
NSSurfacePropEntity m_eHead;
sentrystate_e m_state;
float m_flNextIdleSound;
@ -37,7 +37,7 @@ TFCSentry:ncSurfacePropEntity
void(void) TFCSentry;
virtual void(ncPlayer) Place;
virtual void(NSClientPlayer) Place;
virtual void(void) FinishPlacing;
virtual void(void) Think;
};

View file

@ -64,19 +64,19 @@ TFCSentry::Think(void)
else {
makevectors([0, angles[1], 0]);
m_flWantAngle = dotproduct((origin - t.origin), v_right);
m_flCurrAngle = lerpAngle(m_flCurrAngle, m_flWantAngle, 0.25f);
m_flCurrAngle = Math_Lerp(m_flCurrAngle, m_flWantAngle, 0.25f);
m_eHead.SetBoneControl1(m_flCurrAngle);
print(sprintf("head: %f; want: %f\n", m_flCurrAngle, m_flWantAngle));
/* fire bullets */
input_angles = v_angle = vectoangles(origin - t.origin);
//TraceAttack_FireBullets(1, origin, 5, [0.025,0.025], WEAPON_NONE);
TraceAttack_FireBullets(1, origin, 5, [0.025,0.025], WEAPON_NONE);
}
}
}
void
TFCSentry::Place(ncPlayer pl)
TFCSentry::Place(NSClientPlayer pl)
{
vector newAngles = pl.GetAngles();
newAngles[0] = newAngles[2] = 0;
@ -118,31 +118,30 @@ TFCSentry::FinishPlacing(void)
void
TFCSentry::TFCSentry(void)
{
m_eHead = spawn(ncSurfacePropEntity);
m_eHead = spawn(NSSurfacePropEntity);
SetModel("models/base.mdl");
SetSolid(SOLID_BBOX);
SetMovetype(MOVETYPE_NONE);
SetSize([-16,-16,0], [16,16,20]);
SetTakedamage(DAMAGE_YES);
SetHealth(100);
MakeVulnerable();
m_eHead.SetTakedamage(DAMAGE_YES);
m_eHead.SetHealth(100);
m_eHead.MakeVulnerable();
m_state = SENTRY_IDLE;
}
void
TFCSentry_Build(void)
{
TFPlayer pl = (TFPlayer)self;
int cellType = ammoNumForName("ammo_cells");
player pl = (player)self;
/* only engineers can do this */
if (pl.classtype != CLASS_ENGINEER)
return;
/* it costs cells to build these things */
if (pl.UseAmmo(cellType, TFC_SENTRY_COST) == false) {
/* it costs */
if (pl.m_iAmmoCells < TFC_SENTRY_COST) {
env_message_single(pl, "#Build_nometal");
return;
}
@ -158,6 +157,8 @@ TFCSentry_Build(void)
return;
}
pl.m_iAmmoCells -= TFC_SENTRY_COST;
/* deploy */
TFCSentry sentry = spawn(TFCSentry);
sentry.Place(pl);
@ -166,5 +167,5 @@ TFCSentry_Build(void)
void
TFCSentry_Dismantle(void)
{
TFC_DetonateTypeForPlayer((TFPlayer)self, "TFCSentry");
TFC_DetonateTypeForPlayer((player)self, "TFCSentry");
}

View file

@ -14,6 +14,12 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
Game_InitRules(void)
{
g_grMode = spawn(TFCGameRules);
}
void
Game_Worldspawn(void)
{
@ -36,16 +42,19 @@ Game_Worldspawn(void)
precache_model("models/sentry3.mdl");
precache_model("models/player.mdl");
precache_model("models/w_weaponbox.mdl");
Weapons_Init();
Player_Precache();
FX_Corpse_Init();
}
void weaponbox_spawn(TFPlayer pl)
void weaponbox_spawn(player pl)
{
}
void
CSEv_TFCBuild_i(int type)
{
TFPlayer pl = (TFPlayer)self;
player pl = (player)self;
if (pl.gflags & GF_NOBUILDZONE) {
env_message_single(pl, "#Build_nobuild");

163
src/server/spawn.qc Normal file
View file

@ -0,0 +1,163 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
float
TFCTeamJoin_SmallestTeam(int blue, int red, int yellow, int green)
{
while (blue > 0i || red > 0i || yellow > 0i || green > 0i) {
/* the first team that goes to 0, gets picked. */
if (blue <= 0i)
return 1;
else if (red <= 0i)
return 2;
else if (yellow <= 0i)
return 3;
else if (green <= 0i)
return 4;
blue--;
red--;
yellow--;
green--;
}
/* the first team that goes to 0, gets picked. */
if (blue == 0i)
return 1;
else if (red == 0i)
return 2;
else if (yellow == 0i)
return 3;
else if (green == 0i)
return 4;
return 0;
}
void
CSEv_TeamJoin_f(float f)
{
player pl = (player)self;
/* random... */
if (f == 0) {
int bluePlayers = 0i;
int redPlayers = 0i;
int yellowPlayers = 0i;
int greenPlayers = 0i;
/* hack to get it to never pick this team */
if (g_tfcHasBlueTeam == false)
bluePlayers = (int)cvar("sv_playerslots");
if (g_tfcHasRedTeam == false)
redPlayers = (int)cvar("sv_playerslots");
if (g_tfcHasYellowTeam == false)
yellowPlayers = (int)cvar("sv_playerslots");
if (g_tfcHasGreenTeam == false)
greenPlayers = (int)cvar("sv_playerslots");
/* count all valid players within each team */
for (entity e = world; (e = find(e, ::classname, "player"));) {
if (e.team == 1)
bluePlayers++;
else if (e.team == 2)
redPlayers++;
else if (e.team == 3)
yellowPlayers++;
else if (e.team == 4)
greenPlayers++;
}
/* assign us to the team with the lowest amount of players */
f = TFCTeamJoin_SmallestTeam(bluePlayers, redPlayers, yellowPlayers, greenPlayers);
}
/* mess, do it better */
if (f == 1) {
pl.team = 1; /* Blue */
forceinfokey(pl, "topcolor", "0x9aff");
forceinfokey(pl, "bottomcolor", "0x9aff");
} else if (f == 2) {
pl.team = 2; /* Red */
f -= 10;
forceinfokey(pl, "topcolor", "0xff1800");
forceinfokey(pl, "bottomcolor", "0xff1800");
} else if (f == 3) {
pl.team = 3; /* Yellow */
f -= 20;
forceinfokey(pl, "topcolor", "0xffca00");
forceinfokey(pl, "bottomcolor", "0xffca00");
} else if (f == 4) {
pl.team = 4; /* Green */
f -= 30;
forceinfokey(pl, "topcolor", "0x3bff00");
forceinfokey(pl, "bottomcolor", "0x3bff00");
} else {
return;
}
if (self.health > 0) {
ClientKill();
return;
}
}
/** Called by the client-side VGUI menu when we choose a class. */
void
CSEv_ClassJoin_f(float f)
{
player pl = (player)self;
/* choose a random class. */
if (f == 0) {
float newClass = 0;
while (newClass == 0 || newClass == pl.classtype)
newClass = floor(random(CLASS_SCOUT, CLASS_ENGINEER + 1));
f = newClass;
}
/* invalid */
if (pl.team == 0) {
return;
}
if (self.classname != "player") {
spawnfunc_player();
}
/* invalid */
if (pl.classtype == f)
return;
/* if we're still alive... */
if (pl.health > 0) {
pl.classtype = f;
pl.MakeClass(f);
ClientKill();
} else {
/* insta spawn */
/* assign our class type for safe keeping */
pl.classtype = f;
/* turn the player into the class of his choice */
pl.MakeClass(f);
pl.SpawnIntoGame();
}
}

View file

@ -18,13 +18,13 @@
/* main teleporter */
class
TFCTeleporter:ncSurfacePropEntity
TFCTeleporter:NSSurfacePropEntity
{
float m_flNextTeleport;
void(void) TFCTeleporter;
virtual void(TFPlayer) Place;
virtual void(player) Place;
virtual void(void) FinishPlacing;
virtual void(entity) Touch;
};
@ -68,7 +68,7 @@ TFCTeleporter::Touch(entity eToucher)
}
void
TFCTeleporter::Place(TFPlayer pl)
TFCTeleporter::Place(player pl)
{
SetAngles(pl.GetAngles());
@ -128,15 +128,14 @@ TFCTeleporterExit::TFCTeleporterExit(void)
void
TFCTeleporter_Build(void)
{
TFPlayer pl = (TFPlayer)self;
int cellType = ammoNumForName("ammo_cells");
player pl = (player)self;
/* only engineers can do this */
if (pl.classtype != CLASS_ENGINEER)
return;
/* it costs */
if (pl.UseAmmo(cellType, TFC_TELEPORTER_COST) == false) {
if (pl.m_iAmmoCells < TFC_TELEPORTER_COST) {
env_message_single(pl, "#Build_nometal");
return;
}
@ -152,6 +151,8 @@ TFCTeleporter_Build(void)
return;
}
pl.m_iAmmoCells -= TFC_TELEPORTER_COST;
/* deploy */
TFCTeleporter start = spawn(TFCTeleporter);
start.Place(pl);
@ -160,15 +161,14 @@ TFCTeleporter_Build(void)
void
TFCTeleporterExit_Build(void)
{
TFPlayer pl = (TFPlayer)self;
int cellType = ammoNumForName("ammo_cells");
player pl = (player)self;
/* only engineers can do this */
if (pl.classtype != CLASS_ENGINEER)
return;
/* it costs */
if (pl.UseAmmo(cellType, TFC_TELEPORTER_COST) == false) {
if (pl.m_iAmmoCells < TFC_TELEPORTER_COST) {
env_message_single(pl, "#Build_nometal");
return;
}
@ -184,6 +184,8 @@ TFCTeleporterExit_Build(void)
return;
}
pl.m_iAmmoCells -= TFC_TELEPORTER_COST;
/* deploy */
TFCTeleporterExit end = spawn(TFCTeleporterExit);
end.Place(pl);
@ -192,10 +194,10 @@ TFCTeleporterExit_Build(void)
void
TFCTeleporter_Dismantle(void)
{
TFC_DetonateTypeForPlayer((TFPlayer)self, "TFCTeleporter");
TFC_DetonateTypeForPlayer((player)self, "TFCTeleporter");
}
void
TFCTeleporterExit_Dismantle(void)
{
TFC_DetonateTypeForPlayer((TFPlayer)self, "TFCTeleporterExit");
TFC_DetonateTypeForPlayer((player)self, "TFCTeleporterExit");
}

40
src/server/vox.qc Normal file
View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
Vox_Sentence_Broadcast(string msg)
{
if (!msg || msg == "")
return;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_TFC_VOXMSG);
WriteString(MSG_MULTICAST, msg);
multicast([0,0,0], MULTICAST_ALL_R);
}
void
Vox_Sentence_Single(entity targ, string msg)
{
if (!msg || msg == "")
return;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_TFC_VOXMSG);
WriteString(MSG_MULTICAST, msg);
msg_entity = targ;
multicast([0,0,0], MULTICAST_ONE_R);
}

View file

@ -52,3 +52,26 @@ string g_teammodels_hd[] = {
"models/player/spy/spy2.mdl",
"models/player/engineer/engineer2.mdl"
};
/* are we using a later build of TF? */
bool
TFC_IsLaterBuild(void)
{
if (whichpack(g_teammodels_hd[1]))
return true;
return false;
}
/* stuff */
string
TFC_GetModelForClasstype(classtype_e type)
{
if (TFC_IsLaterBuild() == true)
if (autocvar(tfc_newmodels, 0) == 1)
return g_teammodels[type]; /* on later versions, the old names are the HD ones */
else
return g_teammodels_hd[type];
return g_teammodels[type];
}

View file

@ -5,13 +5,42 @@ weapons.h
flags.h
events.h
../../../valve/src/shared/skeleton.h
../../../valve/src/shared/player.qc
player.qc
../../../valve/src/shared/weapon_common.h
../../../valve/src/shared/animations.h
animations_tfc.h
../../../valve/src/shared/animations.qc
pmove.qc
vox.qc
../../../valve/src/shared/HLWeapon.qc
../../../valve/src/shared/fx_blood.qc
../../../valve/src/shared/fx_corpse.qc
weapon_basesemi.qc
weapon_basemelee.qc
weapon_baseshotgun.qc
weapon_baseprojectile.qc
weapon_baseautomatic.qc
w_asscan.qc
w_autorifle.qc
w_crowbar.qc
w_dbs.qc
w_flamer.qc
w_glauncher.qc
w_grapple.qc
w_incendiary.qc
w_knife.qc
w_medkit.qc
w_nailgun.qc
w_pipebomb.qc
w_railgun.qc
w_rpg.qc
w_sbs.qc
w_sniper.qc
w_supernail.qc
w_tranquil.qc
w_umbrella.qc
w_wrench.qc
weapons.qc
../../../valve/src/shared/weapon_common.qc
#endlist

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2024AAAAAA Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2021 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -14,12 +14,23 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class
TFPlayer:HLPlayer
#include "../../../valve/src/shared/skeleton.h"
/* all potential SendFlags bits we can possibly send */
enumflags
{
PLAYER_TOPFRAME = PLAYER_CUSTOMFIELDSTART,
PLAYER_BOTTOMFRAME,
PLAYER_AMMO1,
PLAYER_AMMO2,
PLAYER_AMMO3,
PLAYER_UNUSED5,
PLAYER_UNUSED6,
PLAYER_UNUSED7
};
void TFPlayer(void);
class player:NSClientPlayer
{
/* class info */
PREDICTED_INT(classtype)
@ -30,15 +41,28 @@ TFPlayer:HLPlayer
PREDICTED_INT(anim_bottom)
PREDICTED_FLOAT(anim_bottom_time)
/* ammo 1 */
PREDICTED_INT(mag_sbs)
PREDICTED_INT(mag_dbs)
PREDICTED_INT(mag_rpg)
PREDICTED_INT(mag_glauncher)
/* ammo 2 */
PREDICTED_INT(m_iAmmoRockets)
PREDICTED_INT(m_iAmmoNails)
PREDICTED_INT(m_iAmmoCells)
PREDICTED_INT(m_iAmmoShells)
PREDICTED_INT(m_iAmmoDetpack)
PREDICTED_INT(m_iAmmoMedikit)
/* ammo 3 */
PREDICTED_INT(mode_tempstate)
PREDICTED_FLOAT(m_flIdleScale)
PREDICTED_FLOAT(m_flHallucination)
virtual bool CanSprint(void);
virtual bool CanCrouch(void);
virtual bool CanProne(void);
virtual bool CanLean(void);
virtual void Physics_Jump(void);
virtual float Physics_MaxSpeed(void);
virtual void ProcessInput(void);
@ -47,22 +71,35 @@ TFPlayer:HLPlayer
nonvirtual void TFC_ReleaseGren1(void);
nonvirtual void TFC_ReleaseGren2(void);
virtual void UpdatePlayerAnimation(float);
virtual void Physics_InputPreMove(void);
#ifdef CLIENT
virtual void ReceiveEntity(float,float);
virtual void PredictPreFrame(void);
virtual void PredictPostFrame(void);
virtual void ClientInputFrame(void);
virtual void UpdateAliveCam(void);
virtual void UpdatePlayerAttachments(bool);
float m_flNextHallucination;
#else
ncTimer gren1;
ncTimer gren2;
NSTimer gren1;
NSTimer gren2;
int m_iMaxHealth;
int m_iMaxArmor;
int m_iMaxShells;
int m_iMaxNails;
int m_iMaxRockets;
int m_iMaxCells;
int m_iMaxDetpack;
int m_iMaxMedikit;
virtual void EvaluateEntity(void);
virtual float SendEntity(entity, float);
virtual void SpawnIntoGame(void);
virtual void MakeClass(classtype_e);
virtual void ServerInputFrame(void);
nonvirtual void TFC_FragSelf(void);
@ -70,24 +107,11 @@ TFPlayer:HLPlayer
#endif
};
void
TFPlayer::TFPlayer(void)
{
}
void Animation_PlayerUpdate(player);
void Animation_TimerUpdate(player, float);
void
TFPlayer::Physics_InputPreMove(void)
{
super::Physics_InputPreMove();
gflags &= ~GF_NOBUILDZONE;
gflags &= ~GF_NOGRENADEZONE;
}
void
TFPlayer::UpdatePlayerAnimation(float timelength)
player::UpdatePlayerAnimation(float timelength)
{
/* calculate our skeletal progression */
Animation_PlayerUpdate(this);
@ -95,46 +119,22 @@ TFPlayer::UpdatePlayerAnimation(float timelength)
Animation_TimerUpdate(this, timelength);
}
/* we invalidate the next two so we can use their input_ bits, INPUT_SPRINT & PRONE */
bool
TFPlayer::CanSprint(void)
{
return (false);
}
bool
TFPlayer::CanProne(void)
{
return (false);
}
bool
TFPlayer::CanCrouch(void)
{
return (true);
}
bool
TFPlayer::CanLean(void)
{
return (false);
}
#ifdef SERVER
void TFCNade_ThrowCaltrop(TFPlayer);
void TFCNade_ThrowHandGrenade(TFPlayer);
void TFCNade_ThrowSecondary(TFPlayer);
void TFCNade_SelfExplode(TFPlayer);
void TFCNade_ThrowCaltrop(player);
void TFCNade_ThrowHandGrenade(player);
void TFCNade_ThrowSecondary(player);
void TFCNade_SelfExplode(player);
void
TFPlayer::TFC_FragSelf(void)
player::TFC_FragSelf(void)
{
print("Primary exploded in your hand!\n");
TFCNade_SelfExplode(this);
}
void
TFPlayer::TFC_ThrowSecondary(void)
player::TFC_ThrowSecondary(void)
{
print("Secondary exploded in your hand!\n");
TFCNade_ThrowSecondary(this);
@ -142,7 +142,7 @@ TFPlayer::TFC_ThrowSecondary(void)
#endif
void
TFPlayer::TFC_CookGren1(void)
player::TFC_CookGren1(void)
{
/* we're already cooking it */
if (gflags & GF_GREN1COOK)
@ -166,7 +166,7 @@ TFPlayer::TFC_CookGren1(void)
}
void
TFPlayer::TFC_ReleaseGren1(void)
player::TFC_ReleaseGren1(void)
{
if (!(gflags & GF_GREN1COOK))
return;
@ -188,7 +188,7 @@ TFPlayer::TFC_ReleaseGren1(void)
}
void
TFPlayer::TFC_CookGren2(void)
player::TFC_CookGren2(void)
{
if (gflags & GF_GREN2COOK)
return;
@ -206,7 +206,7 @@ TFPlayer::TFC_CookGren2(void)
}
void
TFPlayer::TFC_ReleaseGren2(void)
player::TFC_ReleaseGren2(void)
{
if (!(gflags & GF_GREN2COOK))
return;
@ -220,24 +220,113 @@ TFPlayer::TFC_ReleaseGren2(void)
}
void
TFPlayer::ProcessInput(void)
player::ProcessInput(void)
{
super::ProcessInput();
if (input_buttons & INPUT_SPRINT)
if (input_buttons & INPUT_BUTTON6)
TFC_CookGren1();
else
TFC_ReleaseGren1();
if (input_buttons & INPUT_PRONE)
if (input_buttons & INPUT_BUTTON7)
TFC_CookGren2();
else
TFC_ReleaseGren2();
}
#ifdef CLIENT
.string oldmodel;
string Weapons_GetPlayermodel(player, int);
void
TFPlayer::UpdateAliveCam(void)
player::UpdatePlayerAttachments(bool visible)
{
/* draw the flashlight */
if (gflags & GF_FLASHLIGHT) {
vector src;
vector ang;
if (entnum != player_localentnum) {
src = origin + view_ofs;
ang = v_angle;
} else {
src = pSeat->m_vecPredictedOrigin + [0,0,-8];
ang = view_angles;
}
makevectors(ang);
traceline(src, src + (v_forward * 8096), MOVE_NORMAL, this);
if (serverkeyfloat("*bspversion") == BSPVER_HL) {
dynamiclight_add(trace_endpos + (v_forward * -2), 128, [1,1,1]);
} else {
float p = dynamiclight_add(src, 512, [1,1,1], 0, "textures/flashlight");
dynamiclight_set(p, LFIELD_ANGLES, ang);
dynamiclight_set(p, LFIELD_FLAGS, 3);
}
}
/* FIXME: this needs to be incorporated and simplified, now that we can handle it all in-class */
if (!visible)
return;
/* what's the current weapon model supposed to be anyway? */
p_model.oldmodel = Weapons_GetPlayermodel(this, activeweapon);
/* we changed weapons, update skeletonindex */
if (p_model.model != p_model.oldmodel) {
/* free memory */
if (p_model.skeletonindex)
skel_delete(p_model.skeletonindex);
/* set the new model and mark us updated */
setmodel(p_model, p_model.oldmodel);
p_model.model = p_model.oldmodel;
/* set the new skeletonindex */
p_model.skeletonindex = skel_create(p_model.modelindex);
/* hack this thing in here FIXME: this should be done when popping in/out of a pvs */
if (autocvar(cl_himodels, 1, "Use high-quality thisayer models over lower-definition ones"))
setcustomskin(this, "", "geomset 0 2\n");
else
setcustomskin(this, "", "geomset 0 1\n");
}
/* follow thisayer at all times */
setorigin(p_model, origin);
p_model.angles = angles;
skel_build(p_model.skeletonindex, p_model, p_model.modelindex,0, 0, -1);
/* we have to loop through all valid bones of the weapon model and match them
* to the thisayer one */
for (float i = 0; i < g_pbones.length; i++) {
vector bpos;
float pbone = gettagindex(this, g_pbones[i]);
float wbone = gettagindex(p_model, g_pbones[i]);
/* if the bone doesn't ignore in either skeletal mesh, ignore */
if (wbone <= 0 || pbone <= 0)
continue;
bpos = gettaginfo(this, pbone);
/* the most expensive bit */
skel_set_bone_world(p_model, wbone, bpos, v_forward, v_right, v_up);
}
}
void Weapons_AmmoUpdate(entity);
void HUD_AmmoNotify_Check(player pl);
void HUD_ItemNotify_Check(player pl);
void Camera_RunPosBob(vector angles, __inout vector camera_pos);
void Camera_StrafeRoll(__inout vector camera_angle);
void Shake_Update(NSClientPlayer);
void
player::UpdateAliveCam(void)
{
vector cam_pos = GetEyePos();
Camera_RunPosBob(view_angles, cam_pos);
@ -254,7 +343,7 @@ TFPlayer::UpdateAliveCam(void)
g_view.SetCameraAngle(view_angles);
if (vehicle) {
ncVehicle veh = (ncVehicle)vehicle;
NSVehicle veh = (NSVehicle)vehicle;
if (veh.UpdateView)
veh.UpdateView();
@ -272,25 +361,16 @@ TFPlayer::UpdateAliveCam(void)
g_view.AddPunchAngle(punchangle);
}
/*
=================
player::ReceiveEntity
=================
*/
void
TFPlayer::ClientInputFrame(void)
{
super::ClientInputFrame();
/* we need to make sure those aren't actually handled by the server */
if (pSeatTFC->m_bInputGren1 == true) {
input_buttons |= INPUT_PRONE;
}
if (pSeatTFC->m_bInputGren2 == true) {
input_buttons |= INPUT_SPRINT;
}
}
void
TFPlayer::ReceiveEntity(float new, float flChanged)
player::ReceiveEntity(float new, float flChanged)
{
/* the generic client attributes */
ncPlayer::ReceiveEntity(new, flChanged);
super::ReceiveEntity(new, flChanged);
/* animation */
READENTITY_BYTE(anim_top, PLAYER_TOPFRAME)
@ -299,9 +379,22 @@ TFPlayer::ReceiveEntity(float new, float flChanged)
READENTITY_BYTE(anim_bottom, PLAYER_BOTTOMFRAME)
READENTITY_FLOAT(anim_bottom_time, PLAYER_BOTTOMFRAME)
READENTITY_BYTE(classtype, PLAYER_AMMOTYPES)
READENTITY_FLOAT(m_flIdleScale, PLAYER_AMMOTYPES)
READENTITY_FLOAT(m_flHallucination, PLAYER_AMMOTYPES)
READENTITY_BYTE(mag_sbs, PLAYER_AMMO1)
READENTITY_BYTE(mag_dbs, PLAYER_AMMO1)
READENTITY_BYTE(mag_rpg, PLAYER_AMMO1)
READENTITY_BYTE(mag_glauncher, PLAYER_AMMO1)
READENTITY_BYTE(m_iAmmoRockets, PLAYER_AMMO2)
READENTITY_BYTE(m_iAmmoNails, PLAYER_AMMO2)
READENTITY_BYTE(m_iAmmoCells, PLAYER_AMMO2)
READENTITY_BYTE(m_iAmmoShells, PLAYER_AMMO2)
READENTITY_BYTE(m_iAmmoDetpack, PLAYER_AMMO2)
READENTITY_BYTE(m_iAmmoMedikit, PLAYER_AMMO2)
READENTITY_BYTE(mode_tempstate, PLAYER_AMMO3)
READENTITY_BYTE(classtype, PLAYER_AMMO3)
READENTITY_FLOAT(m_flIdleScale, PLAYER_AMMO3)
READENTITY_FLOAT(m_flHallucination, PLAYER_AMMO3)
setorigin(this, origin);
@ -314,52 +407,93 @@ TFPlayer::ReceiveEntity(float new, float flChanged)
if (flChanged == UPDATE_ALL)
PredictPreFrame();
if (flChanged & PLAYER_AMMOTYPES) {
//Weapons_AmmoUpdate(this);
if (flChanged & PLAYER_AMMO1 || flChanged & PLAYER_AMMO2 || flChanged & PLAYER_AMMO3) {
Weapons_AmmoUpdate(this);
HUD_AmmoNotify_Check(this);
}
if (flChanged & PLAYER_ITEMS || flChanged & PLAYER_HEALTH) {
if (flChanged & PLAYER_ITEMS || flChanged & PLAYER_HEALTH)
HUD_ItemNotify_Check(this);
}
if (m_flHallucination > 0.0) {
if (m_flNextHallucination > time) {
if (m_flNextHallucination > time)
return;
}
TFCHallucination_Insert(origin, v_angle);
m_flNextHallucination = time + 0.25f + random(0.25,0.75);
}
}
/*
=================
player::PredictPostFrame
Save the last valid server values away in the _net variants of each field
so we can roll them back later.
=================
*/
void
TFPlayer::PredictPreFrame(void)
player::PredictPreFrame(void)
{
/* the generic client attributes */
ncPlayer::PredictPreFrame();
NSClientPlayer::PredictPreFrame();
SAVE_STATE(anim_top)
SAVE_STATE(anim_top_delay)
SAVE_STATE(anim_top_time)
SAVE_STATE(anim_bottom)
SAVE_STATE(anim_bottom_time)
SAVE_STATE(mag_sbs)
SAVE_STATE(mag_dbs)
SAVE_STATE(mag_rpg)
SAVE_STATE(mag_glauncher)
SAVE_STATE(m_iAmmoRockets)
SAVE_STATE(m_iAmmoNails)
SAVE_STATE(m_iAmmoCells)
SAVE_STATE(m_iAmmoShells)
SAVE_STATE(m_iAmmoDetpack)
SAVE_STATE(m_iAmmoMedikit)
SAVE_STATE(mode_tempstate)
SAVE_STATE(classtype)
SAVE_STATE(m_flIdleScale)
SAVE_STATE(m_flHallucination)
}
/*
=================
player::PredictPostFrame
Where we roll back our values to the ones last sent/verified by the server.
=================
*/
void
TFPlayer::PredictPostFrame(void)
player::PredictPostFrame(void)
{
/* the generic client attributes */
ncPlayer::PredictPostFrame();
NSClientPlayer::PredictPostFrame();
ROLL_BACK(anim_top)
ROLL_BACK(anim_top_delay)
ROLL_BACK(anim_top_time)
ROLL_BACK(anim_bottom)
ROLL_BACK(anim_bottom_time)
ROLL_BACK(mag_sbs)
ROLL_BACK(mag_dbs)
ROLL_BACK(mag_rpg)
ROLL_BACK(mag_glauncher)
ROLL_BACK(m_iAmmoRockets)
ROLL_BACK(m_iAmmoNails)
ROLL_BACK(m_iAmmoCells)
ROLL_BACK(m_iAmmoShells)
ROLL_BACK(m_iAmmoDetpack)
ROLL_BACK(m_iAmmoMedikit)
ROLL_BACK(mode_tempstate)
ROLL_BACK(classtype)
ROLL_BACK(m_flIdleScale)
ROLL_BACK(m_flHallucination)
@ -367,7 +501,7 @@ TFPlayer::PredictPostFrame(void)
#else
void
TFPlayer::ServerInputFrame(void)
player::ServerInputFrame(void)
{
super::ServerInputFrame();
gflags &= ~GF_NOBUILDZONE;
@ -381,10 +515,10 @@ TFPlayer::ServerInputFrame(void)
}
void
TFPlayer::EvaluateEntity(void)
player::EvaluateEntity(void)
{
/* the generic client attributes */
ncPlayer::EvaluateEntity();
NSClientPlayer::EvaluateEntity();
/* animation */
EVALUATE_FIELD(anim_top, PLAYER_TOPFRAME)
@ -393,13 +527,255 @@ TFPlayer::EvaluateEntity(void)
EVALUATE_FIELD(anim_bottom, PLAYER_BOTTOMFRAME)
EVALUATE_FIELD(anim_bottom_time, PLAYER_BOTTOMFRAME)
EVALUATE_FIELD(classtype, PLAYER_AMMOTYPES)
EVALUATE_FIELD(m_flIdleScale, PLAYER_AMMOTYPES)
EVALUATE_FIELD(m_flHallucination, PLAYER_AMMOTYPES)
EVALUATE_FIELD(mag_sbs, PLAYER_AMMO1)
EVALUATE_FIELD(mag_dbs, PLAYER_AMMO1)
EVALUATE_FIELD(mag_rpg, PLAYER_AMMO1)
EVALUATE_FIELD(mag_glauncher, PLAYER_AMMO1)
EVALUATE_FIELD(m_iAmmoRockets, PLAYER_AMMO2)
EVALUATE_FIELD(m_iAmmoNails, PLAYER_AMMO2)
EVALUATE_FIELD(m_iAmmoCells, PLAYER_AMMO2)
EVALUATE_FIELD(m_iAmmoShells, PLAYER_AMMO2)
EVALUATE_FIELD(m_iAmmoDetpack, PLAYER_AMMO2)
EVALUATE_FIELD(m_iAmmoMedikit, PLAYER_AMMO2)
EVALUATE_FIELD(mode_tempstate, PLAYER_AMMO3)
EVALUATE_FIELD(classtype, PLAYER_AMMO3)
EVALUATE_FIELD(m_flIdleScale, PLAYER_AMMO3)
EVALUATE_FIELD(m_flHallucination, PLAYER_AMMO3)
}
void
player::SpawnIntoGame(void)
{
entity spot = world;
/* spawn into the world */
switch (team) {
case 1:
spot = Spawn_SelectRandom("info_teamspawn_blue");
break;
case 2:
spot = Spawn_SelectRandom("info_teamspawn_red");
break;
case 3:
spot = Spawn_SelectRandom("info_teamspawn_yellow");
break;
case 4:
spot = Spawn_SelectRandom("info_teamspawn_green");
break;
}
setorigin(this, spot.origin);
angles = spot.angles;
fixangle = TRUE;
}
void
player::MakeClass(classtype_e class)
{
health = self.max_health = 100;
takedamage = DAMAGE_YES;
solid = SOLID_SLIDEBOX;
movetype = MOVETYPE_WALK;
flags = FL_CLIENT;
viewzoom = 1.0;
/* select our class model */
model = TFC_GetModelForClasstype(classtype);
setmodel(this, model);
setsize(this, VEC_HULL_MIN, VEC_HULL_MAX);
velocity = [0,0,0];
gravity = __NULL__;
armor = activeweapon = g_items = 0;
iBleeds = TRUE;
forceinfokey(this, "*spec", "0");
forceinfokey(this, "*team", ftos(team));
switch (classtype) {
case CLASS_SCOUT:
Weapons_AddItem(this, WEAPON_CROWBAR, -1);
Weapons_AddItem(this, WEAPON_SBS, -1);
Weapons_AddItem(this, WEAPON_NAILGUN, -1);
m_iAmmoShells = 17;
m_iAmmoNails = 100;
m_iMaxHealth = 75;
m_iMaxArmor = 50;
health = m_iMaxHealth;
armor = 25;
m_iMaxShells = 50;
m_iMaxNails = 200;
m_iMaxCells = 100;
m_iMaxRockets = 25;
env_message_single(this, "HELP_SCOUT");
break;
case CLASS_SNIPER:
Weapons_AddItem(this, WEAPON_CROWBAR, -1);
Weapons_AddItem(this, WEAPON_SNIPER, -1);
Weapons_AddItem(this, WEAPON_AUTORIFLE, -1);
Weapons_AddItem(this, WEAPON_NAILGUN, -1);
m_iAmmoShells = 60; /* sniper rifles use shells */
m_iAmmoNails = 50;
m_iMaxHealth = 90;
m_iMaxArmor = 50;
health = m_iMaxHealth;
armor = 0;
m_iMaxShells = 75;
m_iMaxNails = 100;
m_iMaxCells = 50;
m_iMaxRockets = 25;
env_message_single(this, "HELP_SNIPER");
break;
case CLASS_SOLDIER:
Weapons_AddItem(this, WEAPON_CROWBAR, -1);
Weapons_AddItem(this, WEAPON_SBS, -1);
Weapons_AddItem(this, WEAPON_DBS, -1);
Weapons_AddItem(this, WEAPON_RPG, -1);
m_iAmmoShells = 26;
m_iAmmoRockets = 6;
m_iMaxHealth = 100;
m_iMaxArmor = 200;
health = m_iMaxHealth;
armor = 100;
m_iMaxShells = 100;
m_iMaxNails = 100;
m_iMaxCells = 50;
m_iMaxRockets = 50;
env_message_single(this, "HELP_SOLDIER");
break;
case CLASS_DEMO:
Weapons_AddItem(this, WEAPON_CROWBAR, -1);
Weapons_AddItem(this, WEAPON_SBS, -1);
Weapons_AddItem(this, WEAPON_GLAUNCHER, -1);
Weapons_AddItem(this, WEAPON_PIPEBOMB, -1);
m_iAmmoShells = 22;
m_iAmmoRockets = 14;
m_iMaxHealth = 90;
m_iMaxArmor = 100;
health = m_iMaxHealth;
armor = 50;
m_iMaxShells = 75;
m_iMaxNails = 50;
m_iMaxCells = 50;
m_iMaxRockets = 50;
env_message_single(this, "HELP_DEMOMAN");
break;
case CLASS_MEDIC:
Weapons_AddItem(this, WEAPON_MEDKIT, -1);
Weapons_AddItem(this, WEAPON_SBS, -1);
Weapons_AddItem(this, WEAPON_DBS, -1);
Weapons_AddItem(this, WEAPON_SUPERNAIL, -1);
m_iAmmoShells = 26;
m_iAmmoNails = 50;
m_iMaxHealth = 90;
m_iMaxArmor = 100;
health = m_iMaxHealth;
armor = 50;
m_iMaxShells = 75;
m_iMaxNails = 150;
m_iMaxCells = 50;
m_iMaxRockets = 25;
env_message_single(this, "HELP_MEDIC");
break;
case CLASS_HVYWEAPON:
Weapons_AddItem(this, WEAPON_CROWBAR, -1);
Weapons_AddItem(this, WEAPON_SBS, -1);
Weapons_AddItem(this, WEAPON_DBS, -1);
Weapons_AddItem(this, WEAPON_ASSCAN, -1);
m_iAmmoShells = 176; /* all of the heavy's weapons use shells */
m_iMaxHealth = 100;
m_iMaxArmor = 300;
health = m_iMaxHealth;
armor = 150;
m_iMaxShells = 200;
m_iMaxNails = 200;
m_iMaxCells = 50;
m_iMaxRockets = 25;
env_message_single(this, "HELP_HWGUY");
break;
case CLASS_PYRO:
Weapons_AddItem(this, WEAPON_CROWBAR, -1);
Weapons_AddItem(this, WEAPON_SBS, -1);
Weapons_AddItem(this, WEAPON_FLAMER, -1);
Weapons_AddItem(this, WEAPON_INCENDIARY, -1);
m_iAmmoShells = 12;
m_iAmmoCells = 120;
m_iAmmoRockets = 5;
m_iMaxHealth = 100;
m_iMaxArmor = 150;
health = m_iMaxHealth;
armor = 50;
m_iMaxShells = 40;
m_iMaxNails = 50;
m_iMaxCells = 200;
m_iMaxRockets = 60;
env_message_single(this, "HELP_PYRO");
break;
case CLASS_SPY:
Weapons_AddItem(this, WEAPON_KNIFE, -1);
Weapons_AddItem(this, WEAPON_TRANQUIL, -1);
Weapons_AddItem(this, WEAPON_DBS, -1);
Weapons_AddItem(this, WEAPON_NAILGUN, -1);
m_iAmmoShells = 24; /* tranquil and dbs use shells */
m_iAmmoNails = 50;
m_iMaxHealth = 90;
m_iMaxArmor = 100;
health = m_iMaxHealth;
armor = 25;
m_iMaxShells = 40;
m_iMaxNails = 50;
m_iMaxCells = 30;
m_iMaxRockets = 15;
env_message_single(this, "HELP_SPY");
break;
case CLASS_ENGINEER:
Weapons_AddItem(this, WEAPON_WRENCH, -1);
Weapons_AddItem(this, WEAPON_RAILGUN, -1);
Weapons_AddItem(this, WEAPON_DBS, -1);
m_iAmmoCells = 100;
m_iAmmoNails = 25;
m_iAmmoShells = 4;
m_iMaxHealth = 80;
m_iMaxArmor = 50;
health = m_iMaxHealth;
armor = 25;
m_iMaxShells = 50;
m_iMaxNails = 50;
m_iMaxCells = 200;
m_iMaxRockets = 30;
env_message_single(this, "HELP_ENGINEER");
break;
}
g_items |= ITEM_SUIT;
}
/*
=================
player::SendEntity
=================
*/
float
TFPlayer::SendEntity(entity ePEnt, float flChanged)
player::SendEntity(entity ePEnt, float flChanged)
{
/* don't broadcast invisible players */
if (IsFakeSpectator() && ePEnt != this)
@ -409,8 +785,11 @@ TFPlayer::SendEntity(entity ePEnt, float flChanged)
flChanged = OptimiseChangedFlags(ePEnt, flChanged);
WriteByte(MSG_ENTITY, ENT_PLAYER);
WriteFloat(MSG_ENTITY, flChanged);
/* the generic client attributes */
ncPlayer::SendEntity(ePEnt, flChanged);
NSClientPlayer::SendEntity(ePEnt, flChanged);
SENDENTITY_BYTE(anim_top, PLAYER_TOPFRAME)
SENDENTITY_FLOAT(anim_top_time, PLAYER_TOPFRAME)
@ -418,9 +797,22 @@ TFPlayer::SendEntity(entity ePEnt, float flChanged)
SENDENTITY_BYTE(anim_bottom, PLAYER_BOTTOMFRAME)
SENDENTITY_FLOAT(anim_bottom_time, PLAYER_BOTTOMFRAME)
SENDENTITY_BYTE(classtype, PLAYER_AMMOTYPES)
SENDENTITY_FLOAT(m_flIdleScale, PLAYER_AMMOTYPES)
SENDENTITY_FLOAT(m_flHallucination, PLAYER_AMMOTYPES)
SENDENTITY_BYTE(mag_sbs, PLAYER_AMMO1)
SENDENTITY_BYTE(mag_dbs, PLAYER_AMMO1)
SENDENTITY_BYTE(mag_rpg, PLAYER_AMMO1)
SENDENTITY_BYTE(mag_glauncher, PLAYER_AMMO1)
SENDENTITY_BYTE(m_iAmmoRockets, PLAYER_AMMO2)
SENDENTITY_BYTE(m_iAmmoNails, PLAYER_AMMO2)
SENDENTITY_BYTE(m_iAmmoCells, PLAYER_AMMO2)
SENDENTITY_BYTE(m_iAmmoShells, PLAYER_AMMO2)
SENDENTITY_BYTE(m_iAmmoDetpack, PLAYER_AMMO2)
SENDENTITY_BYTE(m_iAmmoMedikit, PLAYER_AMMO2)
SENDENTITY_BYTE(mode_tempstate, PLAYER_AMMO3)
SENDENTITY_BYTE(classtype, PLAYER_AMMO3)
SENDENTITY_FLOAT(m_flIdleScale, PLAYER_AMMO3)
SENDENTITY_FLOAT(m_flHallucination, PLAYER_AMMO3)
return (1);
}

View file

@ -30,7 +30,7 @@
#define PHY_VIEWPOS_CROUCHED [0,0,12]
void
TFPlayer::Physics_Jump(void)
player::Physics_Jump(void)
{
if (waterlevel >= 2) {
if (watertype == CONTENT_WATER) {
@ -49,3 +49,47 @@ TFPlayer::Physics_Jump(void)
}
}
}
float
player::Physics_MaxSpeed(void)
{
float desiredspeed = 300.0f;
/* values courtesy of https://wiki.teamfortress.com/ */
switch (classtype) {
case CLASS_SCOUT:
desiredspeed = 400.0f;
break;
case CLASS_SNIPER:
desiredspeed = 300.0f;
break;
case CLASS_SOLDIER:
desiredspeed = 240.0f;
break;
case CLASS_DEMO:
desiredspeed = 280.0f;
break;
case CLASS_MEDIC:
desiredspeed = 320.0f;
break;
case CLASS_HVYWEAPON:
desiredspeed = 228.0f;
break;
case CLASS_PYRO:
desiredspeed = 300.0f;
break;
case CLASS_SPY:
desiredspeed = 300.0f;
break;
case CLASS_ENGINEER:
desiredspeed = 300.0f;
break;
default:
desiredspeed = 300.0f;
}
if (GetFlags() & FL_CROUCHING)
desiredspeed /= 3;
return desiredspeed;
}

296
src/shared/w_asscan.qc Normal file
View file

@ -0,0 +1,296 @@
/*
* Copyright (c) 2016-2021 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Animations */
enum
{
ASSCAN_IDLE1,
ASSCAN_IDLE2,
ASSCAN_SPINUP,
ASSCAN_SPINDOWN,
ASSCAN_FIRE,
ASSCAN_DRAW,
ASSCAN_HOLSTER
};
#ifdef CLIENT
void w_asscan_ejectshell(void)
{
static void w_asscan_ejectshell_death(void) {
remove(self);
}
static void w_asscan_ejectshell_touch(void) {
if (other == world)
Sound_Play(self, CHAN_BODY, "modelevent_shell.land");
}
entity eShell = spawn();
setmodel(eShell, "models/shell.mdl");
eShell.solid = SOLID_BBOX;
eShell.movetype = MOVETYPE_BOUNCE;
eShell.drawmask = MASK_ENGINE;
eShell.angles = [pSeat->m_eViewModel.angles[0], pSeat->m_eViewModel.angles[1], 0];
eShell.velocity = pSeat->m_vecPredictedVelocity;
makevectors(pSeat->m_eViewModel.angles);
eShell.velocity += (v_forward * 0);
eShell.velocity += (v_right * -80);
eShell.velocity += (v_up * 100);
eShell.touch = w_asscan_ejectshell_touch;
eShell.avelocity = [0,45,900];
eShell.think = w_asscan_ejectshell_death;
eShell.nextthink = time + 2.5f;
setsize(eShell, [0,0,0], [0,0,0]);
setorigin(eShell, pSeat->m_eViewModel.origin + (v_forward * 26) + (v_up * -15));
}
#endif
void
w_asscan_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_asscan.fire");
Sound_Precache("weapon_asscan.reload");
Sound_Precache("weapon_asscan.spindown");
Sound_Precache("weapon_asscan.spinup");
precache_model("models/w_tfac.mdl");
precache_model("models/p_tfac.mdl");
#endif
#ifdef CLIENT
precache_model("models/v_tfac.mdl");
Sound_Precache("modelevent_shell.land");
#endif
}
int
w_asscan_pickup(player pl, int new, int startammo)
{
return (1);
}
void
w_asscan_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, -1, pl.m_iAmmoShells, -1);
}
string
w_asscan_wmodel(void)
{
return "models/w_tfac.mdl";
}
string
w_asscan_pmodel(player pl)
{
return "models/p_mini2.mdl";
}
string
w_asscan_deathmsg(void)
{
return "%s was rolled over by %s' Chaingun.";
}
void
w_asscan_draw(player pl)
{
pl.mode_tempstate = 0;
Weapons_SetModel("models/v_tfac.mdl");
Weapons_ViewAnimation(pl, ASSCAN_DRAW);
}
void
w_asscan_holster(player pl)
{
Weapons_ViewAnimation(pl, ASSCAN_HOLSTER);
}
void
w_asscan_release(player pl)
{
/* end firing */
if (pl.mode_tempstate == 1) {
pl.mode_tempstate = 0;
Weapons_Sound(pl, CHAN_WEAPON, "weapon_asscan.spindown");
Weapons_ViewAnimation(pl, ASSCAN_SPINDOWN);
pl.w_attack_next = 1.0f;
pl.w_idle_next = 4.0f;
return;
}
if (pl.w_idle_next > 0.0)
return;
int r = (float)input_sequence % 2;
if (r) {
Weapons_ViewAnimation(pl, ASSCAN_IDLE1);
} else {
Weapons_ViewAnimation(pl, ASSCAN_IDLE2);
}
pl.w_idle_next = 15.0f;
}
void
w_asscan_primary(player pl)
{
/* rate check */
if (pl.w_attack_next > 0.0)
return;
/* ammo check */
if (pl.m_iAmmoShells <= 0) {
w_asscan_release(pl);
return;
}
/* spin up first */
if (pl.mode_tempstate == 0) {
pl.mode_tempstate = 1;
Weapons_ViewAnimation(pl, ASSCAN_SPINUP);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_asscan.spinup");
pl.w_attack_next = 0.5f;
pl.w_idle_next = pl.w_attack_next;
return;
}
/* from now on we're just going rambo */
pl.m_iAmmoShells--;
Weapons_ViewAnimation(pl, ASSCAN_FIRE);
Weapons_ViewPunchAngle(pl, [random(-2, 2),0,0]);
Weapons_Sound(pl, CHAN_WEAPON, "weapon_asscan.fire");
if (pl.flags & FL_CROUCHING)
Animation_PlayerTop(pl, TFCANIM_CR_SHOOTASSCAN, 0.1f);
else
Animation_PlayerTop(pl, TFCANIM_SHOOTASSCAN, 0.1f);
#ifdef CLIENT
View_AddEvent(w_asscan_ejectshell, 0.0f);
View_SetMuzzleflash(MUZZLE_WEIRD);
#else
TraceAttack_FireBullets(1, Weapons_GetCameraPos(pl), 8, [0.15,0.15], WEAPON_ASSCAN);
#endif
pl.w_attack_next = 0.1f;
pl.w_idle_next = 0.0f;
}
void
w_asscan_hud(player pl)
{
#ifdef CLIENT
vector aicon_pos;
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
Cross_DrawSub(g_cross_spr, [24,24], [48/128,24/128], [0.1875, 0.1875]);
HUD_DrawAmmo2();
drawsubpic(aicon_pos, [24,24], g_hud7_spr, [72/256,72/128], [24/256, 24/128], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
float
w_asscan_aimanim(player pl)
{
return pl.flags & FL_CROUCHING ? TFCANIM_CR_AIMASSCAN : TFCANIM_AIMASSCAN;
}
void
w_asscan_hudpic(player pl, int selected, vector pos, float a)
{
#ifdef CLIENT
vector hud_col;
if (pl.m_iAmmoShells == 0)
hud_col = [1,0,0];
else
hud_col = g_hud_color;
HUD_DrawAmmoBar(pos, pl.m_iAmmoShells, 200, a);
if (selected) {
drawsubpic(
pos,
[170,45],
g_tfchud4_spr,
[0,90/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
g_tfchud3_spr,
[0,45/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
int
w_asscan_isempty(player pl)
{
if (pl.m_iAmmoShells <= 0)
return 1;
return 0;
}
weapontype_t
w_asscan_type(player pl)
{
return WPNTYPE_RANGED;
}
weapon_t w_asscan =
{
.name = "asscan",
.id = ITEM_ASSCAN,
.slot = 3,
.slot_pos = 3,
.weight = WEIGHT_ASSCAN,
.draw = w_asscan_draw,
.holster = w_asscan_holster,
.primary = w_asscan_primary,
.secondary = w_asscan_release,
.reload = __NULL__,
.release = w_asscan_release,
.postdraw = w_asscan_hud,
.precache = w_asscan_precache,
.pickup = w_asscan_pickup,
.updateammo = w_asscan_updateammo,
.wmodel = w_asscan_wmodel,
.pmodel = w_asscan_pmodel,
.deathmsg = w_asscan_deathmsg,
.aimanim = w_asscan_aimanim,
.isempty = w_asscan_isempty,
.type = w_asscan_type,
.hudpic = w_asscan_hudpic
};

Some files were not shown because too many files have changed in this diff Show more