set sv_defaultplayermodel "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
set sv_defaultplayermodel_red "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
set sv_defaultplayermodel_blue "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
+set sv_defaultplayermodel_yellow "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
+set sv_defaultplayermodel_pink "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
set g_respawn_ghosts 0
Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : ITEM_RESPAWNTIME_INITIAL(e)));
}
-void GivePlayerResource(entity player, .float resource_type, float amount)
+int GetResourceType(.float resource_property)
+{
+ switch (resource_property)
+ {
+ case health: { return RESOURCE_HEALTH; }
+ case armorvalue: { return RESOURCE_ARMOR; }
+ case ammo_shells: { return RESOURCE_SHELLS; }
+ case ammo_nails: { return RESOURCE_BULLETS; }
+ case ammo_rockets: { return RESOURCE_ROCKETS; }
+ case ammo_cells: { return RESOURCE_CELLS; }
+ case ammo_plasma: { return RESOURCE_PLASMA; }
+ case ammo_fuel: { return RESOURCE_FUEL; }
+ }
+ error("GetResourceType: Invalid property.");
+ return 0;
+}
+
+.float GetResourceProperty(int resource_type)
+{
+ switch (resource_type)
+ {
+ case RESOURCE_HEALTH: { return health; }
+ case RESOURCE_ARMOR: { return armorvalue; }
+ case RESOURCE_SHELLS: { return ammo_shells; }
+ case RESOURCE_BULLETS: { return ammo_nails; }
+ case RESOURCE_ROCKETS: { return ammo_rockets; }
+ case RESOURCE_CELLS: { return ammo_cells; }
+ case RESOURCE_PLASMA: { return ammo_plasma; }
+ case RESOURCE_FUEL: { return ammo_fuel; }
+ }
+ error("GetResourceProperty: Invalid resource type.");
+ return health;
+}
+
+float GetResourceLimit(int resource_type)
+{
+ float limit;
+ switch (resource_type)
+ {
+ case RESOURCE_HEALTH:
+ {
+ limit = autocvar_g_balance_health_limit;
+ break;
+ }
+ case RESOURCE_ARMOR:
+ {
+ limit = autocvar_g_balance_armor_limit;
+ break;
+ }
+ case RESOURCE_SHELLS:
+ {
+ limit = g_pickup_shells_max;
+ break;
+ }
+ case RESOURCE_BULLETS:
+ {
+ limit = g_pickup_nails_max;
+ break;
+ }
+ case RESOURCE_ROCKETS:
+ {
+ limit = g_pickup_rockets_max;
+ break;
+ }
+ case RESOURCE_CELLS:
+ {
+ limit = g_pickup_cells_max;
+ break;
+ }
+ case RESOURCE_PLASMA:
+ {
+ limit = g_pickup_plasma_max;
+ break;
+ }
+ case RESOURCE_FUEL:
+ {
+ limit = autocvar_g_balance_fuel_limit;
+ break;
+ }
+ default:
+ {
+ error("GetResourceLimit: Invalid resource type.");
+ return 0;
+ }
+ }
+ MUTATOR_CALLHOOK(GetResourceLimit, resource_type, limit);
+ limit = M_ARGV(1, float);
+ if (limit > RESOURCE_AMOUNT_HARD_LIMIT)
+ {
+ limit = RESOURCE_AMOUNT_HARD_LIMIT;
+ }
+ return limit;
+}
+
+void GivePlayerResource(entity player, int resource_type, float amount)
{
if (amount == 0)
{
return;
}
+ bool forbid = MUTATOR_CALLHOOK(GivePlayerResource, player, resource_type,
+ amount);
+ if (forbid)
+ {
+ return;
+ }
+ resource_type = M_ARGV(1, int);
+ amount = M_ARGV(2, float);
+ .float resource_property = GetResourceProperty(resource_type);
+ float max_amount = GetResourceLimit(resource_type);
+ player.(resource_property) = bound(player.(resource_property),
+ player.(resource_property) + amount, max_amount);
switch (resource_type)
{
- case health:
+ case RESOURCE_HEALTH:
{
- // Ugly hack. We do not check if health goes beyond hard limit since
- // currently it is done in player_regen. We need to bring back this
- // check when other code is ported to this function.
- player.health = bound(player.health, player.health + amount,
- autocvar_g_balance_health_limit);
- // Correct code:
- //player.health = bound(player.health, player.health + amount,
- // min(autocvar_g_balance_health_limit,
- // RESOURCE_AMOUNT_HARD_LIMIT));
player.pauserothealth_finished = max(player.pauserothealth_finished,
time + autocvar_g_balance_pause_health_rot);
return;
}
- case armorvalue:
+ case RESOURCE_ARMOR:
{
- // Ugly hack. We do not check if armor goes beyond hard limit since
- // currently it is done in player_regen. We need to bring back this
- // check when other code is ported to this function.
- player.armorvalue = bound(player.armorvalue, player.armorvalue +
- amount, autocvar_g_balance_armor_limit);
- // Correct code:
- //player.armorvalue = bound(player.armorvalue, player.armorvalue +
- // amount, min(autocvar_g_balance_armor_limit,
- // RESOURCE_AMOUNT_HARD_LIMIT));
player.pauserotarmor_finished = max(player.pauserotarmor_finished,
time + autocvar_g_balance_pause_armor_rot);
return;
}
- case ammo_shells:
- case ammo_nails:
- case ammo_rockets:
- case ammo_cells:
- case ammo_plasma:
+ case RESOURCE_FUEL:
{
- GivePlayerAmmo(player, resource_type, amount);
- return;
- }
- case ammo_fuel:
- {
- player.ammo_fuel = bound(player.ammo_fuel, player.ammo_fuel +
- amount, min(g_pickup_fuel_max, RESOURCE_AMOUNT_HARD_LIMIT));
player.pauserotfuel_finished = max(player.pauserotfuel_finished,
time + autocvar_g_balance_pause_fuel_rot);
return;
}
}
-void GivePlayerHealth(entity player, float amount)
+void GivePlayerResourceViaProperty(entity player, .float resource_property,
+ float amount)
{
- GivePlayerResource(player, health, amount);
+ GivePlayerResource(player, GetResourceType(resource_property), amount);
}
-void GivePlayerArmor(entity player, float amount)
+void GivePlayerHealth(entity player, float amount)
{
- GivePlayerResource(player, armorvalue, amount);
+ GivePlayerResource(player, RESOURCE_HEALTH, amount);
}
-void GivePlayerAmmo(entity player, .float ammotype, float amount)
+void GivePlayerArmor(entity player, float amount)
{
- if (amount == 0)
- {
- return;
- }
- float maxvalue = RESOURCE_AMOUNT_HARD_LIMIT;
- switch (ammotype)
- {
- case ammo_shells:
- {
- maxvalue = g_pickup_shells_max;
- break;
- }
- case ammo_cells:
- {
- maxvalue = g_pickup_cells_max;
- break;
- }
- case ammo_rockets:
- {
- maxvalue = g_pickup_rockets_max;
- break;
- }
- case ammo_plasma:
- {
- maxvalue = g_pickup_plasma_max;
- break;
- }
- case ammo_nails:
- {
- maxvalue = g_pickup_nails_max;
- break;
- }
- }
- player.(ammotype) = min(player.(ammotype) + amount,
- min(maxvalue, RESOURCE_AMOUNT_HARD_LIMIT));
+ GivePlayerResource(player, RESOURCE_ARMOR, amount);
}
void GivePlayerFuel(entity player, float amount)
{
- GivePlayerResource(player, ammo_fuel, amount);
+ GivePlayerResource(player, RESOURCE_FUEL, amount);
}
void GivePlayerRandomWeapons(entity player, int num_weapons,
{
amount = ammomax - player.(ammotype);
}
- GivePlayerResource(player, ammotype, amount);
+ GivePlayerResourceViaProperty(player, ammotype, amount);
return true;
}
}
float mi = min(item.(ammotype), ammomax);
if (player.(ammotype) < mi)
{
- GivePlayerResource(player, ammotype, mi - player.(ammotype));
+ GivePlayerResourceViaProperty(player, ammotype, mi -
+ player.(ammotype));
}
return true;
}
/// \brief Unconditional maximum amount of resources the player can have.
const int RESOURCE_AMOUNT_HARD_LIMIT = 999;
+/// \brief Describes the available resource types.
+enum
+{
+ RESOURCE_HEALTH, ///< Health.
+ RESOURCE_ARMOR, ///< Armor.
+ RESOURCE_SHELLS, ///< Shells (used by shotgun).
+ RESOURCE_BULLETS, ///< Bullets (used by machinegun and rifle)
+ RESOURCE_ROCKETS, ///< Rockets (used by mortar, hagar, devastator, etc).
+ RESOURCE_CELLS, ///< Cells (used by electro, crylink, vortex, etc)
+ RESOURCE_PLASMA, ///< Plasma (unused).
+ RESOURCE_FUEL ///< Fuel (used by jetpack).
+};
+
const int AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel
// item networking
void Item_ScheduleInitialRespawn(entity e);
+/// \brief Converts resource entity property to resource type.
+/// \param[in] resource_property Resource entity property to convert.
+/// \return Resource type (a RESOURCE_* constant).
+int GetResourceType(.float resource_property);
+
+/// \brief Converts resource type (a RESOURCE_* constant) to entity property.
+/// \param[in] resource_type Type of the resource.
+/// \return Entity proprty for that resource.
+.float GetResourceProperty(int resource_type);
+
+/// \brief Returns the maximum amount of the given resource.
+/// \param[in] resource_type Type of the resource (a RESOURCE_* constant).
+/// \return Maximum amount of the given resource.
+float GetResourceLimit(int resource_type);
+
/// \brief Gives player a resource such as health, armor or ammo.
/// \param[in,out] player Player to give resource to.
-/// \param[in] resource_type Type of the resource.
+/// \param[in] resource_type Type of the resource (a RESOURCE_* constant).
/// \param[in] amount Amount of resource to give.
/// \return No return.
-void GivePlayerResource(entity player, .float resource_type, float amount);
+void GivePlayerResource(entity player, int resource_type, float amount);
+
+/// \brief Gives player a resource such as health, armor or ammo.
+/// \param[in,out] player Player to give resource to.
+/// \param[in] resource_property Entity property of the resource.
+/// \param[in] amount Amount of resource to give.
+/// \return No return.
+void GivePlayerResourceViaProperty(entity player, .float resource_property,
+ float amount);
/// \brief Gives health to the player.
/// \param[in,out] player Player to give health to.
/// \return No return.
void GivePlayerArmor(entity player, float amount);
-/// \brief Gives ammo of the specified type to the player.
-/// \param[in,out] player Player to give ammo to.
-/// \param[in] type Ammo type property.
-/// \param[in] amount Amount of ammo to give.
-/// \return No return.
-void GivePlayerAmmo(entity player, .float ammotype, float amount);
-
/// \brief Gives fuel to the player.
/// \param[in,out] player Player to give fuel to.
/// \param[in] amount Amount of fuel to give.
#include "rotating.qh"
#ifdef SVQC
+const int FUNC_ROTATING_STARTOFF = BIT(4);
+
void func_rotating_setactive(entity this, int astate)
{
if (astate == ACTIVE_TOGGLE)
this.avelocity = this.pos1;
}
+void func_rotating_reset(entity this)
+{
+ // TODO: reset angles as well?
+
+ if(this.spawnflags & FUNC_ROTATING_STARTOFF)
+ {
+ this.avelocity = '0 0 0';
+ this.active = ACTIVE_NOT;
+ }
+ else
+ {
+ this.avelocity = this.pos1;
+ this.active = ACTIVE_ACTIVE;
+ }
+}
+
/*QUAKED spawnfunc_func_rotating (0 .5 .8) ? - - X_AXIS Y_AXIS
Brush model that spins in place on one axis (default Z).
speed : speed to rotate (in degrees per second)
ambientsound(this.origin, this.noise, VOL_BASE, ATTEN_IDLE);
}
- this.active = ACTIVE_ACTIVE;
this.setactive = func_rotating_setactive;
if (!this.speed)
this.speed = 100;
// FIXME: test if this turns the right way, then remove this comment (negate as needed)
- if (this.spawnflags & 4) // X (untested)
+ if (this.spawnflags & BIT(2)) // X (untested)
this.avelocity = '0 0 1' * this.speed;
// FIXME: test if this turns the right way, then remove this comment (negate as needed)
- else if (this.spawnflags & 8) // Y (untested)
+ else if (this.spawnflags & BIT(3)) // Y (untested)
this.avelocity = '1 0 0' * this.speed;
// FIXME: test if this turns the right way, then remove this comment (negate as needed)
else // Z
this.pos1 = this.avelocity;
+ // do this after setting pos1, so we can safely reactivate the func_rotating
+ if(this.spawnflags & FUNC_ROTATING_STARTOFF)
+ {
+ this.avelocity = '0 0 0';
+ this.active = ACTIVE_NOT;
+ }
+ else
+ this.active = ACTIVE_ACTIVE;
+
if(this.dmg && (this.message == ""))
this.message = " was squished";
if(this.dmg && (this.message2 == ""))
this.nextthink = this.ltime + 999999999;
setthink(this, SUB_NullThink); // for PushMove
- // TODO make a reset function for this one
+ this.reset = func_rotating_reset;
}
#endif
float mina, maxa, limith, limita;
maxa = autocvar_g_balance_armor_rotstable;
mina = autocvar_g_balance_armor_regenstable;
- limith = autocvar_g_balance_health_limit;
- limita = autocvar_g_balance_armor_limit;
+ limith = GetResourceLimit(RESOURCE_HEALTH);
+ limita = GetResourceLimit(RESOURCE_ARMOR);
regen_health_rotstable = regen_health_rotstable * max_mod;
regen_health_stable = regen_health_stable * max_mod;
maxf = autocvar_g_balance_fuel_rotstable;
minf = autocvar_g_balance_fuel_regenstable;
- limitf = autocvar_g_balance_fuel_limit;
+ limitf = GetResourceLimit(RESOURCE_FUEL);
this.ammo_fuel = CalcRotRegen(this.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, frametime * (time > this.pauseregen_finished) * ((this.items & ITEM_JetpackRegen.m_itemid) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > this.pauserotfuel_finished), limitf);
}
MUT_ITEMTOUCH_PICKUP // return this flag to have the item "picked up" and taken even after mutator handled it
};
+/** Called when the amount of player resources changes. Can be used to override
+resource limit. */
+#define EV_GetResourceLimit(i, o) \
+ /** resource type */ i(int, MUTATOR_ARGV_0_int) \
+ /** limit */ i(float, MUTATOR_ARGV_1_float) \
+ /**/ o(float, MUTATOR_ARGV_1_float) \
+ /**/
+MUTATOR_HOOKABLE(GetResourceLimit, EV_GetResourceLimit);
+
+/** Called when player is being given some resource. See RESOURCE_* constants
+for resource types. Return true to forbid giving. */
+#define EV_GivePlayerResource(i, o) \
+ /** player */ i(entity, MUTATOR_ARGV_0_entity) \
+ /** resource type */ i(int, MUTATOR_ARGV_1_int) \
+ /**/ o(int, MUTATOR_ARGV_1_int) \
+ /** amount */ i(float, MUTATOR_ARGV_2_float) \
+ /**/ o(float, MUTATOR_ARGV_2_float) \
+ /**/
+MUTATOR_HOOKABLE(GivePlayerResource, EV_GivePlayerResource);
+
/** called at when a player connect */
#define EV_ClientConnect(i, o) \
/** player */ i(entity, MUTATOR_ARGV_0_entity) \