From 81f29556bf3493da8e290442082ae01c627aefc3 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 2 Apr 2016 23:11:59 -0400 Subject: [PATCH 1/2] - Refactored SBarInfo flow control so negatable commands are handled statically. - Made TArray movable and TDeletingArray a move only type. --- src/g_shared/sbarinfo.cpp | 112 ++++++++++++--------- src/g_shared/sbarinfo_commands.cpp | 151 ++++++++--------------------- src/tarray.h | 34 ++++++- src/templates.h | 3 +- 4 files changed, 137 insertions(+), 163 deletions(-) diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 23733efcf..2fcc29b05 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -206,67 +206,31 @@ class SBarInfoCommandFlowControl : public SBarInfoCommand { public: SBarInfoCommandFlowControl(SBarInfo *script) : SBarInfoCommand(script), truth(false) {} - ~SBarInfoCommandFlowControl() - { - for(unsigned int i = 0;i < 2;i++) - { - for(unsigned int j = 0;j < commands[i].Size();j++) - delete commands[i][j]; - } - } void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) { - for(unsigned int i = 0;i < commands[truth].Size();i++) - commands[truth][i]->Draw(block, statusBar); + for(auto command : commands[truth]) + command->Draw(block, statusBar); } int NumCommands() const { return commands[truth].Size(); } void Parse(FScanner &sc, bool fullScreenOffsets) { - bool elseBlock = false; - SBarInfoCommand *cmd = NULL; - // Should loop no more than twice. - while(true) - { - if(sc.CheckToken('{')) - { - while((cmd = NextCommand(sc)) != NULL) - { - cmd->Parse(sc, fullScreenOffsets); - commands[!elseBlock].Push(cmd); - } - } - else - { - if((cmd = NextCommand(sc)) != NULL) - { - cmd->Parse(sc, fullScreenOffsets); - commands[!elseBlock].Push(cmd); - } - else - sc.ScriptError("Missing command for flow control statement."); - } - - if(!elseBlock && sc.CheckToken(TK_Else)) - { - elseBlock = true; - continue; - } - break; - } + ParseBlock(commands[1], sc, fullScreenOffsets); + if(sc.CheckToken(TK_Else)) + ParseBlock(commands[0], sc, fullScreenOffsets); } void Reset() { for(unsigned int i = 0;i < 2;i++) { - for(unsigned int j = 0;j < commands[i].Size();j++) - commands[i][j]->Reset(); + for(auto command : commands[i]) + command->Reset(); } } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { - for(unsigned int i = 0;i < commands[truth].Size();i++) - commands[truth][i]->Tick(block, statusBar, hudChanged); + for(auto command : commands[truth]) + command->Tick(block, statusBar, hudChanged); } protected: @@ -283,11 +247,65 @@ class SBarInfoCommandFlowControl : public SBarInfoCommand Tick(block, statusBar, true); } + void Negate() + { + swapvalues(commands[0], commands[1]); + } + private: + void ParseBlock(TDeletingArray &commands, FScanner &sc, bool fullScreenOffsets) + { + if(sc.CheckToken('{')) + { + while(SBarInfoCommand *cmd = NextCommand(sc)) + { + cmd->Parse(sc, fullScreenOffsets); + commands.Push(cmd); + } + } + else + { + if(SBarInfoCommand *cmd = NextCommand(sc)) + { + cmd->Parse(sc, fullScreenOffsets); + commands.Push(cmd); + } + else + sc.ScriptError("Missing command for flow control statement."); + } + } + SBarInfoCommand *NextCommand(FScanner &sc); - bool truth; - TArray commands[2]; + TDeletingArray commands[2]; + bool truth; +}; + +class SBarInfoNegatableFlowControl : public SBarInfoCommandFlowControl +{ + public: + SBarInfoNegatableFlowControl(SBarInfo *script) : SBarInfoCommandFlowControl(script) {} + + void Parse(FScanner &sc, bool fullScreenOffsets) + { + bool negate = false; + if(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("not")) + negate = true; + else + sc.UnGet(); + } + + ParseNegatable(sc, fullScreenOffsets); + + SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); + + if(negate) + Negate(); + } + + virtual void ParseNegatable(FScanner &sc, bool fullScreenOffsets) {} }; class SBarInfoMainBlock : public SBarInfoCommandFlowControl diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index e08fb1a20..dcb0cd544 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1830,33 +1830,17 @@ const char* const CommandGameMode::modeNames[] = //////////////////////////////////////////////////////////////////////////////// -class CommandUsesAmmo : public SBarInfoCommandFlowControl +class CommandUsesAmmo : public SBarInfoNegatableFlowControl { public: - CommandUsesAmmo(SBarInfo *script) : SBarInfoCommandFlowControl(script), - negate(false) - { - } + CommandUsesAmmo(SBarInfo *script) : SBarInfoNegatableFlowControl(script) {} - void Parse(FScanner &sc, bool fullScreenOffsets) - { - if(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("not")) - negate = true; - else - sc.ScriptError("Expected 'not', but got '%s' instead.", sc.String); - } - SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); - } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { - SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); + SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged); - SetTruth((statusBar->CPlayer->ReadyWeapon != NULL && (statusBar->CPlayer->ReadyWeapon->AmmoType1 != NULL || statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL)) ^ negate, block, statusBar); + SetTruth(statusBar->CPlayer->ReadyWeapon != NULL && (statusBar->CPlayer->ReadyWeapon->AmmoType1 != NULL || statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL), block, statusBar); } - protected: - bool negate; }; //////////////////////////////////////////////////////////////////////////////// @@ -1872,7 +1856,7 @@ class CommandUsesSecondaryAmmo : public CommandUsesAmmo { SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); - SetTruth((statusBar->CPlayer->ReadyWeapon != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType1 != statusBar->CPlayer->ReadyWeapon->AmmoType2) ^ negate, block, statusBar); + SetTruth(statusBar->CPlayer->ReadyWeapon != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType1 != statusBar->CPlayer->ReadyWeapon->AmmoType2, block, statusBar); } }; @@ -2890,28 +2874,18 @@ class CommandDrawBar : public SBarInfoCommand //////////////////////////////////////////////////////////////////////////////// -class CommandIsSelected : public SBarInfoCommandFlowControl +class CommandIsSelected : public SBarInfoNegatableFlowControl { public: - CommandIsSelected(SBarInfo *script) : SBarInfoCommandFlowControl(script), - negate(false) + CommandIsSelected(SBarInfo *script) : SBarInfoNegatableFlowControl(script) { weapon[0] = NULL; weapon[1] = NULL; } - void Parse(FScanner &sc, bool fullScreenOffsets) + void ParseNegatable(FScanner &sc, bool fullScreenOffsets) { - if(sc.CheckToken(TK_Identifier)) - { - if(sc.Compare("not")) - { - negate = true; - if(!sc.CheckToken(TK_StringConst)) - sc.MustGetToken(TK_Identifier); - } - } - else + if(!sc.CheckToken(TK_Identifier)) sc.MustGetToken(TK_StringConst); for(int i = 0;i < 2;i++) { @@ -2930,24 +2904,18 @@ class CommandIsSelected : public SBarInfoCommandFlowControl else break; } - SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { - SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); + SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged); if(statusBar->CPlayer->ReadyWeapon != NULL) { const PClass *readyWeapon = statusBar->CPlayer->ReadyWeapon->GetClass(); - SetTruth(((weapon[1] != NULL) && - ((negate && (weapon[0] != readyWeapon && weapon[1] != readyWeapon)) || - (!negate && (weapon[0] == readyWeapon || weapon[1] == readyWeapon)))) || - ((weapon[1] == NULL) && - ((!negate && weapon[0] == readyWeapon) || (negate && weapon[0] != readyWeapon))), block, statusBar); + SetTruth(weapon[0] == readyWeapon || (weapon[1] && weapon[1] == readyWeapon), block, statusBar); } } protected: - bool negate; const PClass *weapon[2]; }; @@ -3245,26 +3213,20 @@ FRandom CommandDrawGem::pr_chainwiggle; //use the same method of chain wiggling //////////////////////////////////////////////////////////////////////////////// -class CommandWeaponAmmo : public SBarInfoCommandFlowControl +class CommandWeaponAmmo : public SBarInfoNegatableFlowControl { public: - CommandWeaponAmmo(SBarInfo *script) : SBarInfoCommandFlowControl(script), - conditionAnd(false), negate(false) + CommandWeaponAmmo(SBarInfo *script) : SBarInfoNegatableFlowControl(script), + conditionAnd(false) { ammo[0] = NULL; ammo[1] = NULL; } - void Parse(FScanner &sc, bool fullScreenOffsets) + void ParseNegatable(FScanner &sc, bool fullScreenOffsets) { if(!sc.CheckToken(TK_StringConst)) sc.MustGetToken(TK_Identifier); - if(sc.Compare("not") && sc.TokenType == TK_Identifier) - { - negate = true; - if(!sc.CheckToken(TK_StringConst)) - sc.MustGetToken(TK_Identifier); - } for(int i = 0;i < 2;i++) { ammo[i] = PClass::FindClass(sc.String); @@ -3289,11 +3251,10 @@ class CommandWeaponAmmo : public SBarInfoCommandFlowControl else break; } - SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { - SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); + SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged); if(statusBar->CPlayer->ReadyWeapon != NULL) { @@ -3301,41 +3262,25 @@ class CommandWeaponAmmo : public SBarInfoCommandFlowControl const PClass *AmmoType2 = statusBar->CPlayer->ReadyWeapon->AmmoType2; bool usesammo1 = (AmmoType1 != NULL); bool usesammo2 = (AmmoType2 != NULL); - if(negate && !usesammo1 && !usesammo2) //if the weapon doesn't use ammo don't go though the trouble. - { - SetTruth(true, block, statusBar); - return; - } + //if(!usesammo1 && !usesammo2) //if the weapon doesn't use ammo don't go though the trouble. + //{ + // SetTruth(false, block, statusBar); + // return; + //} //Or means only 1 ammo type needs to match and means both need to match. if(ammo[1] != NULL) { bool match1 = ((usesammo1 && (AmmoType1 == ammo[0] || AmmoType1 == ammo[1])) || !usesammo1); bool match2 = ((usesammo2 && (AmmoType2 == ammo[0] || AmmoType2 == ammo[1])) || !usesammo2); if((!conditionAnd && (match1 || match2)) || (conditionAnd && (match1 && match2))) - { - if(!negate) - { - SetTruth(true, block, statusBar); - return; - } - } - else if(negate) { SetTruth(true, block, statusBar); return; } } - else //Every thing here could probably be one long if statement but then it would be more confusing. + else { if((usesammo1 && (AmmoType1 == ammo[0])) || (usesammo2 && (AmmoType2 == ammo[0]))) - { - if(!negate) - { - SetTruth(true, block, statusBar); - return; - } - } - else if(negate) { SetTruth(true, block, statusBar); return; @@ -3345,33 +3290,26 @@ class CommandWeaponAmmo : public SBarInfoCommandFlowControl SetTruth(false, block, statusBar); } protected: - bool conditionAnd; - bool negate; const PClass *ammo[2]; + bool conditionAnd; }; //////////////////////////////////////////////////////////////////////////////// -class CommandInInventory : public SBarInfoCommandFlowControl +class CommandInInventory : public SBarInfoNegatableFlowControl { public: - CommandInInventory(SBarInfo *script) : SBarInfoCommandFlowControl(script), - conditionAnd(false), negate(false) + CommandInInventory(SBarInfo *script) : SBarInfoNegatableFlowControl(script), + conditionAnd(false) { item[0] = item[1] = NULL; amount[0] = amount[1] = 0; } - void Parse(FScanner &sc, bool fullScreenOffsets) + void ParseNegatable(FScanner &sc, bool fullScreenOffsets) { if(!sc.CheckToken(TK_StringConst)) sc.MustGetToken(TK_Identifier); - if(sc.Compare("not") && sc.TokenType == TK_Identifier) - { - negate = true; - if(!sc.CheckToken(TK_StringConst)) - sc.MustGetToken(TK_Identifier); - } for(int i = 0;i < 2;i++) { item[i] = PClass::FindActor(sc.String); @@ -3402,11 +3340,10 @@ class CommandInInventory : public SBarInfoCommandFlowControl else break; } - SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { - SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); + SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged); AInventory *invItem[2] = { statusBar->CPlayer->mo->FindInventory(item[0]), statusBar->CPlayer->mo->FindInventory(item[1]) }; if (invItem[0] != NULL && amount[0] > 0 && invItem[0]->Amount < amount[0]) invItem[0] = NULL; @@ -3415,16 +3352,15 @@ class CommandInInventory : public SBarInfoCommandFlowControl if (item[1]) { if (conditionAnd) - SetTruth((invItem[0] && invItem[1]) != negate, block, statusBar); + SetTruth(invItem[0] && invItem[1], block, statusBar); else - SetTruth((invItem[0] || invItem[1]) != negate, block, statusBar); + SetTruth(invItem[0] || invItem[1], block, statusBar); } else - SetTruth((invItem[0] != NULL) != negate, block, statusBar); + SetTruth(invItem[0] != NULL, block, statusBar); } protected: bool conditionAnd; - bool negate; PClassActor *item[2]; int amount[2]; }; @@ -3459,42 +3395,31 @@ class CommandAlpha : public SBarInfoMainBlock //////////////////////////////////////////////////////////////////////////////// -class CommandIfHealth : public SBarInfoCommandFlowControl +class CommandIfHealth : public SBarInfoNegatableFlowControl { public: - CommandIfHealth(SBarInfo *script) : SBarInfoCommandFlowControl(script), - negate(false), percentage(false) + CommandIfHealth(SBarInfo *script) : SBarInfoNegatableFlowControl(script), + percentage(false) { } - void Parse(FScanner &sc, bool fullScreenOffsets) + void ParseNegatable(FScanner &sc, bool fullScreenOffsets) { - if (sc.CheckToken(TK_Identifier)) - { - if (sc.Compare("not")) - negate = true; - else - sc.ScriptError("Expected 'not', but got '%s' instead.", sc.String); - } - sc.MustGetToken(TK_IntConst); percentage = sc.CheckToken('%'); hpamount = sc.Number; - - SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets); } void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { - SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); + SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged); int phealth = percentage ? statusBar->CPlayer->mo->health * 100 / statusBar->CPlayer->mo->GetMaxHealth() : statusBar->CPlayer->mo->health; - SetTruth((phealth >= hpamount) ^ negate, block, statusBar); + SetTruth(phealth >= hpamount, block, statusBar); } protected: - bool negate; - bool percentage; int hpamount; + bool percentage; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/src/tarray.h b/src/tarray.h index 7b9d5970b..3ef4f2d99 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -39,6 +39,7 @@ #include #include #include +#include #if !defined(_WIN32) #include // for intptr_t @@ -137,11 +138,17 @@ public: Count = 0; Array = (T *)M_Malloc (sizeof(T)*max); } - TArray (const TArray &other) + TArray (const TArray &other) { DoCopy (other); } - TArray &operator= (const TArray &other) + TArray (TArray &&other) + { + Array = other.Array; other.Array = NULL; + Most = other.Most; other.Most = 0; + Count = other.Count; other.Count = 0; + } + TArray &operator= (const TArray &other) { if (&other != this) { @@ -157,6 +164,21 @@ public: } return *this; } + TArray &operator= (TArray &&other) + { + if (Array) + { + if (Count > 0) + { + DoDelete (0, Count-1); + } + M_Free (Array); + } + Array = other.Array; other.Array = NULL; + Most = other.Most; other.Most = 0; + Count = other.Count; other.Count = 0; + return *this; + } ~TArray () { if (Array) @@ -417,6 +439,14 @@ template class TDeletingArray : public TArray { public: + TDeletingArray() : TArray() {} + TDeletingArray(TDeletingArray &&other) : TArray(std::move(other)) {} + TDeletingArray &operator=(TDeletingArray &&other) + { + TArray::operator=(std::move(other)); + return *this; + } + ~TDeletingArray () { for (unsigned int i = 0; i < TArray::Size(); ++i) diff --git a/src/templates.h b/src/templates.h index 4f75a961a..0737fc4e9 100644 --- a/src/templates.h +++ b/src/templates.h @@ -40,6 +40,7 @@ #endif #include +#include //========================================================================== // @@ -204,7 +205,7 @@ template inline void swapvalues (T &a, T &b) { - T temp = a; a = b; b = temp; + T temp = std::move(a); a = std::move(b); b = std::move(temp); } #endif //__TEMPLATES_H__ From 42edd7db2264622b034c21db32e762957ef64972 Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Sat, 2 Apr 2016 23:47:15 -0400 Subject: [PATCH 2/2] - Added IfInvulnerable SBARINFO command (modified from Blue-Shadow's pull request) --- src/g_shared/sbarinfo_commands.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index dcb0cd544..a471ff8b2 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -3424,6 +3424,23 @@ class CommandIfHealth : public SBarInfoNegatableFlowControl //////////////////////////////////////////////////////////////////////////////// +class CommandIfInvulnerable : public SBarInfoNegatableFlowControl +{ + public: + CommandIfInvulnerable(SBarInfo *script) : SBarInfoNegatableFlowControl(script) + { + } + + void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) + { + SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged); + + SetTruth((statusBar->CPlayer->mo->flags2 & MF2_INVULNERABLE) || (statusBar->CPlayer->cheats & (CF_GODMODE | CF_GODMODE2)), block, statusBar); + } +}; + +//////////////////////////////////////////////////////////////////////////////// + static const char *SBarInfoCommandNames[] = { "drawimage", "drawnumber", "drawswitchableimage", @@ -3434,6 +3451,7 @@ static const char *SBarInfoCommandNames[] = "isselected", "usesammo", "usessecondaryammo", "hasweaponpiece", "inventorybarnotvisible", "weaponammo", "ininventory", "alpha", "ifhealth", + "ifinvulnerable", NULL }; @@ -3447,6 +3465,7 @@ enum SBarInfoCommands SBARINFO_ISSELECTED, SBARINFO_USESAMMO, SBARINFO_USESSECONDARYAMMO, SBARINFO_HASWEAPONPIECE, SBARINFO_INVENTORYBARNOTVISIBLE, SBARINFO_WEAPONAMMO, SBARINFO_ININVENTORY, SBARINFO_ALPHA, SBARINFO_IFHEALTH, + SBARINFO_IFINVULNERABLE, }; SBarInfoCommand *SBarInfoCommandFlowControl::NextCommand(FScanner &sc) @@ -3480,6 +3499,7 @@ SBarInfoCommand *SBarInfoCommandFlowControl::NextCommand(FScanner &sc) case SBARINFO_ININVENTORY: return new CommandInInventory(script); case SBARINFO_ALPHA: return new CommandAlpha(script); case SBARINFO_IFHEALTH: return new CommandIfHealth(script); + case SBARINFO_IFINVULNERABLE: return new CommandIfInvulnerable(script); } sc.ScriptError("Unknown command '%s'.\n", sc.String);