set g_balance_vaporizer_primary_ammo 10
set g_balance_vaporizer_primary_animtime 0.3
set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
set g_balance_vaporizer_primary_refire 1
set g_balance_vaporizer_reload_ammo 0
set g_balance_vaporizer_reload_time 0
set g_balance_vaporizer_primary_ammo 10
set g_balance_vaporizer_primary_animtime 0.3
set g_balance_vaporizer_primary_damage -1
+set g_balance_vaporizer_primary_force 800
set g_balance_vaporizer_primary_refire 1
set g_balance_vaporizer_reload_ammo 0
set g_balance_vaporizer_reload_time 0
set g_balance_vaporizer_primary_ammo 10
set g_balance_vaporizer_primary_animtime 0.3
set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
set g_balance_vaporizer_primary_refire 1
set g_balance_vaporizer_reload_ammo 0
set g_balance_vaporizer_reload_time 0
set g_balance_vaporizer_primary_ammo 10
set g_balance_vaporizer_primary_animtime 0.3
set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
set g_balance_vaporizer_primary_refire 1
set g_balance_vaporizer_reload_ammo 0
set g_balance_vaporizer_reload_time 0
set g_balance_vaporizer_primary_ammo 10
set g_balance_vaporizer_primary_animtime 0.3
set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
set g_balance_vaporizer_primary_refire 1
set g_balance_vaporizer_reload_ammo 0
set g_balance_vaporizer_reload_time 0
set g_balance_vaporizer_primary_ammo 10
set g_balance_vaporizer_primary_animtime 0.3
set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
set g_balance_vaporizer_primary_refire 1
set g_balance_vaporizer_reload_ammo 0
set g_balance_vaporizer_reload_time 0
set g_balance_vaporizer_primary_ammo 10
set g_balance_vaporizer_primary_animtime 0.3
set g_balance_vaporizer_primary_damage 150
+set g_balance_vaporizer_primary_force 800
set g_balance_vaporizer_primary_refire 1
set g_balance_vaporizer_reload_ammo 0
set g_balance_vaporizer_reload_time 0
QCC=${QCC:-$PWD/../../gmqcc/gmqcc${CMAKE_EXECUTABLE_SUFFIX}}
case $1 in
compile)
- ${CPP} ${@:3} | sed 's/^#\(line\)\? \([[:digit:]]\+\) "\(.*\)".*/\n#pragma file(\3)\n#pragma line(\2)/g' > $2
+ ${CPP} ${@:3} | sed -E 's/^#(line)? ([[:digit:]]+) "(.*)".*/'$'\\\n''#pragma file(\3)'$'\\\n''#pragma line(\2)/g' > $2
;;
link)
${QCC} \
int nHidden = 0; \
FOREACH(Weapons, it != WEP_Null, { \
if (weapons_stat & WepSet_FromWeapon(it)) continue; \
- if (it.spawnflags & WEP_FLAG_HIDDEN || it.spawnflags & WEP_FLAG_MUTATORBLOCKED) nHidden += 1; \
+ if ((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) nHidden += 1; \
}); \
vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, panel_size, aspect); \
columns = table_size.x; \
}
else
{
- if (it.spawnflags & WEP_FLAG_MUTATORBLOCKED && !(weapons_stat & WepSet_FromWeapon(it)))
+ if (((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) && !(weapons_stat & WepSet_FromWeapon(it)))
continue;
}
#include <common/mutators/base.qh>
+// register all possible hooks here
+
+// to use a hook, first register your mutator using REGISTER_MUTATOR
+// then create your function using MUTATOR_HOOKFUNCTION
+
/**
* Called when a client command is parsed
* NOTE: hooks MUST start with if (MUTATOR_RETURNVALUE) return false;
CSQCMODEL_ENDIF \
CSQCMODEL_PROPERTY(BIT(10), float, ReadAngle, WriteAngle, v_angle_x) \
CSQCMODEL_PROPERTY(BIT(11), int, ReadByte, WriteByte, traileffect) \
- CSQCMODEL_PROPERTY_SCALED(BIT(12), float, ReadByte, WriteByte, scale, 16, 0, 255) \
+ CSQCMODEL_PROPERTY(BIT(12), float, ReadCoord, WriteCoord, scale) \
CSQCMODEL_PROPERTY(BIT(13), int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME) \
CSQCMODEL_PROPERTY(BIT(16), int, ReadByte, WriteByte, multijump_count) \
#define debug_text_3d_5(pos, msg, align, dur, vel) debug_text_3d_fn(pos, msg, align, dur, vel)
ERASEABLE
-void debug_text_3d_fn(vector pos, string msg, float align, float duration, vector velocity) {
+void debug_text_3d_fn(vector pos, string msg, float align, float duration, vector vel) {
WriteHeader(MSG_BROADCAST, debug_text_3d);
WriteVector(MSG_BROADCAST, pos);
WriteString(MSG_BROADCAST, msg);
WriteFloat(MSG_BROADCAST, align);
WriteFloat(MSG_BROADCAST, duration);
- WriteVector(MSG_BROADCAST, velocity);
+ WriteVector(MSG_BROADCAST, vel);
}
#endif // SVQC
#include <common/stats.qh>
#endif
+#ifdef SVQC
+#include <server/items.qh>
+#endif
+
const int IT_UNLIMITED_WEAPON_AMMO = BIT(0); // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
const int IT_UNLIMITED_SUPERWEAPONS = BIT(1); // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
.float invincible_finished = _STAT(INVINCIBLE_FINISHED);
#define SPAWNFUNC_ITEM(name, item) \
- spawnfunc(name) { StartItem(this, item); }
+ spawnfunc(name) \
+ { \
+ if (!Item_IsDefinitionAllowed(item)) \
+ { \
+ startitem_failed = true; \
+ delete(this); \
+ return; \
+ } \
+ StartItem(this, item); \
+ }
#else
this.realowner.mage_spike = NULL;
Send_Effect(EFFECT_EXPLOSION_SMALL, this.origin, '0 0 0', 1);
- RadiusDamage (this, this.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius),
+ RadiusDamage (this, this.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius),
NULL, NULL, 0, DEATH_MONSTER_MAGE.m_id, DMG_NOWEP, directhitentity);
delete(this);
void M_Mage_Attack_Push(entity this)
{
sound(this, CH_SHOTS, SND_TAGEXP1, 1, ATTEN_NORM);
- RadiusDamage (this, this, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius),
+ RadiusDamage (this, this, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius),
NULL, NULL, (autocvar_g_monster_mage_attack_push_force), DEATH_MONSTER_MAGE.m_id, DMG_NOWEP, this.enemy);
Send_Effect(EFFECT_TE_EXPLOSION, this.origin, '0 0 0', 1);
entity own = this.realowner;
- RadiusDamage(this, own, autocvar_g_monster_wyvern_attack_fireball_damage, autocvar_g_monster_wyvern_attack_fireball_edgedamage, autocvar_g_monster_wyvern_attack_fireball_force,
+ RadiusDamage(this, own, autocvar_g_monster_wyvern_attack_fireball_damage, autocvar_g_monster_wyvern_attack_fireball_edgedamage, autocvar_g_monster_wyvern_attack_fireball_force,
NULL, NULL, autocvar_g_monster_wyvern_attack_fireball_radius, this.projectiledeathtype, DMG_NOWEP, NULL);
FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_monster_wyvern_attack_fireball_radius, it.takedamage == DAMAGE_AIM,
|| (IS_VEHICLE(targ) && !((Monsters_from(this.monsterid)).spawnflags & MON_FLAG_RANGED)) // melee vs vehicle is useless
|| (time < game_starttime) // monsters do nothing before match has started
|| (targ.takedamage == DAMAGE_NO)
+ || (game_stopped)
|| (targ.items & IT_INVISIBILITY)
|| (IS_SPEC(targ) || IS_OBSERVER(targ)) // don't attack spectators
|| (!IS_VEHICLE(targ) && (IS_DEAD(targ) || IS_DEAD(this) || targ.health <= 0 || this.health <= 0))
// generated file; do not modify
#include <common/mutators/mutator/instagib/items.qh>
+#ifdef SVQC
+ #include <common/mutators/mutator/instagib/sv_items.qh>
+#endif
#ifdef SVQC
#include <common/mutators/mutator/instagib/sv_instagib.qh>
#endif
+#include "sv_items.qh"
+
#include "items.qh"
/// \brief Time of ivisibility powerup in seconds.
--- /dev/null
+#pragma once
// generated file; do not modify
+#ifdef SVQC
+ #include <common/mutators/mutator/kick_teamkiller/sv_kick_teamkiller.qh>
+#endif
+#include "sv_kick_teamkiller.qh"
float autocvar_g_kick_teamkiller_rate;
float autocvar_g_kick_teamkiller_lower_limit;
// use the players actual playtime
float playtime = time - CS(attacker).startplaytime;
// rate is in teamkills/minutes, playtime in seconds
- if (teamkills >= autocvar_g_kick_teamkiller_lower_limit &&
+ if (teamkills >= autocvar_g_kick_teamkiller_lower_limit &&
teamkills >= autocvar_g_kick_teamkiller_rate*playtime/60.0)
{
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK_TEAMKILL, attacker.netname);
--- /dev/null
+#pragma once
return true;
}
-MUTATOR_HOOKFUNCTION(melee_only, FilterItem)
+MUTATOR_HOOKFUNCTION(melee_only, FilterItemDefinition)
{
- entity item = M_ARGV(0, entity);
+ entity definition = M_ARGV(0, entity);
- switch (item.itemdef)
+ switch (definition)
{
case ITEM_HealthSmall:
case ITEM_ArmorSmall:
M_ARGV(0, string) = strcat(M_ARGV(0, string), ", NIX");
}
-MUTATOR_HOOKFUNCTION(nix, FilterItem)
+MUTATOR_HOOKFUNCTION(nix, FilterItemDefinition)
{
- entity item = M_ARGV(0, entity);
+ entity definition = M_ARGV(0, entity);
- if(item.itemdef.instanceOfHealth || item.itemdef.instanceOfArmor)
+ if (definition.instanceOfHealth || definition.instanceOfArmor)
{
return !autocvar_g_nix_with_healtharmor;
}
- else if(item.itemdef.instanceOfPowerup)
+ else if (definition.instanceOfPowerup)
{
return !autocvar_g_nix_with_powerups;
}
// generated file; do not modify
+#ifdef SVQC
+ #include <common/mutators/mutator/offhand_blaster/sv_offhand_blaster.qh>
+#endif
+#include "sv_offhand_blaster.qh"
+
string autocvar_g_offhand_blaster = "0";
REGISTER_MUTATOR(offhand_blaster, expr_evaluate(autocvar_g_offhand_blaster));
--- /dev/null
+#pragma once
//============================ Constants ======================================
-enum
-{
- RANDOM_ITEM_TYPE_HEALTH = 1,
- RANDOM_ITEM_TYPE_ARMOR,
- RANDOM_ITEM_TYPE_RESOURCE,
- RANDOM_ITEM_TYPE_WEAPON,
- RANDOM_ITEM_TYPE_POWERUP
-};
-
//======================= Global variables ====================================
// Replace cvars
{
return RandomItems_GetRandomOverkillItemClassName(prefix);
}
- return RandomItems_GetRandomVanillaItemClassName(prefix);
+ return RandomItems_GetRandomVanillaItemClassName(prefix,
+ RANDOM_ITEM_TYPE_ALL);
}
-string RandomItems_GetRandomVanillaItemClassName(string prefix)
+string RandomItems_GetRandomVanillaItemClassName(string prefix, int types)
{
- RandomSelection_Init();
- string cvar_name = sprintf("g_%s_health_probability", prefix);
- if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
- {
- LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
- }
- else
- {
- RandomSelection_AddFloat(RANDOM_ITEM_TYPE_HEALTH, cvar(cvar_name), 1);
- }
- cvar_name = sprintf("g_%s_armor_probability", prefix);
- if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
- {
- LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
- }
- else
+ if (types == 0)
{
- RandomSelection_AddFloat(RANDOM_ITEM_TYPE_ARMOR, cvar(cvar_name), 1);
- }
- cvar_name = sprintf("g_%s_resource_probability", prefix);
- if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
- {
- LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
- }
- else
- {
- RandomSelection_AddFloat(RANDOM_ITEM_TYPE_RESOURCE, cvar(cvar_name), 1);
- }
- cvar_name = sprintf("g_%s_weapon_probability", prefix);
- if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
- {
- LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
- }
- else
- {
- RandomSelection_AddFloat(RANDOM_ITEM_TYPE_WEAPON, cvar(cvar_name), 1);
- }
- cvar_name = sprintf("g_%s_powerup_probability", prefix);
- if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
- {
- LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
- }
- else
- {
- RandomSelection_AddFloat(RANDOM_ITEM_TYPE_POWERUP, cvar(cvar_name), 1);
+ return "";
}
- int item_type = RandomSelection_chosen_float;
- switch (item_type)
+ while (types != 0)
{
- case RANDOM_ITEM_TYPE_HEALTH:
+ string cvar_name;
+ RandomSelection_Init();
+ if (types & RANDOM_ITEM_TYPE_HEALTH)
{
- return RandomItems_GetRandomItemClassNameWithProperty(prefix,
- instanceOfHealth);
+ cvar_name = sprintf("g_%s_health_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_HEALTH,
+ cvar(cvar_name), 1);
+ }
}
- case RANDOM_ITEM_TYPE_ARMOR:
+ if (types & RANDOM_ITEM_TYPE_ARMOR)
{
- return RandomItems_GetRandomItemClassNameWithProperty(prefix,
- instanceOfArmor);
+ cvar_name = sprintf("g_%s_armor_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_ARMOR,
+ cvar(cvar_name), 1);
+ }
}
- case RANDOM_ITEM_TYPE_RESOURCE:
+ if (types & RANDOM_ITEM_TYPE_RESOURCE)
{
- return RandomItems_GetRandomItemClassNameWithProperty(prefix,
- instanceOfAmmo);
+ cvar_name = sprintf("g_%s_resource_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_RESOURCE,
+ cvar(cvar_name), 1);
+ }
+ }
+ if (types & RANDOM_ITEM_TYPE_WEAPON)
+ {
+ cvar_name = sprintf("g_%s_weapon_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_WEAPON, cvar(cvar_name), 1);
+ }
+ }
+ if (types & RANDOM_ITEM_TYPE_POWERUP)
+ {
+ cvar_name = sprintf("g_%s_powerup_probability", prefix);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
+ }
+ else
+ {
+ RandomSelection_AddFloat(RANDOM_ITEM_TYPE_POWERUP, cvar(cvar_name), 1);
+ }
}
- case RANDOM_ITEM_TYPE_WEAPON:
+ int item_type = RandomSelection_chosen_float;
+ string class_name = "";
+ switch (item_type)
{
- RandomSelection_Init();
- FOREACH(Weapons, it != WEP_Null &&
- !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
+ case RANDOM_ITEM_TYPE_HEALTH:
+ {
+ class_name = RandomItems_GetRandomItemClassNameWithProperty(
+ prefix, instanceOfHealth);
+ break;
+ }
+ case RANDOM_ITEM_TYPE_ARMOR:
+ {
+ class_name = RandomItems_GetRandomItemClassNameWithProperty(
+ prefix, instanceOfArmor);
+ break;
+ }
+ case RANDOM_ITEM_TYPE_RESOURCE:
{
- cvar_name = sprintf("g_%s_%s_probability", prefix,
- it.m_canonical_spawnfunc);
- if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ class_name = RandomItems_GetRandomItemClassNameWithProperty(
+ prefix, instanceOfAmmo);
+ break;
+ }
+ case RANDOM_ITEM_TYPE_WEAPON:
+ {
+ RandomSelection_Init();
+ FOREACH(Weapons, it != WEP_Null &&
+ !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED),
{
- LOG_WARNF("Random items: cvar %s doesn't exist.",
- cvar_name);
- continue;
- }
- RandomSelection_AddString(it.m_canonical_spawnfunc,
- cvar(cvar_name), 1);
- });
- return RandomSelection_chosen_string;
+ cvar_name = sprintf("g_%s_%s_probability", prefix,
+ it.m_canonical_spawnfunc);
+ if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
+ {
+ LOG_WARNF("Random items: cvar %s doesn't exist.",
+ cvar_name);
+ continue;
+ }
+ RandomSelection_AddString(it.m_canonical_spawnfunc,
+ cvar(cvar_name), 1);
+ });
+ class_name = RandomSelection_chosen_string;
+ break;
+ }
+ case RANDOM_ITEM_TYPE_POWERUP:
+ {
+ class_name = RandomItems_GetRandomItemClassNameWithProperty(
+ prefix, instanceOfPowerup);
+ break;
+ }
}
- case RANDOM_ITEM_TYPE_POWERUP:
+ if (class_name != "")
{
- return RandomItems_GetRandomItemClassNameWithProperty(prefix,
- instanceOfPowerup);
+ return class_name;
}
+ types &= ~item_type;
}
return "";
}
string RandomItems_GetRandomInstagibItemClassName(string prefix)
{
RandomSelection_Init();
- FOREACH(Items, it.spawnflags & ITEM_FLAG_INSTAGIB,
+ FOREACH(Items, it.spawnflags & ITEM_FLAG_INSTAGIB &&
+ Item_IsDefinitionAllowed(it),
{
string cvar_name = sprintf("g_%s_%s_probability", prefix,
it.m_canonical_spawnfunc);
{
RandomSelection_Init();
FOREACH(Items, (it.spawnflags & ITEM_FLAG_OVERKILL) &&
- !(it.spawnflags & ITEM_FLAG_MUTATORBLOCKED),
+ !(it.spawnflags & ITEM_FLAG_MUTATORBLOCKED) &&
+ Item_IsDefinitionAllowed(it),
{
string cvar_name = sprintf("g_%s_overkill_%s_probability", prefix,
it.m_canonical_spawnfunc);
.bool item_property)
{
RandomSelection_Init();
- FOREACH(Items, it.item_property && (it.spawnflags & ITEM_FLAG_NORMAL),
+ FOREACH(Items, it.item_property && (it.spawnflags & ITEM_FLAG_NORMAL) &&
+ Item_IsDefinitionAllowed(it),
{
string cvar_name = sprintf("g_%s_%s_probability", prefix,
it.m_canonical_spawnfunc);
bool autocvar_g_random_items; ///< Whether to enable random items.
+enum
+{
+ RANDOM_ITEM_TYPE_HEALTH = BIT(0),
+ RANDOM_ITEM_TYPE_ARMOR = BIT(1),
+ RANDOM_ITEM_TYPE_RESOURCE = BIT(2),
+ RANDOM_ITEM_TYPE_WEAPON = BIT(3),
+ RANDOM_ITEM_TYPE_POWERUP = BIT(4),
+ RANDOM_ITEM_TYPE_ALL = BITS(5)
+};
+
/// \brief Returns a random classname of the item.
/// \param[in] prefix Prefix of the cvars that hold probabilities.
/// \return Random classname of the item.
/// \brief Returns a random classname of the vanilla item.
/// \param[in] prefix Prefix of the cvars that hold probabilities.
+/// \param[in] types Bitmask of the types. See RANDOM_ITEM_TYPE constants.
/// \return Random classname of the vanilla item.
/// \note This includes mutator items that don't change gameplay a lot such as
/// jetpack and new toys.
-string RandomItems_GetRandomVanillaItemClassName(string prefix);
+string RandomItems_GetRandomVanillaItemClassName(string prefix, int types);
/// \brief Returns a random classname of the instagib item.
/// \param[in] prefix Prefix of the cvars that hold probabilities.
REGISTRY(Notifications, BITS(11))
REGISTER_REGISTRY(Notifications)
-REGISTRY_SORT(Notifications); STATIC_INIT(Notifications) { FOREACH(Notifications, true, it.m_id = i); }
+REGISTRY_SORT(Notifications);
+STATIC_INIT(Notifications) { FOREACH(Notifications, true, it.m_id = i); }
REGISTRY_CHECK(Notifications)
const int NOTIF_CHOICE_MAX = 50;
#define PHYS_INPUT_BUTTON_ZOOM(s) PHYS_INPUT_BUTTON_BUTTON4(s)
#define PHYS_INPUT_BUTTON_CROUCH(s) PHYS_INPUT_BUTTON_BUTTON5(s)
#define PHYS_INPUT_BUTTON_HOOK(s) PHYS_INPUT_BUTTON_BUTTON6(s)
-
-#ifdef CSQC
-STATIC_INIT(PHYS_INPUT_BUTTON_HOOK)
-{
- localcmd("alias +hook +button6\n");
- localcmd("alias -hook -button6\n");
-}
-#endif
-
#define PHYS_INPUT_BUTTON_INFO(s) PHYS_INPUT_BUTTON_BUTTON7(s)
#define PHYS_INPUT_BUTTON_DRAG(s) PHYS_INPUT_BUTTON_BUTTON8(s)
#define PHYS_INPUT_BUTTON_USE(s) PHYS_INPUT_BUTTON_BUTTON_USE(s)
#define PHYS_INPUT_BUTTON_DODGE(s) PHYS_INPUT_BUTTON_BUTTON11(s)
#ifdef CSQC
-STATIC_INIT(PHYS_INPUT_BUTTON_JETPACK)
+STATIC_INIT(PHYS_INPUT_BUTTON)
{
+ localcmd("alias +hook +button6\n");
+ localcmd("alias -hook -button6\n");
+
localcmd("alias +jetpack +button10\n");
- localcmd("alias -jetpack -button10\n");
-}
+ localcmd("alias -jetpack -button10\n");
-STATIC_INIT(PHYS_INPUT_BUTTON_DODGE)
-{
- localcmd("alias +dodge +button11\n");
- localcmd("alias -dodge -button11\n");
+ localcmd("alias +dodge +button11\n");
+ localcmd("alias -dodge -button11\n");
}
#endif
AUTOCVAR(g_pickup_respawntime_initial_random, int, 1,
"For items that don't start spawned: 0: spawn after their normal respawntime; 1: spawn after `random * respawntime` with the *same* random; 2: same as 1 but each item has separate random");
-float shared_random;
-STATIC_INIT(shared_random) { shared_random = random(); }
void Item_ScheduleInitialRespawn(entity e)
{
Item_Show(e, 0);
// range: respawntime .. respawntime + respawntimejitter
spawn_in = e.respawntime + random() * e.respawntimejitter;
}
- else if (autocvar_g_pickup_respawntime_initial_random == 1)
+ else
{
+ float rnd;
+ if (autocvar_g_pickup_respawntime_initial_random == 1)
+ {
+ static float shared_random = 0;
+ // NOTE this code works only if items are scheduled at the same time (normal case)
+ // NOTE2 random() can't return exactly 1 so this check always work as intended
+ if (!shared_random || floor(time) > shared_random)
+ shared_random = floor(time) + random();
+ rnd = shared_random - floor(time);
+ }
+ else
+ rnd = random();
+
// range:
// if respawntime >= ITEM_RESPAWN_TICKS: ITEM_RESPAWN_TICKS .. respawntime + respawntimejitter
// else: 0 .. ITEM_RESPAWN_TICKS
// this is to prevent powerups spawning unexpectedly without waypoints
- spawn_in = ITEM_RESPAWN_TICKS + shared_random * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
- }
- else
- {
- // range: same as 1
- spawn_in = ITEM_RESPAWN_TICKS + random() * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
+ spawn_in = ITEM_RESPAWN_TICKS + rnd * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
}
Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : spawn_in));
#include "plasma_weapon.qh"
CLASS(PlasmaDualAttack, PlasmaAttack)
+/* flags */ ATTRIB(PlasmaDualAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
/* refname */ ATTRIB(PlasmaDualAttack, netname, string, "turret_plasma_dual");
/* wepname */ ATTRIB(PlasmaDualAttack, m_name, string, _("Dual plasma"));
ENDCLASS(PlasmaDualAttack)
}
}
+STATIC_INIT_LATE(viewloc_cursor)
+{
+ // fix the mouse position on init so it isn't in the corner
+ viewloc_mousepos = '0.5 0 0' * autocvar_vid_conwidth + '0 0.5 0' * autocvar_vid_conheight;
+}
+
#endif
if(a)
f *= a;
- float totaldamage = RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * f, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * f, WEP_CVAR_BOTH(crylink, isprimary, radius),
+ float totaldamage = RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * f, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * f, WEP_CVAR_BOTH(crylink, isprimary, radius),
NULL, NULL, WEP_CVAR_BOTH(crylink, isprimary, force) * f, this.projectiledeathtype, this.weaponentity_fld, toucher);
if(totaldamage && ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 2) || ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 1) && !W_Crylink_Touch_WouldHitFriendly(this, WEP_CVAR_BOTH(crylink, isprimary, radius)))))
isprimary = !(this.projectiledeathtype & HITTYPE_SECONDARY);
- RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(hlac, isprimary, damage), WEP_CVAR_BOTH(hlac, isprimary, edgedamage), WEP_CVAR_BOTH(hlac, isprimary, radius),
+ RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(hlac, isprimary, damage), WEP_CVAR_BOTH(hlac, isprimary, edgedamage), WEP_CVAR_BOTH(hlac, isprimary, radius),
NULL, NULL, WEP_CVAR_BOTH(hlac, isprimary, force), this.projectiledeathtype, this.weaponentity_fld, toucher);
delete(this);
if(this.move_movetype == MOVETYPE_NONE || this.move_movetype == MOVETYPE_FOLLOW)
this.velocity = this.mine_orientation; // particle fx and decals need .velocity
- RadiusDamage(this, this.realowner, WEP_CVAR(minelayer, remote_damage), WEP_CVAR(minelayer, remote_edgedamage), WEP_CVAR(minelayer, remote_radius),
+ RadiusDamage(this, this.realowner, WEP_CVAR(minelayer, remote_damage), WEP_CVAR(minelayer, remote_edgedamage), WEP_CVAR(minelayer, remote_radius),
NULL, NULL, WEP_CVAR(minelayer, remote_force), this.projectiledeathtype | HITTYPE_BOUNCE, this.weaponentity_fld, NULL);
.entity weaponentity = this.weaponentity_fld;
yoda = 0;
damage_goodhits = 0;
- FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, vaporizer_damage, 800, 0, 0, 0, 0, WEP_VAPORIZER.m_id);
+ FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, vaporizer_damage, WEP_CVAR_PRI(vaporizer, force), 0, 0, 0, 0, WEP_VAPORIZER.m_id);
// do this now, as goodhits is disabled below
SendCSQCVaporizerBeamParticle(actor, damage_goodhits);
BEGIN(class) \
P(class, prefix, ammo, float, PRI) \
P(class, prefix, animtime, float, PRI) \
- P(class, prefix, damage, float, PRI) \
+ P(class, prefix, damage, float, PRI) \
+ P(class, prefix, force, float, PRI) \
P(class, prefix, refire, float, PRI) \
P(class, prefix, ammo, float, SEC) \
P(class, prefix, animtime, float, SEC) \
}
/// Maps values between the src and dest range: src_min to dest_min, src_max to dest_max, values between them
-/// to the curresponding values between and extrapolates for values outside the range.
+/// to the corresponding values between and extrapolates for values outside the range.
///
-/// src_min and src_max must not be the same or division by zero accurs.
+/// src_min and src_max must not be the same or division by zero occurs.
///
/// dest_max can be smaller than dest_min if you want the resulting range to be inverted, all values can be negative.
ERASEABLE
#define ATTRIB(...) EVAL_ATTRIB(OVERLOAD_(ATTRIB, __VA_ARGS__))
#define EVAL_ATTRIB(...) __VA_ARGS__
-#define ATTRIB_3(cname, name, type) INIT(cname) {} class(cname) .type name
+#define ATTRIB_3(cname, name, type) class(cname) .type name
#define ATTRIB_4(cname, name, type, val) \
ATTRIB_3(cname, name, type); \
INIT(cname) \
#define REGISTRY(id, max) \
void Register##id(); \
[[accumulate]] void REGISTRY_DEPENDS_(id) {} \
- [[accumulate]] REGISTRY_BEGIN(id) {} \
- [[accumulate]] REGISTRY_END(id) {} \
+ REGISTRY_BEGIN(id) {} \
+ REGISTRY_END(id) {} \
void _Register##id() {} \
int id##_state = 0; \
void Register##id() { if (id##_state) return; id##_state = 1; REGISTRY_DEPENDS_(id); REGISTRY_BEGIN_(id); _Register##id(); id##_state = 2; REGISTRY_END_(id); } \
#include <common/mutators/base.qh>
+// register all possible hooks here
+
+// to use a hook, first register your mutator using REGISTER_MUTATOR
+// then create your function using MUTATOR_HOOKFUNCTION
+
// globals
string cmd_name;
diff = destorg - this.origin;
- if (fabs(diff.x) < 10 && fabs(diff.y) < 10
- && this.goalcurrent == this.goalentity && time < this.goalentity_lock_timeout)
+ // 1. stop if too close to target player (even if frozen)
+ // 2. stop if the locked goal has been reached
+ if ((IS_PLAYER(this.goalcurrent) && vdist(diff, <, 80))
+ || (this.goalcurrent == this.goalentity && time < this.goalentity_lock_timeout && vdist(diff, <, 10)))
{
destorg = this.origin;
- diff.x = 0;
- diff.y = 0;
+ diff = '0 0 0';
}
dir = normalize(diff);
- flatdir = diff;flatdir.z = 0;
- flatdir = normalize(flatdir);
+ flatdir = (diff.z == 0) ? dir : normalize(vec2(diff));
//if (this.bot_dodgevector_time < time)
{
if (trace_ent == this || tracewalk(this, this.origin, this.mins, this.maxs,
tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
{
- LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue");
+ LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue");
navigation_poproute(this);
}
}
string gamemode_name;
-float startitem_failed;
-
string W_Apply_Weaponreplace(string in);
void FixIntermissionClient(entity e);
.WepSet dual_weapons;
IntrusiveList g_monsters;
-STATIC_INIT(g_monsters) { g_monsters = IL_NEW(); }
-
IntrusiveList g_waypoints;
-STATIC_INIT(g_waypoints) { g_waypoints = IL_NEW(); }
-
IntrusiveList g_vehicles;
-STATIC_INIT(g_vehicles) { g_vehicles = IL_NEW(); }
-
IntrusiveList g_turrets;
-STATIC_INIT(g_turrets) { g_turrets = IL_NEW(); }
-
IntrusiveList g_mines;
-STATIC_INIT(g_mines) { g_mines = IL_NEW(); }
-
IntrusiveList g_projectiles;
-STATIC_INIT(g_projectiles) { g_projectiles = IL_NEW(); }
-
IntrusiveList g_items;
-STATIC_INIT(g_items) { g_items = IL_NEW(); }
-
IntrusiveList g_initforplayer;
-STATIC_INIT(g_initforplayer) { g_initforplayer = IL_NEW(); }
-
IntrusiveList g_clones;
-STATIC_INIT(g_clones) { g_clones = IL_NEW(); }
-
-IntrusiveList g_assault_destructibles;
-STATIC_INIT(g_assault_destructibles) { g_assault_destructibles = IL_NEW(); }
-
-IntrusiveList g_assault_objectivedecreasers;
-STATIC_INIT(g_assault_objectivedecreasers) { g_assault_objectivedecreasers = IL_NEW(); }
-
-IntrusiveList g_assault_objectives;
-STATIC_INIT(g_assault_objectives) { g_assault_objectives = IL_NEW(); }
-
IntrusiveList g_spawnpoints;
-STATIC_INIT(g_spawnpoints) { g_spawnpoints = IL_NEW(); }
-
IntrusiveList g_bot_targets;
-STATIC_INIT(g_bot_targets) { g_bot_targets = IL_NEW(); }
-
IntrusiveList g_bot_dodge;
-STATIC_INIT(g_bot_dodge) { g_bot_dodge = IL_NEW(); }
-
IntrusiveList g_damagedbycontents;
-STATIC_INIT(g_damagedbycontents) { g_damagedbycontents = IL_NEW(); }
-
IntrusiveList g_railgunhit;
-STATIC_INIT(g_railgunhit) { g_railgunhit = IL_NEW(); }
-
IntrusiveList g_ladders;
-STATIC_INIT(g_ladders) { g_ladders = IL_NEW(); }
-
IntrusiveList g_locations;
-STATIC_INIT(g_locations) { g_locations = IL_NEW(); }
-
IntrusiveList g_saved_team;
-STATIC_INIT(g_saved_team) { g_saved_team = IL_NEW(); }
-
IntrusiveList g_monster_targets;
-STATIC_INIT(g_monster_targets) { g_monster_targets = IL_NEW(); }
-
IntrusiveList g_pathlib_nodes;
-STATIC_INIT(g_pathlib_nodes) { g_pathlib_nodes = IL_NEW(); }
+STATIC_INIT(defs)
+{
+ g_monsters = IL_NEW();
+ g_waypoints = IL_NEW();
+ g_vehicles = IL_NEW();
+ g_turrets = IL_NEW();
+ g_mines = IL_NEW();
+ g_projectiles = IL_NEW();
+ g_items = IL_NEW();
+ g_initforplayer = IL_NEW();
+ g_clones = IL_NEW();
+ g_spawnpoints = IL_NEW();
+ g_bot_targets = IL_NEW();
+ g_bot_dodge = IL_NEW();
+ g_damagedbycontents = IL_NEW();
+ g_railgunhit = IL_NEW();
+ g_ladders = IL_NEW();
+ g_locations = IL_NEW();
+ g_saved_team = IL_NEW();
+ g_monster_targets = IL_NEW();
+ g_pathlib_nodes = IL_NEW();
+}
}
}
-float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe,
+float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe,
float inflictorselfdamage, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity)
// Returns total damage applies to creatures
{
/// \copyright GNU GPLv2 or any later version.
#include "g_subs.qh"
+#include "mutators/events.qh"
#include <common/weapons/all.qh>
.bool m_isloot; ///< Holds whether item is loot.
/// this item is on the ground.
.bool m_isexpiring;
+entity Item_FindDefinition(string class_name)
+{
+ FOREACH(Items, it.m_canonical_spawnfunc == class_name,
+ {
+ return it;
+ });
+ FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
+ {
+ return it.m_pickup;
+ });
+ return NULL;
+}
+
+bool Item_IsAllowed(string class_name)
+{
+ entity definition = Item_FindDefinition(class_name);
+ if (definition == NULL)
+ {
+ return false;
+ }
+ return Item_IsDefinitionAllowed(definition);
+}
+
+bool Item_IsDefinitionAllowed(entity definition)
+{
+ return !MUTATOR_CALLHOOK(FilterItemDefinition, definition);
+}
+
entity Item_Create(string class_name, vector position, bool no_align)
{
entity item = spawn();
/// \brief Header file that describes the functions related to game items.
/// \copyright GNU GPLv2 or any later version.
+bool startitem_failed;
+
+/// \brief Returns the item definition corresponding to the given class name.
+/// \param[in] class_name Class name to search for.
+/// \return Item definition corresponding to the given class name or NULL is not
+/// found.
+entity Item_FindDefinition(string class_name);
+
+/// \brief Checks whether the items with the specified class name are allowed to
+/// spawn.
+/// \param[in] class_name Item class name to check.
+/// \return True items with the specified class name are allowed to spawn, false
+/// otherwise.
+bool Item_IsAllowed(string class_name);
+
+/// \brief Checks whether the items with the specified definition are allowed to
+/// spawn.
+/// \param[in] definition Item definition to check.
+/// \return True items with the specified definition are allowed to spawn, false
+/// otherwise.
+bool Item_IsDefinitionAllowed(entity definition);
+
/// \brief Creates a new item.
/// \param[in] class_name Class name of the item.
/// \param[in] position Position of the item.
/// \return Item on success, NULL otherwise.
entity Item_Create(string class_name, vector position, bool no_align);
-/// \brief Initializes the item according to classname.
+/// \brief Initializes the item according to class name.
/// \param[in,out] item Item to initialize.
/// \param[in] class_name Class name to use.
/// \return No return.
#include <common/mutators/base.qh>
// register all possible hooks here
+
+// to use a hook, first register your mutator using REGISTER_MUTATOR
+// then create your function using MUTATOR_HOOKFUNCTION
/** called when a player becomes observer, after shared setup */
#define EV_MakePlayerObserver(i, o) \
/**/
MUTATOR_HOOKABLE(CustomizeWaypoint, EV_CustomizeWaypoint);
+/** Check if items having the given definition are allowed to spawn.
+ * Return true to disallow spawning.
+ */
+#define EV_FilterItemDefinition(i, o) \
+ /** item */ i(entity, MUTATOR_ARGV_0_entity) \
+ /**/
+MUTATOR_HOOKABLE(FilterItemDefinition, EV_FilterItemDefinition);
+
/**
* checks if the current item may be spawned (.items and .weapons may be read and written to, as well as the ammo_ fields)
* return error to request removal
.entity sprite;
#define AS_ROUND_DELAY 5
+IntrusiveList g_assault_destructibles;
+IntrusiveList g_assault_objectivedecreasers;
+IntrusiveList g_assault_objectives;
+STATIC_INIT(g_assault)
+{
+ g_assault_destructibles = IL_NEW();
+ g_assault_objectivedecreasers = IL_NEW();
+ g_assault_objectives = IL_NEW();
+}
+
// random functions
void assault_objective_use(entity this, entity actor, entity trigger)
{
#include <server/teamplay.qh>
IntrusiveList g_invasion_roundends;
-STATIC_INIT(g_invasion_roundends) { g_invasion_roundends = IL_NEW(); }
-
IntrusiveList g_invasion_waves;
-STATIC_INIT(g_invasion_waves) { g_invasion_waves = IL_NEW(); }
-
IntrusiveList g_invasion_spawns;
-STATIC_INIT(g_invasion_spawns) { g_invasion_spawns = IL_NEW(); }
+STATIC_INIT(g_invasion)
+{
+ g_invasion_roundends = IL_NEW();
+ g_invasion_waves = IL_NEW();
+ g_invasion_spawns = IL_NEW();
+}
float autocvar_g_invasion_round_timelimit;
float autocvar_g_invasion_spawnpoint_spawn_delay;
return true;
}
-MUTATOR_HOOKFUNCTION(lms, FilterItem)
+MUTATOR_HOOKFUNCTION(lms, FilterItemDefinition)
{
- entity item = M_ARGV(0, entity);
+ entity definition = M_ARGV(0, entity);
- if(autocvar_g_lms_extra_lives)
- if(item.itemdef == ITEM_ExtraLife)
+ if (autocvar_g_lms_extra_lives && definition == ITEM_ExtraLife)
+ {
return false;
-
+ }
return true;
}
}
}
+ if (!Item_IsDefinitionAllowed(wpn.m_pickup))
+ {
+ delete(this);
+ startitem_failed = true;
+ return;
+ }
+
if (!this.respawntime)
{
if (wpn.spawnflags & WEP_FLAG_SUPERWEAPON)
err=$?
set -e
if [ ${err} -ne 0 ]; then return ${err}; fi
- sed 's/^#\(line\)\? \([[:digit:]]\+\) "\(.*\)".*/\n#pragma file(\3)\n#pragma line(\2)/g' "${WORKDIR}/${MODE}.txt"
+ sed -E 's/^#(line)? ([[:digit:]]+) "(.*)".*/'$'\\\n''#pragma file(\3)'$'\\\n''#pragma line(\2)/g' "${WORKDIR}/${MODE}.txt"
}
function qcc() {