From e6b3514bdd6048e5b677385330ec63f9c52c2148 Mon Sep 17 00:00:00 2001 From: Norby Date: Wed, 22 Mar 2017 04:04:31 +0100 Subject: [PATCH 1/2] * Smooth encumbrance system v1.2 --- base/pics/ui/screen.png | Bin 7121 -> 0 bytes base/ufos/ui/equipment.ufo | 18 ++++-- base/ufos/ui/inv_stat.ufo | 28 +++++++--- src/client/battlescape/cl_actor.cpp | 89 +++++++++++++++++++----------- src/client/battlescape/cl_actor.h | 3 +- src/client/battlescape/cl_battlescape.cpp | 2 +- src/client/battlescape/cl_hud.cpp | 20 +++++-- src/client/cl_inventory_callbacks.cpp | 25 +++++++-- src/client/cl_video.cpp | 6 +- src/game/g_actor.cpp | 57 ++++++++++++++++++- src/game/g_actor.h | 1 + src/game/g_combat.cpp | 2 +- src/game/g_health.cpp | 42 -------------- src/game/g_health.h | 1 - src/game/g_match.cpp | 2 +- src/game/g_move.cpp | 4 +- src/game/g_vis.cpp | 2 +- src/game/q_shared.h | 15 ++++- 18 files changed, 202 insertions(+), 115 deletions(-) delete mode 100644 base/pics/ui/screen.png diff --git a/base/pics/ui/screen.png b/base/pics/ui/screen.png deleted file mode 100644 index 55dcacd4f5878b766334ff0a99baafb1fd9f8c6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7121 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 > 0 ) { *node:parent.bt_load@color = "0 1 0 1" } - elif ( <3> < 0 ) { *node:parent.bt_load@color = "1 1 0 1" } - else { *node:parent.bt_load@color = "1 1 1 1" } + if ( <5> > 8 ) { *node:parent.bt_load@color = "0.5 0 0 1" } //darkest red + elif ( <5> > 7 ) { *node:parent.bt_load@color = "0.6 0 0 1" } //darker red + elif ( <5> > 6 ) { *node:parent.bt_load@color = "0.7 0 0 1" } //dark red + elif ( <5> > 5 ) { *node:parent.bt_load@color = "1 0 0 1" } //red + elif ( <5> > 4 ) { *node:parent.bt_load@color = "1 0.4 0 1" } //dark orange + elif ( <5> > 3 ) { *node:parent.bt_load@color = "1 0.7 0 1" } //orange + elif ( <3> < 0 ) { *node:parent.bt_load@color = "1 1 0 1" } //yellow + elif ( <3> > 0 ) { *node:parent.bt_load@color = "0 1 0 1" } //green + else { *node:parent.bt_load@color = "0.56 0.81 0.76 1" } //ufo2.6 theme color if ( <4> > 0 ) { *node:parent.bt_load@flash = true } else { *node:parent.bt_load@flash = false } } diff --git a/base/ufos/ui/inv_stat.ufo b/base/ufos/ui/inv_stat.ufo index 37f6c88611..8a9ac3962c 100644 --- a/base/ufos/ui/inv_stat.ufo +++ b/base/ufos/ui/inv_stat.ufo @@ -79,12 +79,12 @@ local inv_stats_hud = ufox.build_window({ { name = "bt_load", class = "button", - pos = {255, 35}, - contentalign = ufo.ALIGN_CL, - text = "_0/0 Kg", + pos = {65, 36}, + contentalign = ufo.ALIGN_CR, + text = "_0/0 Kg 0 TU (+0)", color = {0.56, 0.81, 0.76, 1}, - flashcolor = {1, 0, 0, 1}, - size = {106, 25}, + flashcolor = {1, 0.5, 0.5, 1}, + size = {306, 25}, on_click = function (sender) ufo.cmd("hud_updateactorload;") end }, { @@ -237,13 +237,25 @@ local inv_stats_hud = ufox.build_window({ { name = "inv_actorload", class = "confunc", - on_click = function (sender, text, tooltip, penalty, warnings) + on_click = function (sender, text, tooltip, penalty, warnings, moveTU) sender:root():child("bt_load"):set_text(text) sender:root():child("bt_load"):set_tooltip(tooltip) - if (penalty > 0) then - sender:root():child("bt_load"):set_color(0, 1, 0, 1) + if (moveTU > 8) then + sender:root():child("bt_load"):set_color(0.5, 0, 0, 1) + elseif (moveTU > 7) then + sender:root():child("bt_load"):set_color(0.6, 0, 0, 1) + elseif (moveTU > 6) then + sender:root():child("bt_load"):set_color(0.7, 0, 0, 1) + elseif (moveTU > 5) then + sender:root():child("bt_load"):set_color(1, 0, 0, 1) + elseif (moveTU > 4) then + sender:root():child("bt_load"):set_color(1, 0.7, 0, 1) + elseif (moveTU > 3) then + sender:root():child("bt_load"):set_color(1, 0.4, 0, 1) elseif (penalty < 0) then sender:root():child("bt_load"):set_color(1, 1, 0, 1) + elseif (penalty > 0) then + sender:root():child("bt_load"):set_color(0, 1, 0, 1) else sender:root():child("bt_load"):set_color(0.56, 0.81, 0.76, 1) end diff --git a/src/client/battlescape/cl_actor.cpp b/src/client/battlescape/cl_actor.cpp index 122a3c0508..86f421ad98 100644 --- a/src/client/battlescape/cl_actor.cpp +++ b/src/client/battlescape/cl_actor.cpp @@ -291,43 +291,66 @@ void CL_ActorReserveTUs (const le_t* le, const reservation_types_t type, const i } /** - * @brief Returns the actor injury modifier of the specified type. - * @param[in] le The actor. - * @param[in] type The injury modifier type. - * @return The injury modifier for this actor. + * @brief Returns the actor modifier of the specified type. + * @param[in] le The local entity of the actor. + * @param[in] type The modifier type. + * @return The modifier for this actor. */ -float CL_ActorInjuryModifier (const le_t* le, const modifier_types_t type) +float CL_ActorModifier (const le_t* le, const modifier_types_t type) { float mod = 0; - if (le) { const character_t* chr = CL_ActorGetChr(le); - if (!chr) - return 0; - const BodyData* bodyTemplate = chr->teamDef->bodyTemplate; - for (int bodyPart = 0; bodyPart < bodyTemplate->numBodyParts(); ++bodyPart) { - const int threshold = le->maxHP * bodyTemplate->woundThreshold(bodyPart); - const int injury = (le->wounds.woundLevel[bodyPart] + le->wounds.treatmentLevel[bodyPart] * 0.5); - if (injury > threshold) - mod += 2 * bodyTemplate->penalty(bodyPart, type) * injury / le->maxHP; - } + mod = CL_ActorModifier (chr, type); + } + return mod; +} - switch (type) { - case MODIFIER_REACTION: - mod += CL_ActorInjuryModifier(le, MODIFIER_SHOOTING); - break; - case MODIFIER_ACCURACY: - case MODIFIER_SHOOTING: - ++mod; - break; - case MODIFIER_MOVEMENT: - mod = ceil(mod); - break; - default: - Com_Printf("CL_ActorInjuryPenalty: Unused modifier type %i\n", type); - mod = 0; - break; - } +/** + * @brief Returns the modifier of the specified type caused by injury and encumbrance. + * @param[in] chr The actor. + * @param[in] type The modifier type. + * @return The modifier for this actor. + */ +float CL_ActorModifier (const character_t* chr, const modifier_types_t type) +{ + float mod = 0; + float weight = 0.0f; + + if (!chr) + return 0; + const BodyData* bodyTemplate = chr->teamDef->bodyTemplate; + for (int bodyPart = 0; bodyPart < bodyTemplate->numBodyParts(); ++bodyPart) { + const int threshold = chr->maxHP * bodyTemplate->woundThreshold(bodyPart); + const int injury = (chr->wounds.woundLevel[bodyPart] + chr->wounds.treatmentLevel[bodyPart] * 0.5); + if (injury > threshold) + mod += 2 * bodyTemplate->penalty(bodyPart, type) * injury / chr->maxHP; + } + + switch (type) { + case MODIFIER_REACTION: + mod += CL_ActorModifier(chr, MODIFIER_SHOOTING); + break; + case MODIFIER_ACCURACY: + case MODIFIER_SHOOTING: + ++mod; + break; + case MODIFIER_MOVEMENT: + mod = ceil(mod); + //reduce movement speed due to encumbrance + weight = ( chr->inv.getWeight() / chr->score.skills[ABILITY_POWER] ) / WEIGHT_FACTOR; + if( weight > WEIGHT_HEAVY ) mod++; + if( weight >= WEIGHT_RED1 ) mod++; + if( weight >= WEIGHT_RED2 ) mod++; + if( weight >= WEIGHT_RED3 ) mod++; + if( weight >= WEIGHT_RED4 ) mod++; + if( weight >= WEIGHT_RED5 ) mod++; + if( weight > WEIGHT_RED6 ) mod++; + break; + default: + Com_Printf("CL_ActorModifier: Unused modifier type %i\n", type); + mod = 0; + break; } return mod; } @@ -344,7 +367,7 @@ int CL_ActorTimeForFireDef (const le_t* le, const fireDef_t* fd, bool reaction) if (!fd) return -1; - return fd->time * CL_ActorInjuryModifier(le, reaction ? MODIFIER_REACTION : MODIFIER_SHOOTING); + return fd->time * CL_ActorModifier(le, reaction ? MODIFIER_REACTION : MODIFIER_SHOOTING); } /* @@ -754,7 +777,7 @@ static byte CL_ActorMoveLength (const le_t* le, const pos3_t to) } return std::min(ROUTING_NOT_REACHABLE, length + static_cast(numSteps - * CL_ActorInjuryModifier(le, MODIFIER_MOVEMENT)) + autostandTU); + * CL_ActorModifier(le, MODIFIER_MOVEMENT)) + autostandTU); } /** diff --git a/src/client/battlescape/cl_actor.h b/src/client/battlescape/cl_actor.h index 4bea2b542a..ecbe2c56c0 100644 --- a/src/client/battlescape/cl_actor.h +++ b/src/client/battlescape/cl_actor.h @@ -81,7 +81,8 @@ void CL_ActorStartMove(le_t* le, const pos3_t to); void CL_ActorShoot(const le_t* le, const pos3_t at); int CL_ActorGetContainerForReload(Item** ic, const Inventory* inv, const objDef_t* weapon); void CL_ActorPlaySound(const le_t* le, actorSound_t soundType); -float CL_ActorInjuryModifier(const le_t* le, const modifier_types_t type); +float CL_ActorModifier(const le_t* le, const modifier_types_t type); +float CL_ActorModifier(const character_t* chr, const modifier_types_t type); int CL_ActorTimeForFireDef(const le_t* le, const fireDef_t* fd, bool reaction = false); void CL_ActorActionMouse(void); diff --git a/src/client/battlescape/cl_battlescape.cpp b/src/client/battlescape/cl_battlescape.cpp index b7ce46cc3f..8d46a4ee14 100644 --- a/src/client/battlescape/cl_battlescape.cpp +++ b/src/client/battlescape/cl_battlescape.cpp @@ -219,7 +219,7 @@ int CL_GetHitProbability (const le_t* actor) Com_Error(ERR_DROP, "No character given for local entity"); const float acc = GET_ACC(chr->score.skills[ABILITY_ACCURACY], - actor->fd->weaponSkill ? chr->score.skills[actor->fd->weaponSkill] : 0.0, CL_ActorInjuryModifier(actor, MODIFIER_ACCURACY)); + actor->fd->weaponSkill ? chr->score.skills[actor->fd->weaponSkill] : 0.0, CL_ActorModifier(actor, MODIFIER_ACCURACY)); const float crouch = (LE_IsCrouched(actor) && actor->fd->crouch) ? actor->fd->crouch : 1.0; diff --git a/src/client/battlescape/cl_hud.cpp b/src/client/battlescape/cl_hud.cpp index 23a8ce7249..8faaa03caf 100644 --- a/src/client/battlescape/cl_hud.cpp +++ b/src/client/battlescape/cl_hud.cpp @@ -907,7 +907,7 @@ static void HUD_UpdateButtons (const le_t* le) HUD_SetWeaponButton(BT_LEFT_RELOAD, BT_STATE_DISABLE); } - const float shootingPenalty = CL_ActorInjuryModifier(le, MODIFIER_SHOOTING); + const float shootingPenalty = CL_ActorModifier(le, MODIFIER_SHOOTING); /* Headgear button */ const Item* headgear = le->inv.getHeadgear(); if (headgear) { @@ -1324,9 +1324,9 @@ static void HUD_UpdateActorLoad_f (void) const character_t* chr = CL_ActorGetChr(selActor); const int invWeight = selActor->inv.getWeight(); const int maxWeight = GAME_GetChrMaxLoad(chr); - const float penalty = GET_ENCUMBRANCE_PENALTY(invWeight, maxWeight); + const float encPenalty = GET_ENCUMBRANCE_PENALTY(invWeight, maxWeight); const int normalTU = GET_TU(chr->score.skills[ABILITY_SPEED], 1.0f - WEIGHT_NORMAL_PENALTY); - const int tus = GET_TU(chr->score.skills[ABILITY_SPEED], penalty); + const int tus = GET_TU(chr->score.skills[ABILITY_SPEED], encPenalty); const int tuPenalty = tus - normalTU; int count = 0; @@ -1352,11 +1352,19 @@ static void HUD_UpdateActorLoad_f (void) if (count > 0) UI_Popup(_("Warning"), popupText); + const int moveTU = TU_MOVE_STRAIGHT + CL_ActorModifier(chr, MODIFIER_MOVEMENT); char label[MAX_VAR]; + Com_sprintf(label, sizeof(label), "%g/%i %s %i %s (%+i) %s: %i", invWeight / WEIGHT_FACTOR, maxWeight, _("Kg"), + tus, _("TU"), tuPenalty, _("Move"), (int)(tus/moveTU) ); + char tooltip[MAX_VAR]; - Com_sprintf(label, sizeof(label), "%g/%i %s", invWeight / WEIGHT_FACTOR, maxWeight, _("Kg")); - Com_sprintf(tooltip, sizeof(tooltip), "%s %i (%+i)", _("TU:"), tus, tuPenalty); - UI_ExecuteConfunc("inv_actorload \"%s\" \"%s\" %f %i", label, tooltip, WEIGHT_NORMAL_PENALTY - (1.0f - penalty), count); + float weight_percent = ((int)(invWeight/maxWeight))/10.0f; + float weight_multiplier = std::min(WEIGHT_MAX_MULTIPLIER, ((int)((1/encPenalty)*10))/10.0f); + Com_sprintf(tooltip, sizeof(tooltip), " %gx %g%% %iTU/%s ", + weight_multiplier, weight_percent, moveTU, _("Move")); + + //call inv_actorload in base/ufos/ui/inv_stat.ufo + UI_ExecuteConfunc("inv_actorload \"%s\" \"%s\" %i %i %i", label, tooltip, tuPenalty, count, moveTU); } /** diff --git a/src/client/cl_inventory_callbacks.cpp b/src/client/cl_inventory_callbacks.cpp index 1c875e8ee7..e186aa8a41 100644 --- a/src/client/cl_inventory_callbacks.cpp +++ b/src/client/cl_inventory_callbacks.cpp @@ -29,6 +29,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "ui/ui_nodes.h" #include "cgame/cl_game.h" #include "ui/ui_popup.h" +#include "renderer/r_image.h" +#include "renderer/r_model.h" +#include "cl_renderer.h" +#include "battlescape/cl_localentity.h" +#include "battlescape/cl_actor.h" static const objDef_t* currentDisplayedObject; static int itemIndex; @@ -349,6 +354,7 @@ static void INV_UpdateObject_f (void) INV_ItemDescription(obj); } + /** * @brief Update the equipment weight for the selected actor. */ @@ -365,9 +371,9 @@ static void INV_UpdateActorLoad_f (void) const float invWeight = chr->inv.getWeight(); const int maxWeight = GAME_GetChrMaxLoad(chr); - const float penalty = GET_ENCUMBRANCE_PENALTY(invWeight, maxWeight); + const float encPenalty = GET_ENCUMBRANCE_PENALTY(invWeight, maxWeight); const int normalTU = GET_TU(chr->score.skills[ABILITY_SPEED], 1.0f - WEIGHT_NORMAL_PENALTY); - const int tus = GET_TU(chr->score.skills[ABILITY_SPEED], penalty); + const int tus = GET_TU(chr->score.skills[ABILITY_SPEED], encPenalty); const int tuPenalty = tus - normalTU; int count = 0; @@ -396,12 +402,19 @@ static void INV_UpdateActorLoad_f (void) if ((Cmd_Argc() < 3 || atoi(Cmd_Argv(2)) == 0) && count > 0) UI_Popup(_("Warning"), popupText); + const int moveTU = TU_MOVE_STRAIGHT + CL_ActorModifier(chr, MODIFIER_MOVEMENT); char label[MAX_VAR]; + Com_sprintf(label, sizeof(label), "%g/%i %s %i %s (%+i) %s: %i", invWeight / WEIGHT_FACTOR, maxWeight, _("Kg"), + tus, _("TU"), tuPenalty, _("Move"), (int)(tus/moveTU) ); + char tooltip[MAX_VAR]; - Com_sprintf(label, sizeof(label), "%g/%i %s %s", invWeight / WEIGHT_FACTOR, maxWeight, _("Kg"), - (count > 0 ? _("Warning!") : "")); - Com_sprintf(tooltip, sizeof(tooltip), "%s %i (%+i)", _("TU:"), tus, tuPenalty); - UI_ExecuteConfunc("%s \"%s\" \"%s\" %f %i", Cmd_Argv(1), label, tooltip, WEIGHT_NORMAL_PENALTY - (1.0f - penalty), count); + float weight_percent = ((int)(invWeight/maxWeight))/10.0f; + float weight_multiplier = std::min(WEIGHT_MAX_MULTIPLIER, ((int)((1/encPenalty)*10))/10.0f); + Com_sprintf(tooltip, sizeof(tooltip), " %gx %g%% %iTU/%s ", + weight_multiplier, weight_percent, moveTU, _("Move")); + + //call equip_actorload in base/ufos/ui/equipment.ufo + UI_ExecuteConfunc("%s \"%s\" \"%s\" %i %i %i", Cmd_Argv(1), label, tooltip, tuPenalty, count, moveTU); } void INV_InitCallbacks (void) diff --git a/src/client/cl_video.cpp b/src/client/cl_video.cpp index 0e75ae2831..96ffa125a9 100644 --- a/src/client/cl_video.cpp +++ b/src/client/cl_video.cpp @@ -71,8 +71,10 @@ static const vidmode_t vid_modes[] = { 1440, 900, 21 }, { 1024, 600, 22 }, /* EEE PC */ { 800, 480, 23 }, /* OpenPandora */ - { 1920, 1080, 24 }, /* 1080p */ - { 1366, 768, 25 } + { 1920, 1080, 24 }, /* 1080p */ + { 1366, 768, 25 }, + { 2048, 1152, 26 }, /* Samsung SyncMaster 2343 */ + { 3840, 2160, 27 } /* UHD TV */ }; /** diff --git a/src/game/g_actor.cpp b/src/game/g_actor.cpp index 68a3cd1dcf..da6b3aed02 100644 --- a/src/game/g_actor.cpp +++ b/src/game/g_actor.cpp @@ -248,7 +248,7 @@ int G_ActorCalculateMaxTU (const Edict* ent) { const int invWeight = ent->chr.inv.getWeight(); const int currentMaxTU = GET_TU(ent->chr.score.skills[ABILITY_SPEED], GET_ENCUMBRANCE_PENALTY(invWeight, - ent->chr.score.skills[ABILITY_POWER])) * G_ActorGetInjuryPenalty(ent, MODIFIER_TU); + ent->chr.score.skills[ABILITY_POWER])) * G_ActorGetPenalty(ent, MODIFIER_TU); return std::min(currentMaxTU, MAX_TU); } @@ -763,5 +763,58 @@ bool G_ActorReload (Actor* actor, const invDef_t* invDef) int G_ActorGetModifiedTimeForFiredef (const Edict* const ent, const fireDef_t* const fd, const bool reaction) { - return fd->time * G_ActorGetInjuryPenalty(ent, reaction ? MODIFIER_REACTION : MODIFIER_SHOOTING); + return fd->time * G_ActorGetPenalty(ent, reaction ? MODIFIER_REACTION : MODIFIER_SHOOTING); } + +/** + * @brief Returns the penalty to the given stat caused by the actor wounds and encumbrance. + * @param[in] ent Pointer to the actor we want to calculate the penalty for. + * @param[in] type The stat we want to calculate the penalty for. + * @return The given penalty for this actor. + */ +float G_ActorGetPenalty (const Edict* const ent, const modifier_types_t type) +{ + float penalty = 0; + float weight = 0.0f; + + const teamDef_t* const teamDef = ent->chr.teamDef; + for (int bodyPart = 0; bodyPart < teamDef->bodyTemplate->numBodyParts(); ++bodyPart) { + const int threshold = ent->chr.maxHP * teamDef->bodyTemplate->woundThreshold(bodyPart); + const int injury = (ent->chr.wounds.woundLevel[bodyPart] + ent->chr.wounds.treatmentLevel[bodyPart] * 0.5); + if (injury > threshold) + penalty += 2 * teamDef->bodyTemplate->penalty(bodyPart, type) * injury / ent->chr.maxHP; + } + + switch (type) { + case MODIFIER_REACTION: + penalty += G_ActorGetPenalty(ent, MODIFIER_SHOOTING); + break; + case MODIFIER_SHOOTING: + case MODIFIER_ACCURACY: + ++penalty; + break; + case MODIFIER_TU: + case MODIFIER_SIGHT: + penalty = 1 - penalty; + break; + case MODIFIER_MOVEMENT: + penalty = ceil(penalty); + //reduce movement speed due to encumbrance + weight = ( ent->chr.inv.getWeight() / ent->chr.score.skills[ABILITY_POWER] ) / WEIGHT_FACTOR; + if( weight > WEIGHT_HEAVY ) penalty++; + if( weight >= WEIGHT_RED1 ) penalty++; + if( weight >= WEIGHT_RED2 ) penalty++; + if( weight >= WEIGHT_RED3 ) penalty++; + if( weight >= WEIGHT_RED4 ) penalty++; + if( weight >= WEIGHT_RED5 ) penalty++; + if( weight > WEIGHT_RED6 ) penalty++; + break; + default: + gi.DPrintf("G_ActorGetPenalty: Unknown modifier type %i\n", type); + penalty = 0; + break; + } + + return penalty; +} + diff --git a/src/game/g_actor.h b/src/game/g_actor.h index 078f685a84..891550719d 100644 --- a/src/game/g_actor.h +++ b/src/game/g_actor.h @@ -61,3 +61,4 @@ int G_ActorGetContentFlags(const vec3_t origin); bool G_ActorInvMove(Actor* actor, const invDef_t* from, Item* fItem, const invDef_t* to, int tx, int ty, bool checkaction); bool G_ActorReload(Actor* actor, const invDef_t* invDef); int G_ActorGetModifiedTimeForFiredef(const Edict* ent, const fireDef_t* const fd, bool reaction); +float G_ActorGetPenalty(const Edict* const ent, const modifier_types_t type); diff --git a/src/game/g_combat.cpp b/src/game/g_combat.cpp index 3b4fe37fbe..b00673319c 100644 --- a/src/game/g_combat.cpp +++ b/src/game/g_combat.cpp @@ -672,7 +672,7 @@ void G_CalcEffectiveSpread (const Actor* shooter, const fireDef_t* fd, vec2_t ef { /* Get accuracy value for this attacker. */ const float acc = GET_ACC(shooter->chr.score.skills[ABILITY_ACCURACY], - fd->weaponSkill ? shooter->chr.score.skills[fd->weaponSkill] : 0, G_ActorGetInjuryPenalty(shooter, MODIFIER_ACCURACY)); + fd->weaponSkill ? shooter->chr.score.skills[fd->weaponSkill] : 0, G_ActorGetPenalty(shooter, MODIFIER_ACCURACY)); /* Base spread multiplier comes from the firedef's spread values. Soldier skills further modify the spread. * A good soldier will tighten the spread, a bad one will widen it, for skillBalanceMinimum values between 0 and 1.*/ diff --git a/src/game/g_health.cpp b/src/game/g_health.cpp index 83e02b7284..4af619c7a7 100644 --- a/src/game/g_health.cpp +++ b/src/game/g_health.cpp @@ -173,48 +173,6 @@ void G_SendWoundStats (Edict* const ent) } } -/** - * @brief Returns the penalty to the given stat caused by the actor wounds. - * @param[in] ent Pointer to the actor we want to calculate the penalty for. - * @param[in] type The stat we want to calculate the penalty for. - * @return The given penalty for this actor. - */ -float G_ActorGetInjuryPenalty (const Edict* const ent, const modifier_types_t type) -{ - float penalty = 0; - - const teamDef_t* const teamDef = ent->chr.teamDef; - for (int bodyPart = 0; bodyPart < teamDef->bodyTemplate->numBodyParts(); ++bodyPart) { - const int threshold = ent->chr.maxHP * teamDef->bodyTemplate->woundThreshold(bodyPart); - const int injury = (ent->chr.wounds.woundLevel[bodyPart] + ent->chr.wounds.treatmentLevel[bodyPart] * 0.5); - if (injury > threshold) - penalty += 2 * teamDef->bodyTemplate->penalty(bodyPart, type) * injury / ent->chr.maxHP; - } - - switch (type) { - case MODIFIER_REACTION: - penalty += G_ActorGetInjuryPenalty(ent, MODIFIER_SHOOTING); - break; - case MODIFIER_SHOOTING: - case MODIFIER_ACCURACY: - ++penalty; - break; - case MODIFIER_TU: - case MODIFIER_SIGHT: - penalty = 1 - penalty; - break; - case MODIFIER_MOVEMENT: - penalty = ceil(penalty); - break; - default: - gi.DPrintf("G_ActorGetInjuryPenalty: Unknown modifier type %i\n", type); - penalty = 0; - break; - } - - return penalty; -} - bool G_IsActorWounded (const Edict* ent, bool serious) { if (ent == nullptr || !G_IsLivingActor(ent) || ent->chr.teamDef == nullptr) diff --git a/src/game/g_health.h b/src/game/g_health.h index 8972244697..efde053992 100644 --- a/src/game/g_health.h +++ b/src/game/g_health.h @@ -30,5 +30,4 @@ void G_DamageActor(Edict* target, const int damage, const vec3_t impact); void G_TreatActor(Actor* target, const fireDef_t* const fd, const int heal, const int healerTeam); void G_BleedWounds(const int team); void G_SendWoundStats(Edict* const ent); -float G_ActorGetInjuryPenalty(const Edict* const ent, const modifier_types_t type); bool G_IsActorWounded(const Edict* ent, bool serious = false); diff --git a/src/game/g_match.cpp b/src/game/g_match.cpp index d7e2b1bae8..2bff9a3fa5 100644 --- a/src/game/g_match.cpp +++ b/src/game/g_match.cpp @@ -48,7 +48,7 @@ static int G_GetEarnedExperience (abilityskills_t skill, Edict* ent) switch (skill) { case ABILITY_POWER: { const float weight = chr->scoreMission->carriedWeight / level.actualRound; - const float penalty = GET_ENCUMBRANCE_PENALTY(weight, chr->score.skills[ABILITY_POWER]); + const float penalty = std::min(1/WEIGHT_MAX_MULTIPLIER, GET_ENCUMBRANCE_PENALTY(weight, chr->score.skills[ABILITY_POWER])); experience = 50 * (weight / WEIGHT_FACTOR / chr->score.skills[ABILITY_POWER]) / penalty; break; } diff --git a/src/game/g_move.cpp b/src/game/g_move.cpp index 97fa754e6b..807ffbd913 100644 --- a/src/game/g_move.cpp +++ b/src/game/g_move.cpp @@ -289,7 +289,7 @@ pos_t G_ActorMoveLength (const Actor* actor, const pathing_t* path, const pos3_t const int autostandTU = useAutostand ? 2 * TU_CROUCH : 0; return std::min(ROUTING_NOT_REACHABLE, length + static_cast(numSteps * - G_ActorGetInjuryPenalty(actor, MODIFIER_MOVEMENT)) + autostandTU); + G_ActorGetPenalty(actor, MODIFIER_MOVEMENT)) + autostandTU); } /** @@ -364,7 +364,7 @@ void G_ClientMove (const Player& player, int visTeam, Actor* actor, const pos3_t G_ReactionFireNotifyClientStartMove(actor); const int initTU = actor->TU; int usedTUs = 0; - const int movingModifier = G_ActorGetInjuryPenalty(actor, MODIFIER_MOVEMENT); + const int movingModifier = G_ActorGetPenalty(actor, MODIFIER_MOVEMENT); while (numdv > 0) { const int step = actor->moveinfo.steps; const byte oldDir = actor->dir; diff --git a/src/game/g_vis.cpp b/src/game/g_vis.cpp index 9ce13fadd1..0da326723f 100644 --- a/src/game/g_vis.cpp +++ b/src/game/g_vis.cpp @@ -166,7 +166,7 @@ int G_VisCheckDist (const Edict* const ent) return MAX_SPOT_DIST_CAMERA; if (G_IsActor(ent)) - return MAX_SPOT_DIST * G_ActorGetInjuryPenalty(ent, MODIFIER_SIGHT); + return MAX_SPOT_DIST * G_ActorGetPenalty(ent, MODIFIER_SIGHT); return MAX_SPOT_DIST; } diff --git a/src/game/q_shared.h b/src/game/q_shared.h index ed3c0c3f2d..e57327e79e 100644 --- a/src/game/q_shared.h +++ b/src/game/q_shared.h @@ -280,15 +280,26 @@ typedef int32_t shoot_types_t; #define MIN_TU 39 #define WEIGHT_LIGHT 0.2f #define WEIGHT_HEAVY 0.5f +#define WEIGHT_RED1 0.66f +#define WEIGHT_RED2 0.74f +#define WEIGHT_RED3 0.82f +#define WEIGHT_RED4 0.9f +#define WEIGHT_RED5 0.94f +#define WEIGHT_RED6 0.98f + #define WEIGHT_NORMAL_PENALTY 0.3f #define WEIGHT_HEAVY_PENALTY 0.6f #define WEIGHT_FACTOR 1000.0f +#define WEIGHT_MAX_MULTIPLIER 2.5f -#define GET_ENCUMBRANCE_PENALTY(weight, max) (1.0f - ((weight) > (max) * WEIGHT_FACTOR * WEIGHT_HEAVY ? WEIGHT_HEAVY_PENALTY : (weight) > (max) * WEIGHT_FACTOR * WEIGHT_LIGHT ? WEIGHT_NORMAL_PENALTY : 0.0f)) +#define GET_ENCUMBRANCE_LEVEL(weight, max) (1.0f - ((weight) > (max) * WEIGHT_FACTOR * WEIGHT_HEAVY ? WEIGHT_HEAVY_PENALTY : (weight) > (max) * WEIGHT_FACTOR * WEIGHT_LIGHT ? WEIGHT_NORMAL_PENALTY : 0.0f)) +#define GET_ENCUMBRANCE_PENALTY(weight, max) (1.0f - (12.0f/MIN_TU-((0.5f-(weight/(max*WEIGHT_FACTOR)))/0.04f)/MIN_TU) ) +#define GET_ENCUMBRANCE_PENALTY2(weight, max) (1.0f - ((weight) > (max) * WEIGHT_FACTOR * WEIGHT_HEAVY ? 12.0f/MIN_TU+(((weight/(max*WEIGHT_FACTOR))-0.5f)/0.02f)/MIN_TU : 12.0f/MIN_TU-((0.5f-(weight/(max*WEIGHT_FACTOR)))/0.04f)/MIN_TU )) /** @todo Skill-influence needs some balancing. */ #define GET_ACC( ab, sk, pn ) ((pn) - (((float)(ab) - 10) / (MAX_SKILL / 2) + ((float)(sk) - 10) / (MAX_SKILL / 2)) / 2) #define GET_MORALE( ab ) (std::min((100 + (ab) * 150/MAX_SKILL), 255)) -#define GET_TU( ab, md ) (MIN_TU * (md) + (ab) * 20 / MAX_SKILL) +#define GET_TU( ab, md ) (MIN_TU * (md) + (ab) * 20 / MAX_SKILL) +#define GET_TU_TO2TU( ab, md ) (MIN_TU * (md) + (ab) * 20 / MAX_SKILL * std::min( 1.0f, (md) * (1 / GET_ENCUMBRANCE_PENALTY(WEIGHT_FACTOR * WEIGHT_HEAVY, 1)))) #define DOOR_OPEN_REVERSE 4 #define GET_SLIDING_DOOR_SHIFT_VECTOR(dir, speed, vecout) \ -- 2.11.0 From 80c4ec7450b77d6ab2cc405df5418201e38f444f Mon Sep 17 00:00:00 2001 From: Norby Date: Thu, 23 Mar 2017 19:06:32 +0100 Subject: [PATCH 2/2] * Smooth encumbrance system v1.3 --- base/ufos/ui/inv_stat.ufo | 16 ++++++++-------- src/client/battlescape/cl_actor.cpp | 23 +++++++++++++++++++---- src/client/battlescape/cl_actor.h | 1 + src/client/battlescape/cl_hud.cpp | 12 ++++++------ src/client/cl_inventory_callbacks.cpp | 10 +++++----- src/game/g_match.cpp | 4 ++-- 6 files changed, 41 insertions(+), 25 deletions(-) diff --git a/base/ufos/ui/inv_stat.ufo b/base/ufos/ui/inv_stat.ufo index 8a9ac3962c..dc20846cfa 100644 --- a/base/ufos/ui/inv_stat.ufo +++ b/base/ufos/ui/inv_stat.ufo @@ -109,7 +109,7 @@ local inv_stats_hud = ufox.build_window({ pos = {0, 0}, label = { name = "label", class = "string", text = "_Strength" }, valuebar = { name = "valuebar", class = "bar", value = "*cvar:mn_vpwr" }, - valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tpwr" } + valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tpwr", pos = {44, 0}, size = {140, 20} } }, { name = "speed", @@ -117,7 +117,7 @@ local inv_stats_hud = ufox.build_window({ pos = {0, 30}, label = { name = "label", class = "string", text = "_Speed" }, valuebar = { name = "valuebar", class = "bar", value = "*cvar:mn_vspd" }, - valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tspd" } + valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tspd", pos = {44, 0}, size = {140, 20} } }, { name = "accuracy", @@ -125,7 +125,7 @@ local inv_stats_hud = ufox.build_window({ pos = {0, 60}, label = { name = "label", class = "string", text = "_Accuracy" }, valuebar = { name = "valuebar", class = "bar", value = "*cvar:mn_vacc" }, - valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tacc" } + valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tacc", pos = {44, 0}, size = {140, 20} } }, { name = "mind", @@ -133,7 +133,7 @@ local inv_stats_hud = ufox.build_window({ pos = {0, 90}, label = { name = "label", class = "string", text = "_Mind" }, valuebar = { name = "valuebar", class = "bar", value = "*cvar:mn_vmnd" }, - valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tmnd" } + valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tmnd", pos = {44, 0}, size = {140, 20} } } }, -- Skills panel @@ -149,7 +149,7 @@ local inv_stats_hud = ufox.build_window({ pos = {0, 0}, label = { name = "label", class = "string", text = "_CQB", tooltip = "_Close Quarters Battle" }, valuebar = { name = "valuebar", class = "bar", value = "*cvar:mn_vcls" }, - valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tcls" } + valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tcls", pos = {44, 0}, size = {140, 20} } }, { name = "ass", @@ -157,7 +157,7 @@ local inv_stats_hud = ufox.build_window({ pos = {0, 30}, label = { name = "label", class = "string", text = "_Assault" }, valuebar = { name = "valuebar", class = "bar", value = "*cvar:mn_vass" }, - valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tass" } + valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tass", pos = {44, 0}, size = {140, 20} } }, { name = "snp", @@ -165,7 +165,7 @@ local inv_stats_hud = ufox.build_window({ pos = {0, 60}, label = { name = "label", class = "string", text = "_Sniper" }, valuebar = { name = "valuebar", class = "bar", value = "*cvar:mn_vsnp" }, - valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tsnp" } + valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_tsnp", pos = {44, 0}, size = {140, 20} } }, { name = "exp", @@ -173,7 +173,7 @@ local inv_stats_hud = ufox.build_window({ pos = {0, 90}, label = { name = "label", class = "string", text = "_Explosives" }, valuebar = { name = "valuebar", class = "bar", value = "*cvar:mn_vexp" }, - valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_texp" } + valuenum = { name = "valuenum", class = "string", text = "*cvar:mn_texp", pos = {44, 0}, size = {140, 20} } } }, diff --git a/src/client/battlescape/cl_actor.cpp b/src/client/battlescape/cl_actor.cpp index 86f421ad98..205f0a2b57 100644 --- a/src/client/battlescape/cl_actor.cpp +++ b/src/client/battlescape/cl_actor.cpp @@ -301,7 +301,7 @@ float CL_ActorModifier (const le_t* le, const modifier_types_t type) float mod = 0; if (le) { const character_t* chr = CL_ActorGetChr(le); - mod = CL_ActorModifier (chr, type); + mod = CL_ActorModifier (chr, type, le); } return mod; } @@ -314,7 +314,20 @@ float CL_ActorModifier (const le_t* le, const modifier_types_t type) */ float CL_ActorModifier (const character_t* chr, const modifier_types_t type) { + return CL_ActorModifier (chr, type, nullptr); +} + +/** + * @brief Returns the modifier of the specified type caused by injury and encumbrance. + * @param[in] chr The actor. + * @param[in] type The modifier type. + * @param[in] le The local entity of the actor. + * @return The modifier for this actor. + */ +float CL_ActorModifier (const character_t* chr, const modifier_types_t type, const le_t* le = nullptr) +{ float mod = 0; + float w = 0.0f; float weight = 0.0f; if (!chr) @@ -329,7 +342,7 @@ float CL_ActorModifier (const character_t* chr, const modifier_types_t type) switch (type) { case MODIFIER_REACTION: - mod += CL_ActorModifier(chr, MODIFIER_SHOOTING); + mod += CL_ActorModifier(chr, MODIFIER_SHOOTING, le); break; case MODIFIER_ACCURACY: case MODIFIER_SHOOTING: @@ -337,8 +350,10 @@ float CL_ActorModifier (const character_t* chr, const modifier_types_t type) break; case MODIFIER_MOVEMENT: mod = ceil(mod); - //reduce movement speed due to encumbrance - weight = ( chr->inv.getWeight() / chr->score.skills[ABILITY_POWER] ) / WEIGHT_FACTOR; + //reduce movement speed due to encumbrance + if( le ) w = le->inv.getWeight(); //when called from HUD_UpdateActorLoad_f during battle chr->inv is not updated so must use le->inv + else w = chr->inv.getWeight(); //when called from INV_UpdateActorLoad_f in base equipment screen + weight = ( w / chr->score.skills[ABILITY_POWER] ) / WEIGHT_FACTOR; if( weight > WEIGHT_HEAVY ) mod++; if( weight >= WEIGHT_RED1 ) mod++; if( weight >= WEIGHT_RED2 ) mod++; diff --git a/src/client/battlescape/cl_actor.h b/src/client/battlescape/cl_actor.h index ecbe2c56c0..338b8c57c0 100644 --- a/src/client/battlescape/cl_actor.h +++ b/src/client/battlescape/cl_actor.h @@ -83,6 +83,7 @@ int CL_ActorGetContainerForReload(Item** ic, const Inventory* inv, const objDef_ void CL_ActorPlaySound(const le_t* le, actorSound_t soundType); float CL_ActorModifier(const le_t* le, const modifier_types_t type); float CL_ActorModifier(const character_t* chr, const modifier_types_t type); +float CL_ActorModifier(const character_t* chr, const modifier_types_t type, const le_t* le); int CL_ActorTimeForFireDef(const le_t* le, const fireDef_t* fd, bool reaction = false); void CL_ActorActionMouse(void); diff --git a/src/client/battlescape/cl_hud.cpp b/src/client/battlescape/cl_hud.cpp index 8faaa03caf..3e9f8168b1 100644 --- a/src/client/battlescape/cl_hud.cpp +++ b/src/client/battlescape/cl_hud.cpp @@ -1322,7 +1322,7 @@ static void HUD_UpdateActorLoad_f (void) return; const character_t* chr = CL_ActorGetChr(selActor); - const int invWeight = selActor->inv.getWeight(); + const float invWeight = selActor->inv.getWeight(); const int maxWeight = GAME_GetChrMaxLoad(chr); const float encPenalty = GET_ENCUMBRANCE_PENALTY(invWeight, maxWeight); const int normalTU = GET_TU(chr->score.skills[ABILITY_SPEED], 1.0f - WEIGHT_NORMAL_PENALTY); @@ -1352,15 +1352,15 @@ static void HUD_UpdateActorLoad_f (void) if (count > 0) UI_Popup(_("Warning"), popupText); - const int moveTU = TU_MOVE_STRAIGHT + CL_ActorModifier(chr, MODIFIER_MOVEMENT); + const int moveTU = TU_MOVE_STRAIGHT + CL_ActorModifier(selActor, MODIFIER_MOVEMENT); char label[MAX_VAR]; - Com_sprintf(label, sizeof(label), "%g/%i %s %i %s (%+i) %s: %i", invWeight / WEIGHT_FACTOR, maxWeight, _("Kg"), - tus, _("TU"), tuPenalty, _("Move"), (int)(tus/moveTU) ); + Com_sprintf(label, sizeof(label), "%g/%i %s %s: %i %i %s (%+i)", invWeight / WEIGHT_FACTOR, maxWeight, _("Kg"), + _("Move"), (int)(tus/moveTU), tus, _("TU"), tuPenalty ); char tooltip[MAX_VAR]; float weight_percent = ((int)(invWeight/maxWeight))/10.0f; - float weight_multiplier = std::min(WEIGHT_MAX_MULTIPLIER, ((int)((1/encPenalty)*10))/10.0f); - Com_sprintf(tooltip, sizeof(tooltip), " %gx %g%% %iTU/%s ", + float weight_multiplier = std::min(WEIGHT_MAX_MULTIPLIER, ((int)((2/encPenalty-1)*10))/10.0f); + Com_sprintf(tooltip, sizeof(tooltip), " %gx %g%% %iTU/%s", weight_multiplier, weight_percent, moveTU, _("Move")); //call inv_actorload in base/ufos/ui/inv_stat.ufo diff --git a/src/client/cl_inventory_callbacks.cpp b/src/client/cl_inventory_callbacks.cpp index e186aa8a41..c1fcdff493 100644 --- a/src/client/cl_inventory_callbacks.cpp +++ b/src/client/cl_inventory_callbacks.cpp @@ -369,7 +369,7 @@ static void INV_UpdateActorLoad_f (void) if (chr == nullptr) return; - const float invWeight = chr->inv.getWeight(); + float invWeight = chr->inv.getWeight(); const int maxWeight = GAME_GetChrMaxLoad(chr); const float encPenalty = GET_ENCUMBRANCE_PENALTY(invWeight, maxWeight); const int normalTU = GET_TU(chr->score.skills[ABILITY_SPEED], 1.0f - WEIGHT_NORMAL_PENALTY); @@ -402,14 +402,14 @@ static void INV_UpdateActorLoad_f (void) if ((Cmd_Argc() < 3 || atoi(Cmd_Argv(2)) == 0) && count > 0) UI_Popup(_("Warning"), popupText); - const int moveTU = TU_MOVE_STRAIGHT + CL_ActorModifier(chr, MODIFIER_MOVEMENT); + int moveTU = TU_MOVE_STRAIGHT + CL_ActorModifier(chr, MODIFIER_MOVEMENT); char label[MAX_VAR]; - Com_sprintf(label, sizeof(label), "%g/%i %s %i %s (%+i) %s: %i", invWeight / WEIGHT_FACTOR, maxWeight, _("Kg"), - tus, _("TU"), tuPenalty, _("Move"), (int)(tus/moveTU) ); + Com_sprintf(label, sizeof(label), "%g/%i %s %s: %i %i %s (%+i)", invWeight / WEIGHT_FACTOR, maxWeight, _("Kg"), + _("Move"), (int)(tus/moveTU), tus, _("TU"), tuPenalty ); char tooltip[MAX_VAR]; float weight_percent = ((int)(invWeight/maxWeight))/10.0f; - float weight_multiplier = std::min(WEIGHT_MAX_MULTIPLIER, ((int)((1/encPenalty)*10))/10.0f); + float weight_multiplier = std::min(WEIGHT_MAX_MULTIPLIER, ((int)((2/encPenalty-1)*10))/10.0f); Com_sprintf(tooltip, sizeof(tooltip), " %gx %g%% %iTU/%s ", weight_multiplier, weight_percent, moveTU, _("Move")); diff --git a/src/game/g_match.cpp b/src/game/g_match.cpp index 2bff9a3fa5..7bbd39cd61 100644 --- a/src/game/g_match.cpp +++ b/src/game/g_match.cpp @@ -48,8 +48,8 @@ static int G_GetEarnedExperience (abilityskills_t skill, Edict* ent) switch (skill) { case ABILITY_POWER: { const float weight = chr->scoreMission->carriedWeight / level.actualRound; - const float penalty = std::min(1/WEIGHT_MAX_MULTIPLIER, GET_ENCUMBRANCE_PENALTY(weight, chr->score.skills[ABILITY_POWER])); - experience = 50 * (weight / WEIGHT_FACTOR / chr->score.skills[ABILITY_POWER]) / penalty; + const float multiplier = std::min(WEIGHT_MAX_MULTIPLIER, 2 / GET_ENCUMBRANCE_PENALTY(weight, chr->score.skills[ABILITY_POWER]) - 1); + experience = 50 * (weight / WEIGHT_FACTOR / chr->score.skills[ABILITY_POWER]) * multiplier; break; } case ABILITY_ACCURACY: -- 2.11.0