From 16b215cb49ef9deec3be743f09935c76e696ef05 Mon Sep 17 00:00:00 2001 From: fyryNy Date: Sun, 17 Mar 2024 20:15:14 +0100 Subject: [PATCH] Bunch of new stuff and fixes - reorganized and slightly modified DebugHelper - added restoring of viewport because some plugins don't do that and it messes with prints here - fix for pickpocket icon not showing for npcs in CoM - added reminder to save the game if too much time passed since last save/load - updated README - fix for slowing time effects from joints, black ore, etc. - added a command to toggle display of invisible triggers near player while debug mode is active - fix for changing position of focus bar not working when `ColorNpcs` is turned off --- README.md | 10 +- .../DATA/TEXTURES/_COMPILED/ICON_SAVE-C.TEX | Bin 0 -> 349556 bytes zUtilities/Commands.cpp | 8 + zUtilities/Const.h | 2 +- zUtilities/DebugHelper.cpp | 398 ++++++++++-------- zUtilities/DebugHelper.h | 11 +- zUtilities/FocusColor.cpp | 20 +- zUtilities/Headers.h | 1 + zUtilities/IconInfo.cpp | 7 + zUtilities/IconInfo.h | 1 + zUtilities/Misc.cpp | 16 + zUtilities/Options.h | 2 + zUtilities/PlayerStatus.cpp | 105 ++++- zUtilities/PlayerStatus.h | 7 + zUtilities/Plugin.cpp | 2 + .../ZenGin/Gothic_UserAPI/oCVisualFX.inl | 4 + 16 files changed, 398 insertions(+), 196 deletions(-) create mode 100644 vdf-include/_WORK/DATA/TEXTURES/_COMPILED/ICON_SAVE-C.TEX diff --git a/README.md b/README.md index 1871742..e217919 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,11 @@ This is a plugin with a set of many quality-of-life and utility features made fo - Insert all items into inventory with `zutilities giveallitems` command. -- Check currently used plugin version through in game console with `zutilities version` command. +- Check currently used plugin version through in game console with `zutilities version` command. + +- Reminds the player to save the game by displaying an icon with a timer after playing without saving the game for too long. + - By default, it reminds the player after 5 minutes since the last save game. It can be changed in `gothic.ini` with `SaveReminder` option. + - It can be turned off by setting `SaveReminder` to `-1` ### Options @@ -175,6 +179,10 @@ KeyTimeMultiplier=KEY_Z TimeMultipliers=1.0|2.5 ; ... defines time multipliers +SaveReminder=5 +; ... Time in minutes after which the reminder to save the game appears on the screen +; ... set to -1 to disable + RecoveryVisualization=1 ; ... enables (1) or disables (0) visualization of healing that hovered in the inventory item gives diff --git a/vdf-include/_WORK/DATA/TEXTURES/_COMPILED/ICON_SAVE-C.TEX b/vdf-include/_WORK/DATA/TEXTURES/_COMPILED/ICON_SAVE-C.TEX new file mode 100644 index 0000000000000000000000000000000000000000..1c51fb9dd32308ce9866656e083a44dfa2d4e6b5 GIT binary patch literal 349556 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 "zUtilities Version", "Shows version number" ); zcon->Register( "zUtilities Debug", "Toggles debug mode" ); zcon->Register( "zUtilities GiveAllItems", "Gives all items" ); + zcon->Register( "zUtilities ShowTriggers", "Toggles the display of invisible triggers in debug mode" ); } } \ No newline at end of file diff --git a/zUtilities/Const.h b/zUtilities/Const.h index 0e84cac..9a1064f 100644 --- a/zUtilities/Const.h +++ b/zUtilities/Const.h @@ -3,7 +3,7 @@ namespace GOTHIC_ENGINE { #define PLUGIN_NAME "ZUTILITIES" -#define VERSION_NUMBER "0.36" +#define VERSION_NUMBER "0.37" #define printWin(a) ogame->GetTextView()->Printwin(a) #define del(x) { delete x; x = nullptr; } } \ No newline at end of file diff --git a/zUtilities/DebugHelper.cpp b/zUtilities/DebugHelper.cpp index 6357164..87c6315 100644 --- a/zUtilities/DebugHelper.cpp +++ b/zUtilities/DebugHelper.cpp @@ -1,228 +1,268 @@ -// Supported with union (c) 2020 Union team +// Supported with union ( c ) 2020 Union team // Union SOURCE file namespace GOTHIC_ENGINE { void DebugHelper::InfoNpc( oCNpc* npc ) { - Print( textView, "Instance", npc->GetInstanceName() + " (" + Z npc->instanz + ")" ); - Print( textView, "Name", npc->GetName( 0 ) ); - Print( textView, "Guild", npc->GetGuildName() + " (" + Z npc->GetGuild() + ")" ); - Print( sideView, "Level", Z npc->level ); - AddSeparator(); - Print( textView, "HP", Z npc->GetAttribute( NPC_ATR_HITPOINTS ) + "/" + Z npc->GetAttribute( NPC_ATR_HITPOINTSMAX ) ); -#if ENGINE >= Engine_G2 - Print( sideView, "1H", Z npc->GetHitChance( NPC_HITCHANCE_1H ) ); -#else - Print( sideView, "1H", Z npc->GetTalentValue( NPC_HITCHANCE_1H ) ); -#endif - Print( textView, "MANA", Z npc->GetAttribute( NPC_ATR_MANA ) + "/" + Z npc->GetAttribute( NPC_ATR_MANAMAX ) ); -#if ENGINE >= Engine_G2 - Print( sideView, "2H", Z npc->GetHitChance( NPC_HITCHANCE_2H ) ); -#else - Print( sideView, "2H", Z npc->GetTalentValue( NPC_HITCHANCE_2H ) ); -#endif - Print( textView, "STR", Z npc->GetAttribute( NPC_ATR_STRENGTH ) ); -#if ENGINE >= Engine_G2 - Print( sideView, "BOW", Z npc->GetHitChance( NPC_HITCHANCE_BOW ) ); -#else - Print( sideView, "BOW", Z npc->GetTalentValue( NPC_HITCHANCE_BOW ) ); -#endif - Print( textView, "DEX", Z npc->GetAttribute( NPC_ATR_DEXTERITY ) ); -#if ENGINE >= Engine_G2 - Print( sideView, "CBOW", Z npc->GetHitChance( NPC_HITCHANCE_CROSSBOW ) ); -#else - Print( sideView, "CBOW", Z npc->GetTalentValue( NPC_HITCHANCE_CROSSBOW ) ); -#endif - AddSeparator(); - Print( textView, "PROT_EDGE", Z npc->GetProtectionByIndex( oEDamageIndex_Edge ) ); - Print( sideView, "DAM_EDGE", Z npc->GetDamageByIndex( oEDamageIndex_Edge ) ); - Print( textView, "PROT_BLUNT", Z npc->GetProtectionByIndex( oEDamageIndex_Blunt ) ); - Print( sideView, "DAM_BLUNT", Z npc->GetDamageByIndex( oEDamageIndex_Blunt ) ); - Print( textView, "PROT_POINT", Z npc->GetProtectionByIndex( oEDamageIndex_Point ) ); - Print( sideView, "DAM_POINT", Z npc->GetDamageByIndex( oEDamageIndex_Point ) ); - Print( textView, "PROT_FIRE", Z npc->GetProtectionByIndex( oEDamageIndex_Fire ) ); - Print( sideView, "DAM_FIRE", Z npc->GetDamageByIndex( oEDamageIndex_Fire ) ); - Print( textView, "PROT_MAGIC", Z npc->GetProtectionByIndex( oEDamageIndex_Magic ) ); - Print( sideView, "DAM_MAGIC", Z npc->GetDamageByIndex( oEDamageIndex_Magic ) ); - Print( textView, "PROT_FLY", Z npc->GetProtectionByIndex( oEDamageIndex_Fly ) ); - Print( sideView, "DAM_FLY", Z npc->GetDamageByIndex( oEDamageIndex_Fly ) ); - Print( textView, "PROT_FALL", Z npc->GetProtectionByIndex( oEDamageIndex_Fall ) ); - Print( sideView, "DAM_FALL", Z npc->GetDamageByIndex( oEDamageIndex_Fall ) ); - Print( textView, "DamageType", Z npc->damagetype ); - AddSeparator(); - Print( textView, "Waypoint", npc->wpname ); - Print( textView, "Flags", Z npc->variousFlags ); - Print( sideView, "NpcType", Z npc->npcType ); - Print( textView, "Attitude", Z npc->GetAttitude( player ) ); - Print( sideView, "PermAttitude", Z npc->GetPermAttitude( player ) ); - Print( textView, "SensesRange", Z npc->senses_range ); - Print( sideView, "DistToPlayer", Z( int )npc->GetDistanceToVob( *player ) ); - Print( textView, "DetectedPlayer", Z npc->HasVobDetected( player ) ); - Print( sideView, "Voice", Z npc->voice ); - Print( textView, "AIState", Z npc->GetAIState() ); - Print( sideView, "DailyRoutine", Z npc->daily_routine ); - Print( textView, "FightMode", Z npc->fmode ); - Print( sideView, "FightTactic", Z npc->fighttactic ); - AddSeparator(); - Print( textView, "FightRangeBase", Z npc->GetFightRangeBase() ); - Print( sideView, "FightRangeFist", Z npc->GetFightRangeFist() ); - Print( textView, "FightRangeDynamic", Z npc->GetFightRangeDynamic() ); - Print( sideView, "FightRange", Z npc->GetFightRange() ); + //LEFT SIDE + Print( leftView, "--- " + npc->_GetClassDef()->className, npc->GetInstanceName() + " ( " + Z npc->instanz + " )" ); + Print( leftView, "Name", npc->GetName( 0 ) ); + Print( leftView, "Level", Z npc->level ); + Print( leftView, "Guild", npc->GetGuildName() + " ( " + Z npc->GetGuild() + " )" ); + Print( leftView, "Voice", Z npc->voice ); + Print( leftView, "Flags", Z npc->variousFlags ); + Print( leftView, "NpcType", Z npc->npcType ); + Print( leftView, "Attitude", Z npc->GetAttitude( player ) ); + Print( leftView, "PermAttitude", Z npc->GetPermAttitude( player ) ); + Print( leftView, "SensesRange", Z npc->senses_range ); + Print( leftView, "DetectedPlayer", Z npc->HasVobDetected( player ) ); + Print( leftView, "DistToPlayer", Z( int )npc->GetDistanceToVob( *player ) ); + + AddSeparator( leftView, "Fight AI" ); + Print( leftView, "FightMode", Z npc->fmode ); + Print( leftView, "FightTactic", Z npc->fighttactic ); + Print( leftView, "FightRangeBase", Z npc->GetFightRangeBase() ); + Print( leftView, "FightRangeFist", Z npc->GetFightRangeFist() ); + Print( leftView, "FightRangeDynamic", Z npc->GetFightRangeDynamic() ); + Print( leftView, "FightRange", Z npc->GetFightRange() ); if ( npc->enemy != nullptr ) - Print( textView, "Enemy", npc->enemy->GetInstanceName() ); + Print( leftView, "Enemy", npc->enemy->GetInstanceName() ); + AddSeparator( leftView, "Visual/Armor" ); if ( zCVisual* visual = npc->GetVisual() ) { - AddSeparator( "Visual" ); - Print( textView, "VisualFile", visual->GetVisualName() ); - Print( textView, "ModelScale", Z npc->model_scale[VX] + Z " " + npc->model_scale[VY] + Z " " + npc->model_scale[VZ] ); - Print( textView, "BodyName", npc->GetVisualBody() ); - Print( textView, "HeadName", npc->GetVisualHead() ); + Print( leftView, "VisualFile", visual->GetVisualName() ); + Print( leftView, "ModelScale", Z npc->model_scale[VX] + Z " " + npc->model_scale[VY] + Z " " + npc->model_scale[VZ] ); + Print( leftView, "BodyName", npc->GetVisualBody() ); + Print( leftView, "HeadName", npc->GetVisualHead() ); #if ENGINE == Engine_G2A - Print( textView, "EffectName", npc->effect ); + Print( leftView, "EffectName", npc->effect ); #endif - if ( oCItem* armor = npc->GetEquippedArmor() ) { - AddSeparator( "Armor" ); - if ( zCVisual* armorVisual = npc->GetVisual() ) - Print( textView, "VisualFile", armorVisual->GetVisualName() ); + } - Print( textView, "VisualChange", armor->GetVisualChange() ); + if ( oCItem* armor = npc->GetEquippedArmor() ) { + Print( leftView, "VisualChange", armor->GetVisualChange() ); #if ENGINE == Engine_G2A - Print( textView, "EffectName", armor->GetEffectName() ); + Print( leftView, "EffectName", armor->GetEffectName() ); #endif - } } + + AddSeparator( leftView, "Routine" ); + Print( leftView, "Waypoint", npc->wpname ); + if ( auto sym = parser->GetSymbol( npc->GetAIState() ) ) + { + Print( leftView, "AIState", sym->name ); + } + else + { + Print( leftView, "AIState", Z npc->GetAIState() ); + } + if ( auto sym = parser->GetSymbol( npc->daily_routine ) ) + { + Print( leftView, "DailyRoutine", sym->name ); + } + else + { + Print( leftView, "DailyRoutine", Z npc->daily_routine ); + } + + //RIGHT SIDE + AddSeparator( rightView, "Attributes" ); + Print( rightView, "HP", Z npc->GetAttribute( NPC_ATR_HITPOINTS ) + "/" + Z npc->GetAttribute( NPC_ATR_HITPOINTSMAX ) ); + Print( rightView, "MANA", Z npc->GetAttribute( NPC_ATR_MANA ) + "/" + Z npc->GetAttribute( NPC_ATR_MANAMAX ) ); + Print( rightView, "STR", Z npc->GetAttribute( NPC_ATR_STRENGTH ) ); + Print( rightView, "DEX", Z npc->GetAttribute( NPC_ATR_DEXTERITY ) ); + + AddSeparator( rightView, "Fight talents" ); +#if ENGINE >= Engine_G2 + Print( rightView, "1H", Z npc->GetHitChance( NPC_HITCHANCE_1H ) ); + Print( rightView, "2H", Z npc->GetHitChance( NPC_HITCHANCE_2H ) ); + Print( rightView, "BOW", Z npc->GetHitChance( NPC_HITCHANCE_BOW ) ); + Print( rightView, "CBOW", Z npc->GetHitChance( NPC_HITCHANCE_CROSSBOW ) ); +#else + Print( rightView, "1H", Z npc->GetTalentValue( NPC_HITCHANCE_1H ) ); + Print( rightView, "2H", Z npc->GetTalentValue( NPC_HITCHANCE_2H ) ); + Print( rightView, "BOW", Z npc->GetTalentValue( NPC_HITCHANCE_BOW ) ); + Print( rightView, "CBOW", Z npc->GetTalentValue( NPC_HITCHANCE_CROSSBOW ) ); +#endif + + AddSeparator( rightView, "Damage" ); + Print( rightView, "DAM_EDGE", Z npc->GetDamageByIndex( oEDamageIndex_Edge ) ); + Print( rightView, "DAM_BLUNT", Z npc->GetDamageByIndex( oEDamageIndex_Blunt ) ); + Print( rightView, "DAM_POINT", Z npc->GetDamageByIndex( oEDamageIndex_Point ) ); + Print( rightView, "DAM_FIRE", Z npc->GetDamageByIndex( oEDamageIndex_Fire ) ); + Print( rightView, "DAM_MAGIC", Z npc->GetDamageByIndex( oEDamageIndex_Magic ) ); + Print( rightView, "DAM_FLY", Z npc->GetDamageByIndex( oEDamageIndex_Fly ) ); + Print( rightView, "DAM_FALL", Z npc->GetDamageByIndex( oEDamageIndex_Fall ) ); + Print( rightView, "DamageType", Z npc->damagetype ); + + AddSeparator( rightView, "Protection" ); + Print( rightView, "PROT_EDGE", Z npc->GetProtectionByIndex( oEDamageIndex_Edge ) ); + Print( rightView, "PROT_BLUNT", Z npc->GetProtectionByIndex( oEDamageIndex_Blunt ) ); + Print( rightView, "PROT_POINT", Z npc->GetProtectionByIndex( oEDamageIndex_Point ) ); + Print( rightView, "PROT_FIRE", Z npc->GetProtectionByIndex( oEDamageIndex_Fire ) ); + Print( rightView, "PROT_MAGIC", Z npc->GetProtectionByIndex( oEDamageIndex_Magic ) ); + Print( rightView, "PROT_FLY", Z npc->GetProtectionByIndex( oEDamageIndex_Fly ) ); + Print( rightView, "PROT_FALL", Z npc->GetProtectionByIndex( oEDamageIndex_Fall ) ); } void DebugHelper::InfoItem( oCItem* item ) { - Print( textView, "Instance", item->GetInstanceName() + " (" + Z item->instanz + ")" ); - Print( textView, "Name", Z item->name ); - Print( textView, "Description", Z item->GetDescription() ); - Print( textView, "Value", Z item->GetValue() ); + Print( leftView, "--- " + item->_GetClassDef()->className, item->GetInstanceName() + " ( " + Z item->instanz + " )" ); + Print( leftView, "Name", Z item->name ); + Print( leftView, "Description", Z item->GetDescription() ); + Print( leftView, "Value", Z item->GetValue() ); + Print( leftView, "Owner", Z item->owner ); + if ( item->ownerGuild ) + Print( leftView, "OwnerGuild", ogame->GetGuilds()->GetGuildName( item->ownerGuild ) + " ( " + Z item->ownerGuild + " )" ); + Print( leftView, "SchemeName", Z item->GetSchemeName() ); + Print( leftView, "Material", Z item->GetSoundMaterial() ); + if ( auto symbol = parser->GetSymbol( item->GetStateFunc() ) ) + Print( leftView, "onState", symbol->name ); + if ( item->HasFlag( ITM_CAT_ARMOR ) || item->HasFlag( ITM_CAT_NF ) || item->HasFlag( ITM_CAT_FF ) || item->HasFlag( ITM_CAT_MUN ) ) { - AddSeparator(); - Print( textView, "PROT_EDGE", Z item->GetProtectionByIndex( oEDamageIndex_Edge ) ); - Print( sideView, "DAM_EDGE", Z item->GetDamageByIndex( oEDamageIndex_Edge ) ); - Print( textView, "PROT_BLUNT", Z item->GetProtectionByIndex( oEDamageIndex_Blunt ) ); - Print( sideView, "DAM_BLUNT", Z item->GetDamageByIndex( oEDamageIndex_Blunt ) ); - Print( textView, "PROT_POINT", Z item->GetProtectionByIndex( oEDamageIndex_Point ) ); - Print( sideView, "DAM_POINT", Z item->GetDamageByIndex( oEDamageIndex_Point ) ); - Print( textView, "PROT_FIRE", Z item->GetProtectionByIndex( oEDamageIndex_Fire ) ); - Print( sideView, "DAM_FIRE", Z item->GetDamageByIndex( oEDamageIndex_Fire ) ); - Print( textView, "PROT_MAGIC", Z item->GetProtectionByIndex( oEDamageIndex_Magic ) ); - Print( sideView, "DAM_MAGIC", Z item->GetDamageByIndex( oEDamageIndex_Magic ) ); - Print( textView, "PROT_FLY", Z item->GetProtectionByIndex( oEDamageIndex_Fly ) ); - Print( sideView, "DAM_FLY", Z item->GetDamageByIndex( oEDamageIndex_Fly ) ); - Print( textView, "PROT_FALL", Z item->GetProtectionByIndex( oEDamageIndex_Fall ) ); - Print( sideView, "DAM_FALL", Z item->GetDamageByIndex( oEDamageIndex_Fall ) ); - Print( textView, "TotalDamage", Z item->damageTotal ); - Print( sideView, "Range", Z item->range ); - Print( textView, "DamageTypes", Z item->damageTypes ); - AddSeparator(); + Print( leftView, "Range", Z item->range ); + + AddSeparator( rightView, "Damage" ); + Print( rightView, "DAM_EDGE", Z item->GetDamageByIndex( oEDamageIndex_Edge ) ); + Print( rightView, "DAM_BLUNT", Z item->GetDamageByIndex( oEDamageIndex_Blunt ) ); + Print( rightView, "DAM_POINT", Z item->GetDamageByIndex( oEDamageIndex_Point ) ); + Print( rightView, "DAM_FIRE", Z item->GetDamageByIndex( oEDamageIndex_Fire ) ); + Print( rightView, "DAM_MAGIC", Z item->GetDamageByIndex( oEDamageIndex_Magic ) ); + Print( rightView, "DAM_FLY", Z item->GetDamageByIndex( oEDamageIndex_Fly ) ); + Print( rightView, "DAM_FALL", Z item->GetDamageByIndex( oEDamageIndex_Fall ) ); + Print( rightView, "TotalDamage", Z item->damageTotal ); + Print( rightView, "DamageTypes", Z item->damageTypes ); + + AddSeparator( rightView, "Protection" ); + Print( rightView, "PROT_EDGE", Z item->GetProtectionByIndex( oEDamageIndex_Edge ) ); + Print( rightView, "PROT_BLUNT", Z item->GetProtectionByIndex( oEDamageIndex_Blunt ) ); + Print( rightView, "PROT_POINT", Z item->GetProtectionByIndex( oEDamageIndex_Point ) ); + Print( rightView, "PROT_FIRE", Z item->GetProtectionByIndex( oEDamageIndex_Fire ) ); + Print( rightView, "PROT_MAGIC", Z item->GetProtectionByIndex( oEDamageIndex_Magic ) ); + Print( rightView, "PROT_FLY", Z item->GetProtectionByIndex( oEDamageIndex_Fly ) ); + Print( rightView, "PROT_FALL", Z item->GetProtectionByIndex( oEDamageIndex_Fall ) ); } else if ( item->spell ) { - AddSeparator( "Spell" ); - Print( textView, "SpellID", Z item->spell ); - Print( sideView, "Circle", Z item->mag_circle ); + AddSeparator( rightView, "Spell" ); + Print( rightView, "SpellID", Z item->spell ); + Print( rightView, "Circle", Z item->mag_circle ); oCSpell* spl = new oCSpell( item->spell ); - Print( textView, "SpellName", spl->GetName() ); + Print( rightView, "SpellName", spl->GetName() ); spl->Release(); - AddSeparator(); } - else - AddSeparator(); + AddSeparator( leftView, "Flags" ); + Print( leftView, "Mainflag", Z item->mainflag ); + Print( leftView, "Flags", Z item->flags ); + + AddSeparator( leftView, "Requirements" ); for ( int i = 0; i < ITM_COND_MAX; i++ ) { if ( !item->cond_atr[i] ) continue; - Print( textView, "Cond" + Z i, Z item->cond_atr[i] + " (" + Z item->cond_value[i] + ")" ); + Print( leftView, GetAttributeName( item->cond_atr[i] ), Z item->cond_value[i] ); } - Print( textView, "Mainflag", Z item->mainflag ); - Print( sideView, "Flags", Z item->flags ); - Print( textView, "Owner", Z item->owner ); - if ( item->ownerGuild ) - Print( textView, "OwnerGuild", ogame->GetGuilds()->GetGuildName( item->ownerGuild ) + " (" + Z item->ownerGuild + ")" ); - Print( textView, "SchemeName", Z item->GetSchemeName() ); - Print( sideView, "Material", Z item->GetSoundMaterial() ); - - int onState = item->GetStateFunc(); - if ( onState != Invalid ) - Print( textView, "onState", Z onState ); - if ( zCVisual* visual = item->GetVisual() ) { - AddSeparator( "Visual" ); - Print( textView, "VisualFile", visual->GetVisualName() ); - Print( textView, "VisualChange", item->GetVisualChange() ); + AddSeparator( leftView, "Visual" ); + Print( leftView, "VisualFile", visual->GetVisualName() ); + Print( leftView, "VisualChange", item->GetVisualChange() ); #if ENGINE == Engine_G2A - Print( textView, "EffectName", item->GetEffectName() ); + Print( leftView, "EffectName", item->GetEffectName() ); #endif } } void DebugHelper::InfoMob( oCMOB* mob ) { - Print( textView, "MobName", mob->name ); - Print( textView, "Name", mob->GetName() ); - Print( textView, "Owner", mob->ownerStr ); - Print( textView, "ScemeName", mob->GetScemeName() ); + Print( leftView, "--- " + mob->_GetClassDef()->className, mob->name ); + Print( leftView, "Name", mob->GetName() ); + Print( leftView, "Owner", mob->ownerStr ); + Print( leftView, "ScemeName", mob->GetScemeName() ); if ( oCMobInter* inter = mob->CastTo() ) { - AddSeparator( "Inter" ); - Print( textView, "UseItem", inter->useWithItem ); - Print( textView, "ConditionFuncName", inter->conditionFunc ); - Print( textView, "OnStateFuncName", inter->onStateFuncName ); + AddSeparator( leftView, "Inter" ); + Print( leftView, "TriggerTarget", inter->triggerTarget ); + Print( leftView, "UseItem", inter->useWithItem ); + Print( leftView, "ConditionFuncName", inter->conditionFunc ); + Print( leftView, "OnStateFuncName", inter->onStateFuncName ); } if ( oCMobLockable* lockable = mob->CastTo() ) { - AddSeparator( "Lockable" ); - Print( textView, "KeyInstance", lockable->keyInstance ); - Print( textView, "LockString", lockable->pickLockStr ); - Print( textView, "Locked", Z lockable->locked ); + AddSeparator( rightView, "Lockable" ); + Print( rightView, "KeyInstance", lockable->keyInstance ); + Print( rightView, "LockString", lockable->pickLockStr ); + Print( rightView, "Locked", Z lockable->locked ); + } + + if ( zCVisual* visual = mob->GetVisual() ) { + AddSeparator( leftView, "Visual" ); + Print( leftView, "VisualFile", visual->GetVisualName() ); } if ( oCMobContainer* container = mob->CastTo() ) + { if ( auto list = container->containList.GetNextInList() ) { int itemCount = container->containList.GetNumInList(); int printedItems = 0; - AddSeparator( "Container" ); + AddSeparator( leftView, "Container" ); while ( list != nullptr ) { - Print( textView, list->GetData()->name, Z list->GetData()->amount ); + Print( leftView, list->GetData()->name, Z list->GetData()->amount ); printedItems++; - if ( itemCount > 5 && printedItems >= 5 ) { - Print( textView, "", "And " + Z( itemCount - printedItems ) + " more..." ); + if ( itemCount > 15 && printedItems >= 15 ) { + Print( leftView, "", "And " + Z( itemCount - printedItems ) + " more..." ); break; } list = list->GetNextInList(); } } - - if ( zCVisual* visual = mob->GetVisual() ) { - AddSeparator( "Visual" ); - Print( textView, "VisualFile", visual->GetVisualName() ); } } - void DebugHelper::AddSeparator( zSTRING str ) { - if ( textLines > 0 ) - textLines++; + void DebugHelper::AddSeparator( zCView* view, zSTRING str ) { + int textLines; + + + if ( view == leftView ) + textLinesLeft++; + else if ( view == rightView ) + textLinesRight++; if ( !str.Length() ) return; - textLines++; - textView->Print( 0, textHeight * textLines, "--- " + str ); + if ( view == rightView ) + { + textLinesRight++; + + textLines = textLinesRight; + } + else + { + textLinesLeft++; + + textLines = textLinesLeft; + } + + view->Print( 0, textHeight * textLines, "--- " + str ); } void DebugHelper::Print( zCView* view, zSTRING name, zSTRING value ) { if ( !value.Length() ) value = "-"; - zSTRING text = (name.Length()) ? name + ": " + value : value; - - if ( view == textView ) - textLines++; + zSTRING text = ( name.Length() ) ? name + ": " + value : value; + int textLines; + if ( view == rightView ) + { + textLinesRight++; + textLines = textLinesRight; + } + else + { + textLinesLeft++; + textLines = textLinesLeft; + } view->Print( 0, textHeight * textLines, text ); } @@ -230,7 +270,6 @@ namespace GOTHIC_ENGINE { bool DebugHelper::TryPrintInfo() { if ( player->inventory2.IsOpen() ) if ( oCItem* item = player->inventory2.GetSelectedItem() ) { - AddSeparator( item->_GetClassDef()->className ); InfoItem( item ); return true; } @@ -239,8 +278,6 @@ namespace GOTHIC_ENGINE { if ( !vob ) return false; - AddSeparator( vob->_GetClassDef()->className ); - if ( oCNpc* npc = vob->CastTo() ) InfoNpc( npc ); else if ( oCItem* item = vob->CastTo() ) @@ -254,11 +291,33 @@ namespace GOTHIC_ENGINE { void DebugHelper::Clear() { if ( mainView == nullptr ) return; - del( textView ); - del( sideView ); + del( leftView ); + del( rightView ); del( mainView ); } + void DebugHelper::ShowTriggerBoxes() { + if (!Options::ShowTriggers) { + return; + } + + zCArray listVobs; + player->CreateVobList(listVobs, 5000.0f); + for (int i = 0; i < listVobs.GetNumInList(); i++) + { + auto vob = listVobs[i]; + + if (!vob) + continue; + + auto trigger = vob->CastTo(); + if (!trigger) + continue; + + trigger->bbox3D.Draw(GFX_RED); + } + } + void DebugHelper::Loop() { if ( !Options::UsingDebugHelper || ogame->pause_screen @@ -273,7 +332,7 @@ namespace GOTHIC_ENGINE { if ( mainView == nullptr ) { int offset = 512 * playerHelper.GetSysScale(); - mainView = new zCView( 0, 1024 - offset, 2304 + offset, 7168 + offset ); + mainView = new zCView( 0, 1024 - offset, 3456 + offset, 7168 + offset ); mainView->InsertBack( "BLACKBACK" ); mainView->SetAlphaBlendFunc( zRND_ALPHA_FUNC_BLEND ); mainView->SetTransparency( 150 ); @@ -282,15 +341,18 @@ namespace GOTHIC_ENGINE { textHeight = mainView->FontY(); margin = textHeight; - textView = new zCView( margin, 0, 8192 - margin, 8192 ); - sideView = new zCView( margin + 8192 * 0.6f, 0, 8192 - margin, 8192 ); - mainView->InsertItem( textView ); - mainView->InsertItem( sideView ); + leftView = new zCView( margin, 0, 8192 - margin, 8192 ); + rightView = new zCView( margin + 8192 * 0.6f, 0, 8192 - margin, 8192 ); + mainView->InsertItem( leftView ); + mainView->InsertItem( rightView ); } - textView->ClrPrintwin(); - sideView->ClrPrintwin(); - textLines = 0; + leftView->ClrPrintwin(); + rightView->ClrPrintwin(); + textLinesLeft = 0; + textLinesRight = 0; + + ShowTriggerBoxes(); if ( TryPrintInfo() ) return; diff --git a/zUtilities/DebugHelper.h b/zUtilities/DebugHelper.h index 62f66bf..ab96dcd 100644 --- a/zUtilities/DebugHelper.h +++ b/zUtilities/DebugHelper.h @@ -4,24 +4,27 @@ namespace GOTHIC_ENGINE { namespace Options { bool UsingDebugHelper = false; + bool ShowTriggers = false; } class DebugHelper { private: zCView* mainView; - zCView* textView; - zCView* sideView; + zCView* leftView; + zCView* rightView; - int textLines; + int textLinesLeft; + int textLinesRight; int textHeight; int margin; void InfoNpc( oCNpc* npc ); void InfoItem( oCItem* item ); void InfoMob( oCMOB* mob ); - void AddSeparator( zSTRING str = "" ); + void AddSeparator( zCView* view, zSTRING str = "" ); void Print( zCView* view, zSTRING name, zSTRING value ); bool TryPrintInfo(); + void ShowTriggerBoxes(); public: void Clear(); diff --git a/zUtilities/FocusColor.cpp b/zUtilities/FocusColor.cpp index 4606f86..8c5f474 100644 --- a/zUtilities/FocusColor.cpp +++ b/zUtilities/FocusColor.cpp @@ -306,21 +306,17 @@ namespace GOTHIC_ENGINE { } zSTRING FocusColor::GetName( zCVob* vob ) { - if ( Options::ColorLockables ) - if ( oCMobLockable* lockable = vob->CastTo() ) - return lockable->GetName(); + if ( oCMobLockable* lockable = vob->CastTo() ) + return lockable->GetName(); - if ( Options::ColorNpcs ) - if ( oCNpc* npc = vob->CastTo() ) - return npc->name[0]; + if ( oCNpc* npc = vob->CastTo() ) + return npc->name[0]; - if ( Options::ColorItems ) - if ( oCItem* item = vob->CastTo() ) - return item->name; + if ( oCItem* item = vob->CastTo() ) + return item->name; - if ( Options::ColorInter ) - if ( oCMobInter* inter = vob->CastTo() ) - return inter->GetName(); + if ( oCMobInter* inter = vob->CastTo() ) + return inter->GetName(); return ""; } diff --git a/zUtilities/Headers.h b/zUtilities/Headers.h index db73881..7cd3f71 100644 --- a/zUtilities/Headers.h +++ b/zUtilities/Headers.h @@ -2,6 +2,7 @@ // Add your headers this // Automatically generated block +#include #pragma region Includes #include "Const.h" #include "Colors.h" diff --git a/zUtilities/IconInfo.cpp b/zUtilities/IconInfo.cpp index 7a9eb41..e26d2be 100644 --- a/zUtilities/IconInfo.cpp +++ b/zUtilities/IconInfo.cpp @@ -9,6 +9,7 @@ namespace GOTHIC_ENGINE { if ( quickSave->IsBusy() || !ogame->GetShowPlayerStatus() || !ogame->game_drawall || ogame->IsOnPause() || playerHelper.IsInInfo() || player->attribute[NPC_ATR_HITPOINTS] <= 0 ) return; + RestoreViewport(); //because some plugins don't restore viewport after Blitting, so it messes with prints in other plugins DrawIcon(); PrintText(); } @@ -41,6 +42,12 @@ namespace GOTHIC_ENGINE { delete view; } + void IconInfo::RestoreViewport() { + int ScreenX, ScreenY, ScreenSX, ScreenSY; + screen->GetViewport(ScreenX, ScreenY, ScreenSX, ScreenSY); + zrenderer->SetViewport(ScreenX, ScreenY, ScreenSX, ScreenSY); + } + IconInfo::IconInfo( int x, int y, int size, zCOLOR color, zSTRING texName, zSTRING text = "" ) : vx( x ), vy( y ), vsize( size ), color( color ), texName( texName ), text( text ) { Draw(); diff --git a/zUtilities/IconInfo.h b/zUtilities/IconInfo.h index 14265a6..bddb4b3 100644 --- a/zUtilities/IconInfo.h +++ b/zUtilities/IconInfo.h @@ -21,6 +21,7 @@ namespace GOTHIC_ENGINE { void Draw(); void DrawIcon(); void PrintText(); + void RestoreViewport(); public: IconInfo( int x, int y, int size, zCOLOR color, zSTRING texName, zSTRING text ); diff --git a/zUtilities/Misc.cpp b/zUtilities/Misc.cpp index 5957f72..0de7335 100644 --- a/zUtilities/Misc.cpp +++ b/zUtilities/Misc.cpp @@ -22,4 +22,20 @@ namespace GOTHIC_ENGINE { string archivePath = string::Combine( "%s\\%s\\%s\.sav", savesDir, slotDir, sav ); return archivePath; } + + zSTRING GetAttributeName( int att ) { + switch ( att ) + { + case NPC_ATR_HITPOINTSMAX: + return "HP"; + case NPC_ATR_MANAMAX: + return "MANA"; + case NPC_ATR_STRENGTH: + return "STR"; + case NPC_ATR_DEXTERITY: + return "DEX"; + default: + return ""; + } + } } \ No newline at end of file diff --git a/zUtilities/Options.h b/zUtilities/Options.h index 98b62f3..fac9c34 100644 --- a/zUtilities/Options.h +++ b/zUtilities/Options.h @@ -92,6 +92,8 @@ namespace GOTHIC_ENGINE { zoptions->AddTrivia( PLUGIN_NAME, "ActivateUsedMunition", "... enables (1) or disables (0) highlighting currently used ranged weapon munition in the inventory" ); zoptions->AddTrivia( PLUGIN_NAME, "AlternativeDialogueBoxes", "... enables (1) or disables (0) alternative dialogue boxes style" ); zoptions->AddTrivia( PLUGIN_NAME, "SelectedDialogueColor", "... defines color of selected line in dialogues" + nline + "... use 'R|G|B' or 'R|G|B|A' format" + nline + "... leave empty to use default color" ); + + zoptions->AddTrivia( PLUGIN_NAME, "SaveReminder", "... Time in minutes after which the reminder to save the game appears on the screen" + nline + "... set to -1 to disable"); } } } \ No newline at end of file diff --git a/zUtilities/PlayerStatus.cpp b/zUtilities/PlayerStatus.cpp index 004f7d4..8e863e4 100644 --- a/zUtilities/PlayerStatus.cpp +++ b/zUtilities/PlayerStatus.cpp @@ -2,6 +2,50 @@ // Union SOURCE file namespace GOTHIC_ENGINE { +#if ENGINE >= Engine_G2 + std::vector vfxs; + HOOK Ivk_InitEffect_Union PATCH( &oCVisualFX::InitEffect, &oCVisualFX::InitEffect_Union ); + void oCVisualFX::InitEffect_Union() { + + if ( visName_S.Search( ".SLW", 1 ) == -1 ) + { + THISCALL( Ivk_InitEffect_Union )(); + return; + } + + vfxs.push_back( this ); + playerStatus.ResetTimeMultiplier(); + + THISCALL( Ivk_InitEffect_Union )(); + } + + HOOK Ivk_EndEffect_Union PATCH(&oCVisualFX::EndEffect, &oCVisualFX::EndEffect_Union); + void oCVisualFX::EndEffect_Union( const int kill ) { + if ( visName_S.Search( ".SLW", 1 ) == -1 ) + { + THISCALL( Ivk_EndEffect_Union )( kill ); + return; + } + + auto it = std::find( vfxs.begin(), vfxs.end(), this ); + if (it != vfxs.end()) + { + vfxs.erase( std::remove( vfxs.begin(), vfxs.end(), this ), vfxs.end() ); + } + + THISCALL( Ivk_EndEffect_Union )( kill ); + } +#endif + + bool PlayerStatus::CanChangeZtimer() + { +#if ENGINE >= Engine_G2 + return vfxs.empty(); +#endif + return true; + } + + HOOK Ivk_CallOnStateFunc_Union PATCH( &oCMobInter::CallOnStateFunc, &oCMobInter::CallOnStateFunc_Union ); void oCMobInter::CallOnStateFunc_Union( oCNpc* npc, int a1 ) { THISCALL( Ivk_CallOnStateFunc_Union )(npc, a1); @@ -36,17 +80,15 @@ namespace GOTHIC_ENGINE { list = list->next; // Whenever the icon will visible or not is based on the npc dialogue including PICKPOCKET word which seems to be used consistently in mods as well. - if ( !info->name.HasWord( "PICKPOCKET" ) ) + if ( !info->name.HasWordI( "pickpocket" ) && !info->name.HasWordI( "_steal" ) && !info->name.HasWordI( "pickme" ) ) + continue; + + if ( info->name.HasWordI( "_DOIT" ) || info->name.HasWordI( "_TRY" ) ) continue; // To avoid targeting possible dialogues related to pickpocketing quests or teach options. - int idx = parser->GetIndex( info->name + "_DOIT" ); - if ( idx == Invalid ) { - // Alternative pickpocket instance name - idx = parser->GetIndex( info->name + "_TRY" ); - if ( idx == Invalid ) - continue; - } + if ( parser->GetIndex( info->name + "_DOIT" ) == Invalid && parser->GetIndex( info->name + "_TRY" ) == Invalid ) + continue; if ( !pickpocketInfos.IsInList( info ) ) pickpocketInfos.Insert( info ); @@ -163,7 +205,7 @@ namespace GOTHIC_ENGINE { #if ENGINE < Engine_G2 HOOK Hook_zCAICamera_CheckKeys PATCH( &zCAICamera::CheckKeys, &zCAICamera::CheckKeys_Union ); void zCAICamera::CheckKeys_Union() { - if ( !Options::UseTimeMultiplier || ztimer->factorMotion == 1.0f ) { + if ( !Options::UseTimeMultiplier || ztimer->factorMotion == 1.0f || !playerStatus.CanChangeZtimer() ) { THISCALL( Hook_zCAICamera_CheckKeys )(); return; } @@ -179,7 +221,7 @@ namespace GOTHIC_ENGINE { HOOK Hook_oCAIHuman_PC_Turnings PATCH( &oCAIHuman::PC_Turnings, &oCAIHuman::PC_Turnings_Union ); void oCAIHuman::PC_Turnings_Union( int forceRotation ) { - if ( !Options::UseTimeMultiplier || ztimer->factorMotion == 1.0f || Pressed( GAME_LEFT ) || Pressed( GAME_RIGHT ) ) { + if ( !Options::UseTimeMultiplier || ztimer->factorMotion == 1.0f || Pressed( GAME_LEFT ) || Pressed( GAME_RIGHT ) || !playerStatus.CanChangeZtimer() ) { THISCALL( Hook_oCAIHuman_PC_Turnings )(forceRotation); return; } @@ -201,6 +243,15 @@ namespace GOTHIC_ENGINE { ztimer->factorMotion = 1.0f; } + void PlayerStatus::ResetSaveReminder() { + if (SaveLoadGameInfo.changeLevel) + { + return; + } + + lastSaveTime = std::chrono::high_resolution_clock::now(); + } + void PlayerStatus::FactorMotion() { if ( !Options::UseTimeMultiplier ) return; @@ -208,6 +259,9 @@ namespace GOTHIC_ENGINE { if ( !Options::TimeMultipliers.GetNum() || playerHelper.IsConUp() ) return; + if ( !CanChangeZtimer() ) + return; + if ( playerHelper.IsDead() || playerHelper.IsInInfo() || ogame->IsOnPause() ) { if ( ztimer->factorMotion != 1.0f ) ztimer->factorMotion = 1.0f; @@ -299,6 +353,36 @@ namespace GOTHIC_ENGINE { IconInfo icon = IconInfo( screen->FontY(), screen->FontY() * 2.5 * infoIcons, screen->FontY() * 0.9f, color, texture, Z amount ); } + void PlayerStatus::ShowSaveReminder() { + if ( + Options::SaveReminder == Invalid + || !ogame + || !player + || playerHelper.IsBusy() + || quickSave->IsBusy() + || playerHelper.IsDead() + || playerHelper.IsConUp() + || !ogame->GetShowPlayerStatus() + || !ogame->game_drawall + ) + { + return; + } + + auto ElapsedTime = std::chrono::high_resolution_clock::now() - lastSaveTime; + auto ElapsedMins = std::chrono::duration_cast(ElapsedTime); + auto ElapsedSeconds = std::chrono::duration_cast(ElapsedTime - ElapsedMins); + if ( ElapsedTime >= static_cast( Options::SaveReminder ) ) + { + zSTRING str = ( ElapsedMins.count() < 10 ? "0" : "" ) + Z ElapsedMins.count() + ":" + ( ElapsedSeconds.count() < 10 ? "0" : "" ) + Z static_cast( ElapsedSeconds.count() ); + + zSTRING texture = "ICON_SAVE"; // https://game-icons.net/1x1/lorc/disc.html + + infoIcons++; + IconInfo icon = IconInfo(screen->FontY(), screen->FontY() * 2.5 * infoIcons, screen->FontY() * 0.9f, GFX_RED, texture, str); + } + } + void PlayerStatus::StatusBars() { if ( !hpBar ) hpBar = new StatusBar( ogame->hpBar ); @@ -352,6 +436,7 @@ namespace GOTHIC_ENGINE { FactorMotion(); ShowGameTime(); ShowMunitionAmount(); + ShowSaveReminder(); HandleMunitionLoop(); RenderSelectedItem(); } diff --git a/zUtilities/PlayerStatus.h b/zUtilities/PlayerStatus.h index e35fe13..a2dc4c8 100644 --- a/zUtilities/PlayerStatus.h +++ b/zUtilities/PlayerStatus.h @@ -6,6 +6,7 @@ namespace GOTHIC_ENGINE { bool ShowGameTime, ShowMunitionAmount, ShowTargetProtection, ShowPickpocketIcon, UseTimeMultiplier; int KeyTimeMultiplier; Array TimeMultipliers; + int SaveReminder; void PlayerStatus() { ShowGameTime = zoptions->ReadBool( PLUGIN_NAME, "ShowGameTime", false ); @@ -22,6 +23,8 @@ namespace GOTHIC_ENGINE { TimeMultipliers.Clear(); for ( int i = 0; i < MulStrings.GetNum(); i++ ) TimeMultipliers.Insert( MulStrings[i].Shrink().ToReal32() ); + + SaveReminder = zoptions->ReadInt(PLUGIN_NAME, "SaveReminder", 5); } } @@ -32,9 +35,11 @@ namespace GOTHIC_ENGINE { StatusBar* swimBar; int multiplierIndex = 0; int infoIcons = 0; + std::chrono::high_resolution_clock::time_point lastSaveTime; void ShowGameTime(); void ShowMunitionAmount(); + void ShowSaveReminder(); void StatusBars(); void FactorMotion(); @@ -47,9 +52,11 @@ namespace GOTHIC_ENGINE { StatusBar* focusBar; bool CanPickpocketNpc( oCNpc* npc ); void GetPickpocketInfos(); + bool CanChangeZtimer(); bool KnowStateFunc( zCVob* vob ); void TryAddStateFunc( zCVob* vob ); void ResetTimeMultiplier(); + void ResetSaveReminder(); void Clear(); void Loop(); void Archive( zCArchiver* ar ); diff --git a/zUtilities/Plugin.cpp b/zUtilities/Plugin.cpp index e12e2ee..e28aa1a 100644 --- a/zUtilities/Plugin.cpp +++ b/zUtilities/Plugin.cpp @@ -44,6 +44,7 @@ namespace GOTHIC_ENGINE { void Game_SaveEnd() { quickSave->saveEnd = true; Archive(); + playerStatus.ResetSaveReminder(); } void LoadBegin() { @@ -61,6 +62,7 @@ namespace GOTHIC_ENGINE { #if ENGINE >= Engine_G2 playerStatus.GetPickpocketInfos(); #endif + playerStatus.ResetSaveReminder(); } void Game_LoadBegin_NewGame() { diff --git a/zUtilities/ZenGin/Gothic_UserAPI/oCVisualFX.inl b/zUtilities/ZenGin/Gothic_UserAPI/oCVisualFX.inl index 4f58bf6..abdbea8 100644 --- a/zUtilities/ZenGin/Gothic_UserAPI/oCVisualFX.inl +++ b/zUtilities/ZenGin/Gothic_UserAPI/oCVisualFX.inl @@ -3,3 +3,7 @@ // User API for oCVisualFX // Add your methods here +#if ENGINE >= Engine_G2 +void InitEffect_Union(); +void EndEffect_Union(const int); +#endif \ No newline at end of file