]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'Lyberta/URS2' into Lyberta/RandomStartWeapons
authorLyberta <lyberta@lyberta.net>
Mon, 28 Aug 2017 04:45:39 +0000 (07:45 +0300)
committerLyberta <lyberta@lyberta.net>
Mon, 28 Aug 2017 04:45:39 +0000 (07:45 +0300)
defaultOverkill.cfg
qcsrc/common/t_items.qc
qcsrc/common/t_items.qh
qcsrc/common/triggers/func/rotating.qc
qcsrc/server/client.qc
qcsrc/server/mutators/events.qh

index 1dc68c70de1a085b438bc79d4cf7a947ae5e4d1c..2444301b9e7b34c75b8bacf3ebdd367615ec4939 100644 (file)
@@ -14,6 +14,8 @@ set sv_defaultcharacter 1
 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
 
index 0f1e621610521eaa3141179c930e96819c2ba389..5f545151b1eb88d201217bef61e64f237221ca5f 100644 (file)
@@ -682,57 +682,134 @@ void Item_ScheduleInitialRespawn(entity e)
        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;
@@ -740,58 +817,25 @@ void GivePlayerResource(entity player, .float resource_type, float amount)
        }
 }
 
-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,
@@ -889,7 +933,7 @@ float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax
                        {
                                amount = ammomax - player.(ammotype);
                        }
-                       GivePlayerResource(player, ammotype, amount);
+                       GivePlayerResourceViaProperty(player, ammotype, amount);
                        return true;
                }
        }
@@ -898,7 +942,8 @@ float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax
                float mi = min(item.(ammotype), ammomax);
                if (player.(ammotype) < mi)
                {
-                       GivePlayerResource(player, ammotype, mi - player.(ammotype));
+                       GivePlayerResourceViaProperty(player, ammotype, mi -
+                               player.(ammotype));
                }
                return true;
        }
index f633148f9b95658b2e830407b53ca57195aaaaaa..1cf55b13dd405ebca472fde9ac57af73beced6c7 100644 (file)
@@ -7,6 +7,19 @@
 /// \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
@@ -87,12 +100,35 @@ void Item_ScheduleRespawn(entity e);
 
 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.
@@ -106,13 +142,6 @@ void GivePlayerHealth(entity player, float amount);
 /// \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.
index 9715c25452dcaef75849c5700f6b37c5a09b6b05..6268dcfeb86ea6f5fc7d9b981b7e22dd34240bc9 100644 (file)
@@ -1,5 +1,7 @@
 #include "rotating.qh"
 #ifdef SVQC
+const int FUNC_ROTATING_STARTOFF = BIT(4);
+
 void func_rotating_setactive(entity this, int astate)
 {
        if (astate == ACTIVE_TOGGLE)
@@ -18,6 +20,22 @@ void func_rotating_setactive(entity this, int astate)
                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)
@@ -34,16 +52,15 @@ spawnfunc(func_rotating)
                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
@@ -51,6 +68,15 @@ spawnfunc(func_rotating)
 
        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 == ""))
@@ -72,6 +98,6 @@ spawnfunc(func_rotating)
        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
index 1997b8e5776d887fd26f804585845b04a70f550e..4e03cde9cde343d51dcd0cb40d14d11ac3d64ab5 100644 (file)
@@ -1632,8 +1632,8 @@ void player_regen(entity this)
                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;
@@ -1660,7 +1660,7 @@ void player_regen(entity this)
 
                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);
        }
index bc09d7a8cd9d92d3da6340807e8a09fd13b384cc..eddb1e5caaf7fb09991760723c7a8f55f38df5ba 100644 (file)
@@ -620,6 +620,26 @@ enum {
        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) \