#include "utils" #include "WeaponCustomBase" #include "monster_custom" void WeaponCustomMapInit() { WeaponCustom::WeaponCustomMapInit_internal(); } void WeaponCustomMapActivate() { WeaponCustom::WeaponCustomMapActivate_internal(); } namespace WeaponCustom { void WeaponCustomMapInit_internal() { g_Game.PrecacheModel( g_watersplash_spr ); // used for water splash effect g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom", "weapon_custom" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom_ammo", "weapon_custom_ammo" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom_shoot", "weapon_custom_shoot" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom_bullet", "weapon_custom_bullet" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom_melee", "weapon_custom_melee" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom_projectile", "weapon_custom_projectile" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom_beam", "weapon_custom_beam" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom_sound", "weapon_custom_sound" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom_effect", "weapon_custom_effect" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::weapon_custom_user_effect", "weapon_custom_user_effect" ); g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::WeaponCustomProjectile", "custom_projectile" ); } void WeaponCustomMapActivate_internal() { g_map_activated = true; // Hook up weapon_custom with weapon_custom_shoot array@ keys = custom_weapons.getKeys(); for (uint i = 0; i < keys.length(); i++) { weapon_custom@ wep = cast( custom_weapons[keys[i]] ); wep.link_shoot_settings(); } // Hook up ambient_generic with weapon_custom_shoot array@ keys2 = custom_weapon_shoots.getKeys(); for (uint i = 0; i < keys2.length(); i++) { weapon_custom_shoot@ shoot = cast( custom_weapon_shoots[keys2[i]] ); shoot.loadExternalSoundSettings(); shoot.loadExternalEffectSettings(); } } bool g_map_activated = false; string g_watersplash_spr = "sprites/wep_smoke_01.spr"; // WeaponCustomBase will read this to get weapon_custom settings // Also let's us know which weapon slots are used (Auto weapon slot position depends on this) dictionary custom_weapons; dictionary custom_ammos; dictionary custom_weapon_shoots; dictionary custom_weapon_effects; int MAX_BEAMS = 256; // any more and you get console spam and game freezes (acutal max is 258 or 259 I think) int REC_BEAMS = 8; // 8 * 32 players = 256 int MAX_WEAPON_SLOT_POSITION = 10; int MIN_WEAPON_SLOT_POSITION = 5; int MAX_WEAPON_SLOT = 5; int REC_BULLETS_PER_SECOND = 32; // max recommended bullets per second (shotgun has most BPS) bool debug_mode = false; // weapon spawn flags int FL_WEP_SELECTONEMPTY = 1; int FL_WEP_NOAUTORELOAD = 2; int FL_WEP_NOAUTOSWITCHEMPTY = 4; int FL_WEP_LIMITINWORLD = 8; int FL_WEP_EXHAUSTIBLE = 16; int FL_WEP_HIDE_SECONDARY_AMMO = 32; int FL_WEP_LASER_SIGHT = 64; int FL_WEP_NO_JUMP = 128; int FL_WEP_WAIT_FOR_PROJECTILES = 256; int FL_WEP_EXCLUSIVE_HOLD = 512; // mapper-placed weapon spawn flags int FL_DISABLE_RESPAWN = 1024; int FL_USE_ONLY = 256; // shoot spawn flags int FL_SHOOT_IF_NOT_DAMAGE = 1; int FL_SHOOT_IF_NOT_MISS = 2; int FL_SHOOT_NO_MELEE_SOUND_OVERLAP = 4; int FL_SHOOT_RESPONSIVE_WINDUP = 8; int FL_SHOOT_PARTIAL_AMMO_SHOOT = 16; int FL_SHOOT_QUAKE_MUZZLEFLASH = 32; int FL_SHOOT_NO_AUTOFIRE = 64; int FL_SHOOT_PROJ_NO_ORIENT = 128; int FL_SHOOT_IN_WATER = 256; int FL_SHOOT_NO_BUBBLES = 512; int FL_SHOOT_DETONATE_SATCHELS = 1024; // shoot effect flags int FL_EFFECT_EXPLOSION = 1; int FL_EFFECT_RICOCHET = 2; int FL_EFFECT_SPARKS = 4; int FL_EFFECT_LIGHTS = 8; int FL_EFFECT_BUBBLES_IN_AIR = 16; int FL_EFFECT_GUNSHOT_RICOCHET = 32; int FL_EFFECT_TARBABY = 64; int FL_EFFECT_TARBABY2 = 128; int FL_EFFECT_BURST = 256; int FL_EFFECT_LAVA = 512; int FL_EFFECT_TELEPORT = 1024; // User effect flags int FL_UEFFECT_USER_SOUNDS = 1; int FL_UEFFECT_KILL_ACTIVE = 2; // shoot sound flags int FL_SOUND_NO_WATER_EFFECT = 1; float REVIVE_RADIUS = 64; enum shoot_types { SHOOT_BULLETS, SHOOT_MELEE, SHOOT_PROJECTILE, SHOOT_BEAM } enum tertiary_ammo_types { TAMMO_NONE, TAMMO_SAME_AS_PRIMARY, TAMMO_SAME_AS_SECONDARY } enum spread_func { SPREAD_GAUSSIAN, SPREAD_UNIFORM, } enum fire_mode { PRIMARY, SECONDARY, TERTIARY } enum projectile_action { PROJ_ACT_IMPACT=1, PROJ_ACT_BOUNCE, PROJ_ACT_ATTACH } enum projectile_type { PROJECTILE_ARGRENADE=1, PROJECTILE_BANANA, PROJECTILE_BOLT, PROJECTILE_DISPLACER, PROJECTILE_GRENADE, PROJECTILE_HORNET, PROJECTILE_HVR, PROJECTILE_MORTAR, PROJECTILE_RPG, PROJECTILE_SHOCK, PROJECTILE_WEAPON, PROJECTILE_TRIPMINE, PROJECTILE_CUSTOM, PROJECTILE_OTHER } enum beam_type { BEAM_DISABLED = -1, BEAM_LINEAR, BEAM_SPIRAL, BEAM_LINEAR_OPAQUE, BEAM_SPIRAL_OPAQUE, BEAM_PROJECTILE } enum user_beam_modes { UBEAM_DISABLED, UBEAM_ATTACH_ATTACH, UBEAM_ATTACH_POINT, UBEAM_POINT_POINT, } enum explosion_types { EXPLODE_SPRITE, EXPLODE_SPRITE_PARTICLES, EXPLODE_DISK, EXPLODE_CYLINDER, EXPLODE_TORUS } enum windup_ease { EASE_NONE, EASE_IN, EASE_OUT, EASE_INOUT, EASE_IN_HEAVY, EASE_OUT_HEAVY, EASE_INOUT_HEAVY } enum windup_actions { WINDUP_SHOOT_ON_RELEASE, WINDUP_SHOOT_ONCE, WINDUP_SHOOT_CONSTANT, WINDUP_SHOOT_ONCE_IF_HELD, } enum player_anim_refs { ANIM_REF_CROWBAR, // also includes wrench for windups ANIM_REF_GREN, ANIM_REF_TRIP, ANIM_REF_ONEHANDED, ANIM_REF_PYTHON, // One Hnaded with more recoil ANIM_REF_SHOTGUN, ANIM_REF_GAUSS, ANIM_REF_MP5, ANIM_REF_RPG, ANIM_REF_EGON, ANIM_REF_SQUEAK, ANIM_REF_HIVE, ANIM_REF_BOW, // also includes scope animations ANIM_REF_MINIGUN, ANIM_REF_UZIS, ANIM_REF_M16, // also includes grenade launch anim (m203) ANIM_REF_SNIPER, // also includes scope animations ANIM_REF_SAW, } enum heal_modes { HEAL_OFF, HEAL_FRIENDS, HEAL_FOES, HEAL_ALL, HEAL_REVIVE_FRIENDS, HEAL_REVIVE_FOES, HEAL_REVIVE_ALL, } enum hook_types { HOOK_DISABLED, HOOK_PROJECTILE, HOOK_INSTANT } enum hook_modes { HOOK_MODE_PULL, HOOK_MODE_PULL_LEAST_WEIGHT, HOOK_MODE_REPEL, HOOK_MODE_SWING, } enum hook_targets { HOOK_EVERYTHING, HOOK_WORLD_ONLY, HOOK_MONSTERS_ONLY, } enum heal_targets { HEALT_HUMANS, HEALT_ALIENS, HEALT_MACHINES, HEALT_BREAKABLES, HEALT_MACHINES_AND_BREAKABLES, HEALT_HUMANS_AND_ALIENS, HEALT_EVERYTHING, } enum shell_types { SHELL_NONE, SHELL_SMALL, SHELL_LARGE, SHELL_SHOTGUN, } enum fire_actions { FIRE_ACT_SHOOT, FIRE_ACT_LASER, FIRE_ACT_ZOOM, FIRE_ACT_ALT, FIRE_ACT_WINDUP } enum overcharge_actions { OVERCHARGE_CONTINUE, OVERCHARGE_CANCEL, OVERCHARGE_SHOOT } enum primary_fire_modes { PRIMARY_NO_CHANGE, PRIMARY_FIRE, PRIMARY_ALT_FIRE, PRIMARY_TOGGLE } enum projectile_follow_modes { FOLLOW_NONE, FOLLOW_CROSSHAIRS, FOLLOW_ENEMIES, } enum reload_modes { RELOAD_SIMPLE, RELOAD_STAGED, RELOAD_STAGED_RESPONSIVE, RELOAD_EFFECT_CHAIN } array g_panim_refs = { "crowbar", "gren", "trip", "onehanded", "python", "shotgun", "gauss", "mp5", "rpg", "egon", "squeak", "hive", "bow", "minigun", "uzis", "m16", "sniper", "saw" }; array g_ammo_types = { "buckshot", "health", "556", "m40a1", "argrenades", "357", "9mm", "shock charges", "sporeclip", "uranium", "rockets", "bolts", "trip mine", "satchel charge", "hand grenade", "snarks", "hornets" }; enum beam_alt_modes { BEAM_ALT_DISABLED, BEAM_ALT_TOGGLE, BEAM_ALT_LINEAR, BEAM_ALT_LINEAR_TOGGLE, BEAM_ALT_EASE, BEAM_ALT_RANDOM } class BeamOptions { int type; int width; int noise; int scrollRate; float time; string sprite; Color color; Color alt_color; int alt_width; int alt_noise; int alt_scrollRate; int alt_mode; float alt_time; } class ProjectileOptions { int type = PROJECTILE_CUSTOM; int world_event = PROJ_ACT_ATTACH; int monster_event = PROJ_ACT_ATTACH; float speed = 0; float life = 0; float elasticity = 0.8; // percentage of reflected velocity float gravity = 0.0; // percentage of normal gravity float air_friction = 0; float water_friction = 0; float size = 0.001; // hull size (all dimensions) Vector dir = Vector(0,0,1); string entity_class; // custom projectile entity string model; WeaponSound move_snd; string sprite; Color sprite_color; float sprite_scale; Vector angles; Vector avel; Vector offset; Vector player_vel_inf; int follow_mode = FOLLOW_NONE; float follow_radius = 0.0f; float follow_angle = 30.0f; Vector follow_time; string trail_spr; int trail_sprId = 2; // remove me int trail_life; int trail_width; Color trail_color; float trail_effect_freq; float bounce_effect_delay; }; class AmmoDrop { string cname; int dropAmt = 0; } class weapon_custom_bullet : weapon_custom_shoot { void Spawn() { weapon_custom_shoot::Spawn(); shoot_type = SHOOT_BULLETS; } }; class weapon_custom_melee : weapon_custom_shoot { void Spawn() { weapon_custom_shoot::Spawn(); shoot_type = SHOOT_MELEE; } }; class weapon_custom_projectile : weapon_custom_shoot { void Spawn() { weapon_custom_shoot::Spawn(); shoot_type = SHOOT_PROJECTILE; } }; class weapon_custom_beam : weapon_custom_shoot { void Spawn() { weapon_custom_shoot::Spawn(); shoot_type = SHOOT_BEAM; } }; class weapon_custom_shoot : ScriptBaseEntity { weapon_custom@ weapon; int shoot_type; array sounds; // shoot sounds array shoot_anims; // shoot or melee swing array melee_anims; // melee hit anims array melee_hit_sounds; array melee_flesh_sounds; array shoot_fail_snds; WeaponSound shoot_empty_snd; int shoot_empty_anim; int ammo_cost; float cooldown = 0.5; float cooldown_fail = 0.5; Vector recoil; Vector kickback; Vector knockback; float max_range; int heal_mode; int heal_targets; float damage; int damage_type; int damage_type2; int gib_type; bool friendly_fire; int bullets; int bullet_type; // see docs for "Bullet" int bullet_color = -1; int bullet_spread_func; int bullet_decal; float bullet_spread; float bullet_delay; // burst fire delay float melee_miss_cooldown; ProjectileOptions@ projectile = ProjectileOptions(); float beam_impact_speed; string beam_impact_spr; float beam_impact_spr_scale; int beam_impact_spr_fps; Color beam_impact_spr_color; int beam_ricochet_limit; // maximum number of ricochets float beam_ammo_cooldown; weapon_custom_effect@ effect1 = weapon_custom_effect(); weapon_custom_effect@ effect2 = weapon_custom_effect(); weapon_custom_effect@ effect3 = weapon_custom_effect(); weapon_custom_effect@ effect4 = weapon_custom_effect(); weapon_custom_user_effect@ user_effect1; // shoot weapon_custom_user_effect@ user_effect2; // overcharge weapon_custom_user_effect@ user_effect3; // cooldown weapon_custom_user_effect@ user_effect4; // windup weapon_custom_user_effect@ user_effect5; // toggle to weapon_custom_user_effect@ user_effect6; // victim effect (monster attacking player) string user_effect1_str; string user_effect2_str; string user_effect3_str; string user_effect4_str; string user_effect5_str; string user_effect6_str; float rico_angle; Vector muzzle_flash_color; Vector muzzle_flash_adv; float toggle_cooldown; float windup_time; float windup_min_time; float wind_down_time; float wind_down_cancel_time; float windup_mult; float windup_kick_mult; float windup_anim_time; WeaponSound windup_snd; WeaponSound wind_down_snd; WeaponSound windup_loop_snd; int windup_pitch_start; int windup_pitch_end; int windup_easing; int windup_action; int windup_cost; int windup_anim; int wind_down_anim; int windup_anim_loop; float windup_overcharge_time; float windup_overcharge_cooldown; float windup_movespeed; float windup_shoot_movespeed; int windup_overcharge_action; int windup_overcharge_anim; int hook_type; int hook_pull_mode; int hook_targets; int hook_anim; int hook_anim2; float hook_force; float hook_speed; float hook_max_speed; float hook_delay; float hook_delay2; string hook_texture_filter; WeaponSound hook_snd; WeaponSound hook_snd2; int shell_type = 0; string shell_model; Vector shell_offset; Vector shell_vel; float shell_delay; WeaponSound shell_delay_snd; float shell_spread; int shell_idx; array beams = {BeamOptions(), BeamOptions()}; bool KeyValue( const string& in szKey, const string& in szValue ) { if (szKey == "sounds") sounds = parseSounds(szValue); else if (szKey == "shoot_fail_snds") shoot_fail_snds = parseSounds(szValue); else if (szKey == "shoot_anims") shoot_anims = szValue.Split(";"); else if (szKey == "shoot_empty_snd") shoot_empty_snd.file = szValue; else if (szKey == "shoot_empty_anim") shoot_empty_anim = atoi(szValue); else if (szKey == "ammo_cost") ammo_cost = atoi(szValue); //else if (szKey == "shoot_type") shoot_type = atoi(szValue); else if (szKey == "cooldown") cooldown = atof(szValue); else if (szKey == "cooldown_fail") cooldown_fail = atof(szValue); else if (szKey == "recoil") recoil = parseVector(szValue); else if (szKey == "kickback") kickback = parseVector(szValue); else if (szKey == "knockback") knockback = parseVector(szValue); else if (szKey == "max_range") max_range = atof(szValue); else if (szKey == "heal_mode") heal_mode = atoi(szValue); else if (szKey == "heal_targets") heal_targets = atoi(szValue); else if (szKey == "damage_amt") damage = atof(szValue); else if (szKey == "damage_type") damage_type = atoi(szValue); else if (szKey == "damage_type2") damage_type2 = atoi(szValue); else if (szKey == "gib_type") gib_type = atoi(szValue); else if (szKey == "friendly_fire") friendly_fire = atoi(szValue) == 1; else if (szKey == "shell_type") {shell_type = atoi(szValue); update_shell_type();} else if (szKey == "shell_model") shell_model = szValue; else if (szKey == "shell_offset") shell_offset = parseVector(szValue); else if (szKey == "shell_vel") shell_vel = parseVector(szValue); else if (szKey == "shell_spread") shell_spread = atof(szValue); else if (szKey == "shell_delay") shell_delay = atof(szValue); else if (szKey == "shell_delay_snd") shell_delay_snd.file = szValue; else if (szKey == "bullets") bullets = atoi(szValue); else if (szKey == "bullet_type") bullet_type = atoi(szValue); else if (szKey == "bullet_spread") bullet_spread = atof(szValue); else if (szKey == "bullet_delay") bullet_delay = atof(szValue); else if (szKey == "bullet_color") bullet_color = atoi(szValue); else if (szKey == "bullet_spread_func") bullet_spread_func = atoi(szValue); else if (szKey == "bullet_decal") bullet_decal = atoi(szValue); else if (szKey == "melee_anims") melee_anims = szValue.Split(";"); else if (szKey == "melee_hit_sounds") melee_hit_sounds = parseSounds(szValue); else if (szKey == "melee_flesh_sounds") melee_flesh_sounds = parseSounds(szValue); else if (szKey == "melee_miss_cooldown") melee_miss_cooldown = atof(szValue); else if (szKey == "hook_type") hook_type = atoi(szValue); else if (szKey == "hook_targets") hook_targets = atoi(szValue); else if (szKey == "hook_pull_mode") hook_pull_mode = atoi(szValue); else if (szKey == "hook_anim") hook_anim = atoi(szValue); else if (szKey == "hook_anim2") hook_anim2 = atoi(szValue); else if (szKey == "hook_force") hook_force = atof(szValue); else if (szKey == "hook_speed") hook_speed = atof(szValue); else if (szKey == "hook_max_speed") hook_max_speed = atof(szValue); else if (szKey == "hook_delay") hook_delay = atof(szValue); else if (szKey == "hook_delay2") hook_delay2 = atof(szValue); else if (szKey == "hook_texture_filter") hook_texture_filter = szValue; else if (szKey == "hook_sound") hook_snd.file = szValue; else if (szKey == "hook_sound2") hook_snd2.file = szValue; else if (szKey == "projectile_type") projectile.type = atoi(szValue); else if (szKey == "projectile_world_event") projectile.world_event = atoi(szValue); else if (szKey == "projectile_monster_event") projectile.monster_event = atoi(szValue); else if (szKey == "projectile_speed") projectile.speed = atof(szValue); else if (szKey == "projectile_life") projectile.life = atof(szValue); else if (szKey == "projectile_bounce") projectile.elasticity = atof(szValue); else if (szKey == "projectile_grav") projectile.gravity = atof(szValue); else if (szKey == "projectile_water_friction") projectile.water_friction = atof(szValue); else if (szKey == "projectile_air_friction") projectile.air_friction = atof(szValue); else if (szKey == "projectile_class") projectile.entity_class = szValue; else if (szKey == "projectile_mdl") projectile.model = szValue; else if (szKey == "projectile_snd") projectile.move_snd.file = szValue; else if (szKey == "projectile_spr") projectile.sprite = szValue; else if (szKey == "projectile_spr_color") projectile.sprite_color = parseColor(szValue); else if (szKey == "projectile_spr_scale") projectile.sprite_scale = atof(szValue); else if (szKey == "projectile_size") projectile.size = atof(szValue); else if (szKey == "projectile_trail_spr") projectile.trail_spr = szValue; else if (szKey == "projectile_trail_life") projectile.trail_life = atoi(szValue); else if (szKey == "projectile_trail_width") projectile.trail_width = atoi(szValue); else if (szKey == "projectile_trail_color") projectile.trail_color = parseColor(szValue); else if (szKey == "projectile_angles") projectile.angles = parseVector(szValue); else if (szKey == "projectile_avel") projectile.avel = parseVector(szValue); else if (szKey == "projectile_offset") projectile.offset = parseVector(szValue); else if (szKey == "projectile_player_vel_inf")projectile.player_vel_inf = parseVector(szValue); else if (szKey == "projectile_follow_mode") projectile.follow_mode = atoi(szValue); else if (szKey == "projectile_follow_radius") projectile.follow_radius = atof(szValue); else if (szKey == "projectile_follow_angle") projectile.follow_angle = atof(szValue); else if (szKey == "projectile_follow_time") projectile.follow_time = parseVector(szValue); else if (szKey == "projectile_trail_effect_freq") projectile.trail_effect_freq = atof(szValue); else if (szKey == "projectile_dir") projectile.dir = parseVector(szValue); else if (szKey == "bounce_effect_delay") projectile.bounce_effect_delay = atof(szValue); else if (szKey == "beam_impact_speed") beam_impact_speed = atof(szValue); else if (szKey == "beam_impact_spr") beam_impact_spr = szValue; else if (szKey == "beam_impact_spr_scale") beam_impact_spr_scale = atof(szValue); else if (szKey == "beam_impact_spr_fps") beam_impact_spr_fps = atoi(szValue); else if (szKey == "beam_impact_spr_color") beam_impact_spr_color = parseColor(szValue); else if (szKey == "beam_ricochet_limit") beam_ricochet_limit = atoi(szValue); else if (szKey == "beam_ammo_cooldown") beam_ammo_cooldown = atof(szValue); else if (szKey == "beam1_type") beams[0].type = atoi(szValue); else if (szKey == "beam1_time") beams[0].time = atof(szValue); else if (szKey == "beam1_spr") beams[0].sprite = szValue; else if (szKey == "beam1_color") beams[0].color = parseColor(szValue); else if (szKey == "beam1_width") beams[0].width = atoi(szValue); else if (szKey == "beam1_noise") beams[0].noise = atoi(szValue); else if (szKey == "beam1_scroll") beams[0].scrollRate = atoi(szValue); else if (szKey == "beam1_alt_color") beams[0].alt_color = parseColor(szValue); else if (szKey == "beam1_alt_width") beams[0].alt_width = atoi(szValue); else if (szKey == "beam1_alt_noise") beams[0].alt_noise = atoi(szValue); else if (szKey == "beam1_alt_scroll") beams[0].alt_scrollRate = atoi(szValue); else if (szKey == "beam1_alt_mode") beams[0].alt_mode = atoi(szValue); else if (szKey == "beam1_alt_time") beams[0].alt_time = atof(szValue); else if (szKey == "beam2_type") beams[1].type = atoi(szValue); else if (szKey == "beam2_time") beams[1].time = atof(szValue); else if (szKey == "beam2_spr") beams[1].sprite = szValue; else if (szKey == "beam2_color") beams[1].color = parseColor(szValue); else if (szKey == "beam2_width") beams[1].width = atoi(szValue); else if (szKey == "beam2_noise") beams[1].noise = atoi(szValue); else if (szKey == "beam2_scroll") beams[1].scrollRate = atoi(szValue); else if (szKey == "beam2_alt_color") beams[1].alt_color = parseColor(szValue); else if (szKey == "beam2_alt_width") beams[1].alt_width = atoi(szValue); else if (szKey == "beam2_alt_noise") beams[1].alt_noise = atoi(szValue); else if (szKey == "beam2_alt_scroll") beams[1].alt_scrollRate = atoi(szValue); else if (szKey == "beam2_alt_mode") beams[1].alt_mode = atoi(szValue); else if (szKey == "beam2_alt_time") beams[1].alt_time = atof(szValue); else if (szKey == "effect1_name") effect1.name = szValue; else if (szKey == "effect2_name") effect2.name = szValue; else if (szKey == "effect3_name") effect3.name = szValue; else if (szKey == "effect4_name") effect4.name = szValue; else if (szKey == "user_effect1") user_effect1_str = szValue; else if (szKey == "user_effect2") user_effect2_str = szValue; else if (szKey == "user_effect3") user_effect3_str = szValue; else if (szKey == "user_effect4") user_effect4_str = szValue; else if (szKey == "user_effect5") user_effect5_str = szValue; else if (szKey == "user_effect6") user_effect6_str = szValue; else if (szKey == "rico_angle") rico_angle = atof(szValue); else if (szKey == "muzzle_flash_color") muzzle_flash_color = parseVector(szValue); else if (szKey == "muzzle_flash_adv") muzzle_flash_adv = parseVector(szValue); else if (szKey == "toggle_cooldown") toggle_cooldown = atof(szValue); else if (szKey == "windup_time") windup_time = atof(szValue); else if (szKey == "windup_min_time") windup_min_time = atof(szValue); else if (szKey == "wind_down_time") wind_down_time = atof(szValue); else if (szKey == "wind_down_cancel_time") wind_down_cancel_time = atof(szValue); else if (szKey == "windup_mult") windup_mult = atof(szValue); else if (szKey == "windup_kick_mult") windup_kick_mult = atof(szValue); else if (szKey == "windup_snd") windup_snd.file = szValue; else if (szKey == "windup_loop_snd") windup_loop_snd.file = szValue; else if (szKey == "wind_down_snd") wind_down_snd.file = szValue; else if (szKey == "windup_pitch_start") windup_pitch_start = atoi(szValue); else if (szKey == "windup_pitch_end") windup_pitch_end = atoi(szValue); else if (szKey == "windup_easing") windup_easing = atoi(szValue); else if (szKey == "windup_action") windup_action = atoi(szValue); else if (szKey == "windup_cost") windup_cost = atoi(szValue); else if (szKey == "windup_anim") windup_anim = atoi(szValue); else if (szKey == "wind_down_anim") wind_down_anim = atoi(szValue); else if (szKey == "windup_anim_time") windup_anim_time = atof(szValue); else if (szKey == "windup_anim_loop") windup_anim_loop = atoi(szValue); else if (szKey == "windup_overcharge_time") windup_overcharge_time = atof(szValue); else if (szKey == "windup_overcharge_cooldown") windup_overcharge_cooldown = atof(szValue); else if (szKey == "windup_overcharge_action") windup_overcharge_action = atoi(szValue); else if (szKey == "windup_overcharge_anim") windup_overcharge_anim = atoi(szValue); else if (szKey == "windup_movespeed") windup_movespeed = atof(szValue); else if (szKey == "windup_shoot_movespeed") windup_shoot_movespeed = atof(szValue); else return BaseClass.KeyValue( szKey, szValue ); if (szKey == "sounds" or szKey == "melee_hit_sounds" or szKey == "melee_flesh_sounds" or szKey == "shoot_fail_snds" or szKey == "windup_snd" or szKey == "wind_down_snd" or szKey == "windup_loop_snd" or szKey == "hook_sound" or szKey == "hook_sound2" or szKey == "projectile_snd" or szKey == "shell_delay_snd" or szKey == "shoot_empty_snd") { if (g_map_activated) loadExternalSoundSettings(); } if (szKey == "effect1_name" or szKey == "effect2_name" or szKey == "effect3_name" or szKey == "effect4_name" or szKey == "user_effect1" or szKey == "user_effect2" or szKey == "user_effect3" or szKey == "user_effect4" or szKey == "user_effect5" or szKey == "user_effect6") { if (g_map_activated) loadExternalEffectSettings(); } return true; } bool isPrimary() { return @weapon.fire_settings[0] == @this; } bool isSecondary() { return @weapon.fire_settings[1] == @this; } bool isTertiary() { return @weapon.fire_settings[2] == @this; } void loadExternalSoundSettings() { loadSoundSettings(sounds); loadSoundSettings(melee_hit_sounds); loadSoundSettings(melee_flesh_sounds); loadSoundSettings(shoot_fail_snds); loadSoundSettings(windup_snd); loadSoundSettings(wind_down_snd); loadSoundSettings(windup_loop_snd); loadSoundSettings(hook_snd); loadSoundSettings(hook_snd2); loadSoundSettings(projectile.move_snd); loadSoundSettings(shell_delay_snd); loadSoundSettings(shoot_empty_snd); } void loadExternalEffectSettings() { @effect1 = loadEffectSettings(effect1); @effect2 = loadEffectSettings(effect2); @effect3 = loadEffectSettings(effect3); @effect4 = loadEffectSettings(effect4); @user_effect1 = loadUserEffectSettings(user_effect1, user_effect1_str); @user_effect2 = loadUserEffectSettings(user_effect2, user_effect2_str); @user_effect3 = loadUserEffectSettings(user_effect3, user_effect3_str); @user_effect4 = loadUserEffectSettings(user_effect4, user_effect4_str); @user_effect5 = loadUserEffectSettings(user_effect5, user_effect5_str); @user_effect6 = loadUserEffectSettings(user_effect6, user_effect6_str); } int damageType(int defaultType) { int dtype = defaultType; if (damage_type >= 0) dtype = damage_type; return dtype | damage_type2 | gib_type; } WeaponSound@ getRandomShootSound() { if (sounds.length() == 0) return null; int randIdx = Math.RandomLong(0, sounds.length()-1); return sounds[randIdx]; } WeaponSound@ getRandomMeleeHitSound() { if (melee_hit_sounds.length() == 0) return WeaponSound(); int randIdx = Math.RandomLong(0, melee_hit_sounds.length()-1); return melee_hit_sounds[randIdx]; } WeaponSound@ getRandomMeleeFleshSound() { if (melee_flesh_sounds.length() == 0) return null; int randIdx = Math.RandomLong(0, melee_flesh_sounds.length()-1); return melee_flesh_sounds[randIdx]; } WeaponSound@ getRandomShootFailSound() { if (shoot_fail_snds.length() == 0) return null; int randIdx = Math.RandomLong(0, shoot_fail_snds.length()-1); return shoot_fail_snds[randIdx]; } bool validateSettings() { return true; } void Spawn() { if (string(pev.targetname).Length() == 0) { println(logPrefix + "weapon_custom_shoot has no targetname and will not be used."); return; } else if (custom_weapon_shoots.exists(pev.targetname)) { println(logPrefix + "more than weapon_custom_shoot has the targetname '" + pev.targetname + "'"); } // projectiles count as 2 bullets because they can spawn lots of special effects int iBullets = shoot_type == SHOOT_BULLETS ? bullets : 0; //int iProjectiles = pev.spawnflags & FL_SHOOT_PROJECTILE != 0 ? 2 : 0; float bps = (1.0f / cooldown) * iBullets; if (int(bps) > REC_BULLETS_PER_SECOND) println("\nWEAPON_CUSTOM WARNING: " + pev.targetname + " bullets per second (" + int(bps) + ") is greater than the max recommended (" + REC_BULLETS_PER_SECOND + ")\n" "Your game might freeze occasionally with 'Overflow 2048 temporary ents!' spammed in console\n"); int iBeams = shoot_type == SHOOT_BEAM ? beam_ricochet_limit+1 : 0; if (beams[1].type != BEAM_DISABLED) iBeams *= 2; if (iBeams > REC_BEAMS) println("\nWEAPON_CUSTOM WARNING: " + pev.targetname + " max beams (" + int(iBeams) + ") is greater than the max recommended (" + REC_BEAMS + ")\n" "Your game might freeze occasionally with 'Overflow beam entity list!' spammed in console\n"); custom_weapon_shoots[pev.targetname] = @this; Precache(); } int PrecacheModel(string model) { if (model.Length() > 0) { debugln("Precaching model for " + pev.targetname + ": " + model); return g_Game.PrecacheModel( model ); } return -1; } void PrecacheSound(string sound) { if (sound.Length() > 0) { debugln("Precaching sound for " + pev.targetname + ": " + sound); g_SoundSystem.PrecacheSound( sound ); } } bool can_fire_underwater() { return pev.spawnflags & FL_SHOOT_IN_WATER != 0; } void update_shell_type() { switch(shell_type) { case SHELL_SMALL: shell_idx = g_Game.PrecacheModel( "models/shell.mdl" ); break; case SHELL_LARGE: shell_idx = g_Game.PrecacheModel( "models/saw_shell.mdl" ); break; case SHELL_SHOTGUN: shell_idx = g_Game.PrecacheModel( "models/shotgunshell.mdl" ); break; } if (shell_model.Length() > 0) shell_idx = g_Game.PrecacheModel( shell_model ); } void Precache() { for (uint i = 0; i < sounds.length(); i++) PrecacheSound(sounds[i].file); for (uint i = 0; i < melee_hit_sounds.length(); i++) PrecacheSound(melee_hit_sounds[i].file); for (uint i = 0; i < melee_flesh_sounds.length(); i++) PrecacheSound(melee_flesh_sounds[i].file); for (uint i = 0; i < shoot_fail_snds.length(); i++) PrecacheSound(shoot_fail_snds[i].file); PrecacheSound(windup_snd.file); PrecacheSound(wind_down_snd.file); PrecacheSound(windup_loop_snd.file); PrecacheSound(hook_snd.file); PrecacheSound(hook_snd2.file); PrecacheSound(shell_delay_snd.file); PrecacheSound(shoot_empty_snd.file); PrecacheSound(projectile.move_snd.file); PrecacheModel(beam_impact_spr); PrecacheModel(beams[0].sprite); PrecacheModel(beams[1].sprite); PrecacheModel(shell_model); // TODO: PrecacheOther for custom entities if (projectile.type == PROJECTILE_ARGRENADE) PrecacheModel( "models/grenade.mdl" ); if (projectile.type == PROJECTILE_MORTAR) { PrecacheModel( "models/mortarshell.mdl" ); PrecacheSound( "weapons/ofmortar.wav" ); } if (projectile.type == PROJECTILE_HVR) PrecacheModel( "models/HVR.mdl" ); PrecacheModel( projectile.model ); PrecacheModel( projectile.sprite ); if (projectile.trail_spr.Length() > 0) projectile.trail_sprId = PrecacheModel( projectile.trail_spr ); if (projectile.entity_class.Length() > 0) g_Game.PrecacheOther( projectile.entity_class ); /* kingpin ball PrecacheModel( "sprites/nhth1.spr" ); PrecacheModel( "sprites/shockwave.spr" ); PrecacheModel( "sprites/muz7.spr" ); PrecacheSound( "kingpin/kingpin_seeker_amb.wav" ); PrecacheSound( "tor/tor-staff-discharge.wav" ); PrecacheSound( "debris/beamstart14.wav" ); */ } } class weapon_custom : ScriptBaseEntity { string weapon_classname; string primary_fire; // targetname of weapon_custom_shoot string primary_alt_fire; WeaponSound primary_empty_snd; string primary_ammo_type; string primary_ammo_drop_class; int primary_ammo_drop_amt; float primary_regen_time; int primary_regen_amt; int default_ammo; int default_ammo2 = -1; int secondary_action; string secondary_fire; WeaponSound secondary_empty_snd; string secondary_ammo_type; string secondary_ammo_drop_class; int secondary_ammo_drop_amt; float secondary_regen_time; int secondary_regen_amt; int tertiary_action; string tertiary_fire; WeaponSound tertiary_empty_snd; int tertiary_ammo_type; string wpn_v_model; string wpn_w_model; string wpn_p_model; string hud_sprite; string hud_sprite_folder; string laser_sprite; float laser_sprite_scale; Color laser_sprite_color; int wpn_w_model_body; int zoom_fov; int max_live_projectiles = 0; array idle_anims; float idle_time; float deploy_time; WeaponSound deploy_snd; float movespeed; WeaponSound reload_snd; WeaponSound reload_start_snd; WeaponSound reload_end_snd; WeaponSound reload_cancel_snd; float reload_time; float reload_start_time; float reload_end_time; float reload_cancel_time; int reload_start_anim; int reload_end_anim; int reload_cancel_anim; int reload_anim; int reload_empty_anim; int reload_mode; int reload_ammo_amt; int clip_size2 = 0; int reload_mode2 = 0; float reload_time2 = 1; int reload_anim2 = 1; WeaponSound reload_snd2; string user_effect_r2_str; weapon_custom_user_effect@ user_effect1; // reload weapon_custom_user_effect@ user_effect2; // empty reload weapon_custom_user_effect@ user_effect3; // weapon_custom_user_effect@ user_effect_r2; // secondary reload string user_effect1_str; string user_effect2_str; string user_effect3_str; int deploy_anim; int player_anims; int slot; int slotPosition; int priority; // auto switch priority bool matchingAmmoTypes = false; // primary and secondary fire settings array fire_settings = { weapon_custom_shoot(), weapon_custom_shoot(), weapon_custom_shoot() }; array alt_fire_settings = { weapon_custom_shoot(), weapon_custom_shoot(), weapon_custom_shoot() }; //weapon_custom_ammo@ primary_custom_ammo; //weapon_custom_ammo@ secondary_custom_ammo; bool KeyValue( const string& in szKey, const string& in szValue ) { bool relink = false; // Only custom keyvalues get sent here if (szKey == "weapon_name") weapon_classname = szValue; else if (szKey == "movespeed") { movespeed = atof(szValue); update_active_weapons(szKey, szValue); } else if (szKey == "default_ammo") default_ammo = atoi(szValue); else if (szKey == "default_ammo2") default_ammo2 = atoi(szValue); else if (szKey == "primary_fire") { primary_fire = szValue; relink = true; } else if (szKey == "primary_alt_fire") { primary_alt_fire = szValue; relink = true; } else if (szKey == "primary_empty_snd") primary_empty_snd.file = szValue; else if (szKey == "primary_ammo") primary_ammo_type = szValue; else if (szKey == "primary_ammo_drop") primary_ammo_drop_class = szValue; else if (szKey == "primary_regen_time") primary_regen_time = atof(szValue); else if (szKey == "primary_regen_amt") primary_regen_amt = atoi(szValue); else if (szKey == "secondary_action") secondary_action = atoi(szValue); else if (szKey == "secondary_fire") { secondary_fire = szValue; relink = true; } else if (szKey == "secondary_empty_snd") secondary_empty_snd.file = szValue; else if (szKey == "secondary_ammo") secondary_ammo_type = szValue; else if (szKey == "secondary_ammo_drop") secondary_ammo_drop_class = szValue; else if (szKey == "secondary_regen_time") secondary_regen_time = atof(szValue); else if (szKey == "secondary_regen_amt") secondary_regen_amt = atoi(szValue); else if (szKey == "tertiary_action") tertiary_action = atoi(szValue); else if (szKey == "tertiary_fire") { tertiary_fire = szValue; relink = true; } else if (szKey == "tertiary_empty_snd") tertiary_empty_snd.file = szValue; else if (szKey == "tertiary_ammo") tertiary_ammo_type = atoi(szValue); else if (szKey == "deploy_snd") deploy_snd.file = szValue; else if (szKey == "reload_snd") reload_snd.file = szValue; else if (szKey == "reload_snd2") reload_snd2.file = szValue; else if (szKey == "reload_start_snd") reload_start_snd.file = szValue; else if (szKey == "reload_end_snd") reload_end_snd.file = szValue; else if (szKey == "reload_cancel_snd") reload_cancel_snd.file = szValue; else if (szKey == "reload_start_time") reload_start_time = atof(szValue); else if (szKey == "reload_end_time") reload_end_time = atof(szValue); else if (szKey == "reload_cancel_time") reload_cancel_time = atof(szValue); else if (szKey == "reload_start_anim") reload_start_anim = atoi(szValue); else if (szKey == "reload_end_anim") reload_end_anim = atoi(szValue); else if (szKey == "reload_cancel_anim") reload_cancel_anim = atoi(szValue); else if (szKey == "reload_ammo_amt") reload_ammo_amt = atoi(szValue); else if (szKey == "reload_mode") reload_mode = atoi(szValue); else if (szKey == "reload_mode2") reload_mode2 = atoi(szValue); else if (szKey == "reload_anim") reload_anim = atoi(szValue); else if (szKey == "reload_anim2") reload_anim2 = atoi(szValue); else if (szKey == "reload_empty_anim") reload_empty_anim = atoi(szValue); else if (szKey == "reload_time") reload_time = atof(szValue); else if (szKey == "reload_time2") reload_time2 = atof(szValue); else if (szKey == "secondary_clip") clip_size2 = atoi(szValue); else if (szKey == "user_effect1") user_effect1_str = szValue; else if (szKey == "user_effect2") user_effect2_str = szValue; else if (szKey == "user_effect3") user_effect3_str = szValue; else if (szKey == "user_effect_r2") user_effect_r2_str = szValue; else if (szKey == "weapon_slot") slot = atoi(szValue); else if (szKey == "weapon_slot_pos") slotPosition = atoi(szValue); else if (szKey == "wpn_v_model") wpn_v_model = szValue; else if (szKey == "wpn_w_model") wpn_w_model = szValue; else if (szKey == "wpn_p_model") wpn_p_model = szValue; else if (szKey == "wpn_w_model_body") wpn_w_model_body = atoi(szValue); else if (szKey == "deploy_anim") deploy_anim = atoi(szValue); else if (szKey == "idle_anims") idle_anims = szValue.Split(";"); else if (szKey == "idle_time") idle_time = atof(szValue); else if (szKey == "deploy_time") deploy_time = atof(szValue); else if (szKey == "zoom_fov") zoom_fov = atoi(szValue); else if (szKey == "laser_sprite") laser_sprite = szValue; else if (szKey == "laser_sprite_scale") laser_sprite_scale = atof(szValue); else if (szKey == "laser_sprite_color") laser_sprite_color = parseColor(szValue); else if (szKey == "hud_sprite") hud_sprite = szValue; else if (szKey == "sprite_directory") hud_sprite_folder = szValue; else if (szKey == "weapon_priority") priority = atoi(szValue); else if (szKey == "player_anims") player_anims = atoi(szValue); else if (szKey == "projectile_max_alive") max_live_projectiles = atoi(szValue); else return BaseClass.KeyValue( szKey, szValue ); if (relink and g_map_activated) link_shoot_settings(); return true; } void update_active_weapons(string changedKey, string newValue) { if (!g_map_activated) return; CBaseEntity@ ent = null; do { @ent = g_EntityFuncs.FindEntityByClassname(ent, weapon_classname); if (ent !is null) { WeaponCustomBase@ c_wep = cast(CastToScriptClass(ent)); if (changedKey == "movespeed") c_wep.applyPlayerSpeedMult(); } } while (ent !is null); } void link_shoot_settings() { loadExternalSoundSettings(); loadExternalEffectSettings(); if (primary_fire.Length() == 0 and secondary_fire.Length() == 0) { println(logPrefix + weapon_classname + " has no primary or secondary fire function set"); return; } bool foundPrimary = false; bool foundAltPrimary = false; bool foundSecondary = false; bool foundTertiary = false; array@ keys2 = custom_weapon_shoots.getKeys(); for (uint k = 0; k < keys2.length(); k++) { weapon_custom_shoot@ shoot = cast( custom_weapon_shoots[keys2[k]] ); if (shoot.pev.targetname == primary_fire and primary_fire.Length() > 0) { @fire_settings[0] = shoot; @shoot.weapon = this; foundPrimary = true; } if (shoot.pev.targetname == secondary_fire and secondary_fire.Length() > 0) { @fire_settings[1] = shoot; @shoot.weapon = this; foundSecondary = true; } if (shoot.pev.targetname == tertiary_fire and tertiary_fire.Length() > 0) { @fire_settings[2] = shoot; @shoot.weapon = this; foundTertiary = true; } if (shoot.pev.targetname == primary_alt_fire and primary_alt_fire.Length() > 0) { @alt_fire_settings[0] = shoot; @shoot.weapon = this; foundAltPrimary = true; } } if (!foundPrimary and primary_fire.Length() > 0) println(logPrefix + " Couldn't find primary fire entity " + primary_fire + " for " + weapon_classname); if (!foundSecondary and secondary_fire.Length() > 0) println(logPrefix + " Couldn't find secondary fire entity '" + secondary_fire + "' for " + weapon_classname); if (!foundTertiary and tertiary_fire.Length() > 0) println(logPrefix + " Couldn't find tertiary fire entity " + tertiary_fire + " for " + weapon_classname); if (!foundAltPrimary and primary_alt_fire.Length() > 0) println(logPrefix + " Couldn't find alternate primary fire entity " + primary_alt_fire + " for " + weapon_classname); } int clip_size() { return self.pev.skin; } weapon_custom_shoot@ get_shoot_settings(int fmode) { return @fire_settings[fmode]; } string getPlayerAnimExt() { if (player_anims < 0 or player_anims >= int(g_panim_refs.length())) return g_panim_refs[ANIM_REF_ONEHANDED]; return g_panim_refs[player_anims]; } int getRandomIdleAnim() { if (idle_anims.length() == 0) return 0; int randIdx = Math.RandomLong(0, idle_anims.length()-1); return atoi( idle_anims[randIdx] ); } bool validateSettings() { // clamp values if (slot < 0 or slot > MAX_WEAPON_SLOT) slot = 0; if (slotPosition < MIN_WEAPON_SLOT_POSITION or slotPosition > MAX_WEAPON_SLOT_POSITION) slotPosition = -1; // check that slot isn't filled if (slotPosition == -1) // user chose "Auto" { slotPosition = getFreeWeaponSlotPosition(slot); if (slotPosition == -1 or !isFreeWeaponSlot(slot, slotPosition)) println(logPrefix + weapon_classname + " Can't fit in weapon slot " + slot +". Move this weapon to another slot and try again."); } else if (!isFreeWeaponSlot(slot, slotPosition)) { println(logPrefix + "The weapon slot you chose for " + weapon_classname + " is filled. Choose another slot or slot position and try again."); } return true; } bool isFreeWeaponSlot(int slot, int position) { if (slot < 0 or slot > MAX_WEAPON_SLOT) return false; if (position < MIN_WEAPON_SLOT_POSITION or position > MAX_WEAPON_SLOT_POSITION) return false; // there aren't actually 6 weapons in this slot, but pos 5 and 6 don't work for some reason if (slot == 1 and position < 7) return false; array@ stateKeys = custom_weapons.getKeys(); for (uint i = 0; i < stateKeys.length(); i++) { weapon_custom@ settings = cast( custom_weapons[stateKeys[i]] ); if (settings.slot == slot and settings.slotPosition == position) return false; } // TODO: What if another weapon script registered a weapon here? return true; } int getFreeWeaponSlotPosition(int slot) { for (int i = MIN_WEAPON_SLOT_POSITION; i < MAX_WEAPON_SLOT_POSITION; i++) { if (isFreeWeaponSlot(slot, i)) return i; } return MAX_WEAPON_SLOT_POSITION; } void loadExternalSoundSettings() { loadSoundSettings(primary_empty_snd); loadSoundSettings(secondary_empty_snd); loadSoundSettings(reload_snd); loadSoundSettings(reload_snd2); loadSoundSettings(reload_start_snd); loadSoundSettings(reload_end_snd); } void loadExternalEffectSettings() { @user_effect1 = loadUserEffectSettings(user_effect1, user_effect1_str); @user_effect2 = loadUserEffectSettings(user_effect2, user_effect2_str); @user_effect3 = loadUserEffectSettings(user_effect3, user_effect3_str); @user_effect_r2 = loadUserEffectSettings(user_effect_r2, user_effect_r2_str); } float getReloadTime(bool emptyReload=false, bool secondary=false) { if (reload_mode == RELOAD_SIMPLE) return secondary ? reload_time2 : reload_time; float time = 0; weapon_custom_user_effect@ ef = emptyReload ? @user_effect2 : @user_effect1; if (secondary) @ef = @user_effect_r2; for (int i = 0; i < 128; i++) // ...just in case someone tries an endless reload loop { if (ef is null) break; time += ef.delay; @ef = @ef.next_effect; } return time; } AmmoDrop getSmallestAmmoDropType(string ammoType) { AmmoDrop best; if (ammoType == "buckshot") { best.cname = "ammo_buckshot"; } else if (ammoType == "556") { best.cname = "ammo_556"; } else if (ammoType == "m40a1") { best.cname = "ammo_762"; } else if (ammoType == "argrenades") { best.cname = "ammo_ARgrenades"; } else if (ammoType == "357") { best.cname = "ammo_357"; } else if (ammoType == "9mm") { best.cname = "ammo_9mmclip"; } else if (ammoType == "sporeclip") { best.cname = "ammo_sporeclip"; } else if (ammoType == "uranium") { best.cname = "ammo_gaussclip"; } else if (ammoType == "rockets") { best.cname = "ammo_rpgclip"; } else if (ammoType == "bolts") { best.cname = "ammo_crossbow"; } best.dropAmt = getAmmoDropAmt(best.cname); // check custom ammos array@ keys = custom_ammos.getKeys(); for (uint i = 0; i < keys.length(); i++) { weapon_custom_ammo@ ammo = cast( custom_ammos[keys[i]] ); if (ammo.custom_ammo_type == ammoType and (ammo.give_ammo < best.dropAmt or best.dropAmt == -1)) { best.cname = ammo.ammo_classname; best.dropAmt = ammo.give_ammo; } } return best; } int getAmmoDropAmt(string ammoClass) { if (ammoClass.Length() == 0) return -1; if (ammoClass == "ammo_357") { return 6; } else if (ammoClass == "ammo_556") { return 100; } else if (ammoClass == "ammo_762") { return 5; } else if (ammoClass == "ammo_9mmAR") { return 50; } else if (ammoClass == "ammo_9mmbox") { return 200; } else if (ammoClass == "ammo_9mmclip") { return 17; } else if (ammoClass == "ammo_ARgrenades") { return 2; } else if (ammoClass == "ammo_buckshot") { return 12; } else if (ammoClass == "ammo_crossbow") { return 5; } else if (ammoClass == "ammo_gaussclip") { return 20; } else if (ammoClass == "ammo_rpgclip") { return 2; } else if (ammoClass == "ammo_sporeclip") { return 1; } else if (ammoClass == "ammo_uziclip") { return 32; } array@ keys = custom_ammos.getKeys(); for (uint i = 0; i < keys.length(); i++) { weapon_custom_ammo@ ammo = cast( custom_ammos[keys[i]] ); if (ammo.ammo_classname == ammoClass) return ammo.give_ammo; } return -1; } void Spawn() { if (weapon_classname.Length() > 0) { validateSettings(); // load ammo drop amounts if a specific drop class was set primary_ammo_drop_amt = getAmmoDropAmt(primary_ammo_drop_class); secondary_ammo_drop_amt = getAmmoDropAmt(secondary_ammo_drop_class); if (primary_ammo_drop_amt == -1 and primary_ammo_drop_class.Length() > 0) println("WEAPON_CUSTOM ERROR: " + weapon_classname + " uses an invalid primary ammo drop class: " + primary_ammo_drop_class); if (secondary_ammo_drop_amt == -1 and secondary_ammo_drop_class.Length() > 0) println("WEAPON_CUSTOM ERROR: " + weapon_classname + " uses an invalid primary ammo drop class: " + secondary_ammo_drop_class); // automatically determine ammo drop classes if none was set if (primary_ammo_drop_class.Length() == 0 and primary_ammo_type.Length() > 0) { AmmoDrop bestMatch = getSmallestAmmoDropType(primary_ammo_type); primary_ammo_drop_class = bestMatch.cname; primary_ammo_drop_amt = bestMatch.dropAmt; } if (secondary_ammo_drop_class.Length() == 0 and secondary_ammo_type.Length() > 0) { AmmoDrop bestMatch = getSmallestAmmoDropType(primary_ammo_type); secondary_ammo_drop_class = bestMatch.cname; secondary_ammo_drop_amt = bestMatch.dropAmt; } if (debug_mode) println("Assigning " + weapon_classname + " to slot " + slot + " at position " + slotPosition); custom_weapons[weapon_classname] = @this; g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::WeaponCustomBase", weapon_classname ); if (pev.spawnflags & FL_WEP_HIDE_SECONDARY_AMMO != 0) { g_ItemRegistry.RegisterWeapon( weapon_classname, hud_sprite_folder, primary_ammo_type, "", primary_ammo_drop_class, secondary_ammo_drop_class); } else { g_ItemRegistry.RegisterWeapon( weapon_classname, hud_sprite_folder, primary_ammo_type, secondary_ammo_type, primary_ammo_drop_class, secondary_ammo_drop_class); } matchingAmmoTypes = primary_ammo_type.ToLowercase() == secondary_ammo_type.ToLowercase(); Precache(); } else println("weapon_custom creation failed. No weapon_class specified"); } void PrecacheModel(string model) { if (model.Length() > 0) { debugln("Precaching model for " + weapon_classname + ": " + model); g_Game.PrecacheModel( model ); } } void PrecacheSound(string sound) { if (sound.Length() > 0) { debugln("Precaching sound for " + weapon_classname + ": " + sound); g_SoundSystem.PrecacheSound( sound ); } } void Precache() { PrecacheSound(primary_empty_snd.file); PrecacheSound(secondary_empty_snd.file); PrecacheSound(deploy_snd.file); PrecacheSound(reload_snd.file); PrecacheSound(reload_snd2.file); PrecacheSound(reload_start_snd.file); PrecacheSound(reload_end_snd.file); PrecacheModel(wpn_v_model); PrecacheModel(wpn_w_model); PrecacheModel(wpn_p_model); PrecacheModel(hud_sprite); PrecacheModel(laser_sprite); } }; class weapon_custom_ammo : ScriptBaseEntity { string ammo_classname; string w_model; WeaponSound pickup_snd; int give_ammo; int max_ammo; int ammo_type; string custom_ammo_type; bool KeyValue( const string& in szKey, const string& in szValue ) { if (szKey == "ammo_name") ammo_classname = szValue; else if (szKey == "w_model") w_model = szValue; else if (szKey == "pickup_snd") pickup_snd.file = szValue; else if (szKey == "give_ammo") give_ammo = atoi(szValue); else if (szKey == "max_ammo") max_ammo = atoi(szValue); else if (szKey == "ammo_type") ammo_type = atoi(szValue); else if (szKey == "custom_ammo_type") custom_ammo_type = szValue; else return BaseClass.KeyValue( szKey, szValue ); return true; } void loadExternalSoundSettings() { loadSoundSettings(pickup_snd); } void Spawn() { if (ammo_classname.Length() > 0) { custom_ammos[ammo_classname] = @this; g_CustomEntityFuncs.RegisterCustomEntity( "WeaponCustom::AmmoCustomBase", ammo_classname ); Precache(); } else println("weapon_custom creation failed. No weapon_class specified"); } void PrecacheModel(string model) { if (model.Length() > 0) { debugln("Precaching model for " + ammo_classname + ": " + model); g_Game.PrecacheModel( model ); } } void PrecacheSound(string sound) { if (sound.Length() > 0) { debugln("Precaching sound for " + ammo_classname + ": " + sound); g_SoundSystem.PrecacheSound( sound ); } } void Precache() { PrecacheSound(pickup_snd.file); PrecacheModel(w_model); } }; class weapon_custom_sound : ScriptBaseEntity { WeaponSound next_snd; bool KeyValue( const string& in szKey, const string& in szValue ) { return BaseClass.KeyValue( szKey, szValue ); } void Spawn() { next_snd.file = pev.noise; Precache(); } void loadExternalSoundSettings() { loadSoundSettings(next_snd); } void PrecacheSound(string sound) { if (sound.Length() > 0) { debugln("Precaching sound for " + pev.targetname + ": " + sound); g_SoundSystem.PrecacheSound( sound ); } } void Precache() { PrecacheSound(pev.message); } void Use(CBaseEntity@ pActivator, CBaseEntity@ pCaller, USE_TYPE useType, float flValue = 0.0f) { WeaponSound snd; snd.file = pev.message; @snd.options = @this; snd.play(pev.origin); } }; class weapon_custom_effect : ScriptBaseEntity { string name; bool valid = false; float delay = 0; int explosion_style; float explode_radius; float explode_damage; float explode_offset; float explode_spr_scale; float explode_spr_fps; string explode_water_spr; string explode_spr; int damage_type; int damage_type2; int gib_type; int blood_stream; string explode_smoke_spr; float explode_smoke_spr_scale; float explode_smoke_spr_fps; float explode_smoke_delay; float explode_beam_radius; int explode_beam_width; int explode_beam_life; int explode_beam_noise; Color explode_beam_color; int explode_beam_frame; int explode_beam_fps; int explode_beam_scroll; int explode_bubbles; Vector explode_bubble_mins; Vector explode_bubble_maxs; float explode_bubble_delay; float explode_bubble_speed; string explode_bubble_spr; Color explode_light_color; Color explode_light_color2; Vector explode_light_adv; Vector explode_light_adv2; int explode_gibs; string explode_gib_mdl; int explode_gib_mat; int explode_gib_speed; int explode_gib_rand; int explode_gib_effects; array sounds; int rico_decal; string rico_part_spr; int rico_part_count; int rico_part_scale; int rico_part_speed; int rico_trace_count; int rico_trace_color; int rico_trace_speed; int rico_trace_rand; string glow_spr; int glow_spr_scale; int glow_spr_life; int glow_spr_opacity; int spray_count; string spray_sprite; int spray_speed; int spray_rand; int burst_life; int burst_radius; int burst_color; int implode_count; int implode_radius; int implode_life; float shake_radius; float shake_amp; float shake_freq; float shake_time; int rico_scale; string next_effect_str; weapon_custom_effect@ next_effect; bool next_effect_loaded = false; bool KeyValue( const string& in szKey, const string& in szValue ) { if (szKey == "explosion_style") explosion_style = atoi(szValue); else if (szKey == "delay") delay = atof(szValue); else if (szKey == "blood_stream") blood_stream = atoi(szValue); else if (szKey == "explode_radius") explode_radius = atof(szValue); else if (szKey == "explode_dmg") explode_damage = atof(szValue); else if (szKey == "explode_offset") explode_offset = atof(szValue); else if (szKey == "explode_spr") explode_spr = szValue; else if (szKey == "explode_water_spr") explode_water_spr = szValue; else if (szKey == "explode_spr_scale") explode_spr_scale = atof(szValue); else if (szKey == "explode_spr_fps") explode_spr_fps = atof(szValue); else if (szKey == "explode_smoke_spr") explode_smoke_spr = szValue; else if (szKey == "explode_smoke_spr_scale") explode_smoke_spr_scale = atof(szValue); else if (szKey == "explode_smoke_spr_fps") explode_smoke_spr_fps = atof(szValue); else if (szKey == "explode_smoke_delay") explode_smoke_delay = atof(szValue); else if (szKey == "explode_light_color") explode_light_color = parseColor(szValue); else if (szKey == "explode_light_adv") explode_light_adv = parseVector(szValue); else if (szKey == "explode_light_color2") explode_light_color2 = parseColor(szValue); else if (szKey == "explode_light_adv2") explode_light_adv2 = parseVector(szValue); else if (szKey == "explode_beam_width") explode_beam_width = atoi(szValue); else if (szKey == "explode_beam_life") explode_beam_life = atoi(szValue); else if (szKey == "explode_beam_noise") explode_beam_noise = atoi(szValue); else if (szKey == "explode_beam_frame") explode_beam_frame = atoi(szValue); else if (szKey == "explode_beam_fps") explode_beam_fps = atoi(szValue); else if (szKey == "explode_beam_scroll") explode_beam_scroll = atoi(szValue); else if (szKey == "explode_beam_radius") explode_beam_radius = atof(szValue); else if (szKey == "explode_beam_color") explode_beam_color = parseColor(szValue); else if (szKey == "implode_count") implode_count = atoi(szValue); else if (szKey == "implode_radius") implode_radius = atoi(szValue); else if (szKey == "implode_life") implode_life = atoi(szValue); else if (szKey == "shake_radius") shake_radius = atof(szValue); else if (szKey == "shake_amp") shake_amp = atof(szValue); else if (szKey == "shake_freq") shake_freq = atof(szValue); else if (szKey == "shake_time") shake_time = atof(szValue); else if (szKey == "burst_life") burst_life = atoi(szValue); else if (szKey == "burst_radius") burst_radius = atoi(szValue); else if (szKey == "burst_color") burst_color = atoi(szValue); else if (szKey == "spray_count") spray_count = atoi(szValue); else if (szKey == "spray_sprite") spray_sprite = szValue; else if (szKey == "spray_speed") spray_speed = atoi(szValue); else if (szKey == "spray_rand") spray_rand = atoi(szValue); else if (szKey == "explode_gibs") explode_gibs = atoi(szValue); else if (szKey == "explode_gib_speed") explode_gib_speed = atoi(szValue); else if (szKey == "explode_gib_model") explode_gib_mdl = szValue; else if (szKey == "explode_gib_mat") explode_gib_mat = atoi(szValue); else if (szKey == "explode_gib_rand") explode_gib_rand = atoi(szValue); else if (szKey == "explode_gib_effects")explode_gib_effects = atoi(szValue); else if (szKey == "glow_spr") glow_spr = szValue; else if (szKey == "glow_spr_scale") glow_spr_scale = atoi(szValue); else if (szKey == "glow_spr_life") glow_spr_life = atoi(szValue); else if (szKey == "glow_spr_opacity") glow_spr_opacity = atoi(szValue); else if (szKey == "damage_type") damage_type = atoi(szValue); else if (szKey == "damage_type2") damage_type2 = atoi(szValue); else if (szKey == "gib_type") gib_type = atoi(szValue); else if (szKey == "sounds") sounds = parseSounds(szValue); else if (szKey == "rico_decal") rico_decal = atoi(szValue); else if (szKey == "rico_part_spr") rico_part_spr = szValue; else if (szKey == "rico_part_count") rico_part_count = atoi(szValue); else if (szKey == "rico_part_scale") rico_part_scale = atoi(szValue); else if (szKey == "rico_part_speed") rico_part_speed = atoi(szValue); else if (szKey == "rico_trace_count") rico_trace_count = atoi(szValue); else if (szKey == "rico_trace_speed") rico_trace_speed = atoi(szValue); else if (szKey == "rico_trace_rand") rico_trace_rand = atoi(szValue); else if (szKey == "rico_trace_color") rico_trace_color = atoi(szValue); else if (szKey == "explode_bubbles") explode_bubbles = atoi(szValue); else if (szKey == "explode_bubble_mins") explode_bubble_mins = parseVector(szValue); else if (szKey == "explode_bubble_maxs") explode_bubble_maxs = parseVector(szValue); else if (szKey == "explode_bubble_delay") explode_bubble_delay = atof(szValue); else if (szKey == "explode_bubble_spr") explode_bubble_spr = szValue; else if (szKey == "rico_scale") rico_scale = atoi(szValue); else if (szKey == "next_effect") next_effect_str = szValue; else return BaseClass.KeyValue( szKey, szValue ); return true; } void Spawn() { Precache(); } void loadExternalSoundSettings() { loadSoundSettings(sounds); } void loadExternalEffectSettings() { if (next_effect_loaded) return; // fix recursion crash next_effect_loaded = true; @next_effect = loadEffectSettings(next_effect, next_effect_str); } WeaponSound@ getRandomSound() { if (sounds.length() == 0) return null; int randIdx = Math.RandomLong(0, sounds.length()-1); return sounds[randIdx]; } void PrecacheSound(string sound) { if (sound.Length() > 0) { debugln("Precaching sound for " + pev.targetname + ": " + sound); g_SoundSystem.PrecacheSound( sound ); } } int PrecacheModel(string model) { if (model.Length() > 0) { debugln("Precaching model for " + pev.targetname + ": " + model); return g_Game.PrecacheModel( model ); } return -1; } int damageType() { return damage_type | damage_type2 | gib_type; } void Precache() { for (uint i = 0; i < sounds.length(); i++) PrecacheSound(sounds[i].file); PrecacheModel( explode_spr ); PrecacheModel( explode_smoke_spr ); PrecacheModel( explode_gib_mdl ); PrecacheModel(rico_part_spr); PrecacheModel(explode_water_spr); PrecacheModel(explode_bubble_spr); PrecacheModel(glow_spr); PrecacheModel(spray_sprite); } void Use(CBaseEntity@ pActivator, CBaseEntity@ pCaller, USE_TYPE useType, float flValue = 0.0f) { EHandle h_ent = self; Math.MakeVectors( pev.angles ); custom_effect(pev.origin, @this, h_ent, h_ent, h_ent, g_Engine.v_forward, 0); } }; class weapon_custom_user_effect : ScriptBaseEntity { bool valid = false; float delay = 0; array sounds; float self_damage; int damage_type; int damage_type2; int gib_type; int primary_mode; Vector add_angle; Vector add_angle_rand; float add_angle_time; Vector punch_angle; Vector push_vel; string action_sprite; float action_sprite_height; float action_sprite_time; int fade_mode; Color fade_color; float fade_hold; float fade_time; int wep_anim; int anim; // thirdperson anim float anim_speed; // thirdperson anim int anim_frame; // thirdperson anim int player_sprite_count; string player_sprite; float player_sprite_freq; float player_sprite_time; float glow_time; int glow_amt; Vector glow_color; string next_effect_str; weapon_custom_user_effect@ next_effect; bool next_effect_loaded = false; // TODO: There should really just be another entity that holds beam settings int beam_mode; int beam_type; int beam_width; int beam_noise; int beam_scroll; float beam_time; Vector beam_start; Vector beam_end; Color beam_color; string beam_spr; string v_model; string p_model; string w_model; int w_model_body; string hud_text; int triggerstate; bool KeyValue( const string& in szKey, const string& in szValue ) { if (szKey == "delay") delay = atof(szValue); else if (szKey == "sounds") sounds = parseSounds(szValue); else if (szKey == "self_damage") self_damage = atof(szValue); else if (szKey == "damage_type") damage_type = atoi(szValue); else if (szKey == "damage_type2") damage_type2 = atoi(szValue); else if (szKey == "gib_type") gib_type = atoi(szValue); else if (szKey == "primary_mode") primary_mode = atoi(szValue); else if (szKey == "hud_text") hud_text = szValue; else if (szKey == "beam_mode") beam_mode = atoi(szValue); else if (szKey == "beam_type") beam_type = atoi(szValue); else if (szKey == "beam_width") beam_width = atoi(szValue); else if (szKey == "beam_noise") beam_noise = atoi(szValue); else if (szKey == "beam_scroll") beam_scroll = atoi(szValue); else if (szKey == "beam_time") beam_time = atof(szValue); else if (szKey == "beam_start") beam_start = parseVector(szValue); else if (szKey == "beam_end") beam_end = parseVector(szValue); else if (szKey == "beam_color") beam_color = parseColor(szValue); else if (szKey == "beam_spr") beam_spr = szValue; else if (szKey == "add_angle") add_angle = parseVector(szValue); else if (szKey == "add_angle_rand") add_angle_rand = parseVector(szValue); else if (szKey == "add_angle_time") add_angle_time = atof(szValue); else if (szKey == "punch_angle") punch_angle = parseVector(szValue); else if (szKey == "push_vel") push_vel = parseVector(szValue); else if (szKey == "action_sprite") action_sprite = szValue; else if (szKey == "action_sprite_height") action_sprite_height = atof(szValue); else if (szKey == "action_sprite_time") action_sprite_time = atof(szValue); else if (szKey == "fade_mode") fade_mode = atoi(szValue); else if (szKey == "fade_color") fade_color = parseColor(szValue); else if (szKey == "fade_hold") fade_hold = atof(szValue); else if (szKey == "fade_time") fade_time = atof(szValue); else if (szKey == "wep_anim") wep_anim = atoi(szValue); else if (szKey == "anim") anim = atoi(szValue); else if (szKey == "anim_speed") anim_speed = atof(szValue); else if (szKey == "anim_frame") anim_frame = atoi(szValue); else if (szKey == "player_sprite_count") player_sprite_count = atoi(szValue); else if (szKey == "player_sprite") player_sprite = szValue; else if (szKey == "player_sprite_freq") player_sprite_freq = atof(szValue); else if (szKey == "player_sprite_time") player_sprite_time = atof(szValue); else if (szKey == "glow_color") glow_color = parseVector(szValue); else if (szKey == "glow_amt") glow_amt = atoi(szValue); else if (szKey == "glow_time") glow_time = atof(szValue); else if (szKey == "v_model") v_model = szValue; else if (szKey == "p_model") p_model = szValue; else if (szKey == "w_model") w_model = szValue; else if (szKey == "w_model_body") w_model_body = atoi(szValue); else if (szKey == "triggerstate") triggerstate = atoi(szValue); else if (szKey == "next_effect") next_effect_str = szValue; else return BaseClass.KeyValue( szKey, szValue ); return true; } void Spawn() { Precache(); } void loadExternalSoundSettings() { loadSoundSettings(sounds); } void loadExternalUserEffectSettings() { if (next_effect_loaded) return; // fix recursion crash next_effect_loaded = true; @next_effect = loadUserEffectSettings(next_effect, next_effect_str); } WeaponSound@ getRandomSound() { if (sounds.length() == 0) return null; int randIdx = Math.RandomLong(0, sounds.length()-1); return sounds[randIdx]; } void PrecacheSound(string sound) { if (sound.Length() > 0) { debugln("Precaching sound for " + pev.targetname + ": " + sound); g_SoundSystem.PrecacheSound( sound ); } } int PrecacheModel(string model) { if (model.Length() > 0) { debugln("Precaching model for " + pev.targetname + ": " + model); return g_Game.PrecacheModel( model ); } return -1; } int damageType() { return damage_type | damage_type2 | gib_type; } void Precache() { for (uint i = 0; i < sounds.length(); i++) PrecacheSound(sounds[i].file); PrecacheModel( action_sprite ); PrecacheModel( player_sprite ); PrecacheModel( v_model ); PrecacheModel( p_model ); PrecacheModel( w_model ); } void Use(CBaseEntity@ pActivator, CBaseEntity@ pCaller, USE_TYPE useType, float flValue = 0.0f) { EHandle h_plr; EHandle h_wep = null; if (pCaller !is null and pCaller.IsPlayer()) h_plr = pCaller; else h_plr = pActivator; if (pActivator !is null and pActivator.IsPlayer() or pCaller !is null and pCaller.IsPlayer()) custom_user_effect(h_plr, h_wep, @this); } }; }