From e1e4d550cc6fa3f4d52de93b2a2e448905a0f70e Mon Sep 17 00:00:00 2001 From: cbnolok Date: Sun, 19 Nov 2023 17:50:51 +0100 Subject: [PATCH 01/90] Missing comma. --- src/game/CServerConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 354b0cc75..ddaf9b3f7 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -1967,7 +1967,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * break; case RC_BUILD: #ifdef __GITREVISION__ - sVal.Format("%s, rev: %u" __GITBRANCH__, __GITREVISION__ ); + sVal.Format("%u (%s)", __GITBRANCH__, __GITREVISION__ ); #else sVal = __DATE__; #endif From 855dd7dec90bac63bca8e2e545dfd4f8004ad59b Mon Sep 17 00:00:00 2001 From: Raylde <50953519+Raylde@users.noreply.github.com> Date: Fri, 24 Nov 2023 17:49:57 +0100 Subject: [PATCH 02/90] Fix crafting (#1190) --- src/game/clients/CClientUse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/clients/CClientUse.cpp b/src/game/clients/CClientUse.cpp index b9b934500..5f62d7e90 100644 --- a/src/game/clients/CClientUse.cpp +++ b/src/game/clients/CClientUse.cpp @@ -645,7 +645,7 @@ bool CClient::Skill_Menu(SKILL_TYPE skill, lpctstr skillmenu, ITEMID_TYPE itemus Args.m_VarsLocal.SetNumNew("ItemUsed", itemused); if (IsTrigUsed(TRIGGER_SKILLMENU)) { - if (m_pChar->Skill_OnCharTrigger(skill, CTRIG_SkillMenu, &Args) == TRIGRET_RET_TRUE) + if (m_pChar->OnTrigger(CTRIG_SkillMenu, m_pChar, &Args) == TRIGRET_RET_TRUE ) return true; skillmenu = Args.m_VarsLocal.GetKeyStr("Skillmenu", false); From 901745842218f6c08ff7f1ef5ae675252a94a257 Mon Sep 17 00:00:00 2001 From: Raylde <50953519+Raylde@users.noreply.github.com> Date: Fri, 1 Dec 2023 14:36:42 +0100 Subject: [PATCH 03/90] Add editorconfig (#1188) --- .editorconfig | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..ad8d27d64 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +trim_trailing_whitespace = true +end_of_line = lf +insert_final_newline = true + +# Tab indentation (no size specified) +[Makefile] +indent_style = tab + +[*.{c,h,cpp,hpp}] +indent_size = 4 +indent_style = space +cpp_indent_case_contents_when_block = true +cpp_new_line_before_open_brace_namespace = same_line +cpp_indent_namespace_contents = true From 5e35e448361634cfea355a5bcd57b68fd21607af Mon Sep 17 00:00:00 2001 From: Jhobean <51728381+Jhobean@users.noreply.github.com> Date: Thu, 7 Dec 2023 13:02:28 -0500 Subject: [PATCH 04/90] Fix Issue #1191 CANMASK no save on server reboot (#1192) --- src/game/chars/CChar.cpp | 2 ++ src/game/items/CItem.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 5145247d0..a4418766e 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -3929,6 +3929,8 @@ void CChar::r_Write( CScript & s ) s.WriteKeyFormat("DAM", "%" PRIu16 ",%" PRIu16, m_attackBase, m_attackBase + m_attackRange); if ( m_defense ) s.WriteKeyVal("ARMOR", m_defense); + if (m_CanMask) + s.WriteKeyVal("CANMASK", m_CanMask); const uint uiActUID = m_Act_UID.GetObjUID(); if ((uiActUID & UID_UNUSED) != UID_UNUSED) diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 50385b8b4..13d04cf0c 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2364,6 +2364,8 @@ void CItem::r_Write( CScript & s ) s.WriteKeyFormat("DAM", "%hu,%hu", m_attackBase, m_attackBase + m_attackRange); if ( m_defenseBase ) s.WriteKeyFormat("ARMOR", "%hu,%hu", m_defenseBase, m_defenseBase + m_defenseRange); + if (m_CanMask) + s.WriteKeyVal("CANMASK", m_CanMask); if (!GetSpawn()) { if ( m_itNormal.m_more1 ) From c9cfc6c182465601ae62efc7343ab512556ecfd4 Mon Sep 17 00:00:00 2001 From: Raylde <50953519+Raylde@users.noreply.github.com> Date: Thu, 7 Dec 2023 19:02:57 +0100 Subject: [PATCH 05/90] Fix cancel target death (#1186) --- src/game/chars/CCharAct.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index 2d85540bd..f75b768ef 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -3261,6 +3261,7 @@ bool CChar::Death() pClient->addPlayerWarMode(); pClient->addSeason(SEASON_Desolate); pClient->addMapWaypoint(pCorpse, MAPWAYPOINT_Corpse); // add corpse map waypoint on enhanced clients + pClient->addTargetCancel(); // cancel target if player death CItem *pPack = LayerFind(LAYER_PACK); if ( pPack ) From 8753fc33912e2e45e4ce4c43657e74b327e35a68 Mon Sep 17 00:00:00 2001 From: Raylde <50953519+Raylde@users.noreply.github.com> Date: Fri, 8 Dec 2023 19:20:21 +0100 Subject: [PATCH 06/90] Feature/meditation fail movement (#1184) --- src/game/CServerConfig.cpp | 9 +++++++-- src/game/CServerConfig.h | 3 ++- src/game/chars/CCharAct.cpp | 8 ++++++++ src/sphere.ini | 5 +++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index ddaf9b3f7..595adfb93 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -196,6 +196,7 @@ CServerConfig::CServerConfig() _uiExperimentalFlags= 0; _uiOptionFlags = (OF_Command_Sysmsgs|OF_NoHouseMuteSpeech); _uiAreaFlags = AREAF_RoomInheritsFlags; + _fMeditationMovementAbort = false; m_iMaxSkill = SKILL_QTY; m_iWalkBuffer = 15; @@ -591,6 +592,7 @@ enum RC_TYPE RC_MAXSIZECLIENTOUT, // _uiMaxSizeClientOut RC_MAXSIZEPERTICK, // _uiNetMaxLengthPerTick RC_MD5PASSWORDS, // m_fMd5Passwords + RC_MEDITATIONMOVEMENTABORT, // _fMeditationMovementAbort RC_MEDIUMCANHEARGHOSTS, // m_iMediumCanHearGhosts RC_MINCHARDELETETIME, RC_MINKARMA, // m_iMinKarma @@ -699,6 +701,7 @@ enum RC_TYPE RC_QTY }; +// NOTE: Need to be alphabetized order const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY+1] { { "ACCTFILES", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sAcctBaseDir) }}, @@ -860,6 +863,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY+1] { "MAXSIZECLIENTOUT", { ELEM_INT64, static_castOFFSETOF(CServerConfig,_iMaxSizeClientOut) }}, { "MAXSIZEPERTICK", { ELEM_INT, static_castOFFSETOF(CServerConfig,_uiNetMaxLengthPerTick) }}, { "MD5PASSWORDS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fMd5Passwords) }}, + { "MEDITATIONMOVEMENTABORT",{ ELEM_BOOL, static_castOFFSETOF(CServerConfig,_fMeditationMovementAbort) }}, { "MEDIUMCANHEARGHOSTS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iMediumCanHearGhosts) }}, { "MINCHARDELETETIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iMinCharDeleteTime) }}, { "MINKARMA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iMinKarma) }}, @@ -1419,8 +1423,9 @@ bool CServerConfig::r_LoadVal( CScript &s ) case RC_WALKBUFFER: m_iWalkBuffer = s.GetArgVal() * MSECS_PER_TENTH; break; - - + case RC_MEDITATIONMOVEMENTABORT: + _fMeditationMovementAbort = s.GetArgVal() > 0 ? true : false; + break; default: return( sm_szLoadKeys[i].m_elem.SetValStr( this, s.GetArgRaw())); } diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 2615fa544..627ff909f 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -367,7 +367,8 @@ extern class CServerConfig : public CResourceHolder bool m_iPacketDeathAnimation; // packet 02c bool m_fDisplayPercentAr; // Display the ARMOR value in the tooltip as the % bool m_fDisplayElementalResistance; //Display the Elemental and MAxElemental Resistances on the paperdoll and tooltips (RESFIRE/RESCOLD/RESENERGY/RESPOISON) even if combat flag Elemental Engine is disabled. - + bool _fMeditationMovementAbort; // Meditation fails if the player moves. + // Flags for controlling pvp/pvm behaviour of players uint m_iCombatFlags; // combat flags uint m_iMagicFlags; // magic flags diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index f75b768ef..bb9d6e6f1 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -1306,6 +1306,14 @@ void CChar::UpdateMove( const CPointMap & ptOld, CClient * pExcludeClient, bool m_fStatusUpdate &= ~SU_UPDATE_MODE; EXC_TRY("UpdateMove"); + + // if skill is meditation, cancel it if we move + if (g_Cfg._fMeditationMovementAbort && Skill_GetActive() == SKILL_MEDITATION) + { + //cancel meditation if we move + Skill_Fail(true); + } + EXC_SET_BLOCK("FOR LOOP"); ClientIterator it; for ( CClient* pClient = it.next(); pClient != nullptr; pClient = it.next() ) diff --git a/src/sphere.ini b/src/sphere.ini index bc16cca20..051d7bcb2 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -435,6 +435,11 @@ SpeedScaleFactor=15000 // PARRYERA_ARSCALING 080 // Shields AR scales with Parrying skill, not compatible with Combat Elemental Engine. CombatParryingEra=01|010 +// Meditation behaviour +// 0 = Meditation allow movement +// 1 = Meditation abort on movement +MeditationMovementAbort=0 + //When enabled, display, in the tooltip, the Armor of the item as a percentage of its full armor value, the percentage is based upon the body parts the item covers. DisplayArmorAsPercent = 0 From b5845968c5ea03edeb02d8e5a83399825113cd3e Mon Sep 17 00:00:00 2001 From: Raylde <50953519+Raylde@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:37:35 +0100 Subject: [PATCH 07/90] Fix herding dupe char (#1185) --- src/game/chars/CCharSkill.cpp | 27 +++++++++++++++++++++++++++ src/tables/defmessages.tbl | 1 + 2 files changed, 28 insertions(+) diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index 6a9c23849..ac2bf0f83 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -2459,6 +2459,27 @@ int CChar::Skill_Herding( SKTRIG_TYPE stage ) { case SKTRIG_START: { + // CanSeeLos if pChar or m_Act_P + if ( !CanSeeLOS(pChar) || !CanSeeLOS(m_Act_p) ) + { + SysMessageDefault(DEFMSG_MSG_MOUNT_DIST); + return -SKTRIG_ABORT; + } + + // tamed pets cannot be herded + if ( !pChar->IsStatFlag(STATF_PET) ) + { + SysMessagef(g_Cfg.GetDefaultMsg( DEFMSG_TAMING_TAME ), pChar->GetName()); + return -SKTRIG_ABORT; + } + + // is a valid point? + if ( !m_Act_p.IsValidPoint()) + { + SysMessageDefault(DEFMSG_LOCATION_INVALID); + return -SKTRIG_ABORT; + } + if ( !g_Cfg.IsSkillFlag( Skill_GetActive(), SKF_NOANIM ) ) UpdateAnimate(ANIM_ATTACK_WEAPON); @@ -2471,6 +2492,12 @@ int CChar::Skill_Herding( SKTRIG_TYPE stage ) case SKTRIG_SUCCESS: { + // check if is disconnected or ridden + if ( pChar->IsDisconnected() || pChar->IsStatFlag(STATF_RIDDEN) ) + { + return -SKTRIG_ABORT; + } + if ( IsPriv(PRIV_GM) ) { if ( pChar->GetPrivLevel() > GetPrivLevel() ) diff --git a/src/tables/defmessages.tbl b/src/tables/defmessages.tbl index 095ca0c51..bf79462ae 100644 --- a/src/tables/defmessages.tbl +++ b/src/tables/defmessages.tbl @@ -1166,5 +1166,6 @@ MSG(NUDGED_OBJECTS, "Objects Nudged!") MSG(TILE_SAME_POINT, "Thats the same point") MSG(HOUSE_ADD_LIMIT, "House redeeded. You already own the maximum number of houses permitable.") MSG(DEED_NAME, "Deed to a %s") +MSG(LOCATION_INVALID, "That location is not valid.") #undef MSG \ No newline at end of file From 56f6e6c9c33f69d3945fbd2d02b1933fa0875132 Mon Sep 17 00:00:00 2001 From: DavideRei <118212274+DavideRei@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:43:17 +0100 Subject: [PATCH 08/90] Editable DispID for chars (#1178) --- Changelog.txt | 3 +++ src/game/chars/CChar.cpp | 53 +++++++++++++++++++++++++++++++++++--- src/game/chars/CChar.h | 2 ++ src/tables/CChar_props.tbl | 1 + 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 2f830e38d..c8a0c951a 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3435,3 +3435,6 @@ Additionally, the problem of zig-zag issue following in the South direction has 18-11-2023, Nolok - Fixed: House customization sending wrong component data, breaking it. + +09-12-2023, DavideRei +- Added: DispID can now also be used on chars, to change their appearance. diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index a4418766e..8fc303ca4 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -294,6 +294,7 @@ CChar::CChar( CREID_TYPE baseID ) : _wPrev_Hue = HUE_DEFAULT; _iPrev_id = CREID_INVALID; SetID( baseID ); + m_dwDispIndex = baseID; CCharBase* pCharDef = Char_GetDef(); ASSERT(pCharDef); @@ -1515,9 +1516,46 @@ word CChar::GetBaseID() const CREID_TYPE CChar::GetDispID() const { - const CCharBase * pCharDef = Char_GetDef(); - ASSERT(pCharDef); - return pCharDef->GetDispID(); + if (CCharBase::IsValidDispID(m_dwDispIndex)) + { + return m_dwDispIndex; + } + else + { + const CCharBase * pCharDef = Char_GetDef(); + ASSERT(pCharDef); + return pCharDef->GetDispID(); + } +} + +// Setting the visual "ID" for this. +bool CChar::SetDispID(CREID_TYPE id) +{ + ADDTOCALLSTACK("CChar::SetDispID"); + // Just change what this char looks like. + // do not change it's basic type. + + if (id == GetDispID()) + return true; + + if (CCharBase::IsValidDispID(id)) + { + m_dwDispIndex = id; + Update(); + } + else + { + const CCharBase* pCharDef = Char_GetDef(); + ASSERT(pCharDef); + + m_dwDispIndex = pCharDef->GetDispID(); + if (!CCharBase::IsValidDispID((CREID_TYPE)(m_dwDispIndex))) + { + g_Log.EventError("DispID of base Char (0% " PRIx32 ") not valid\n", m_dwDispIndex); + return false; + } + } + return true; } // Just set the base id and not the actual display id. @@ -2783,6 +2821,9 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo } } return true; + case CHC_DISPID: + sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, GetDispID())); + break; case CHC_DISPIDDEC: // for properties dialog. sVal.FormatVal( pCharDef->m_trackID ); return true; @@ -3633,6 +3674,8 @@ bool CChar::r_LoadVal( CScript & s ) case CHC_DISMOUNT: Horse_UnMount(); break; + case CHC_DISPID: + return SetDispID((CREID_TYPE)(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr()))); case CHC_EMOTEACT: { bool fSet = IsStatFlag(STATF_EMOTEACTION); @@ -3932,6 +3975,10 @@ void CChar::r_Write( CScript & s ) if (m_CanMask) s.WriteKeyVal("CANMASK", m_CanMask); + const CREID_TYPE iDispID = GetDispID(); + if (iDispID != GetID()) + s.WriteKeyStr("DISPID", g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, iDispID))); + const uint uiActUID = m_Act_UID.GetObjUID(); if ((uiActUID & UID_UNUSED) != UID_UNUSED) s.WriteKeyHex("ACT", uiActUID); diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index e585cf80e..b6901d1ee 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -154,6 +154,7 @@ class CChar : public CObjBase, public CContainer, public CTextConsole HUE_TYPE _wPrev_Hue; // Backup of skin color. in case of polymorph etc. HUE_TYPE _wBloodHue; // Replicating CharDef's BloodColor on the char, or overriding it. + CREID_TYPE m_dwDispIndex; //To change the DispID instance // Skills, Stats and health ushort m_Skill[SKILL_QTY]; // List of skills ( skill * 10 ) @@ -367,6 +368,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; CREID_TYPE GetID() const; virtual word GetBaseID() const override; CREID_TYPE GetDispID() const; + bool SetDispID(CREID_TYPE id); void SetID( CREID_TYPE id ); virtual lpctstr GetName() const override; diff --git a/src/tables/CChar_props.tbl b/src/tables/CChar_props.tbl index bacaae28e..2c51836d7 100644 --- a/src/tables/CChar_props.tbl +++ b/src/tables/CChar_props.tbl @@ -32,6 +32,7 @@ ADD(DAMADJUSTED, "DAMADJUSTED") ADD(DEX, "DEX") ADD(DIR, "DIR") ADD(DISMOUNT, "DISMOUNT") +ADD(DISPID, "DISPID") ADD(DISPIDDEC, "DISPIDDEC") ADD(EMOTEACT, "EMOTEACT") ADD(EMOTECOLOROVERRIDE, "EMOTECOLOROVERRIDE") From ea20f76c5427a653d2afee9a89240720cbde6d66 Mon Sep 17 00:00:00 2001 From: Jhobean <51728381+Jhobean@users.noreply.github.com> Date: Wed, 13 Dec 2023 01:00:51 -0500 Subject: [PATCH 09/90] Fix issue #1097 (CAN_O_NOSLEEP not work on server reboot) (#1198) --- src/game/CSector.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/game/CSector.cpp b/src/game/CSector.cpp index 866ed24e3..ff7c954e0 100644 --- a/src/game/CSector.cpp +++ b/src/game/CSector.cpp @@ -949,7 +949,8 @@ void CSector::MoveItemToSector( CItem * pItem ) { if (_CanSleep(true)) { - pItem->GoSleep(); + if (!pItem->CanTick()) + pItem->GoSleep(); } else { @@ -1011,7 +1012,8 @@ bool CSector::MoveCharToSector( CChar * pChar ) } else if (!pChar->IsSleeping()) // An NPC entered, but the sector is sleeping { - pChar->GoSleep(); // then make the NPC sleep too. + if (!pChar->CanTick()) + pChar->GoSleep(); // then make the NPC sleep too. } } else From a5d57147d968bd4912853ecdc76a8f2032774441 Mon Sep 17 00:00:00 2001 From: cbnolok Date: Wed, 13 Dec 2023 19:30:30 +0100 Subject: [PATCH 10/90] Fixed: Rare crash occurring when a NPC is selecting an attackable target, but there's only one target (not attackable) in sight. (#1193) --- Changelog.txt | 3 + src/game/CServerConfig.cpp | 2 +- src/game/CTeleport.cpp | 5 -- src/game/CTeleport.h | 2 +- src/game/chars/CChar.h | 4 +- src/game/chars/CCharFight.cpp | 5 +- src/game/chars/CCharNPCAct_Fight.cpp | 22 ++++++-- src/game/chars/CCharNPCStatus.cpp | 2 +- src/network/linuxev.cpp | 83 ++++++++++++++++++++++------ src/network/linuxev.h | 20 +++---- 10 files changed, 101 insertions(+), 47 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index c8a0c951a..4e85ee106 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3438,3 +3438,6 @@ Additionally, the problem of zig-zag issue following in the South direction has 09-12-2023, DavideRei - Added: DispID can now also be used on chars, to change their appearance. + +13-12-2023, Nolok +- Fixed: Rare crash occurring when a NPC is selecting an attackable target, but there's only one target (not attackable) in sight. diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 595adfb93..bb879b969 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -4441,7 +4441,7 @@ bool CServerConfig::LoadIni( bool fTest ) if( !fTest ) { g_Log.Event(LOGL_FATAL|LOGM_INIT|LOGF_CONSOLE_ONLY, SPHERE_FILE ".ini has not been found.\n"); - g_Log.Event(LOGL_FATAL|LOGM_INIT|LOGF_CONSOLE_ONLY, "Download a sample sphere.ini from https://github.com/Sphereserver/Source-experimental/tree/master/src\n"); + g_Log.Event(LOGL_FATAL|LOGM_INIT|LOGF_CONSOLE_ONLY, "Download a sample sphere.ini from https://github.com/Sphereserver/Source-X/tree/master/src\n"); } return false; } diff --git a/src/game/CTeleport.cpp b/src/game/CTeleport.cpp index 48a25aa99..1b07a7193 100644 --- a/src/game/CTeleport.cpp +++ b/src/game/CTeleport.cpp @@ -42,8 +42,3 @@ bool CTeleport::RealizeTeleport() else return false; } - -CTeleport::~CTeleport() noexcept -{ - fprintf(stderr, "deleted %s.\n", _ptDst.WriteUsed()); -} diff --git a/src/game/CTeleport.h b/src/game/CTeleport.h index 0c0476115..6a566304a 100644 --- a/src/game/CTeleport.h +++ b/src/game/CTeleport.h @@ -21,7 +21,7 @@ class CTeleport : public CPointSort // The static world teleporters. _fNpc = false; } explicit CTeleport(tchar* pszArgs); - ~CTeleport() noexcept; + ~CTeleport() noexcept = default; CTeleport(const CTeleport& copy) = delete; CTeleport& operator=(const CTeleport& other) = delete; diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index b6901d1ee..0b8fc7029 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -1044,7 +1044,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; SKILL_TYPE Fight_GetWeaponSkill() const; DAMAGE_TYPE Fight_GetWeaponDamType(const CItem* pWeapon = nullptr) const; int Fight_CalcDamage( const CItem * pWeapon, bool bNoRandom = false, bool bGetMax = true ) const; - bool Fight_IsAttackable(); + bool Fight_IsAttackableState(); // Attacker System enum ATTACKER_CLEAR_TYPE @@ -1243,7 +1243,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; bool NPC_LookAtItem( CItem * pItem, int iDist ); bool NPC_LookAround( bool fForceCheckItems = false ); int NPC_WalkToPoint(bool fRun = false); - CChar * NPC_FightFindBestTarget(); + CChar * NPC_FightFindBestTarget(const std::vector * pvExcludeList = nullptr); bool NPC_FightMagery(CChar * pChar); bool NPC_FightCast(CObjBase * &pChar ,CObjBase * pSrc, SPELL_TYPE &spell, int &skill, int iHealThreshold, bool bIgnoreAITargetChoice = false); bool NPC_FightArchery( CChar * pChar ); diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index cb1f61a52..2e3e967fa 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -1208,7 +1208,7 @@ int CChar::Fight_CalcDamage( const CItem * pWeapon, bool bNoRandom, bool bGetMax return( Calc_GetRandVal2(iDmgMin, iDmgMax) ); } -bool CChar::Fight_IsAttackable() +bool CChar::Fight_IsAttackableState() { ADDTOCALLSTACK("CChar::IsAttackable"); return !IsDisconnected() && !IsStatFlag(STATF_DEAD|STATF_STONE|STATF_INVISIBLE|STATF_INSUBSTANTIAL|STATF_HIDDEN|STATF_INVUL); @@ -1383,7 +1383,8 @@ void CChar::Fight_HitTry() // I can't hit this target, try switch to another one if (m_pNPC) { - if ( !Fight_Attack(NPC_FightFindBestTarget()) ) + std::vector vExcludeTargets { pCharTarg }; // Ignore the current target, i want other npcs + if (!Fight_Attack(NPC_FightFindBestTarget(&vExcludeTargets))) { Skill_Start(SKILL_NONE); m_Fight_Targ_UID.InitUID(); diff --git a/src/game/chars/CCharNPCAct_Fight.cpp b/src/game/chars/CCharNPCAct_Fight.cpp index ad6224335..2b7e3d589 100644 --- a/src/game/chars/CCharNPCAct_Fight.cpp +++ b/src/game/chars/CCharNPCAct_Fight.cpp @@ -54,7 +54,7 @@ bool CChar::NPC_FightArchery(CChar * pChar) return true; } -CChar * CChar::NPC_FightFindBestTarget() +CChar * CChar::NPC_FightFindBestTarget(const std::vector* pvExcludeList) { ADDTOCALLSTACK("CChar::NPC_FightFindBestTarget"); ASSERT(m_pNPC); @@ -74,17 +74,26 @@ CChar * CChar::NPC_FightFindBestTarget() for (size_t i = 0; i < m_lastAttackers.size(); ) { LastAttackers &refAttacker = m_lastAttackers[i]; - pChar = CUID(refAttacker.charUID).CharFind(); + pChar = CUID::CharFindFromUID(refAttacker.charUID); if (!pChar) { ++i; continue; } - if (!pChar->Fight_IsAttackable()) + if (!pChar->Fight_IsAttackableState()) { ++i; continue; } + if (pvExcludeList) + { + if (pvExcludeList->cend() != std::find(pvExcludeList->cbegin(), pvExcludeList->cend(), pChar)) + { + ++i; + continue; + } + } + if (refAttacker.ignore) { bool bIgnore = true; @@ -140,10 +149,13 @@ CChar * CChar::NPC_FightFindBestTarget() return pClosest ? pClosest : pChar; } - // New target not found, check if I can keep attacking my current target + // New target not found, return the current target, if any CChar *pTarget = m_Fight_Targ_UID.CharFind(); if (pTarget) - return pTarget; + { + if (!pvExcludeList || (pvExcludeList->cend() == std::find(pvExcludeList->cbegin(), pvExcludeList->cend(), pTarget))) + return pTarget; + } return nullptr; } diff --git a/src/game/chars/CCharNPCStatus.cpp b/src/game/chars/CCharNPCStatus.cpp index 7c8c07ecd..1c5a307af 100644 --- a/src/game/chars/CCharNPCStatus.cpp +++ b/src/game/chars/CCharNPCStatus.cpp @@ -849,7 +849,7 @@ int CChar::NPC_GetAttackContinueMotivation( CChar * pChar, int iMotivation ) con if ( !pChar ) return 0; - if ( !pChar->Fight_IsAttackable() ) + if ( !pChar->Fight_IsAttackableState() ) return -100; if ( m_pNPC->m_Brain == NPCBRAIN_GUARD ) return 100; diff --git a/src/network/linuxev.cpp b/src/network/linuxev.cpp index 518cab3df..943945587 100644 --- a/src/network/linuxev.cpp +++ b/src/network/linuxev.cpp @@ -26,18 +26,23 @@ } */ -// Call this function when the socket is readable again -> we are not sending data anymore -// The data is sent (if the checks are passing) at each tick on a CNetworkThread, which sets also isSendingAsync to true. If in that tick -// the CNetworkThread can't send the data (maybe because socketslave_cb wasn't called, so onAsyncSendComplete wasn't called), wait for the next tick. -static void socketslave_cb(struct ev_loop *loop, struct ev_io *w, int revents) +// Call this callback function when the socket is readable or writable again -> we are not sending data anymore +// The data is sent when there's some queued data to send. +static void socketslave_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) { - ev_io_stop(loop, w); - CNetState* state = reinterpret_cast( w->data ); + // libev could call this function aliasing ev_io as a ev_watcher. + // ev_watcher is a "parent" struct of ev_io, they share the first member variables. + // it's a evil trick, but does the job since C doesn't have struct inheritance + + ev_io_stop(loop, watcher); + CNetState* state = reinterpret_cast( watcher->data ); if ( !g_Serv.IsLoading() ) { if ( revents & EV_READ ) { + // This happens when the client socket is readable (i can try to retrieve data), this does NOT mean + // that i have data to read. It might also mean that i have done writing to the socket? // g_NetworkOut.onAsyncSendComplete(state); } else if ( revents & EV_WRITE ) @@ -48,19 +53,19 @@ static void socketslave_cb(struct ev_loop *loop, struct ev_io *w, int revents) } } - if ( state->isSendingAsync() ) + if (state->isSendingAsync()) { - ev_io_start(loop, w); + ev_io_start(loop, watcher); } } -LinuxEv::LinuxEv(void) : AbstractSphereThread("T_NetLoop", IThread::High) +LinuxEv::LinuxEv(void) : AbstractSphereThread("T_NetLoopOut", IThread::High) + //, m_watchMainsock{} { - m_eventLoop = ev_loop_new(EV_BACKEND_LIST); - ASSERT(m_eventLoop != nullptr); // libev probably couldn't find sys/poll.h, select.h and other includes (compiling on ubuntu with both x86_64 and i386 compilers? or more gcc versions?) - ev_set_io_collect_interval(m_eventLoop, 0.01); - - memset(&m_watchMainsock, 0, sizeof(ev_io)); + // Right now, we use libev to send asynchronously packets to clients. + m_eventLoop = ev_loop_new(ev_recommended_backends() | EVFLAG_NOENV); + ASSERT(m_eventLoop != nullptr); // if fails, libev config.h probably was not configured properly + ev_set_io_collect_interval(m_eventLoop, 5e-3); // interval: the second is the unit, use decimals for smaller intervals } LinuxEv::~LinuxEv(void) @@ -68,15 +73,52 @@ LinuxEv::~LinuxEv(void) ev_loop_destroy(m_eventLoop); } +void LinuxEv::printInitInfo() +{ + g_Log.Event(LOGM_CLIENTS_LOG, "Networking: Libev. Initialized with backend 0x%x.\n", ev_backend(m_eventLoop)); +} + void LinuxEv::onStart() { - // g_Log.Event(LOGM_CLIENTS_LOG, "Event start backend 0x%x\n", ev_backend(m_eventLoop)); AbstractSphereThread::onStart(); } - + +static void periodic_cb(struct ev_loop* /*loop*/, ev_periodic* /*w*/, int /*revents*/) noexcept +{ + ; +} + void LinuxEv::tick() { - ev_run(m_eventLoop, EVRUN_NOWAIT); + /* + A flags value of EVRUN_NOWAIT will look for new events, + will handle those events and any already outstanding ones, + but will not wait and block your process in case there are no events and will return after one iteration of the loop. + */ + //ev_run(m_eventLoop, EVRUN_NOWAIT); + + // Trying a different approach: enter the event loop, run again if exits. + // ev_run will keep handling events until either no event watchers are active anymore or "ev_break" was called + +#ifdef _DEBUG + g_Log.EventDebug("Networking: Libev. Starting event loop.\n"); +#endif + + // This periodic timer keeps awake the event loop. We could have used ev_ref but it had its problems... + // Don't ask me why (maybe i don't get how this actually should work, and this is only a workaround), + // but if we rely on ev_ref to increase the event loop reference counter to keep it alive without this periodic timer/callback, + // the loop will ignore the io_collect_interval. Moreover, it will make the polling backend in use (like most frequently epoll) wait the maximum + // time (MAX_BLOCKTIME in ev.c, circa 60 seconds) to collect incoming data, only then the callback will be called. So each batch of packets + // would be processed every 60 seconds... + struct ev_periodic periodic_check; + ev_periodic_init(&periodic_check, periodic_cb, 0, 5e-3, nullptr); + ev_periodic_start(m_eventLoop, &periodic_check); + + ev_run(m_eventLoop, 0); + +#ifdef _DEBUG + g_Log.EventDebug("Networking: Libev. Event loop STOPPED.\n"); +#endif } void LinuxEv::waitForClose() @@ -96,6 +138,13 @@ void LinuxEv::registerClient(CNetState * state, EventsID eventCheck) memset(state->iocb(), 0, sizeof(ev_io)); + // Right now we support only async writing to the socket. + // Pure async read would mean to call functions and access data typically managed by the main thread, + // but the core isn't designed for such usage, nor we have all the thread synchronization methods for every possible stuff we might need. + // A fair compromise TODO would be to async read incoming data, parse that in packets that will be stored in a buffer periodically accessed and processed + // by the main thread. + ASSERT(0 == (eventCheck & ~EV_WRITE)); + #ifdef _WIN32 int fd = EV_WIN32_HANDLE_TO_FD(state->m_socket.GetSocket()); ev_io_init(state->iocb(), socketslave_cb, fd, (int)eventCheck); diff --git a/src/network/linuxev.h b/src/network/linuxev.h index fcda6147d..728472893 100644 --- a/src/network/linuxev.h +++ b/src/network/linuxev.h @@ -11,12 +11,6 @@ #include "../../lib/libev/src/ev.h" #include "../common/sphere_library/smutex.h" #include "../sphere/threads.h" - - #ifdef _BSD - #define EV_BACKEND_LIST (EVBACKEND_SELECT | EVBACKEND_POLL | EVBACKEND_KQUEUE) - #else - #define EV_BACKEND_LIST (EVBACKEND_SELECT | EVBACKEND_POLL | EVBACKEND_EPOLL) - #endif class CClient; class CNetState; @@ -36,25 +30,25 @@ private: struct ev_loop * m_eventLoop; - struct ev_io m_watchMainsock; + // struct ev_io m_watchMainsock; // Watcher for Sphere's socket, to accept incoming connections (async read). public: LinuxEv(void); virtual ~LinuxEv(void); - private: - LinuxEv(const LinuxEv& copy); - LinuxEv& operator=(const LinuxEv& other); + LinuxEv(const LinuxEv& copy) = delete; + LinuxEv& operator=(const LinuxEv& other) = delete; public: - virtual void onStart(); - virtual void tick(); - virtual void waitForClose(); + virtual void onStart() override; + virtual void tick() override; + virtual void waitForClose() override; private: void forceClientevent(CNetState *, EventsID); public: + void printInitInfo(); void forceClientread(CNetState *); void forceClientwrite(CNetState *); // -------------------------------------- From 646b9d18f459dfc3ee150e4feaca2d24502a2010 Mon Sep 17 00:00:00 2001 From: DavideRei <118212274+DavideRei@users.noreply.github.com> Date: Wed, 31 Jan 2024 08:33:44 +0100 Subject: [PATCH 11/90] CSFile Windows creation file mode fix (#1205) --- src/common/sphere_library/CSFile.cpp | 10 +++++++--- src/game/chars/CChar.cpp | 6 ++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/common/sphere_library/CSFile.cpp b/src/common/sphere_library/CSFile.cpp index 9fc7df31d..a34572ccb 100644 --- a/src/common/sphere_library/CSFile.cpp +++ b/src/common/sphere_library/CSFile.cpp @@ -131,13 +131,17 @@ bool CSFile::_Open( lpctstr ptcFilename, uint uiModeFlags ) dwShareMode = 0; if ( uiModeFlags & OF_CREATE ) - dwCreationDisposition = (OPEN_ALWAYS|CREATE_NEW); + dwCreationDisposition = CREATE_ALWAYS; else dwCreationDisposition = OPEN_EXISTING; _fileDescriptor = CreateFile( ptcFilename, dwDesiredAccess, dwShareMode, nullptr, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr ); #else - _fileDescriptor = open( ptcFilename, uiModeFlags ); + uint uiFilePermissions = 0; + if (uiModeFlags & OF_CREATE) + uiFilePermissions = (S_IRWXU | S_IRWXG | S_IRWXO); //777 + + _fileDescriptor = open( ptcFilename, uiModeFlags, uiFilePermissions); #endif // _WIN32 return (_fileDescriptor != _kInvalidFD); @@ -492,4 +496,4 @@ bool CSFile::FileExists(lpctstr ptcFilePath) // static struct stat fileStat; return ( stat( ptcFilePath, &fileStat) != -1 ); #endif -} \ No newline at end of file +} diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 8fc303ca4..6953a2393 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -1558,7 +1558,6 @@ bool CChar::SetDispID(CREID_TYPE id) return true; } -// Just set the base id and not the actual display id. // NOTE: Never return nullptr void CChar::SetID( CREID_TYPE id ) { @@ -1576,7 +1575,10 @@ void CChar::SetID( CREID_TYPE id ) pCharDef = CCharBase::FindCharBase(id); } - + + //Update DispId + m_dwDispIndex = id; + ASSERT(pCharDef != nullptr); CCharBase* pCharOldDef = Char_GetDef(); From 4bd64cffc73ddd8982d56bf137407aab6a862e27 Mon Sep 17 00:00:00 2001 From: drk84 Date: Mon, 12 Feb 2024 11:11:28 +0100 Subject: [PATCH 12/90] Updated SphereCrypt.ini. (#1211) --- Changelog.txt | 3 +++ src/sphereCrypt.ini | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Changelog.txt b/Changelog.txt index 4e85ee106..7b6e1a228 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3441,3 +3441,6 @@ Additionally, the problem of zig-zag issue following in the South direction has 13-12-2023, Nolok - Fixed: Rare crash occurring when a NPC is selecting an attackable target, but there's only one target (not attackable) in sight. + +12-02-2024, Drk84 +- Updated SphereCrypt.ini. \ No newline at end of file diff --git a/src/sphereCrypt.ini b/src/sphereCrypt.ini index 4d214b1f1..b24ad8556 100644 --- a/src/sphereCrypt.ini +++ b/src/sphereCrypt.ini @@ -24,6 +24,8 @@ ENC_LOGIN 4 // Rotation cipher used for the Login Server crypt by every client, [SPHERECRYPT] //Classic Clients +70010100 039C411AD 0A803DE7F ENC_TFISH //7.0.101 +70010000 03A3D83BD 0A9F5127F ENC_TFISH //7.0.100 7009900 03A7731CD 0A9CE5E7F ENC_TFISH // 7.0.99 7009800 03AA8ABDD 0A9AB227F ENC_TFISH // 7.0.98 7009700 03AE221ED 0A9F47E7F ENC_TFISH // 7.0.97 From 49341257dab80698e8d41a914bacf4f603b8a981 Mon Sep 17 00:00:00 2001 From: Jhobean <51728381+Jhobean@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:13:35 -0400 Subject: [PATCH 13/90] Add some item props functionnality (#1131) --- Changelog.txt | 12 ++- src/game/chars/CChar.h | 1 + src/game/chars/CCharAct.cpp | 1 + src/game/chars/CCharFight.cpp | 99 ++++++++++++++++++- src/game/components/CCPropsItemEquippable.cpp | 24 ++--- 5 files changed, 121 insertions(+), 16 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 7b6e1a228..13bf32317 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3429,7 +3429,7 @@ Additionally, the problem of zig-zag issue following in the South direction has 02-11-2023, Jhobean - Modified: @Mount added argument ARGN1 - ARGN1 (rw) = The itemID of the item containing the animation use when moounting. (Anim # is in tiledata of this item) + ARGN1 (rw) = The itemID of the item containing the animation use when moounting. (Anim # is in tiledata of this item) NOTE: When mounting a pet you'll read a non sense random value but you can replace it by an ITEMID to force anim Example: 03ea6 for Llama anim or 03e9f for gray horse anim. Yes 03ea6 is a ship part but in tiledata it link to anim 828 @@ -3442,5 +3442,13 @@ Additionally, the problem of zig-zag issue following in the South direction has 13-12-2023, Nolok - Fixed: Rare crash occurring when a NPC is selecting an attackable target, but there's only one target (not attackable) in sight. + + + + 12-02-2024, Drk84 -- Updated SphereCrypt.ini. \ No newline at end of file +- Updated SphereCrypt.ini. + +13-03-2024, Jhobean +- Added: Item properties functionnality:HITAREAPHYSICAL,HITAREAFIRE,HITAREACOLD,HITAREAPOISON,HITAREAENERGY,HITFIREBALL,HITHARM,HITLIGHTNING,HITMAGICARROW,REFLECTPHYSICALDAM + diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 0b8fc7029..b1f125c7b 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -1300,6 +1300,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; // Outside events that occur to us. int OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhysical = 0, int iDmgFire = 0, int iDmgCold = 0, int iDmgPoison = 0, int iDmgEnergy = 0, SPELL_TYPE spell = SPELL_NONE ); + void OnTakeDamageInflictArea(int iDmg, CChar* pSrc, DAMAGE_TYPE uType, int iDmgPhysical = 0, int iDmgFire = 0, int iDmgCold = 0, int iDmgPoison = 0, int iDmgEnergy = 0, HUE_TYPE effectHue = HUE_DEFAULT, SOUND_TYPE effectSound = SOUND_NONE); void OnHarmedBy( CChar * pCharSrc ); bool OnAttackedBy( CChar * pCharSrc, bool fPetsCommand = false, bool fShouldReveal = true ); diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index bb9d6e6f1..4a90c9469 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -2214,6 +2214,7 @@ bool CChar::ItemEquip( CItem * pItem, CChar * pCharMsg, bool fFromDClick ) if (pItem->IsTypeWeapon()) { + //Necromancy Curse weapon CItem * pCursedMemory = LayerFind(LAYER_SPELL_Curse_Weapon); // Remove the cursed state from SPELL_Curse_Weapon. if (pCursedMemory) pItem->ModPropNum(pItemCCPItemEquippable, PROPIEQUIP_HITLEECHLIFE, + pCursedMemory->m_itSpell.m_spelllevel, pItemBaseCCPItemEquippable); diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 2e3e967fa..90fd013d4 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -939,8 +939,21 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys pSrc->Sound(0x1F1); pSrc->Effect(EFFECT_OBJ, ITEMID_FX_CURSE_EFFECT, this, 10, 16); } - } - } + } + } + // Check if REFLECTPHYSICALDAM will reflect some damage back. + // Preventing recurrent reflection with DAMAGE_REACTIVE. + if (!(uType & DAMAGE_REACTIVE)) + { + int iReflectPhysical = (ushort)std::min(GetPropNum(pCCPChar, PROPCH_REFLECTPHYSICALDAM, pBaseCCPChar),250); //Capped to 250 + + if (iReflectPhysical) + { + int iReflectPhysicalDam = (iDmg * iReflectPhysical) / 100; + pSrc->OnTakeDamage(iReflectPhysicalDam, this, (DAMAGE_TYPE)(DAMAGE_FIXED | DAMAGE_REACTIVE), iDmgPhysical, iDmgFire, iDmgCold, iDmgPoison, iDmgEnergy); + } + } + } } @@ -983,6 +996,48 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys return iDmg; } +void CChar::OnTakeDamageInflictArea(int iDmg, CChar* pSrc, DAMAGE_TYPE uType, int iDmgPhysical, int iDmgFire, int iDmgCold, int iDmgPoison, int iDmgEnergy, HUE_TYPE effectHue, SOUND_TYPE effectSound) +{ + ADDTOCALLSTACK("CChar::OnTakeDamageInflictArea"); + + bool fMakeSound = false; + + int iDistance = 5; + if (IsAosFlagEnabled(FEATURE_AOS_DAMAGE)) + iDistance=10; // 5 for ML and 10 for aos + + CWorldSearch AreaChars(GetTopPoint(), iDistance); + for (;;) + //pSrc = Char make the attack + //pChar = Char scanned on the loop iteration + //this = Char get the initial hit + { + CChar* pChar = AreaChars.GetChar(); + if (!pChar) + break; + if ((pChar == this) || (pChar == pSrc)) //This char already receive the base hit. Damage already done + continue; + if (pChar->Fight_CanHit(pSrc,true) == WAR_SWING_INVALID) //Check if target can be hit (I am invul, stone etc. Target is Disconnected,safe zone etc) + continue; + if (!pChar->m_pClient && pChar->NPC_IsOwnedBy(pSrc,false)) // it's my pet? + continue; + if (pChar->Noto_CalcFlag(pSrc) == NOTO_GOOD) //Avoid to hit someone we can't legally attack (same guild, same party, Vendor etc) + continue; + if (!pChar->CanSeeLOS(pSrc)) //Avoid hit someone in nearby house + continue; + + /* On servUo they modify the damage depending of the distance with this formula + There no info about this on UO Wiki + damage *= ( 11 - from.GetDistanceToSqrt( m ) ) / 10; */ + + pChar->OnTakeDamage(iDmg, pSrc, uType, iDmgPhysical, iDmgFire, iDmgCold, iDmgPoison, iDmgEnergy); + pChar->Effect(EFFECT_OBJ, ITEMID_FX_SPARKLE_2, this, 1, 15, false, effectHue); + fMakeSound = true; + } + if (fMakeSound && (effectSound != SOUND_NONE)) + Sound(effectSound); +} + //******************************************************************************* // Fight specific memories. @@ -2167,6 +2222,46 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) if ( fMakeLeechSound ) Sound(0x44d); + if (pWeapon) + { + + if (GetPropNum(pCCPChar, PROPCH_HITAREAPHYSICAL, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnTakeDamageInflictArea(iDmg / 2, this, DAMAGE_HIT_BLUNT, 100, 0, 0, 0, 0, static_cast(0x32), static_cast(0x10E)); + + bool fElemental = IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE); + if (fElemental) + { + + if (GetPropNum(pCCPChar, PROPCH_HITAREAFIRE, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnTakeDamageInflictArea(iDmg / 2, this, DAMAGE_FIRE, 0, 100, 0, 0, 0, static_cast(0x488), static_cast(0x11D)); + + if (GetPropNum(pCCPChar, PROPCH_HITAREACOLD, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnTakeDamageInflictArea(iDmg / 2, this, DAMAGE_COLD, 0, 0, 100, 0, 0, static_cast(0x834), static_cast(0xFC)); + + if (GetPropNum(pCCPChar, PROPCH_HITAREAPOISON, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnTakeDamageInflictArea(iDmg / 2, this, DAMAGE_POISON, 0, 0, 0, 100, 0, static_cast(0x48E), static_cast(0x205)); + + if (GetPropNum(pCCPChar, PROPCH_HITAREAENERGY, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnTakeDamageInflictArea(iDmg / 2, this, DAMAGE_ENERGY, 0, 0, 0, 0, 100, static_cast(0x78), static_cast(0x1F1)); + + } + + if (GetPropNum(pCCPChar, PROPCH_HITDISPEL, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnSpellEffect(SPELL_Dispel, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); + + if (GetPropNum(pCCPChar, PROPCH_HITFIREBALL, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnSpellEffect(SPELL_Fireball, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); + + if (GetPropNum(pCCPChar, PROPCH_HITHARM, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnSpellEffect(SPELL_Harm, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); + + if (GetPropNum(pCCPChar, PROPCH_HITLIGHTNING, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnSpellEffect(SPELL_Lightning, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); + + if (GetPropNum(pCCPChar, PROPCH_HITMAGICARROW, pBaseCCPChar) > Calc_GetRandLLVal(100)) + pCharTarg->OnSpellEffect(SPELL_Magic_Arrow, this, Skill_GetAdjusted(SKILL_MAGERY), pWeapon); + } + // Make blood effects if ( pCharTarg->_wBloodHue != (HUE_TYPE)(-1) ) { diff --git a/src/game/components/CCPropsItemEquippable.cpp b/src/game/components/CCPropsItemEquippable.cpp index fa3f597e8..37dba2b27 100644 --- a/src/game/components/CCPropsItemEquippable.cpp +++ b/src/game/components/CCPropsItemEquippable.cpp @@ -331,39 +331,39 @@ void CCPropsItemEquippable::AddPropsTooltipData(CObjBase* pLinkedObj) case PROPIEQUIP_FASTERCASTRECOVERY: // unimplemented ADDTNUM(1060412); // faster cast recovery ~1_val~ break; - case PROPIEQUIP_HITAREACOLD: // unimplemented + case PROPIEQUIP_HITAREACOLD: if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) ADDTNUM(1060416); // hit cold area ~1_val~% break; - case PROPIEQUIP_HITAREAENERGY: // unimplemented + case PROPIEQUIP_HITAREAENERGY: if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) ADDTNUM(1060418); // hit energy area ~1_val~% break; - case PROPIEQUIP_HITAREAFIRE: // unimplemented + case PROPIEQUIP_HITAREAFIRE: if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) ADDTNUM(1060419); // hit fire area ~1_val~% break; - case PROPIEQUIP_HITAREAPHYSICAL: // unimplemented + case PROPIEQUIP_HITAREAPHYSICAL: if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) ADDTNUM(1060428); // hit physical area ~1_val~% break; - case PROPIEQUIP_HITAREAPOISON: // unimplemented + case PROPIEQUIP_HITAREAPOISON: if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) ADDTNUM(1060429); // hit poison area ~1_val~% break; case PROPIEQUIP_HITCURSE: // unimplemented ADDTNUM(1113712); // Hit Curse ~1_val~% break; - case PROPIEQUIP_HITDISPEL: // unimplemented + case PROPIEQUIP_HITDISPEL: ADDTNUM(1060417); // hit dispel ~1_val~% break; case PROPIEQUIP_HITFATIGUE: // unimplemented ADDTNUM(1113700); // // Hit Fatigue ~1_val~% break; - case PROPIEQUIP_HITFIREBALL: // unimplemented + case PROPIEQUIP_HITFIREBALL: ADDTNUM(1060420); // hit fireball ~1_val~% break; - case PROPIEQUIP_HITHARM: // unimplemented + case PROPIEQUIP_HITHARM: ADDTNUM(1060421); // hit harm ~1_val~% break; case PROPIEQUIP_HITLEECHLIFE: @@ -375,7 +375,7 @@ void CCPropsItemEquippable::AddPropsTooltipData(CObjBase* pLinkedObj) case PROPIEQUIP_HITLEECHSTAM: ADDTNUM(1060430); // hit stamina leech ~1_val~% break; - case PROPIEQUIP_HITLIGHTNING: // unimplemented + case PROPIEQUIP_HITLIGHTNING: ADDTNUM(1060422); // hit lightning ~1_val~% break; case PROPIEQUIP_HITLOWERATK: // unimplemented @@ -384,10 +384,10 @@ void CCPropsItemEquippable::AddPropsTooltipData(CObjBase* pLinkedObj) case PROPIEQUIP_HITLOWERDEF: // unimplemented ADDTNUM(1060425); // hit lower defense ~1_val~% break; - case PROPIEQUIP_HITMAGICARROW: // unimplemented + case PROPIEQUIP_HITMAGICARROW: ADDTNUM(1060426); // hit magic arrow ~1_val~% break; - case PROPIEQUIP_HITMANADRAIN: // unimplemented + case PROPIEQUIP_HITMANADRAIN: ADDTNUM(1113699); // Hit Mana Drain ~1_val~% break; case PROPIEQUIP_HITSPARKS: // unimplemented @@ -459,7 +459,7 @@ void CCPropsItemEquippable::AddPropsTooltipData(CObjBase* pLinkedObj) case PROPIEQUIP_REACTIVEPARALYZE: // Unimplemented ADDT(1112364); // reactive paralyze break; - case PROPIEQUIP_REFLECTPHYSICALDAM: // Unimplemented + case PROPIEQUIP_REFLECTPHYSICALDAM: ADDTNUM(1060442); // reflect physical damage ~1_val~% break; case PROPIEQUIP_REGENFOOD: // unimplemented From 3be9ce6c56b5b1bcdeef13fc41c27cce4c8c1500 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sat, 23 Mar 2024 19:21:48 +0000 Subject: [PATCH 14/90] Couple of Fixes Fixed: The issue that causes more1/2 not saved correctly for spellbook. (Issue: #1221) Fixed: Players automatically become criminal to everyone when attack someone. (Issue: #1213) Fixed: CallGuard not working correctly on the players that only criminal for target. (Issue: #1213) --- src/game/chars/CCharFight.cpp | 37 ++++++++++++++++++----------------- src/game/items/CItem.cpp | 14 ++++++++++--- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 90fd013d4..021ae1280 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -37,7 +37,7 @@ void CChar::OnNoticeCrime( CChar * pCriminal, CChar * pCharMark ) if ( m_pPlayer ) { // I have the option of attacking the criminal. or calling the guards. - bool fMakeCriminal = true; + bool fMakeCriminal = false; //We don't need to call guards automatically in default. if (IsTrigUsed(TRIGGER_SEECRIME)) { CScriptTriggerArgs Args; @@ -46,9 +46,9 @@ void CChar::OnNoticeCrime( CChar * pCriminal, CChar * pCharMark ) OnTrigger(CTRIG_SeeCrime, pCriminal, &Args); fMakeCriminal = Args.m_iN1 ? true : false; } - if (fMakeCriminal) + Memory_AddObjTypes(pCriminal, MEMORY_SAWCRIME); //Memory should always be added to the player. + if (fMakeCriminal) //We call guards automatically if ARGN1 set to 1 (true) in trigger. { - Memory_AddObjTypes( pCriminal, MEMORY_SAWCRIME ); pCriminal->Noto_Criminal(pCharMark, true); } return; @@ -107,11 +107,13 @@ bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObj CChar * pChar = AreaChars.GetChar(); if ( pChar == nullptr ) break; - if ( this == pChar ) - continue; // I saw myself before. - if (pChar->GetPrivLevel() > GetPrivLevel()) // If a GM sees you it it not a crime. + if (this == pChar) // Ignore the player himself. + continue; + if (pChar == pCharMark) // Attacked player should be ignored. + continue; + if (pChar->IsPriv(PRIV_GM)) // GMs also should be ignored. continue; - if ( ! pChar->CanSeeLOS( this, LOS_NB_WINDOWS )) //what if I was standing behind a window when I saw a crime? :) + if ( ! pChar->CanSeeLOS( this, LOS_NB_WINDOWS )) // What if I was standing behind a window when I saw a crime? :) continue; const bool fYour = (pCharMark && ( pCharMark == pChar )); @@ -170,7 +172,9 @@ bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObj void CChar::CallGuards() { ADDTOCALLSTACK("CChar::CallGuards"); - if (!m_pArea || !m_pArea->IsGuarded() || IsStatFlag(STATF_DEAD|STATF_STONE)) + if (!m_pPlayer && (!m_pArea || !m_pArea->IsGuarded())) + return; + if (IsStatFlag(STATF_DEAD|STATF_STONE)) return; // Spam check, not calling this more than once per second, which will cause an excess of calls and checks on crowded areas because of the 2 CWorldSearch. @@ -184,15 +188,15 @@ void CChar::CallGuards() { if (pCriminal == this) continue; - if (!pCriminal->m_pArea->IsGuarded()) - continue; if (!CanDisturb(pCriminal)) // don't allow guards to be called on someone we can't disturb continue; // Mark person as criminal if I saw him criming // Only players call guards this way. NPC's flag criminal instantly - if (m_pPlayer && Memory_FindObjTypes(pCriminal, MEMORY_SAWCRIME)) + if (m_pPlayer && Memory_FindObjTypes(pCriminal, MEMORY_SAWCRIME)) + { pCriminal->Noto_Criminal(this, true); + } if (!pCriminal->IsStatFlag(STATF_CRIMINAL) && !(pCriminal->Noto_IsEvil() && g_Cfg.m_fGuardsOnMurderers)) continue; @@ -349,13 +353,10 @@ bool CChar::OnAttackedBy(CChar * pCharSrc, bool fCommandPet, bool fShouldReveal) { if (IsClientActive()) // I decide if this is a crime. { - if (!fCommandPet || g_Cfg.m_fAttackingIsACrime) - { - OnNoticeCrime(pCharSrc, this); - CChar* pCharMark = pCharSrc->IsStatFlag(STATF_PET) ? pCharSrc->NPC_PetGetOwner() : pCharSrc; - if (pCharMark != pCharSrc) - OnNoticeCrime(pCharMark, this); - } + OnNoticeCrime(pCharSrc, this); + CChar* pCharMark = pCharSrc->IsStatFlag(STATF_PET) ? pCharSrc->NPC_PetGetOwner() : nullptr; + if (pCharMark != nullptr) + OnNoticeCrime(pCharMark, this); } else { diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 13d04cf0c..cc4c97c8e 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2249,6 +2249,10 @@ void CItem::r_WriteMore1(CSString & sVal) switch (GetType()) { + case IT_SPELLBOOK: + sVal.FormatHex(m_itSpellbook.m_spells1); + return; + case IT_TREE: case IT_GRASS: case IT_ROCK: @@ -2300,6 +2304,10 @@ void CItem::r_WriteMore2( CSString & sVal ) switch ( GetType()) { + case IT_SPELLBOOK: + sVal.FormatHex(m_itSpellbook.m_spells1); + return; + case IT_FRUIT: case IT_FOOD: case IT_FOOD_RAW: @@ -4337,11 +4345,11 @@ uint CItem::AddSpellbookSpell( SPELL_TYPE spell, bool fUpdate ) return 1; // Add spell to spellbook bitmask: - const uint i = spell - (pBookDef->m_ttSpellbook.m_iOffset + 1); + const uint i = (uint)spell - (pBookDef->m_ttSpellbook.m_iOffset + 1u); if ( i < 32u ) // Replaced the <= with < because of the formula above, the first 32 spells have an i value from 0 to 31 and are stored in more1. - m_itSpellbook.m_spells1 |= (1 << i); + m_itSpellbook.m_spells1 |= (1u << i); else if ( i < 64u ) // Replaced the <= with < because of the formula above, the remaining 32 spells have an i value from 32 to 63 and are stored in more2. - m_itSpellbook.m_spells2 |= (1 << (i-32u)); + m_itSpellbook.m_spells2 |= (1u << (i-32u)); //else if ( i <= 96 ) // m_itSpellbook.m_spells3 |= (1 << (i-64)); //not used anymore? else From c4ba839b9e290722fa034cdce228caee29960dd0 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sat, 23 Mar 2024 21:36:54 +0000 Subject: [PATCH 15/90] Update CItem.cpp --- src/game/items/CItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index cc4c97c8e..3e6137bce 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2305,7 +2305,7 @@ void CItem::r_WriteMore2( CSString & sVal ) switch ( GetType()) { case IT_SPELLBOOK: - sVal.FormatHex(m_itSpellbook.m_spells1); + sVal.FormatHex(m_itSpellbook.m_spells2); return; case IT_FRUIT: From 980eb5b9314e4a1fbde83b8b16f3d3bcb4aef463 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 24 Mar 2024 13:10:40 +0000 Subject: [PATCH 16/90] Couple of Fixes Fixed: The wrong input of Kill trigger, to make it compatible with older sphere versions. (Issue: #1210) Added: New Layer LAYER_STORAGE (80) to let scripters create their own storage system. (Issue: #1209) - Only t_container and t_container_locked can be equipped to this layer. --- src/game/CWorld.cpp | 4 ++++ src/game/chars/CCharAct.cpp | 3 ++- src/game/chars/CCharStatus.cpp | 10 ++++++++++ src/game/items/CItem.cpp | 12 ++++++++++++ src/game/uo_files/uofiles_enums.h | 2 ++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/game/CWorld.cpp b/src/game/CWorld.cpp index 7334772eb..87f67ea88 100644 --- a/src/game/CWorld.cpp +++ b/src/game/CWorld.cpp @@ -129,6 +129,10 @@ lpctstr GetReasonForGarbageCode(int iCode = -1) pStr = "Item equipped in the memory layer but it isn't a memory"; break; + case 0x2232: + pStr = "Item equipped in the storage layer but it isn't a container"; + break; + case 0x2233: pStr = "Item equipped in the mount memory layer but it isn't a mount memory"; break; diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index 4a90c9469..9b93b165b 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -3145,7 +3145,8 @@ bool CChar::Death() { CScriptTriggerArgs args(this); args.m_iN1 = GetAttackersCount(); - if ( pKiller->OnTrigger(CTRIG_Kill, this, &args) == TRIGRET_RET_TRUE ) + args.m_pO1 = this; + if ( pKiller->OnTrigger(CTRIG_Kill, pKiller, &args) == TRIGRET_RET_TRUE ) continue; } diff --git a/src/game/chars/CCharStatus.cpp b/src/game/chars/CCharStatus.cpp index 09ab990bc..21ac547ce 100644 --- a/src/game/chars/CCharStatus.cpp +++ b/src/game/chars/CCharStatus.cpp @@ -358,6 +358,16 @@ LAYER_TYPE CChar::CanEquipLayer( CItem *pItem, LAYER_TYPE layer, CChar *pCharMsg default: return LAYER_NONE; // not legal! } + case LAYER_STORAGE: + fCantEquip = true; + switch (pItem->GetType()) + { + case IT_CONTAINER: + case IT_CONTAINER_LOCKED: + fCantEquip = false; + break; + } + break; case LAYER_HAIR: if ( !pItem->IsType(IT_HAIR) ) fCantEquip = true; diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 3e6137bce..a66fd91b2 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -1141,6 +1141,18 @@ int CItem::FixWeirdness() return iResultCode; // get rid of it. } break; + case LAYER_STORAGE: + switch (GetType()) + { + case IT_CONTAINER: + case IT_CONTAINER_LOCKED: + SetAttr(ATTR_MOVE_NEVER); + break; + default: + iResultCode = 0x2232; + return iResultCode; + } + break; case LAYER_VENDOR_STOCK: case LAYER_VENDOR_EXTRA: case LAYER_VENDOR_BUYS: diff --git a/src/game/uo_files/uofiles_enums.h b/src/game/uo_files/uofiles_enums.h index c2cded6ab..39e56c30f 100644 --- a/src/game/uo_files/uofiles_enums.h +++ b/src/game/uo_files/uofiles_enums.h @@ -554,6 +554,8 @@ enum LAYER_TYPE // defined by UO. Only one item can be in a slot. //Individual Spell Layers LAYER_SPELL_Mana_Drain, + + LAYER_STORAGE, //80 New Storage layer, can equip t_container and t_container_locked. LAYER_QTY }; From 1037519e6adb3dcc4f94d56aaec2fb23c812ae49 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 24 Mar 2024 14:08:28 +0000 Subject: [PATCH 17/90] Couple of Fixes Changed: Decay time removed from spawned item, as Sphere gives tons of invalid link errors when items decayed. (Issue: #1218) --- src/game/components/CCSpawn.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/components/CCSpawn.cpp b/src/game/components/CCSpawn.cpp index 65a316aac..52a8ad6a7 100644 --- a/src/game/components/CCSpawn.cpp +++ b/src/game/components/CCSpawn.cpp @@ -328,7 +328,8 @@ void CCSpawn::GenerateItem() } pItem->ClrAttr(pItem->m_Attr & (ATTR_OWNED | ATTR_MOVE_ALWAYS)); - pItem->SetDecayTime(g_Cfg.m_iDecay_Item); // it will decay eventually to be replaced later + //Spawned item shouldn't have decay time, as sphere gives tons of invalid link error when items removed. + //pItem->SetDecayTime(g_Cfg.m_iDecay_Item); // it will decay eventually to be replaced later if (IsTrigUsed(TRIGGER_SPAWN)) { CScriptTriggerArgs args; From 229f4fa86297761b01b7d9f49c789f182d43564e Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 24 Mar 2024 15:27:00 +0000 Subject: [PATCH 18/90] Couple of Fixes Added: New spellflag SPELLFLAG_ASNYC to randomize field timers like old sphere versions. (Issue: #1169) Added: New spellflag SPELLFLAG_TARG_ONLYSELF to make spell only be used on character himself. (Issue: #1171) --- Changelog.txt | 17 +++++++++---- src/common/resource/sections/CSpellDef.cpp | 8 +++---- src/common/resource/sections/CSpellDef.h | 8 +++---- src/game/chars/CCharNPCAct_Magic.cpp | 28 ++++++++++++---------- src/game/chars/CCharSpell.cpp | 4 ++++ src/game/clients/CClientTarg.cpp | 6 +++++ src/game/game_macros.h | 3 ++- src/tables/defmessages.tbl | 3 ++- 8 files changed, 50 insertions(+), 27 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 13bf32317..3fc9625bb 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3442,13 +3442,22 @@ Additionally, the problem of zig-zag issue following in the South direction has 13-12-2023, Nolok - Fixed: Rare crash occurring when a NPC is selecting an attackable target, but there's only one target (not attackable) in sight. - - - - 12-02-2024, Drk84 - Updated SphereCrypt.ini. 13-03-2024, Jhobean - Added: Item properties functionnality:HITAREAPHYSICAL,HITAREAFIRE,HITAREACOLD,HITAREAPOISON,HITAREAENERGY,HITFIREBALL,HITHARM,HITLIGHTNING,HITMAGICARROW,REFLECTPHYSICALDAM +24-03-2024, xwerswoodx +Fixed: The issue that causes more1/2 not saved correctly for spellbook. (Issue: #1221) +Fixed: Players automatically become criminal to everyone when attack someone. (Issue: #1213) +Fixed: CallGuard not working correctly on the players that only criminal for target. (Issue: #1213, #1040) +Fixed: The wrong input of Kill trigger, to make it compatible with older sphere versions. (Issue: #1210) +Added: New Layer LAYER_STORAGE (80) to let scripters create their own storage system. (Issue: #1209) + Only t_container and t_container_locked can be equipped to this layer. +Changed: Decay time removed from spawned items, as Sphere gives tons of invalid link errors when items decayed. (Issue: #1218) +Added: New spellflag SPELLFLAG_ASNYC (0100000000) to randomize field timers like old sphere versions. (Issue: #1169) + SPELLFLAG_ASYNC should be added to defs. +Added: New spellflag SPELLFLAG_TARG_ONLYSELF (0200000000) to make spell only be used on character himself. (Issue: #1171) + SPELLFLAG_TARG_ONLYSELF should be added to defs. + //magery_9 "You can only use this spell on yourself." could be added to defmessages. diff --git a/src/common/resource/sections/CSpellDef.cpp b/src/common/resource/sections/CSpellDef.cpp index 11ef9e2ef..9087fc192 100644 --- a/src/common/resource/sections/CSpellDef.cpp +++ b/src/common/resource/sections/CSpellDef.cpp @@ -116,10 +116,10 @@ bool CSpellDef::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc sVal.FormatVal( m_idEffect ); break; case SPC_FLAGS: - sVal.FormatVal( m_dwFlags ); + sVal.FormatULLVal( m_dwFlags ); break; case SPC_GROUP: - sVal.FormatVal( m_dwGroup ); + sVal.FormatULLVal( m_dwGroup ); break; case SPC_INTERRUPT: sVal = m_Interrupt.Write(); @@ -228,10 +228,10 @@ bool CSpellDef::r_LoadVal( CScript &s ) m_idEffect = (ITEMID_TYPE)(g_Cfg.ResourceGetIndexType( RES_ITEMDEF, s.GetArgStr())); break; case SPC_FLAGS: - m_dwFlags = s.GetArgVal(); + m_dwFlags = s.GetArgULLVal(); break; case SPC_GROUP: - m_dwGroup = s.GetArgVal(); + m_dwGroup = s.GetArgULLVal(); break; case SPC_INTERRUPT: m_Interrupt.Load( s.GetArgRaw()); diff --git a/src/common/resource/sections/CSpellDef.h b/src/common/resource/sections/CSpellDef.h index c81d5dc16..e47c2e52a 100644 --- a/src/common/resource/sections/CSpellDef.h +++ b/src/common/resource/sections/CSpellDef.h @@ -42,8 +42,8 @@ enum SPTRIG_TYPE class CSpellDef : public CResourceLink { private: - dword m_dwFlags; // Spell Flags. - dword m_dwGroup; // Spell group. + uint64 m_dwFlags; // Spell Flags. + uint64 m_dwGroup; // Spell group. CSString m_sName; // Spell name @@ -71,7 +71,7 @@ class CSpellDef : public CResourceLink public: /** - * @fn bool CSpellDef::IsSpellType( dword wFlags ) const + * @fn bool CSpellDef::IsSpellType( uint64 wFlags ) const * * @brief Check if this Spell has the given flags. * @@ -79,7 +79,7 @@ class CSpellDef : public CResourceLink * * @return true if match, false if not. */ - bool IsSpellType( dword wFlags ) const + bool IsSpellType( uint64 wFlags ) const { return (( m_dwFlags & wFlags ) ? true : false ); } diff --git a/src/game/chars/CCharNPCAct_Magic.cpp b/src/game/chars/CCharNPCAct_Magic.cpp index 8eccd2659..7a45bd1cb 100644 --- a/src/game/chars/CCharNPCAct_Magic.cpp +++ b/src/game/chars/CCharNPCAct_Magic.cpp @@ -316,26 +316,28 @@ bool CChar::NPC_FightCast(CObjBase * &pTarg, CObjBase * pSrc, SPELL_TYPE &spell, if (NPC_GetAiFlags()&NPC_AI_COMBAT && !bIgnoreAITargetChoice) { - // search for the neariest friend in combat - CWorldSearch AreaChars(GetTopPoint(), UO_MAP_VIEW_SIGHT); - for (;;) - { - pTarget = AreaChars.GetChar(); - if (!pTarget) - break; - - CItemMemory *pMemory = pTarget->Memory_FindObj(pTarg); - if (pMemory && pMemory->IsMemoryTypes(MEMORY_FIGHT | MEMORY_HARMEDBY | MEMORY_IRRITATEDBY)) + if (!pSpellDef->IsSpellType(SPELLFLAG_TARG_ONLYSELF)) { + // search for the neariest friend in combat if the spell has no SPELLFLAG_TARG_ONLYSELF flag. + CWorldSearch AreaChars(GetTopPoint(), UO_MAP_VIEW_SIGHT); + for (;;) { - pFriend[iFriendIndex++] = pTarget; - if (iFriendIndex >= 4) + pTarget = AreaChars.GetChar(); + if (!pTarget) break; + + CItemMemory* pMemory = pTarget->Memory_FindObj(pTarg); + if (pMemory && pMemory->IsMemoryTypes(MEMORY_FIGHT | MEMORY_HARMEDBY | MEMORY_IRRITATEDBY)) + { + pFriend[iFriendIndex++] = pTarget; + if (iFriendIndex >= 4) + break; + } } } } // i cannot cast this on self. ok, then friends only - if (pSpellDef->IsSpellType(SPELLFLAG_TARG_NOSELF)) + if (pSpellDef->IsSpellType(SPELLFLAG_TARG_NOSELF) && !pSpellDef->IsSpellType(SPELLFLAG_TARG_ONLYSELF)) //Make sure the spell has no ONLYSELF flag to avoid issues. { pFriend[0] = pFriend[1]; pFriend[1] = pFriend[2]; diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 239fd4481..9ad6e694c 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -2262,6 +2262,10 @@ void CChar::Spell_Field(CPointMap pntTarg, ITEMID_TYPE idEW, ITEMID_TYPE idNS, u pSpell->SetAttr(ATTR_MAGIC); pSpell->SetHue(iColor); pSpell->GenerateScript(this); + + if (pSpellDef->IsSpellType(SPELLFLAG_ASYNC)) // If the spell has ASYNC flag, the timers should be randomized. + iDuration += (int64)Calc_GetRandLLVal(iDuration / 2); + pSpell->MoveToDecay( ptg, iDuration * MSECS_PER_TENTH, true); } } diff --git a/src/game/clients/CClientTarg.cpp b/src/game/clients/CClientTarg.cpp index 333d651f5..6136896a7 100644 --- a/src/game/clients/CClientTarg.cpp +++ b/src/game/clients/CClientTarg.cpp @@ -1475,6 +1475,12 @@ bool CClient::OnTarg_Skill_Magery( CObjBase * pObj, const CPointMap & pt ) } } + if (pObj != m_pChar && pSpell->IsSpellType(SPELLFLAG_TARG_ONLYSELF) && !IsPriv(PRIV_GM)) + { + SysMessageDefault(DEFMSG_MAGERY_9); + return true; + } + if (pObj == m_pChar && pSpell->IsSpellType( SPELLFLAG_TARG_NOSELF ) && !IsPriv(PRIV_GM) ) { SysMessageDefault( DEFMSG_MAGERY_3 ); diff --git a/src/game/game_macros.h b/src/game/game_macros.h index 3d00fbb27..416ceb67a 100644 --- a/src/game/game_macros.h +++ b/src/game/game_macros.h @@ -105,6 +105,7 @@ typedef dword DAMAGE_TYPE; // describe a type of damage. #define SPELLFLAG_CURSE 0x20000000 // Curses just like Weaken,Purge Magic,Curse,etc. #define SPELLFLAG_HEAL 0x40000000 // Healing spell #define SPELLFLAG_TICK 0x80000000 // A ticking spell like Poison. - +#define SPELLFLAG_ASYNC 0x100000000 // Make the field items have random timers. +#define SPELLFLAG_TARG_ONLYSELF 0x200000000 // You can only target yourself. #endif // _INC_GAME_MACROS_H diff --git a/src/tables/defmessages.tbl b/src/tables/defmessages.tbl index bf79462ae..77dd32bd7 100644 --- a/src/tables/defmessages.tbl +++ b/src/tables/defmessages.tbl @@ -341,6 +341,7 @@ MSG(MAGERY_5, "You have not yet finished preparing the spell.") MSG(MAGERY_6, "An anti-magic field disturbs the spell.") MSG(MAGERY_7, "You cannot target a player with this spell.") MSG(MAGERY_8, "You cannot target an NPC with this spell.") +MSG(MAGERY_9, "You can only use this spell on yourself.") MSG(MAKESUCCESS_1, "Due to your poor skill, the item is of shoddy quality") MSG(MAKESUCCESS_2, "You were barely able to make this item. It is of poor quality") MSG(MAKESUCCESS_3, "You make the item, but it is of below average quality") @@ -1168,4 +1169,4 @@ MSG(HOUSE_ADD_LIMIT, "House redeeded. You already own the max MSG(DEED_NAME, "Deed to a %s") MSG(LOCATION_INVALID, "That location is not valid.") -#undef MSG \ No newline at end of file +#undef MSG From c5bf09be67b0b1e9aa90252bd9e52a3745b64fca Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 24 Mar 2024 15:33:14 +0000 Subject: [PATCH 19/90] Couple of Fixes --- src/game/chars/CCharSpell.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 9ad6e694c..37d07a957 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -2264,7 +2264,7 @@ void CChar::Spell_Field(CPointMap pntTarg, ITEMID_TYPE idEW, ITEMID_TYPE idNS, u pSpell->GenerateScript(this); if (pSpellDef->IsSpellType(SPELLFLAG_ASYNC)) // If the spell has ASYNC flag, the timers should be randomized. - iDuration += (int64)Calc_GetRandLLVal(iDuration / 2); + iDuration += Calc_GetRandLLVal(iDuration / 2); pSpell->MoveToDecay( ptg, iDuration * MSECS_PER_TENTH, true); } From cc67d8cd6c32954ab78fe0991d020f20661a9592 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 24 Mar 2024 15:35:02 +0000 Subject: [PATCH 20/90] Couple of Fixes --- src/tables/defmessages.tbl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tables/defmessages.tbl b/src/tables/defmessages.tbl index 77dd32bd7..4997f4a24 100644 --- a/src/tables/defmessages.tbl +++ b/src/tables/defmessages.tbl @@ -341,7 +341,7 @@ MSG(MAGERY_5, "You have not yet finished preparing the spell.") MSG(MAGERY_6, "An anti-magic field disturbs the spell.") MSG(MAGERY_7, "You cannot target a player with this spell.") MSG(MAGERY_8, "You cannot target an NPC with this spell.") -MSG(MAGERY_9, "You can only use this spell on yourself.") +MSG(MAGERY_9, "You can only use this spell on yourself.") MSG(MAKESUCCESS_1, "Due to your poor skill, the item is of shoddy quality") MSG(MAKESUCCESS_2, "You were barely able to make this item. It is of poor quality") MSG(MAKESUCCESS_3, "You make the item, but it is of below average quality") From 422c945f5e95a9b1e7023ab34766ffb4110f7a97 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 24 Mar 2024 17:57:38 +0000 Subject: [PATCH 21/90] Couple of Fixes Changed: SERV.LOG command changed to support console colors. (Issue: #1158) --- src/common/CLog.cpp | 17 +++++++++++---- src/common/CLog.h | 10 +++++---- src/game/CServer.cpp | 49 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/common/CLog.cpp b/src/common/CLog.cpp index 4d1d835f8..8f74104e9 100644 --- a/src/common/CLog.cpp +++ b/src/common/CLog.cpp @@ -6,7 +6,7 @@ #include "CLog.h" -int CEventLog::VEvent(dword dwMask, lpctstr pszFormat, va_list args) noexcept +int CEventLog::VEvent(dword dwMask, lpctstr pszFormat, va_list args, ConsoleTextColor iColor) noexcept { if (pszFormat == nullptr || pszFormat[0] == '\0') return 0; @@ -21,7 +21,7 @@ int CEventLog::VEvent(dword dwMask, lpctstr pszFormat, va_list args) noexcept // if ( ( pFix = strchr( pszText, 0x0C ) ) ) // *pFix = ' '; - return EventStr(dwMask, pszTemp); + return EventStr(dwMask, pszTemp, iColor); } int CEventLog::Event(dword dwMask, lpctstr pszFormat, ...) noexcept @@ -60,6 +60,15 @@ int CEventLog::EventWarn(lpctstr pszFormat, ...) noexcept return iret; } +int CEventLog::EventCustom(ConsoleTextColor iColor, dword dwMask, lpctstr pszFormat, ...) noexcept +{ + va_list vargs; + va_start(vargs, pszFormat); + int iret = VEvent(dwMask, pszFormat, vargs, iColor); + va_end(vargs); + return iret; +} + #ifdef _DEBUG int CEventLog::EventEvent(lpctstr pszFormat, ...) noexcept { @@ -204,7 +213,7 @@ bool CLog::OpenLog(lpctstr pszBaseDirName) // name set previously. THREAD_UNIQUE_LOCK_RETURN(CLog::_OpenLog(pszBaseDirName)); } -int CLog::EventStr( dword dwMask, lpctstr pszMsg ) noexcept +int CLog::EventStr( dword dwMask, lpctstr pszMsg, ConsoleTextColor iLogColor) noexcept { ADDTOCALLSTACK("CLog::EventStr"); // NOTE: This could be called in odd interrupt context so don't use dynamic stuff @@ -217,7 +226,7 @@ int CLog::EventStr( dword dwMask, lpctstr pszMsg ) noexcept try { - ConsoleTextColor iLogTextColor = CTCOL_DEFAULT; + ConsoleTextColor iLogTextColor = iLogColor; ConsoleTextColor iLogTypeColor = CTCOL_DEFAULT; // Put up the date/time. diff --git a/src/common/CLog.h b/src/common/CLog.h index 0178d156a..71f5fa5ea 100644 --- a/src/common/CLog.h +++ b/src/common/CLog.h @@ -44,7 +44,8 @@ enum LOG_TYPE LOGM_KILLS = 0x010000, // Log player combat results. LOGM_HTTP = 0x020000, LOGM_NOCONTEXT = 0x040000, // do not include context information - LOGM_DEBUG = 0x080000 // debug kind of message with "DEBUG:" prefix + LOGM_DEBUG = 0x080000, // debug kind of message with "DEBUG:" prefix + LOGM_QTY = 0x0FFF00 // All masks. }; class CSError; @@ -58,15 +59,16 @@ class CEventLog // May include __LINE__ or __FILE__ macro as well ? protected: - virtual int EventStr(dword dwMask, lpctstr pszMsg) noexcept = 0; + virtual int EventStr(dword dwMask, lpctstr pszMsg, ConsoleTextColor iColor = CTCOL_DEFAULT) noexcept = 0; - int VEvent(dword dwMask, lpctstr pszFormat, va_list args) noexcept; + int VEvent(dword dwMask, lpctstr pszFormat, va_list args, ConsoleTextColor iColor = CTCOL_DEFAULT) noexcept; public: int _cdecl Event( dword dwMask, lpctstr pszFormat, ... ) noexcept __printfargs(3,4); int _cdecl EventDebug(lpctstr pszFormat, ...) noexcept __printfargs(2,3); int _cdecl EventError(lpctstr pszFormat, ...) noexcept __printfargs(2,3); int _cdecl EventWarn(lpctstr pszFormat, ...) noexcept __printfargs(2,3); + int _cdecl EventCustom(ConsoleTextColor iColor, dword dwMask, lpctstr pszFormat, ...) noexcept __printfargs(3, 4); #ifdef _DEBUG int _cdecl EventEvent( lpctstr pszFormat, ... ) noexcept __printfargs(2,3); #endif //_DEBUG @@ -117,7 +119,7 @@ public: bool OpenLog(lpctstr pszName = nullptr); bool IsLoggedLevel( LOG_TYPE level ) const; bool IsLogged( dword dwMask ) const; - virtual int EventStr( dword dwMask, lpctstr pszMsg ) noexcept final; // final: for now, it doesn't have any other virtual methods + virtual int EventStr( dword dwMask, lpctstr pszMsg, ConsoleTextColor iLogColor = CTCOL_DEFAULT ) noexcept final; // final: for now, it doesn't have any other virtual methods void _cdecl CatchEvent( const CSError * pErr, lpctstr pszCatchContext, ... ) __printfargs(3,4); void _cdecl CatchStdException( const std::exception * pExc, lpctstr pszCatchContext, ... ) __printfargs(3,4); diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index d3c705279..0f97ae897 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -1717,14 +1717,47 @@ bool CServer::r_Verb( CScript &s, CTextConsole * pSrc ) case SV_LOG: { lpctstr pszArgs = s.GetArgStr(); - int mask = LOGL_EVENT; - if ( pszArgs && ( *pszArgs == '@' )) - { - ++pszArgs; - if ( *pszArgs != '@' ) - mask |= LOGM_NOCONTEXT; - } - g_Log.Event(mask, "%s\n", pszArgs); + dword Args[] = { (dword)CTCOL_DEFAULT, (dword)LOGL_EVENT, (dword)0 }; + dword mask = Args[1]; + if (*pszArgs == '@') + { + ++pszArgs; + if (*pszArgs == '@') // @@ = just a @ symbol + goto log_cont; + + const char* c = pszArgs; + pszArgs = strchr(c, ' '); + + if (!pszArgs) + return false; + + for (int i = 0; (c < pszArgs) && (i < 3); ) + { + if (*c == ',') // default value, skip it + { + ++i; + ++c; + continue; + } + Args[i] = (Exp_GetDWVal(c)); + ++i; + + if (*c == ',') + ++c; + else + break; // no more args here! + } + ++pszArgs; + if (Args[0] > (dword)CTCOL_QTY || Args[0] < (dword)0) + Args[0] = (dword)CTCOL_DEFAULT; + if (Args[1] > (dword)LOGL_QTY || Args[1] < (dword)1) + Args[1] = (dword)LOGL_EVENT; + if (Args[2] > (dword)LOGM_QTY) + Args[2] = (dword)0; + mask = Args[1] | Args[2]; + } +log_cont: + g_Log.EventCustom((ConsoleTextColor)Args[0], mask, "%s\n", pszArgs); } break; From 841a230c447fbd89e9c10aabd25a69ca0ca67178 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 24 Mar 2024 18:12:16 +0000 Subject: [PATCH 22/90] Update CLog.h --- src/common/CLog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/CLog.h b/src/common/CLog.h index 71f5fa5ea..2fb9f13f2 100644 --- a/src/common/CLog.h +++ b/src/common/CLog.h @@ -68,7 +68,7 @@ class CEventLog int _cdecl EventDebug(lpctstr pszFormat, ...) noexcept __printfargs(2,3); int _cdecl EventError(lpctstr pszFormat, ...) noexcept __printfargs(2,3); int _cdecl EventWarn(lpctstr pszFormat, ...) noexcept __printfargs(2,3); - int _cdecl EventCustom(ConsoleTextColor iColor, dword dwMask, lpctstr pszFormat, ...) noexcept __printfargs(3, 4); + int _cdecl EventCustom(ConsoleTextColor iColor, dword dwMask, lpctstr pszFormat, ...) noexcept __printfargs(4,5); #ifdef _DEBUG int _cdecl EventEvent( lpctstr pszFormat, ... ) noexcept __printfargs(2,3); #endif //_DEBUG From 0980cd86cc39e4a58a76c4d244f185c1710f79dd Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 24 Mar 2024 20:36:56 +0000 Subject: [PATCH 23/90] Couple of Fixes Added: Sphere.ini setting CanPetsDrinkPotion (true in default) to make pets drink potion when their owner drop it on it. (Issue: #1147) --- src/game/CServerConfig.cpp | 5 ++++- src/game/CServerConfig.h | 1 + src/game/chars/CCharNPCAct.cpp | 17 ++++++++++++++--- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index bb879b969..00da9910f 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -1,4 +1,4 @@ -#include "../common/resource/sections/CDialogDef.h" +#include "../common/resource/sections/CDialogDef.h" #include "../common/resource/sections/CItemTypeDef.h" #include "../common/resource/sections/CSkillClassDef.h" #include "../common/resource/sections/CRandGroupDef.h" @@ -111,6 +111,7 @@ CServerConfig::CServerConfig() // In game effects. m_fCanUndressPets = true; + m_fCanPetsDrinkPotion = true; m_fMonsterFight = false; m_fMonsterFear = false; m_iLightDungeon = 27; @@ -456,6 +457,7 @@ enum RC_TYPE RC_BANKMAXITEMS, RC_BANKMAXWEIGHT, RC_BUILD, + RC_CANPETSDRINKPOTION, // m_fCanPetsDrinkPotion RC_CANSEESAMEPLEVEL, // m_iCanSeeSamePLevel RC_CANUNDRESSPETS, // m_fCanUndressPets RC_CHARTAGS, // m_fCharTags @@ -727,6 +729,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY+1] { "BANKMAXITEMS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iBankIMax) }}, { "BANKMAXWEIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iBankWMax) }}, { "BUILD", { ELEM_VOID, 0 }}, + { "CANPETSDRINKPOTION", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCanPetsDrinkPotion) }}, { "CANSEESAMEPLEVEL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCanSeeSamePLevel) }}, { "CANUNDRESSPETS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCanUndressPets) }}, { "CHARTAGS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCharTags) }}, diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 627ff909f..59b719516 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -324,6 +324,7 @@ extern class CServerConfig : public CResourceHolder bool m_fFlipDroppedItems; // Flip dropped items. int m_iItemsMaxAmount; // Max amount allowed for stackable items. bool m_fCanUndressPets; // Can players undress their pets? + bool m_fCanPetsDrinkPotion; // Can pets drink potion when their owner dropped potion on it. bool m_fMonsterFight; // Will creatures fight amoung themselves. bool m_fMonsterFear; // will they run away if hurt ? uint m_iContainerMaxItems; // Maximum number of items allowed in a container item. diff --git a/src/game/chars/CCharNPCAct.cpp b/src/game/chars/CCharNPCAct.cpp index 7a5fb8c91..d123ce766 100644 --- a/src/game/chars/CCharNPCAct.cpp +++ b/src/game/chars/CCharNPCAct.cpp @@ -2058,9 +2058,6 @@ bool CChar::NPC_OnItemGive( CChar *pCharSrc, CItem *pItem ) return false; } - if ( pCharSrc->IsPriv(PRIV_GM) ) - return ItemBounce(pItem); - if ( !CanCarry(pItem) ) { if ( NPC_CanSpeak() ) @@ -2068,6 +2065,20 @@ bool CChar::NPC_OnItemGive( CChar *pCharSrc, CItem *pItem ) return false; } + if (pItem->IsType(IT_POTION)) + { + if (g_Cfg.m_fCanPetsDrinkPotion == true) + { + if (Use_Item(pItem)) + return true; + else + return false; //If can't use item, return it inside player's backpack. + } + } + + if (pCharSrc->IsPriv(PRIV_GM)) + return ItemBounce(pItem); + // Place item on backpack CItemContainer *pPack = GetPack(); if ( !pPack ) From 422bacbea3a3fe280c695084f75f101c887c9115 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 24 Mar 2024 20:37:03 +0000 Subject: [PATCH 24/90] Update Changelog.txt --- Changelog.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Changelog.txt b/Changelog.txt index 3fc9625bb..7c522a214 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3461,3 +3461,10 @@ Added: New spellflag SPELLFLAG_ASNYC (0100000000) to randomize field timers like Added: New spellflag SPELLFLAG_TARG_ONLYSELF (0200000000) to make spell only be used on character himself. (Issue: #1171) SPELLFLAG_TARG_ONLYSELF should be added to defs. //magery_9 "You can only use this spell on yourself." could be added to defmessages. +Changed: SERV.LOG command changed to support console colors. (Issue: [Feature Request] Colored Serv & Src Log System #1158) + SERV.LOG works same as before. + Usage of custom color system is: SERV.LOG @color,type,mask message + Example: SERV.LOG @CTCOL_RED,LOGL_EVENT,LOGM_NOCONTEXT|LOGM_KILLS message + LOGM, LOGL and CTCOL values should be added to defs. +Added: Sphere.ini setting CanPetsDrinkPotion (true in default) to make pets drink potion when their owner drop it on it. (Issue: #1147) + CanPetsDrinkPotion = 0 can be added to sphere.ini to disable that. \ No newline at end of file From 6df3fc4cbe418df511a0323b52bd5fb41e480b13 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Mon, 25 Mar 2024 14:55:44 +0000 Subject: [PATCH 25/90] Couple of Fixes Fixed: Missing fCheckOnly checks block the taming skill. (Issue: #1219) --- Changelog.txt | 5 +++-- src/game/chars/CChar.cpp | 10 +++++----- src/game/chars/CCharUse.cpp | 39 ++++++++++++++++++++----------------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 7c522a214..e0560e4b9 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3456,7 +3456,7 @@ Fixed: The wrong input of Kill trigger, to make it compatible with older sphere Added: New Layer LAYER_STORAGE (80) to let scripters create their own storage system. (Issue: #1209) Only t_container and t_container_locked can be equipped to this layer. Changed: Decay time removed from spawned items, as Sphere gives tons of invalid link errors when items decayed. (Issue: #1218) -Added: New spellflag SPELLFLAG_ASNYC (0100000000) to randomize field timers like old sphere versions. (Issue: #1169) +Added: New spellflag SPELLFLAG_ASYNC (0100000000) to randomize field timers like old sphere versions. (Issue: #1169) SPELLFLAG_ASYNC should be added to defs. Added: New spellflag SPELLFLAG_TARG_ONLYSELF (0200000000) to make spell only be used on character himself. (Issue: #1171) SPELLFLAG_TARG_ONLYSELF should be added to defs. @@ -3467,4 +3467,5 @@ Changed: SERV.LOG command changed to support console colors. (Issue: [Feature Re Example: SERV.LOG @CTCOL_RED,LOGL_EVENT,LOGM_NOCONTEXT|LOGM_KILLS message LOGM, LOGL and CTCOL values should be added to defs. Added: Sphere.ini setting CanPetsDrinkPotion (true in default) to make pets drink potion when their owner drop it on it. (Issue: #1147) - CanPetsDrinkPotion = 0 can be added to sphere.ini to disable that. \ No newline at end of file + CanPetsDrinkPotion = 0 can be added to sphere.ini to disable that. +Fixed: Missing fCheckOnly checks block the taming skill. (Issue: #1219) \ No newline at end of file diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 6953a2393..8eb49800f 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -3408,17 +3408,17 @@ bool CChar::r_LoadVal( CScript & s ) UpdateStatsFlag(); return true; } - else if (!strnicmp(ptcKey, "DELETE", 6)) + else if (!strnicmp(ptcKey, "DELETE", 6) || !strnicmp(ptcKey, "DEL", 3)) { if (!m_followers.empty()) { CUID uid = (CUID)s.GetArgDWVal(); for (std::vector::iterator it = m_followers.begin(); it != m_followers.end(); ) { - if (uid == *it) - it = m_followers.erase(it); - else - ++it; + if (uid == *it) + it = m_followers.erase(it); + else + ++it; } } return true; diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index a03ad57c1..2d830f638 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1160,25 +1160,28 @@ bool CChar::FollowersUpdate( CChar * pChar, short iFollowerSlots, bool fCheckOnl short iMaxFollower = (short)(GetDefNum("MAXFOLLOWER", true)); if (IsSetEF(EF_FollowerList)) { - if (iFollowerSlots > 0) - { - bool fExists = false; - for (std::vector::iterator it = m_followers.begin(); it != m_followers.end();) - { - if (*it == pChar->GetUID()) - { - fExists = true; - break; - } - ++it; - } + if (iFollowerSlots >= 0) + { + bool fExists = false; + for (std::vector::iterator it = m_followers.begin(); it != m_followers.end();) + { + if (*it == pChar->GetUID()) + { + fExists = true; + break; + } + ++it; + } - if (!fExists && ( (short)(m_followers.size()) < iMaxFollower || IsPriv(PRIV_GM))) - m_followers.emplace_back(pChar->GetUID()); - else - return false; - } - else + if (!fExists && ((short)(m_followers.size()) < iMaxFollower || IsPriv(PRIV_GM))) + { + if (!fCheckOnly) + m_followers.emplace_back(pChar->GetUID()); + } + else + return false; + } + else if (!fCheckOnly) { for (std::vector::iterator it = m_followers.begin(); it != m_followers.end();) { From 0948503e5dc4870a642adf0092410a5f43ebf964 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 26 Mar 2024 20:06:37 +0000 Subject: [PATCH 26/90] Couple of Fixes Added: New trigger @Drink added for characters. (Issue: #1162) Added: New trigger @AfkMode added for characters. (Issue: #1161) Added: New trigger @Reveal added for characters. (Issue: #1157) Added: New triggers @ArrowQuest_Add and @ArrowQuest_Close added for characters. (Issue: #1116) Added: New function triggers f_onaccount_block and f_onaccount_unblock. (Issue: #1156) Added: New function trigger f_onserver_broadcast. (Issue: #1145) Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReductionAmount to @Hit trigger. (Issue: #1159) --- Changelog.txt | 45 +++++++++++++- src/game/CObjBase.h | 7 ++- src/game/CWorldComm.cpp | 10 ++++ src/game/chars/CChar.cpp | 102 ++++++++++++++++++++++++++++++-- src/game/chars/CChar.h | 3 + src/game/chars/CCharAct.cpp | 6 ++ src/game/chars/CCharFight.cpp | 18 +++++- src/game/chars/CCharUse.cpp | 46 ++++++++++++-- src/game/clients/CAccount.cpp | 46 +++++++++++--- src/game/clients/CAccount.h | 1 + src/game/clients/CClientMsg.cpp | 17 ++++++ src/game/items/CItemBase.h | 1 + src/tables/defmessages.tbl | 3 +- src/tables/triggers.tbl | 13 ++-- 14 files changed, 290 insertions(+), 28 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index e0560e4b9..adf048d45 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3466,6 +3466,49 @@ Changed: SERV.LOG command changed to support console colors. (Issue: [Feature Re Usage of custom color system is: SERV.LOG @color,type,mask message Example: SERV.LOG @CTCOL_RED,LOGL_EVENT,LOGM_NOCONTEXT|LOGM_KILLS message LOGM, LOGL and CTCOL values should be added to defs. + +25-03-2024, xwerswoodx Added: Sphere.ini setting CanPetsDrinkPotion (true in default) to make pets drink potion when their owner drop it on it. (Issue: #1147) CanPetsDrinkPotion = 0 can be added to sphere.ini to disable that. -Fixed: Missing fCheckOnly checks block the taming skill. (Issue: #1219) \ No newline at end of file +Fixed: Missing fCheckOnly checks block the taming skill. (Issue: #1219) + +26-03-2024, xwerswoodx +Added: New trigger @Drink added for characters. (Issue: #1162) + I: The character drinking the item. + SRC: The character drinking the item. + ARGO = the item that drank + ARGN1 = cooldown (in seconds) + ARGN2 = consumption amount (1 in default) + LOCAL.BottleID = empty bottle id that will be given when after item drank. (Will be given ARGN2 amount of empty bottle in default) + - Returns: + 1: Stops character from drinking the item. + 5: Let character to drink but will only give 1 empty bottle. + 6: Let character to drink but will not give any empty bottle. + - Messages: + DRINK_NOT_ENOUGH, "You don't have enough %s to drink this." +Added: New trigger @AfkMode added for characters. (Issue: #1161) + I: The character changing AFK status. + SRC: The character changing AFK status. + ARGN1 = Current Afk Status + ARGN2 = Next Afk Status + - Returns: + 1: Stops character from switching afk status. +Added: New trigger @Reveal added for characters. (Issue: #1157) + I: The character who is revealing. + SRC: The character who is revealing. + - Returns: + 1: Prevents character from being revealed. +Added: New triggers @ArrowQuest_Add and @ArrowQuest_Close added for characters. (Issue: #1116) + I: The character who activating/deactivating arrow quest. + SRC: The character who activating/deactivating arrow quest. +Added: New function triggers f_onaccount_block and f_onaccount_unblock. (Issue: #1156) + ARGS = Account name. + - Returns: + 1: Prevents account from blocking/unblocking. +Added: New function trigger f_onserver_broadcast. (Issue: #1145) + ARGS = message + - Returns: + 1: Prevents server to send broadcast message. +Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReductionAmount to @Hit trigger. (Issue: #1159) + LOCAL.ItemPoisonReductionChance = Is the chance that weapon reduce poison morez. (Default 100%) + LOCAL.ItemPoisonReductionAmount = Is the amount that weapon reduce. (Default: CurrentPoisonAmount/ 2) \ No newline at end of file diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index 1293b8b1a..5ff8923f6 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -1081,7 +1081,10 @@ enum CTRIG_TYPE : short { CTRIG_AAAUNUSED = 0, CTRIG_AddMulti, // Adds the given multi to the CMultiStorage of this char (player). + CTRIG_AfkMode, // Switch AFK mode by using .AFK command. CTRIG_AfterClick, // I'm not yet clicked, name should be generated before. + CTRIG_ArrowQuest_Add, + CTRIG_ArrowQuest_Close, CTRIG_Attack, // I am attacking someone (SRC). CTRIG_CallGuards, // I'm calling guards. // Here starts @charXXX section @@ -1113,7 +1116,8 @@ enum CTRIG_TYPE : short CTRIG_DelMulti, // Delete the given multi to the CMultiStorage of this char (player). CTRIG_Destroy, // I am nearly destroyed. CTRIG_Dismount, // I'm dismounting. - CTRIG_DYE, + CTRIG_Drink, // I'm drinking something. + CTRIG_DYE, CTRIG_Eat, // I'm eating something. CTRIG_EnvironChange, // my environment changed somehow (light,weather,season,region) CTRIG_ExpChange, // EXP is going to change @@ -1221,6 +1225,7 @@ enum CTRIG_TYPE : short CTRIG_Rename, // Changing my name or pets one. CTRIG_Resurrect, // I'm going to resurrect via function or spell. + CTRIG_Reveal, // Character is revealing. CTRIG_SeeCrime, // I am seeing a crime. CTRIG_SeeHidden, // I'm about to see a hidden char. CTRIG_SeeSnoop, // I see someone Snooping something. diff --git a/src/game/CWorldComm.cpp b/src/game/CWorldComm.cpp index 556000273..4ae8167cd 100644 --- a/src/game/CWorldComm.cpp +++ b/src/game/CWorldComm.cpp @@ -3,6 +3,7 @@ #include "chars/CChar.h" #include "clients/CClient.h" #include "CWorldComm.h" +#include "CServer.h" static const SOUND_TYPE sm_Sounds_Ghost[] = @@ -222,6 +223,15 @@ void CWorldComm::Broadcast(lpctstr pMsg) // static { // System broadcast in bold text ADDTOCALLSTACK("CWorldComm::Broadcast"); + + CScriptTriggerArgs args; + args.Init(pMsg); + TRIGRET_TYPE iRet = TRIGRET_RET_FALSE; + g_Serv.r_Call("f_onserver_broadcast", &g_Serv, &args, nullptr, &iRet); + if (iRet == TRIGRET_RET_TRUE) + return; + pMsg = args.m_s1; + Speak( nullptr, pMsg, HUE_TEXT_DEF, TALKMODE_BROADCAST, FONT_BOLD ); } diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 8eb49800f..2f897b539 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -35,7 +35,10 @@ lpctstr const CChar::sm_szTrigName[CTRIG_QTY+1] = // static { "@AAAUNUSED", "@AddMulti", // Adding a multi to the MultiStorage, + "@AfkMode", // Changing afk mode by using .AFK command. "@AfterClick", + "@ArrowQuest_Add", + "@ArrowQuest_Close", "@Attack", // I am attacking someone (SRC) "@CallGuards", @@ -67,6 +70,7 @@ lpctstr const CChar::sm_szTrigName[CTRIG_QTY+1] = // static "@DelMulti", // Removing a multi to the MultiStorage, "@Destroy", //+I am nearly destroyed "@Dismount", // I am trying to get rid of my ride right now + "@Drink", // I am drinking something. "@Dye", // My color has been changed "@Eat", "@EnvironChange", // my environment changed somehow (light,weather,season,region) @@ -175,6 +179,7 @@ lpctstr const CChar::sm_szTrigName[CTRIG_QTY+1] = // static "@Rename", "@Resurrect", + "@Reveal", // Character is revealing. "@SeeCrime", // I saw a crime "@SeeHidden", // Can I see hidden chars? "@SeeSnoop", @@ -4222,12 +4227,20 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc // toggle ? { bool fAFK = ( Skill_GetActive() == NPCACT_NAPPING ); - bool fMode; - if ( s.HasArgs()) - fMode = ( s.GetArgVal() != 0 ); - else - fMode = ! fAFK; - if ( fMode != fAFK ) + bool fMode = (s.GetArgVal() != 0 ? true : !fAFK); + + if (IsTrigUsed(TRIGGER_AFKMODE)) + { + CScriptTriggerArgs args(fAFK, fMode); + TRIGRET_TYPE iRet = OnTrigger(CTRIG_AfkMode, this, &args); + fAFK = args.m_iN1 > 0 ? true : false; + fMode = args.m_iN2 > 0 ? true : false; + + if (iRet == TRIGRET_RET_TRUE) //Block AFK mode switching if RETURN 1 in Trigger. + return true; + } + + if ( fMode != fAFK ) { if ( fMode ) { @@ -5032,6 +5045,83 @@ void CChar::ChangeExperience(llong delta, CChar *pCharDead) } } +bool CChar::CanConsume(CItem* pItem, word iQty) +{ + ADDTOCALLSTACK("CChar::CanConsume"); + if (!pItem || iQty <= 0) + return true; + + word iQtyMax = pItem->GetAmount(); + if (iQty <= iQtyMax) + return true; + + CObjBaseTemplate* pTopObj = pItem->GetTopLevelObj(); + if (!pTopObj) + iQty = iQty - iQtyMax; + else if (pTopObj) + { + CChar* pTopChar = dynamic_cast(pTopObj); + if (pTopObj == pItem || (pTopChar && pTopChar != this)) + iQty = iQty - iQtyMax; + } + + if (IsContainer()) + { + CItemBase* pItemDef = pItem->Item_GetDef(); + CContainer* pCont = dynamic_cast(this); + if (pCont) + { + CResourceQtyArray Resources; + Resources.Load(pItemDef->GetResourceName()); + return pCont->ResourceConsume(&Resources, iQty, true) >= iQty; + } + } + return false; +} + +bool CChar::ConsumeAmount(CItem* pItem, word iQty) +{ + ADDTOCALLSTACK("CChar::ConsumeFromPack"); + + if (!pItem || iQty <= 0) + return true; + + word iQtyMax = pItem->GetAmount(); + if (iQty < iQtyMax) + { + pItem->SetAmountUpdate(iQtyMax - iQty); + return true; + } + else if (iQty == iQtyMax) + { + pItem->Delete(); + return true; + } + else + { + iQty = iQty - iQtyMax; + CItemBase* pItemDef = pItem->Item_GetDef(); + if (pItemDef) + { + lpctstr resName = pItemDef->GetResourceName(); + pItem->Delete(); + CContainer* pCont = dynamic_cast(this); + if (pCont) + { + CResourceQtyArray Resources; + Resources.Load(resName); + if (pCont->ResourceConsume(&Resources, iQty, true)) + { + pCont->ResourceConsume(&Resources, iQty); + return true; + } + } + + } + } + return false; +} + // returns uint CChar::GetSkillTotal(int what, bool how) { diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index b1f125c7b..be892ce65 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -837,6 +837,9 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; void ChangeExperience(llong delta = 0, CChar *pCharDead = nullptr); uint GetSkillTotal(int what = 0, bool how = true); + bool CanConsume(CItem* pItem, word iQty); + bool ConsumeAmount(CItem* pItem, word iQty); + // skills and actions. ------------------------------------------- static bool IsSkillBase( SKILL_TYPE skill ) noexcept; static bool IsSkillNPC( SKILL_TYPE skill ) noexcept; diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index 9b93b165b..6f5746fb6 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -2287,6 +2287,12 @@ bool CChar::Reveal( uint64 iFlags ) if ( !IsStatFlag(iFlags) ) return false; + if (IsTrigUsed(TRIGGER_REVEAL)) + { + if (OnTrigger(CTRIG_Reveal, this, nullptr) == TRIGRET_RET_TRUE) + return false; + } + CClient* pClient = IsClientActive() ? GetClientActive() : nullptr; if (pClient && pClient->m_pHouseDesign) { diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 021ae1280..a489c7398 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -2074,6 +2074,15 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) CScriptTriggerArgs Args(iDmg, iDmgType, pWeapon); Args.m_VarsLocal.SetNum("ItemDamageChance", 25); + Args.m_VarsLocal.SetNum("ItemPoisonReductionChance", 100); + Args.m_VarsLocal.SetNum("ItemPoisonReductionAmount", 1); + int32 iPoison = 0; + if (pWeapon) + { + iPoison = Calc_GetRandVal(pWeapon->m_itWeapon.m_poison_skill); + Args.m_VarsLocal.SetNum("ItemPoisonReductionAmount", iPoison / 2); + } + if ( pAmmo && pAmmo->GetUID().IsValidUID() ) Args.m_VarsLocal.SetNum("Arrow",(dword)pAmmo->GetUID()); @@ -2133,11 +2142,14 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) if ( !IsSetCombatFlags(COMBAT_NOPOISONHIT) && pWeapon->m_itWeapon.m_poison_skill && (pWeapon->m_itWeapon.m_poison_skill > Calc_GetRandVal(100) || pWeapon->m_itWeapon.m_poison_skill < 10)) { - byte iPoisonDeliver = (byte)(Calc_GetRandVal(pWeapon->m_itWeapon.m_poison_skill)); + byte iPoisonDeliver = (byte)(iPoison); pCharTarg->SetPoison(10 * iPoisonDeliver, iPoisonDeliver / 5, this); - pWeapon->m_itWeapon.m_poison_skill -= iPoisonDeliver / 2; // reduce weapon poison charges - pWeapon->UpdatePropertyFlag(); + if (Args.m_VarsLocal.GetKeyNum("ItemPoisonReductionChance") > Calc_GetRandVal(100)) + { + pWeapon->m_itWeapon.m_poison_skill -= (byte)(Args.m_VarsLocal.GetKeyNum("ItemPoisonReductionAmount")); // reduce weapon poison charges + pWeapon->UpdatePropertyFlag(); + } } // Check if the weapon will be damaged diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 2d830f638..f988e331a 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -990,6 +990,34 @@ void CChar::Use_Drink( CItem * pItem ) const CItemBase *pItemDef = pItem->Item_GetDef(); ITEMID_TYPE idbottle = (ITEMID_TYPE)pItemDef->m_ttDrink.m_ridEmpty.GetResIndex(); + dword dwDelay = (pItemDef->m_ttDrink.m_ridDelay ? pItemDef->m_ttDrink.m_ridDelay: (pItem->IsType(IT_BOOZE) ? 1500u : 15u)) * 10; //Minimum should be 1 as if we set 0, it makes effect cooldown infinite. + word wConsume = (word)1; + word wBottleAmount = wConsume; + + if (IsTrigUsed(TRIGGER_DRINK)) + { + CScriptTriggerArgs args(dwDelay, wConsume); + args.m_pO1 = pItem; + args.m_VarsLocal.SetNumNew("BottleId", idbottle); + TRIGRET_TYPE iRet = OnTrigger(CTRIG_Drink, this, &args); + idbottle = (ITEMID_TYPE)args.m_VarsLocal.GetKeyNum("BottleId"); + dwDelay = (dword)(args.m_iN1 > 0 ? args.m_iN1 : 1); //0 causes stays memory infinitely. + wConsume = (word)args.m_iN2; + wBottleAmount = wConsume; + + if (iRet == TRIGRET_RET_TRUE) + return; + else if (iRet == TRIGRET_ELSEIF) + wBottleAmount = 1; + else if (iRet == TRIGRET_RET_HALFBAKED) + wBottleAmount = 0; + } + + if (wConsume > 0 && !CanConsume(pItem, wConsume)) // We need to check if he can consume, before creating effects. + { + SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_DRINK_NOT_ENOUGH), pItem->GetName()); + return; + } if ( pItem->IsType(IT_BOOZE) ) { @@ -1012,7 +1040,7 @@ void CChar::Use_Drink( CItem * pItem ) } else { - CItem *pSpell = Spell_Effect_Create(SPELL_Liquor, LAYER_FLAG_Drunk, g_Cfg.GetSpellEffect(SPELL_Liquor, iStrength), 150*MSECS_PER_TENTH, this); + CItem *pSpell = Spell_Effect_Create(SPELL_Liquor, LAYER_FLAG_Drunk, g_Cfg.GetSpellEffect(SPELL_Liquor, iStrength), (int64)dwDelay, this); pSpell->m_itSpell.m_spellcharges = 10; // how long to last. } } @@ -1034,7 +1062,7 @@ void CChar::Use_Drink( CItem * pItem ) OnSpellEffect((SPELL_TYPE)(RES_GET_INDEX(pItem->m_itPotion.m_Type)), this, iSkillQuality, pItem); // Give me the marker that i've used a potion. - Spell_Effect_Create(SPELL_NONE, LAYER_FLAG_PotionUsed, g_Cfg.GetSpellEffect(SPELL_NONE, iSkillQuality), 150, this); + Spell_Effect_Create(SPELL_NONE, LAYER_FLAG_PotionUsed, g_Cfg.GetSpellEffect(SPELL_NONE, iSkillQuality), (int64)dwDelay, this); } else if ( pItem->IsType(IT_DRINK) && IsSetOF(OF_DrinkIsFood) ) { @@ -1060,11 +1088,19 @@ void CChar::Use_Drink( CItem * pItem ) //Sound(sm_DrinkSounds[Calc_GetRandVal(ARRAY_COUNT(sm_DrinkSounds))]); UpdateAnimate(ANIM_EAT); - pItem->ConsumeAmount(); + if (wConsume > 0) //if ARGN2 > 0, consume. + ConsumeAmount(pItem, wConsume); // Create the empty bottle ? - if ( idbottle != ITEMID_NOTHING ) - ItemBounce(CItem::CreateScript(idbottle, this), false); + if (idbottle != ITEMID_NOTHING) + { + CItem* pBottle = CItem::CreateScript(idbottle, this); + if (wBottleAmount > 0) + { + pBottle->SetAmount(wBottleAmount); + ItemBounce(pBottle, false); + } + } } CChar * CChar::Use_Figurine( CItem * pItem, bool fCheckFollowerSlots ) diff --git a/src/game/clients/CAccount.cpp b/src/game/clients/CAccount.cpp index 5f92a0876..eebc5c756 100644 --- a/src/game/clients/CAccount.cpp +++ b/src/game/clients/CAccount.cpp @@ -389,6 +389,33 @@ bool CAccounts::Cmd_ListUnused(CTextConsole * pSrc, lpctstr pszDays, lpctstr psz return true; } +void CAccount::SetBlockStatus(bool fNewStatus) +{ + if (!g_Serv.IsLoading()) + { + if (IsPriv(PRIV_BLOCKED) && fNewStatus == false) { + + CScriptTriggerArgs Args; + Args.Init(GetName()); + TRIGRET_TYPE iRet = TRIGRET_RET_FALSE; + g_Serv.r_Call("f_onaccount_unblock", &g_Serv, &Args, nullptr, &iRet); + if (iRet == TRIGRET_RET_TRUE) + return; + ClearPrivFlags(PRIV_BLOCKED); + } + else if (!IsPriv(PRIV_BLOCKED) && fNewStatus == true) + { + CScriptTriggerArgs Args; + Args.Init(GetName()); + TRIGRET_TYPE iRet = TRIGRET_RET_FALSE; + g_Serv.r_Call("f_onaccount_block", &g_Serv, &Args, nullptr, &iRet); + if (iRet == TRIGRET_RET_TRUE) + return; + SetPrivFlags(PRIV_BLOCKED); + } + } +} + bool CAccounts::Account_OnCmd( tchar * pszArgs, CTextConsole * pSrc ) { ADDTOCALLSTACK("CAccounts::Account_OnCmd"); @@ -774,7 +801,8 @@ bool CAccount::Kick( CTextConsole * pSrc, bool fBlock ) if ( fBlock ) { - SetPrivFlags( PRIV_BLOCKED ); + //SetPrivFlags( PRIV_BLOCKED ); + SetBlockStatus(true); pSrc->SysMessagef( g_Cfg.GetDefaultMsg(DEFMSG_MSG_ACC_BLOCK), GetName() ); } @@ -1328,11 +1356,13 @@ bool CAccount::r_LoadVal( CScript & s ) case AC_BLOCK: if ( ! s.HasArgs() || s.GetArgVal()) { - SetPrivFlags( PRIV_BLOCKED ); + //SetPrivFlags( PRIV_BLOCKED ); + SetBlockStatus(true); } else { - ClearPrivFlags( PRIV_BLOCKED ); + //ClearPrivFlags( PRIV_BLOCKED ); + SetBlockStatus(false); } break; case AC_CHARUID: @@ -1638,10 +1668,12 @@ bool CAccount::r_Verb( CScript &s, CTextConsole * pSrc ) return true; } case AV_BLOCK: - if ( ! s.HasArgs() || s.GetArgVal()) - SetPrivFlags(PRIV_BLOCKED); - else - ClearPrivFlags(PRIV_BLOCKED); + if (!s.HasArgs() || s.GetArgVal()) + //SetPrivFlags(PRIV_BLOCKED); + SetBlockStatus(true); + else + //ClearPrivFlags(PRIV_BLOCKED); + SetBlockStatus(false); return true; case AV_KICK: diff --git a/src/game/clients/CAccount.h b/src/game/clients/CAccount.h index 4b6b7722b..be36dbf93 100644 --- a/src/game/clients/CAccount.h +++ b/src/game/clients/CAccount.h @@ -346,6 +346,7 @@ class CAccount : public CScriptObj * @return CClient logged into de CAccount, nullptr otherwise. */ CClient * FindClient( const CClient * pExclude = nullptr ) const; + void SetBlockStatus(bool fNewStatus); }; diff --git a/src/game/clients/CClientMsg.cpp b/src/game/clients/CClientMsg.cpp index 87e4cbb0e..9b826cf92 100644 --- a/src/game/clients/CClientMsg.cpp +++ b/src/game/clients/CClientMsg.cpp @@ -567,6 +567,23 @@ void CClient::addArrowQuest( int x, int y, int id ) const { ADDTOCALLSTACK("CClient::addArrowQuest"); + CScriptTriggerArgs args(x, y); + if (this->GetNetState()->isClientVersion(MINCLIVER_HS) || this->GetNetState()->isClientEnhanced()) + args.m_iN3 = id; + else + args.m_iN3 = 0; + + if (x > 0) + { + if (IsTrigUsed(TRIGGER_ARROWQUEST_ADD)) + m_pChar->OnTrigger(CTRIG_ArrowQuest_Add, m_pChar, &args); + } + else + { + if (IsTrigUsed(TRIGGER_ARROWQUEST_CLOSE)) + m_pChar->OnTrigger(CTRIG_ArrowQuest_Close, m_pChar, &args); + } + new PacketArrowQuest(this, x, y, id); } diff --git a/src/game/items/CItemBase.h b/src/game/items/CItemBase.h index 5d7a9f7c5..bbb5c2faa 100644 --- a/src/game/items/CItemBase.h +++ b/src/game/items/CItemBase.h @@ -200,6 +200,7 @@ class CItemBase : public CBaseBaseDef struct { CResourceIDBase m_ridEmpty; // tdata1= the empty container. IT_POTION_EMPTY IT_PITCHER_EMPTY + dword m_ridDelay; //tdata2= how long someone need to wait to drink again after using it (in seconds). } m_ttDrink; // IT_SHIP_PLANK diff --git a/src/tables/defmessages.tbl b/src/tables/defmessages.tbl index 4997f4a24..885d0353b 100644 --- a/src/tables/defmessages.tbl +++ b/src/tables/defmessages.tbl @@ -86,7 +86,8 @@ MSG(CONT_TOOSMALL, "The container is too small for that") MSG(CORPSE_NAME, "%s of %s") MSG(DETECTHIDDEN_SUCC, "You find %s") MSG(DRINK_CANTMOVE, "You can't move the item.") -MSG(DRINK_POTION_DELAY, "You can't drink another potion yet") +MSG(DRINK_POTION_DELAY, "You can't drink another potion yet") +MSG(DRINK_NOT_ENOUGH, "You don't have enough %s to drink this.") MSG(EVALINT_INT_1, "dumb as a rock") MSG(EVALINT_INT_10, "superhumanly intelligent") MSG(EVALINT_INT_2, "fairly stupid") diff --git a/src/tables/triggers.tbl b/src/tables/triggers.tbl index 9d266e0b9..080a9123e 100644 --- a/src/tables/triggers.tbl +++ b/src/tables/triggers.tbl @@ -9,8 +9,11 @@ ADD(ABORT) ADD(ADDMULTI) ADD(ADDREDCANDLE) ADD(ADDOBJ) -ADD(ADDWHITECANDLE) -ADD(AFTERCLICK) +ADD(ADDWHITECANDLE) +ADD(AFKMODE) +ADD(AFTERCLICK) +ADD(ARROWQUEST_ADD) +ADD(ARROWQUEST_CLOSE) ADD(ATTACK) ADD(BUY) ADD(CALLGUARDS) @@ -42,7 +45,8 @@ ADD(DEATHCORPSE) ADD(DELMULTI) ADD(DELOBJ) ADD(DESTROY) -ADD(DISMOUNT) +ADD(DISMOUNT) +ADD(DRINK) ADD(DROPON_CHAR) ADD(DROPON_GROUND) ADD(DROPON_ITEM) @@ -167,7 +171,8 @@ ADD(RENAME) ADD(RESOURCEFOUND) ADD(RESOURCEGATHER) ADD(RESOURCETEST) -ADD(RESURRECT) +ADD(RESURRECT) +ADD(REVEAL) ADD(SEECRIME) ADD(SEEHIDDEN) ADD(SEESNOOP) From ea8ac5984a8196e05a2a3bc5bec7e6a75fe97e65 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 26 Mar 2024 20:18:11 +0000 Subject: [PATCH 27/90] Update Changelog.txt --- Changelog.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.txt b/Changelog.txt index adf048d45..23e31feda 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3511,4 +3511,5 @@ Added: New function trigger f_onserver_broadcast. (Issue: #1145) 1: Prevents server to send broadcast message. Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReductionAmount to @Hit trigger. (Issue: #1159) LOCAL.ItemPoisonReductionChance = Is the chance that weapon reduce poison morez. (Default 100%) - LOCAL.ItemPoisonReductionAmount = Is the amount that weapon reduce. (Default: CurrentPoisonAmount/ 2) \ No newline at end of file + LOCAL.ItemPoisonReductionAmount = Is the amount that weapon reduce. (Default: CurrentPoisonAmount/ 2) +Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) \ No newline at end of file From 62b51d66c77308e630196186566fb307dcec733e Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 26 Mar 2024 21:01:18 +0000 Subject: [PATCH 28/90] Couple of Fixes Added: MAGICF_REACTIVEARMORTH (010000) MAGICF flag to Sphere.ini to let people decide if reactive armor should reflect two handed weapons. --- Changelog.txt | 3 ++- src/game/CServerConfig.h | 3 ++- src/game/chars/CCharFight.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 23e31feda..db0640a21 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3512,4 +3512,5 @@ Added: New function trigger f_onserver_broadcast. (Issue: #1145) Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReductionAmount to @Hit trigger. (Issue: #1159) LOCAL.ItemPoisonReductionChance = Is the chance that weapon reduce poison morez. (Default 100%) LOCAL.ItemPoisonReductionAmount = Is the amount that weapon reduce. (Default: CurrentPoisonAmount/ 2) -Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) \ No newline at end of file +Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) +Added: MAGICF_REACTIVEARMORTH (010000) MAGICF flag to Sphere.ini to let people decide if reactive armor should reflect two handed weapons. \ No newline at end of file diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 59b719516..b6955c19e 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -160,7 +160,8 @@ enum MAGICFLAGS_TYPE MAGICF_OVERRIDEFIELDS = 0x0001000, // Prevent cast multiple field spells on the same tile, making the new field tile remove the previous field MAGICF_CASTPARALYZED = 0x0002000, // Can cast even if paralyzed MAGICF_NOREFLECTOWN = 0x0004000, // Do not reflect the own spells if the spell reflected from the target. - MAGICF_DELREFLECTOWN = 0x0008000 // Remove reflection instead of damaging himself when NOREFLECTOWN active if the spell reflected from another target. + MAGICF_DELREFLECTOWN = 0x0008000, // Remove reflection instead of damaging himself when NOREFLECTOWN active if the spell reflected from another target. + MAGICF_REACTIVEARMORTH = 0x0010000 // Reactive armor reflect two handed weapons. }; enum REVEALFLAGS_TYPE diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index a489c7398..80bd46d70 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -923,7 +923,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys // Preventing recurrent reflection with DAMAGE_REACTIVE. if ( IsStatFlag(STATF_REACTIVE) && !((uType & DAMAGE_GOD) || (uType & DAMAGE_REACTIVE)) ) { - if ( GetTopDist3D(pSrc) < 2 ) + if (GetTopDist3D(pSrc) < 2 || (IsSetMagicFlags(MAGICF_REACTIVEARMORTH) && GetTopDist3D(pSrc) <= 2)) { CItem* pReactive = LayerFind(LAYER_SPELL_Reactive); From 2dbe9baf312547467d6700b85407606a54318792 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 27 Mar 2024 21:01:23 +0000 Subject: [PATCH 29/90] Couple of Fixes Fixed: Possible fix for accesses and bans not loading for multis. (Issue: #1223) --- Changelog.txt | 5 ++++- src/game/items/CItemMulti.cpp | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Changelog.txt b/Changelog.txt index db0640a21..a019a0747 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3513,4 +3513,7 @@ Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReduction LOCAL.ItemPoisonReductionChance = Is the chance that weapon reduce poison morez. (Default 100%) LOCAL.ItemPoisonReductionAmount = Is the amount that weapon reduce. (Default: CurrentPoisonAmount/ 2) Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) -Added: MAGICF_REACTIVEARMORTH (010000) MAGICF flag to Sphere.ini to let people decide if reactive armor should reflect two handed weapons. \ No newline at end of file +Added: MAGICF_REACTIVEARMORTH (010000) MAGICF flag to Sphere.ini to let people decide if reactive armor should reflect two handed weapons. + +27-03-2024, xwerswoodx +Fixed: Possible fix for accesses and bans not loading for multis. (Issue: #1223) \ No newline at end of file diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index 7e793334f..f5d30e774 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -2539,6 +2539,7 @@ void CItemMulti::r_Write(CScript & s) } } } + if (!_lFriends.empty()) { for (const CUID& uid : _lFriends) @@ -2550,6 +2551,24 @@ void CItemMulti::r_Write(CScript & s) } } + if (!_lAccesses.empty()) + { + for (const CUID& uid : _lAccesses) + { + if (uid.IsValidUID()) + s.WriteKeyHex("ADDACCESS", (dword)uid); + } + } + + if (!_lBans.empty()) + { + for (const CUID& uid : _lBans) + { + if (uid.IsValidUID()) + s.WriteKeyHex("ADDBANS", (dword)uid); + } + } + if (!_lComps.empty()) { for (const CUID& uid : _lComps) From 4240b0f672a80e174db2d61b23a2cdaf17a453ed Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 27 Mar 2024 21:04:23 +0000 Subject: [PATCH 30/90] Update CItemMulti.cpp --- src/game/items/CItemMulti.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index f5d30e774..4afc7b6a2 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -2565,7 +2565,7 @@ void CItemMulti::r_Write(CScript & s) for (const CUID& uid : _lBans) { if (uid.IsValidUID()) - s.WriteKeyHex("ADDBANS", (dword)uid); + s.WriteKeyHex("ADDBAN", (dword)uid); } } From 6bc46464f114fcbcf314006d5f1da0ac1c3a6aab Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 27 Mar 2024 23:04:27 +0000 Subject: [PATCH 31/90] Couple of Fixes Fixed: Possible fix for wrong damage calculation of slayer bonus damage. (Issue: #1179) --- Changelog.txt | 3 ++- src/game/chars/CCharFight.cpp | 22 +++++++++++----------- src/game/components/CCFaction.cpp | 3 +-- src/game/components/CCFaction.h | 10 +++++----- src/game/items/CItem.cpp | 3 ++- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index a019a0747..f813be44c 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3516,4 +3516,5 @@ Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. ( Added: MAGICF_REACTIVEARMORTH (010000) MAGICF flag to Sphere.ini to let people decide if reactive armor should reflect two handed weapons. 27-03-2024, xwerswoodx -Fixed: Possible fix for accesses and bans not loading for multis. (Issue: #1223) \ No newline at end of file +Fixed: Possible fix for accesses and bans not loading for multis. (Issue: #1223) +Fixed: Possible fix for wrong damage calculation of slayer bonus damage. (Issue: #1179) \ No newline at end of file diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 80bd46d70..96fdcedf0 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -802,21 +802,21 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys const CCFaction *pSrcFaction = pSrc->GetFaction(); if (pWeapon) { - pSlayer = pWeapon->GetFaction(); - if (pSlayer && pWeapon->GetSlayer()->GetFactionID() != FACTION_NONE) + pSlayer = pWeapon->GetSlayer(); + if (pSlayer && pSlayer->GetFactionID() != FACTION_NONE) { if (m_pNPC) // I'm an NPC attacked (Should the attacker be a player to get the bonus?). { - if (pSlayer->GetFactionID() != FACTION_NONE) + if (pFaction && pFaction->GetFactionID() != FACTION_NONE) { - iDmgBonus = pSlayer->GetSlayerDamageBonus(pWeapon->GetSlayer()); + iDmgBonus = pSlayer->GetSlayerDamageBonus(pFaction); } } else if (m_pPlayer && pSrc->m_pNPC) // Wielding a slayer type against its opposite will cause the attacker to take more damage { - if (pSrcFaction->GetFactionID() != FACTION_NONE) + if (pFaction && pFaction->GetFactionID() != FACTION_NONE) { - iDmgBonus = pSlayer->GetSlayerDamagePenalty(pSrcFaction); + iDmgBonus = pSlayer->GetSlayerDamagePenalty(pFaction); } } } @@ -827,20 +827,20 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys if (pTalisman) { pSlayer = pTalisman->GetSlayer(); - if (pSlayer && pSlayer->GetFactionID() != FACTION_NONE) + if (pSlayer && pSlayer->GetFactionID() != FACTION_NONE) { if (m_pNPC) // I'm an NPC attacked (Should the attacker be a player to get the bonus?). { - if (pFaction->GetFactionID() != FACTION_NONE) + if (pFaction && pFaction->GetFactionID() != FACTION_NONE) { - iDmgBonus = pFaction->GetSlayerDamageBonus(pSlayer); + iDmgBonus = pSlayer->GetSlayerDamageBonus(pFaction); } } else if (m_pPlayer && pSrc->m_pNPC) // Wielding a slayer type against its opposite will cause the attacker to take more damage { - if (pSrcFaction->GetFactionID() != FACTION_NONE) + if (pFaction && pFaction->GetFactionID() != FACTION_NONE) { - iDmgBonus = pFaction->GetSlayerDamagePenalty(pSrcFaction); + iDmgBonus = pSlayer->GetSlayerDamagePenalty(pFaction); } } } diff --git a/src/game/components/CCFaction.cpp b/src/game/components/CCFaction.cpp index 8a5cae485..8a75438c1 100644 --- a/src/game/components/CCFaction.cpp +++ b/src/game/components/CCFaction.cpp @@ -7,8 +7,7 @@ #include "../items/CItem.h" -CFactionDef::CFactionDef() : - _iFaction(FACTION_NONE) +CFactionDef::CFactionDef() : _iFaction(FACTION_NONE) { } diff --git a/src/game/components/CCFaction.h b/src/game/components/CCFaction.h index 7b45a8d18..c9084f89f 100644 --- a/src/game/components/CCFaction.h +++ b/src/game/components/CCFaction.h @@ -15,18 +15,18 @@ class CItem; The Original Slayers fall into 6 groups. Abyss, Arachnid, Elemental, Humanoid, Reptilian and Undead. Each group has a Super Slayer that will increase damage/success on all monsters within that group. Each of those groups have an opposing group. (i.e. Humanoid vs. Undead) - – The opposing group will do double damage to anyone wielding the Slayer. - – Mondain’s Legacy Slayers, usually found on Talismans, do not have an opposing group. + – The opposing group will do double damage to anyone wielding the Slayer. + – Mondain’s Legacy Slayers, usually found on Talismans, do not have an opposing group. A successful use of a Slayer Weapon, Spellbook or Instrument will yield a little white flash on the monster. Super Slayer Weapons will do double damage to the monsters they are meant for. - “Single Slayers” or Slayers that fall into a Super Slayer subcategory will do triple damage + “Single Slayers†or Slayers that fall into a Super Slayer subcategory will do triple damage Slayer Weapons can both be found as monster loot and be crafted by using a runic crafting tool. Slayer Spellbooks will cause single target, direct damage spells to do double damage to the monsters they are meant for. Player written Slayer Spellbooks can only be crafted by scribes with high magery skill using a scribe pen. Slayer Instruments will increase your success chance by 20% when used on the creatures it is meant for. Slayer Instruments will decrease your success chance by 20% when used on the creatures from its opposing group. Slayer Instruments can only be found as monster loot. - Slayer Talismans are found on Mondain’s Legacy monsters or as Quest Rewards. + Slayer Talismans are found on Mondain’s Legacy monsters or as Quest Rewards. */ #define DAMAGE_SLAYER_LESSER 3 // Lesser Slayer does x3 damage. @@ -103,7 +103,7 @@ enum NPC_FACTION : llong FACTION_LIZARDMAN = 0x8000000, FACTION_REPTILIAN_QTY, - // Old Mondain’s Legacy Slayers + // Old Mondain’s Legacy Slayers FACTION_BAT = 0x10000000, FACTION_BEAR = 0x20000000, FACTION_BEETLE = 0x40000000, diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index a66fd91b2..32e31cda1 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -3862,7 +3862,8 @@ bool CItem::SetType(IT_TYPE type, bool fPreCheck) } else if (!pComp) { - SubscribeComponent(new CCFaction()); + CItemBase* pItemDef = Item_GetDef(); + SubscribeComponent(new CCFaction(pItemDef->_pFaction)); } return true; From 4a684b08f61f932b896e654b397de097457e582a Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Thu, 28 Mar 2024 11:38:07 +0000 Subject: [PATCH 32/90] REGION_FLAG_HOUSE Added: REGION_FLAG_HOUSE (0x0100) flag for houses. (Issue: #1154) --- src/game/CRegion.h | 46 ++++++++++++++++------------------- src/game/chars/CCharFight.cpp | 2 +- src/game/items/CItemMulti.cpp | 5 ++++ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/game/CRegion.h b/src/game/CRegion.h index 947ee22d0..5f8d45265 100644 --- a/src/game/CRegion.h +++ b/src/game/CRegion.h @@ -36,32 +36,28 @@ class CRegion : public CResourceDef, public CRegionBase CSString m_sName; // Name of the region. CSString m_sGroup; -#define REGION_ANTIMAGIC_ALL 0x000001 // All magic banned here. -#define REGION_ANTIMAGIC_RECALL_IN 0x000002 // Teleport,recall in to this, and mark -#define REGION_ANTIMAGIC_RECALL_OUT 0x000004 // can't recall out of here. -#define REGION_ANTIMAGIC_GATE 0x000008 -#define REGION_ANTIMAGIC_TELEPORT 0x000010 // Can't teleport into here. -#define REGION_ANTIMAGIC_DAMAGE 0x000020 // just no bad magic here - -#define REGION_FLAG_SHIP 0x000040 // This is a ship region. ship commands -#define REGION_FLAG_NOBUILDING 0x000080 // No building in this area - -#define REGION_FLAG_ANNOUNCE 0x000200 // Announce to all who enter. -#define REGION_FLAG_INSTA_LOGOUT 0x000400 // Instant Log out is allowed here. (hotel) -#define REGION_FLAG_UNDERGROUND 0x000800 // dungeon type area. (no weather) -#define REGION_FLAG_NODECAY 0x001000 // Things on the ground don't decay here. - -#define REGION_FLAG_SAFE 0x002000 // This region is safe from all harm. -#define REGION_FLAG_GUARDED 0x004000 // try TAG.GUARDOWNER -#define REGION_FLAG_NO_PVP 0x008000 // Players cannot directly harm each other here. -#define REGION_FLAG_ARENA 0x010000 // Anything goes. no murder counts or crimes. - -#define REGION_FLAG_NOMINING 0x020000// Can't use mining in this region. -#define REGION_FLAG_WALK_NOBLOCKHEIGHT 0x040000// Ignore char height for walkchecks inside this area. - +#define REGION_ANTIMAGIC_ALL 0x0000001 // All magic banned here. +#define REGION_ANTIMAGIC_RECALL_IN 0x0000002 // Teleport,recall in to this, and mark +#define REGION_ANTIMAGIC_RECALL_OUT 0x0000004 // can't recall out of here. +#define REGION_ANTIMAGIC_GATE 0x0000008 +#define REGION_ANTIMAGIC_TELEPORT 0x0000010 // Can't teleport into here. +#define REGION_ANTIMAGIC_DAMAGE 0x0000020 // just no bad magic here +#define REGION_FLAG_SHIP 0x0000040 // This is a ship region. ship commands +#define REGION_FLAG_NOBUILDING 0x0000080 // No building in this area +#define REGION_FLAG_HOUSE 0x0000100 // This is a house region. +#define REGION_FLAG_ANNOUNCE 0x0000200 // Announce to all who enter. +#define REGION_FLAG_INSTA_LOGOUT 0x0000400 // Instant Log out is allowed here. (hotel) +#define REGION_FLAG_UNDERGROUND 0x0000800 // dungeon type area. (no weather) +#define REGION_FLAG_NODECAY 0x0001000 // Things on the ground don't decay here. +#define REGION_FLAG_SAFE 0x0002000 // This region is safe from all harm. +#define REGION_FLAG_GUARDED 0x0004000 // try TAG.GUARDOWNER +#define REGION_FLAG_NO_PVP 0x0008000 // Players cannot directly harm each other here. +#define REGION_FLAG_ARENA 0x0010000 // Anything goes. no murder counts or crimes. +#define REGION_FLAG_NOMINING 0x0020000 // Can't use mining in this region. +#define REGION_FLAG_WALK_NOBLOCKHEIGHT 0x0040000 // Ignore char height for walkchecks inside this area. #define REGION_FLAG_INHERIT_PARENT_EVENTS 0x0100000 -#define REGION_FLAG_INHERIT_PARENT_FLAGS 0x0200000 -#define REGION_FLAG_INHERIT_PARENT_TAGS 0x0400000 +#define REGION_FLAG_INHERIT_PARENT_FLAGS 0x00200000 +#define REGION_FLAG_INHERIT_PARENT_TAGS 0x00400000 dword m_dwFlags; diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 96fdcedf0..574da963f 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -799,7 +799,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys int iDmgBonus = 1; const CCFaction *pSlayer = nullptr; const CCFaction *pFaction = GetFaction(); - const CCFaction *pSrcFaction = pSrc->GetFaction(); + //const CCFaction *pSrcFaction = pSrc->GetFaction(); if (pWeapon) { pSlayer = pWeapon->GetSlayer(); diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index 4afc7b6a2..367318b36 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -228,6 +228,11 @@ bool CItemMulti::MultiRealizeRegion() { dwFlags |= REGION_FLAG_SHIP; } + else if (IsType(IT_MULTI) || IsType(IT_MULTI_CUSTOM)) + { + if (Multi_GetSign()->IsType(IT_SIGN_GUMP)) + dwFlags |= REGION_FLAG_HOUSE; + } else { dwFlags |= pRegionBack->GetRegionFlags(); // Houses get some of the attribs of the land around it. From 1786757a4b984b2c7c6e60264301be8204cca240 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sat, 30 Mar 2024 13:26:36 +0000 Subject: [PATCH 33/90] @MurderMark Update Added: ARGO object for @MurderMark trigger to get killed character. --- Changelog.txt | 9 +- src/game/chars/CCharNotoriety.cpp | 154 +++++++++++++++--------------- 2 files changed, 83 insertions(+), 80 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index f813be44c..21c0f07c6 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3517,4 +3517,11 @@ Added: MAGICF_REACTIVEARMORTH (010000) MAGICF flag to Sphere.ini to let people d 27-03-2024, xwerswoodx Fixed: Possible fix for accesses and bans not loading for multis. (Issue: #1223) -Fixed: Possible fix for wrong damage calculation of slayer bonus damage. (Issue: #1179) \ No newline at end of file +Fixed: Possible fix for wrong damage calculation of slayer bonus damage. (Issue: #1179) + +28-03-2024, xwerswoodx +Added: REGION_FLAG_HOUSE (0x0100) for houses. (Issue: #1154) + REGION_FLAG_HOUSE 0100 should be added defs. + +30-03-2024, xwerswoodx +Added: ARGO object for @MurderMark trigger to get killed character. \ No newline at end of file diff --git a/src/game/chars/CCharNotoriety.cpp b/src/game/chars/CCharNotoriety.cpp index 7ae807d01..491e5f6f3 100644 --- a/src/game/chars/CCharNotoriety.cpp +++ b/src/game/chars/CCharNotoriety.cpp @@ -552,102 +552,98 @@ void CChar::Noto_Karma( int iKarmaChange, int iBottom, bool fMessage, CChar* pNP void CChar::Noto_Kill(CChar * pKill, int iTotalKillers) { - ADDTOCALLSTACK("CChar::Noto_Kill"); + ADDTOCALLSTACK("CChar::Noto_Kill"); + if (!pKill) + return; - if ( !pKill ) - return; - - // What was their noto to me ? - NOTO_TYPE NotoThem = pKill->Noto_GetFlag( this, false ); + // What was their noto to me ? + NOTO_TYPE NotoThem = pKill->Noto_GetFlag( this, false ); - // Fight is over now that i have won. (if i was fighting at all ) - // ie. Magery cast might not be a "fight" - Fight_Clear(pKill); - if ( pKill == this ) - return; + // Fight is over now that i have won. (if i was fighting at all ) + // ie. Magery cast might not be a "fight" + Fight_Clear(pKill); + if (pKill == this) + return; - if ( m_pNPC ) - { - if ( pKill->m_pNPC ) - { + if ( m_pNPC ) + { + if (pKill->m_pNPC) + { if (m_pNPC->m_Brain == NPCBRAIN_GUARD) // don't create corpse if NPC got killed by a guard { pKill->StatFlag_Set(STATF_CONJURED); return; } - } - } - else if ( NotoThem < NOTO_GUILD_SAME ) - { - // I'm a murderer ! - if ( !IsPriv(PRIV_GM) ) - { - CScriptTriggerArgs args; - args.m_iN1 = m_pPlayer->m_wMurders + 1LL; - args.m_iN2 = true; - args.m_iN3 = false; - - if ( IsTrigUsed(TRIGGER_MURDERMARK) ) - { - OnTrigger(CTRIG_MurderMark, this, &args); - if (args.m_iN1 < 0) - args.m_iN1 = 0; - } + } + } + else if (NotoThem < NOTO_GUILD_SAME) + { + // I'm a murderer ! + if (!IsPriv(PRIV_GM)) + { + CScriptTriggerArgs args; + args.m_iN1 = m_pPlayer->m_wMurders + 1LL; + args.m_iN2 = true; + args.m_iN3 = false; + args.m_pO1 = pKill; - if ( args.m_iN3 < 1 ) - { - m_pPlayer->m_wMurders = (word)(args.m_iN1); - if (args.m_iN2) - Noto_Criminal(); + if ( IsTrigUsed(TRIGGER_MURDERMARK) ) + { + OnTrigger(CTRIG_MurderMark, this, &args); + if (args.m_iN1 < 0) + args.m_iN1 = 0; + } - Noto_Murder(); - } + if (args.m_iN3 < 1) + { + m_pPlayer->m_wMurders = (word)(args.m_iN1); + if (args.m_iN2) + Noto_Criminal(); - NotoSave_Update(); - } - } + Noto_Murder(); + } + NotoSave_Update(); + } + } - // No fame/karma/exp gain on these conditions - if ( NotoThem == NOTO_GUILD_SAME || pKill->IsStatFlag(STATF_CONJURED) ) - return; + // No fame/karma/exp gain on these conditions + if (NotoThem == NOTO_GUILD_SAME || pKill->IsStatFlag(STATF_CONJURED)) + return; - int iPrvLevel = Noto_GetLevel(); // store title before fame/karma changes to check if it got changed - + int iPrvLevel = Noto_GetLevel(); // store title before fame/karma changes to check if it got changed Noto_Fame(g_Cfg.Calc_FameKill(pKill) / iTotalKillers, pKill); Noto_Karma(g_Cfg.Calc_KarmaKill(pKill, NotoThem) / iTotalKillers, INT32_MIN, false, pKill); - if ( g_Cfg.m_bExperienceSystem && (g_Cfg.m_iExperienceMode & EXP_MODE_RAISE_COMBAT) ) - { - int change = (pKill->m_exp / 10) / iTotalKillers; - if ( change ) - { - if ( m_pPlayer && pKill->m_pPlayer ) - change = (change * g_Cfg.m_iExperienceKoefPVP) / 100; - else - change = (change * g_Cfg.m_iExperienceKoefPVM) / 100; - } - - if ( change ) - { - // bonuses of different experiences - if ( (m_exp * 4) < pKill->m_exp ) // 200% [exp < 1/4 of killed] - change *= 2; - else if ( (m_exp * 2) < pKill->m_exp ) // 150% [exp < 1/2 of killed] - change = (change * 3) / 2; - else if ( m_exp <= pKill->m_exp ) // 100% [exp <= killed] - ; - else if ( m_exp < (pKill->m_exp * 2) ) // 50% [exp < 2 * killed] - change /= 2; - else if ( m_exp < (pKill->m_exp * 3) ) // 25% [exp < 3 * killed] - change /= 4; - else // 10% [exp >= 3 * killed] - change /= 10; - } - - ChangeExperience(change, pKill); - } + if (g_Cfg.m_bExperienceSystem && (g_Cfg.m_iExperienceMode & EXP_MODE_RAISE_COMBAT)) + { + int change = (pKill->m_exp / 10) / iTotalKillers; + if (change) + { + if (m_pPlayer && pKill->m_pPlayer) + change = (change * g_Cfg.m_iExperienceKoefPVP) / 100; + else + change = (change * g_Cfg.m_iExperienceKoefPVM) / 100; + } - Noto_ChangeNewMsg(iPrvLevel); // inform any title changes + if (change) + { + // bonuses of different experiences + if ((m_exp * 4) < pKill->m_exp) // 200% [exp < 1/4 of killed] + change *= 2; + else if ((m_exp * 2) < pKill->m_exp) // 150% [exp < 1/2 of killed] + change = (change * 3) / 2; + else if (m_exp <= pKill->m_exp) // 100% [exp <= killed] + ; + else if (m_exp < (pKill->m_exp * 2)) // 50% [exp < 2 * killed] + change /= 2; + else if (m_exp < (pKill->m_exp * 3)) // 25% [exp < 3 * killed] + change /= 4; + else // 10% [exp >= 3 * killed] + change /= 10; + } + ChangeExperience(change, pKill); + } + Noto_ChangeNewMsg(iPrvLevel); // inform any title changes } void CChar::NotoSave_Add( CChar * pChar, NOTO_TYPE value, NOTO_TYPE color ) From c52eea53b444785a7f4b7eb9e4489256f48f2259 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sat, 30 Mar 2024 16:02:33 +0000 Subject: [PATCH 34/90] @RegionResource Fix Fixed: ARGN1 (reap amount) doesn't updated depends on the amount left on bit. (Issue: #1224) Added: ARGO to get bit uid under @ResourceGather and @RegionResourceGather triggers. --- Changelog.txt | 4 +++- src/game/chars/CCharSkill.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Changelog.txt b/Changelog.txt index 21c0f07c6..2d3d74fc0 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3524,4 +3524,6 @@ Added: REGION_FLAG_HOUSE (0x0100) for houses. (Issue: #1154) REGION_FLAG_HOUSE 0100 should be added defs. 30-03-2024, xwerswoodx -Added: ARGO object for @MurderMark trigger to get killed character. \ No newline at end of file +Added: ARGO object for @MurderMark trigger to get killed character. +Fixed: ARGN1 (reap amount) doesn't updated depends on the amount left on bit. (Issue: #1224) +Added: ARGO to get bit uid under @ResourceGather and @RegionResourceGather triggers. \ No newline at end of file diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index ac2bf0f83..e7c72a1c1 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -1009,10 +1009,13 @@ CItem * CChar::Skill_NaturalResource_Create( CItem * pResBit, SKILL_TYPE skill ) if ( wAmount > wMaxAmount ) wAmount = wMaxAmount; } + if (wAmount > pResBit->GetAmount()) + wAmount = pResBit->GetAmount(); //(Region)ResourceGather behaviour CScriptTriggerArgs Args(0, 0, pResBit); Args.m_VarsLocal.SetNum("ResourceID",pOreDef->m_ReapItem); + Args.m_pO1 = pResBit; Args.m_iN1 = wAmount; TRIGRET_TYPE tRet = TRIGRET_RET_DEFAULT; if ( IsTrigUsed(TRIGGER_REGIONRESOURCEGATHER) ) From ceaf0a397734b80e98f0ddebce11d0e1939c2690 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 31 Mar 2024 17:41:15 +0100 Subject: [PATCH 35/90] Multi Invalid Region Fix Fixed: Possible fix for the OnRegionTrigger getting called on invalid region while multi creating/removing. --- Changelog.txt | 5 ++++- src/game/chars/CCharAct.cpp | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 2d3d74fc0..95a546100 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3526,4 +3526,7 @@ Added: REGION_FLAG_HOUSE (0x0100) for houses. (Issue: #1154) 30-03-2024, xwerswoodx Added: ARGO object for @MurderMark trigger to get killed character. Fixed: ARGN1 (reap amount) doesn't updated depends on the amount left on bit. (Issue: #1224) -Added: ARGO to get bit uid under @ResourceGather and @RegionResourceGather triggers. \ No newline at end of file +Added: ARGO to get bit uid under @ResourceGather and @RegionResourceGather triggers. + +31-03-2024, xwerswoodx +Fixed: Possible fix for the OnRegionTrigger getting called on invalid region while multi creating/removing. \ No newline at end of file diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index 6f5746fb6..c0712a39d 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -3618,7 +3618,7 @@ TRIGRET_TYPE CChar::CheckLocation( bool fStanding ) } // This could get REALLY EXPENSIVE ! - if ( IsTrigUsed(TRIGGER_STEP) ) + if ( m_pArea && IsTrigUsed(TRIGGER_STEP) ) //Check if m_pArea is exists because it may be invalid if it try to walk while multi removing? { if ( m_pArea->OnRegionTrigger( this, RTRIG_STEP ) == TRIGRET_RET_TRUE ) return TRIGRET_RET_FALSE; From d7f76141d3868bcb6970a331519c9af7d812452e Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 2 Apr 2024 18:34:57 +0100 Subject: [PATCH 36/90] CAN Flags DWORD to UINT64 Changed: dword CAN flags changed with uint64 to increase limits. --- Changelog.txt | 5 +- src/common/CServerMap.cpp | 100 +++++----- src/common/CServerMap.h | 14 +- src/game/CBase.cpp | 8 +- src/game/CBase.h | 6 +- src/game/CObjBase.cpp | 6 +- src/game/CObjBase.h | 14 +- src/game/CWorldMap.cpp | 250 ++++++++++++------------- src/game/CWorldMap.h | 4 +- src/game/chars/CChar.cpp | 60 +++--- src/game/chars/CChar.h | 8 +- src/game/chars/CCharAct.cpp | 24 +-- src/game/chars/CCharLOS.cpp | 22 +-- src/game/chars/CCharSpell.cpp | 14 +- src/game/chars/CCharStatus.cpp | 104 +++++----- src/game/clients/CClient.cpp | 4 +- src/game/components/CCMultiMovable.cpp | 11 +- src/game/items/CItem.cpp | 10 +- src/game/items/CItem.h | 4 +- src/game/items/CItemBase.cpp | 64 +++---- src/game/items/CItemBase.h | 12 +- src/game/items/CItemMulti.cpp | 8 +- src/game/items/CItemMultiCustom.cpp | 4 +- src/network/send.cpp | 2 +- 24 files changed, 380 insertions(+), 378 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 95a546100..064f0a786 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3529,4 +3529,7 @@ Fixed: ARGN1 (reap amount) doesn't updated depends on the amount left on bit. (I Added: ARGO to get bit uid under @ResourceGather and @RegionResourceGather triggers. 31-03-2024, xwerswoodx -Fixed: Possible fix for the OnRegionTrigger getting called on invalid region while multi creating/removing. \ No newline at end of file +Fixed: Possible fix for the OnRegionTrigger getting called on invalid region while multi creating/removing. + +02-04-2024, xwerswoodx +Changed: dword CAN flags changed with uint64 to increase limits. \ No newline at end of file diff --git a/src/common/CServerMap.cpp b/src/common/CServerMap.cpp index aeb464eb5..8cdda9552 100644 --- a/src/common/CServerMap.cpp +++ b/src/common/CServerMap.cpp @@ -1,4 +1,4 @@ -// +// // CServerMap.cpp // @@ -45,21 +45,21 @@ int64 CCachedMulItem::GetCacheAge() const return (CWorldGameTime::GetCurrentTime().GetTimeRaw() - m_timeRef ); } -CServerMapBlockState::CServerMapBlockState( dword dwBlockFlags, char z, int iHeight, height_t zHeight ) : - m_dwBlockFlags(dwBlockFlags), m_z(z), m_iHeight(iHeight), m_zClimb(0), m_zHeight(zHeight) +CServerMapBlockState::CServerMapBlockState( uint64 uiBlockFlags, char z, int iHeight, height_t zHeight ) : + m_uiBlockFlags(uiBlockFlags), m_z(z), m_iHeight(iHeight), m_zClimb(0), m_zHeight(zHeight) { // m_z = PLAYER_HEIGHT - m_Top.m_dwBlockFlags = 0; + m_Top.m_uiBlockFlags = 0; m_Top.m_dwTile = 0; m_Top.m_z = UO_SIZE_Z; // the z of the item that would be over our head. m_Top.m_height = 0; - m_Bottom.m_dwBlockFlags = CAN_I_BLOCK; // The bottom item has these blocking flags. + m_Bottom.m_uiBlockFlags = CAN_I_BLOCK; // The bottom item has these blocking flags. m_Bottom.m_dwTile = 0; m_Bottom.m_z = UO_SIZE_MIN_Z; // the z we would stand on, m_Bottom.m_height = 0; - m_Lowest.m_dwBlockFlags = CAN_I_BLOCK; + m_Lowest.m_uiBlockFlags = CAN_I_BLOCK; m_Lowest.m_dwTile = 0; m_Lowest.m_z = UO_SIZE_Z; m_Lowest.m_height = 0; @@ -67,20 +67,20 @@ CServerMapBlockState::CServerMapBlockState( dword dwBlockFlags, char z, int iHei m_zClimbHeight = 0; } -CServerMapBlockState::CServerMapBlockState( dword dwBlockFlags, char z, int iHeight, char zClimb, height_t zHeight ) : - m_dwBlockFlags(dwBlockFlags), m_z(z), m_iHeight(iHeight), m_zClimb(zClimb), m_zHeight(zHeight) +CServerMapBlockState::CServerMapBlockState( uint64 uiBlockFlags, char z, int iHeight, char zClimb, height_t zHeight ) : + m_uiBlockFlags(uiBlockFlags), m_z(z), m_iHeight(iHeight), m_zClimb(zClimb), m_zHeight(zHeight) { - m_Top.m_dwBlockFlags = 0; + m_Top.m_uiBlockFlags = 0; m_Top.m_dwTile = 0; m_Top.m_z = UO_SIZE_Z; // the z of the item that would be over our head. m_Top.m_height = 0; - m_Bottom.m_dwBlockFlags = CAN_I_BLOCK; // The bottom item has these blocking flags. + m_Bottom.m_uiBlockFlags = CAN_I_BLOCK; // The bottom item has these blocking flags. m_Bottom.m_dwTile = 0; m_Bottom.m_z = UO_SIZE_MIN_Z; // the z we would stand on, m_Bottom.m_height = 0; - m_Lowest.m_dwBlockFlags = CAN_I_BLOCK; + m_Lowest.m_uiBlockFlags = CAN_I_BLOCK; m_Lowest.m_dwTile = 0; m_Lowest.m_z = UO_SIZE_Z; m_Lowest.m_height = 0; @@ -108,14 +108,14 @@ lpctstr CServerMapBlockState::GetTileName( dword dwID ) // static return pStr; } -bool CServerMapBlockState::CheckTile( dword dwItemBlockFlags, char zBottom, height_t zHeight, dword dwID ) +bool CServerMapBlockState::CheckTile( uint64 uiItemBlockFlags, char zBottom, height_t zHeight, dword dwID ) { ADDTOCALLSTACK("CServerMapBlockState::CheckTile"); // RETURN: // true = continue processing char zTop = zBottom; - if ( (dwItemBlockFlags & CAN_I_CLIMB) ) + if ( (uiItemBlockFlags & CAN_I_CLIMB) ) zTop = minimum(zTop + ( zHeight / 2 ), UO_SIZE_Z); // standing position is half way up climbable items. else zTop = minimum(zTop + zHeight, UO_SIZE_Z); @@ -124,29 +124,29 @@ bool CServerMapBlockState::CheckTile( dword dwItemBlockFlags, char zBottom, heig return true; // hover flag has no effect for non-hovering entities - if ( (dwItemBlockFlags & CAN_I_HOVER) && !(m_dwBlockFlags & CAN_C_HOVER) ) - dwItemBlockFlags &= ~CAN_I_HOVER; + if ( (uiItemBlockFlags & CAN_I_HOVER) && !(m_uiBlockFlags & CAN_C_HOVER) ) + uiItemBlockFlags &= ~CAN_I_HOVER; - if ( ! dwItemBlockFlags ) // no effect. + if ( ! uiItemBlockFlags ) // no effect. return true; // If this item does not block me at all then i guess it just does not count. - if ( ! ( dwItemBlockFlags &~ m_dwBlockFlags )) + if (!(uiItemBlockFlags &~ m_uiBlockFlags)) { // this does not block me. - if ( dwItemBlockFlags & CAN_I_PLATFORM ) // i can always walk on the platform. + if ( uiItemBlockFlags & CAN_I_PLATFORM ) // i can always walk on the platform. zBottom = zTop; - else if ( ! ( dwItemBlockFlags & CAN_I_CLIMB )) + else if (!(uiItemBlockFlags & CAN_I_CLIMB)) zTop = zBottom; // or i could walk under it. } if ( zTop < m_Lowest.m_z ) { - m_Lowest = {dwItemBlockFlags, dwID, zTop, zHeight}; + m_Lowest = {uiItemBlockFlags, dwID, zTop, zHeight}; } // if i can't fit under this anyhow. it is something below me. (potentially) // we can climb a bit higher to reach climbables and platforms - if ( zBottom < (m_z + (( m_iHeight + ((dwItemBlockFlags & (CAN_I_CLIMB|CAN_I_PLATFORM)) ? zHeight : 0) ) / 2)) ) + if ( zBottom < (m_z + (( m_iHeight + ((uiItemBlockFlags & (CAN_I_CLIMB|CAN_I_PLATFORM)) ? zHeight : 0) ) / 2)) ) { // This is the new item ( that would be ) under me. // NOTE: Platform items should take precedence over non-platforms. @@ -155,12 +155,12 @@ bool CServerMapBlockState::CheckTile( dword dwItemBlockFlags, char zBottom, heig { if ( zTop == m_Bottom.m_z ) { - if ( m_Bottom.m_dwBlockFlags & CAN_I_PLATFORM ) + if ( m_Bottom.m_uiBlockFlags & CAN_I_PLATFORM ) return true; - else if ( (m_Bottom.m_dwBlockFlags & CAN_I_WATER) && !(dwItemBlockFlags & CAN_I_PLATFORM)) + else if ( (m_Bottom.m_uiBlockFlags & CAN_I_WATER) && !(uiItemBlockFlags & CAN_I_PLATFORM)) return true; } - m_Bottom = {dwItemBlockFlags, dwID, zTop, zHeight}; + m_Bottom = {uiItemBlockFlags, dwID, zTop, zHeight}; } } else @@ -168,29 +168,29 @@ bool CServerMapBlockState::CheckTile( dword dwItemBlockFlags, char zBottom, heig // I could potentially fit under this. ( it would be above me ) if ( zBottom <= m_Top.m_z ) { - m_Top = {dwItemBlockFlags, dwID, zTop, zHeight}; + m_Top = {uiItemBlockFlags, dwID, zTop, zHeight}; } } return true; } -bool CServerMapBlockState::CheckTile_Item( dword dwItemBlockFlags, char zBottom, height_t zHeight, dword dwID ) +bool CServerMapBlockState::CheckTile_Item( uint64 uiItemBlockFlags, char zBottom, height_t zHeight, dword dwID ) { ADDTOCALLSTACK("CServerMapBlockState::CheckTile_Item"); // RETURN: // true = continue processing // hover flag has no effect for non-hovering entities - if ( (dwItemBlockFlags & CAN_I_HOVER) && !(m_dwBlockFlags & CAN_C_HOVER) ) - dwItemBlockFlags &= ~CAN_I_HOVER; + if ((uiItemBlockFlags & CAN_I_HOVER) && !(m_uiBlockFlags & CAN_C_HOVER)) + uiItemBlockFlags &= ~CAN_I_HOVER; - if ( ! dwItemBlockFlags ) // no effect. + if (!uiItemBlockFlags) // no effect. return true; short zTop = zBottom; - if ( (dwItemBlockFlags & CAN_I_CLIMB) && (dwItemBlockFlags & CAN_I_PLATFORM) ) + if ((uiItemBlockFlags & CAN_I_CLIMB) && (uiItemBlockFlags & CAN_I_PLATFORM)) zTop = minimum(zTop + ( zHeight / 2 ), UO_SIZE_Z); // standing position is half way up climbable items (except platforms). else zTop = minimum(zTop + zHeight, UO_SIZE_Z); @@ -203,7 +203,7 @@ bool CServerMapBlockState::CheckTile_Item( dword dwItemBlockFlags, char zBottom, if ( zTop < m_Lowest.m_z ) { - m_Lowest = {dwItemBlockFlags, dwID, (char)zTop, zHeight}; + m_Lowest = {uiItemBlockFlags, dwID, (char)zTop, zHeight}; } // Why was this block of code added? By returning, it blocks the m_Bottom state to be updated @@ -218,22 +218,22 @@ bool CServerMapBlockState::CheckTile_Item( dword dwItemBlockFlags, char zBottom, } */ - if ( zBottom <= (m_zClimb + ((dwItemBlockFlags & CAN_I_CLIMB) ? zHeight / 2 : 0)) ) + if ( zBottom <= (m_zClimb + ((uiItemBlockFlags & CAN_I_CLIMB) ? zHeight / 2 : 0)) ) { if ( zTop >= m_Bottom.m_z ) { if ( zTop == m_Bottom.m_z ) { - if ((dwItemBlockFlags & CAN_I_PLATFORM) && (m_Bottom.m_height != 0)) + if ((uiItemBlockFlags & CAN_I_PLATFORM) && (m_Bottom.m_height != 0)) ; // this platform (floor?) tile is on the top of a solid item (which has a height != 0), so i should consider as if i'm actually walking on the platform - else if ( dwItemBlockFlags & CAN_I_CLIMB ) // climbable items have the highest priority + else if (uiItemBlockFlags & CAN_I_CLIMB) // climbable items have the highest priority ; - else if ( m_Bottom.m_dwBlockFlags & CAN_I_PLATFORM ) //than items with CAN_I_PLATFORM + else if ( m_Bottom.m_uiBlockFlags & CAN_I_PLATFORM ) //than items with CAN_I_PLATFORM return true; } - m_Bottom = {dwItemBlockFlags, dwID, (char)zTop, zHeight}; + m_Bottom = {uiItemBlockFlags, dwID, (char)zTop, zHeight}; - if ( dwItemBlockFlags & CAN_I_CLIMB ) // return climb height + if (uiItemBlockFlags & CAN_I_CLIMB) // return climb height m_zClimbHeight = (( zHeight + 1 )/2); //if height is an odd number, then we need to add 1; if it isn't, this does nothing else m_zClimbHeight = 0; @@ -246,29 +246,29 @@ bool CServerMapBlockState::CheckTile_Item( dword dwItemBlockFlags, char zBottom, { return true; }*/ -/* else if (wItemBlockFlags &~(m_dwBlockFlags)) // if this does not block me... (here CAN_I_CLIMB = CAN_C_FLY makes sense, as we cannot reach the climbable) +/* else if (uiItemBlockFlags &~(m_uiBlockFlags)) // if this does not block me... (here CAN_I_CLIMB = CAN_C_FLY makes sense, as we cannot reach the climbable) { - if (!(wItemBlockFlags & (CAN_I_PLATFORM | CAN_I_ROOF))) // if it is not a platform or roof, skip + if (!(uiItemBlockFlags & (CAN_I_PLATFORM | CAN_I_ROOF))) // if it is not a platform or roof, skip { return true; } }*/ if ( zBottom < m_Top.m_z ) { - m_Top = {dwItemBlockFlags, dwID, zBottom, zHeight}; + m_Top = {uiItemBlockFlags, dwID, zBottom, zHeight}; } } return true; } -bool CServerMapBlockState::CheckTile_Terrain( dword dwItemBlockFlags, char z, dword dwID ) +bool CServerMapBlockState::CheckTile_Terrain( uint64 uiItemBlockFlags, char z, dword dwID ) { ADDTOCALLSTACK("CServerMapBlockState::CheckTile_Terrain"); // RETURN: // true = i can step on it, so continue processing - if ( ! dwItemBlockFlags ) // no effect. + if (!uiItemBlockFlags) // no effect. return true; if ( z < m_Bottom.m_z ) // below something i can already step on. @@ -276,20 +276,20 @@ bool CServerMapBlockState::CheckTile_Terrain( dword dwItemBlockFlags, char z, dw if ( z < m_Lowest.m_z ) { - m_Lowest = {dwItemBlockFlags, dwID, z, 0}; + m_Lowest = {uiItemBlockFlags, dwID, z, 0}; } if ( z <= m_iHeight ) { if ( z >= m_Bottom.m_z ) { - if ( (m_Bottom.m_dwBlockFlags & (CAN_I_PLATFORM|CAN_I_CLIMB)) && (z - m_Bottom.m_z <= 4) ) + if ( (m_Bottom.m_uiBlockFlags & (CAN_I_PLATFORM|CAN_I_CLIMB)) && (z - m_Bottom.m_z <= 4) ) return true; if ( z > m_z + PLAYER_HEIGHT/2 ) { - if ( (m_Bottom.m_dwBlockFlags & (CAN_I_PLATFORM|CAN_I_CLIMB)) && (z >= m_Bottom.m_z + PLAYER_HEIGHT/2) ) // we can walk under it + if ( (m_Bottom.m_uiBlockFlags & (CAN_I_PLATFORM|CAN_I_CLIMB)) && (z >= m_Bottom.m_z + PLAYER_HEIGHT/2) ) // we can walk under it { - m_Top = {dwItemBlockFlags, dwID, z, 0}; + m_Top = {uiItemBlockFlags, dwID, z, 0}; return true; } } @@ -297,18 +297,18 @@ bool CServerMapBlockState::CheckTile_Terrain( dword dwItemBlockFlags, char z, dw { if (m_Bottom.m_height != 0) ; // this land tile is on the top of a solid item (which has a height != 0), so i should consider as if i'm actually walking on the landtile - else if ( (m_Bottom.m_dwBlockFlags & (CAN_I_PLATFORM|CAN_I_CLIMB)) && (z - m_Bottom.m_z <= 4) ) + else if ((m_Bottom.m_uiBlockFlags & (CAN_I_PLATFORM|CAN_I_CLIMB)) && (z - m_Bottom.m_z <= 4)) return true; } //DEBUG_ERR(("wItemBlockFlags 0x%x\n",wItemBlockFlags)); - m_Bottom = {dwItemBlockFlags, dwID, z, 0}; + m_Bottom = {uiItemBlockFlags, dwID, z, 0}; m_zClimbHeight = 0; } } - else if ( z < m_Top.m_z ) + else if (z < m_Top.m_z) { // I could potentially fit under this. ( it would be above me ) - m_Top = {dwItemBlockFlags, dwID, z, 0}; + m_Top = {uiItemBlockFlags, dwID, z, 0}; } return true; } diff --git a/src/common/CServerMap.h b/src/common/CServerMap.h index ae8473229..ef33a88ea 100644 --- a/src/common/CServerMap.h +++ b/src/common/CServerMap.h @@ -73,7 +73,7 @@ class CServerStaticsBlock struct CServerMapBlocker { - dword m_dwBlockFlags; // How does this item block ? CAN_I_PLATFORM + uint64 m_uiBlockFlags; // How does this item block ? CAN_I_PLATFORM dword m_dwTile; // TERRAIN_QTY + id. char m_z; // Top (z + ((climbable item) ? height/2 : height)) of a solid object, or bottom (z) of non blocking one. height_t m_height; // The actual height of the item (0 if terrain) @@ -91,7 +91,7 @@ struct CServerMapBlockState // CAN_C_FIRE_IMMUNE = i can walk into lava etc. - CAN_I_FIRE = UFLAG1_DAMAGE // CAN_C_HOVER = i can follow hover routes. - CAN_I_HOVER = UFLAG4_HOVEROVER - const dword m_dwBlockFlags; // The block flags we (the specific char who requested this class instance) can overcome. + const uint64 m_uiBlockFlags; // The block flags we (the specific char who requested this class instance) can overcome. const char m_z; // the z we start at. (stay at if we are flying) const int m_iHeight; // The height we need to stand here. const char m_zClimb; // We can climb at this height @@ -103,17 +103,17 @@ struct CServerMapBlockState CServerMapBlocker m_Lowest; // the lowest item we have found. public: - CServerMapBlockState( dword dwBlockFlags, char m_z, int iHeight = PLAYER_HEIGHT, height_t zHeight = PLAYER_HEIGHT ); - CServerMapBlockState( dword dwBlockFlags, char m_z, int iHeight, char zClimb, height_t zHeight = PLAYER_HEIGHT ); + CServerMapBlockState( uint64 uiBlockFlags, char m_z, int iHeight = PLAYER_HEIGHT, height_t zHeight = PLAYER_HEIGHT ); + CServerMapBlockState( uint64 uiBlockFlags, char m_z, int iHeight, char zClimb, height_t zHeight = PLAYER_HEIGHT ); private: CServerMapBlockState(const CServerMapBlockState& copy); CServerMapBlockState& operator=(const CServerMapBlockState& other); public: - bool CheckTile( dword dwItemBlockFlags, char zBottom, height_t zheight, dword wID ); - bool CheckTile_Item( dword dwItemBlockFlags, char zBottom, height_t zheight, dword wID ); - bool CheckTile_Terrain( dword dwItemBlockFlags, char z, dword dwID ); + bool CheckTile( uint64 uiItemBlockFlags, char zBottom, height_t zheight, dword wID ); + bool CheckTile_Item( uint64 uiItemBlockFlags, char zBottom, height_t zheight, dword wID ); + bool CheckTile_Terrain( uint64 uiItemBlockFlags, char z, dword dwID ); static lpctstr GetTileName( dword dwID ); }; diff --git a/src/game/CBase.cpp b/src/game/CBase.cpp index 2991258bb..9c65ea33c 100644 --- a/src/game/CBase.cpp +++ b/src/game/CBase.cpp @@ -82,9 +82,9 @@ void CBaseBaseDef::SetTypeName( lpctstr pszName ) m_sName = pszName; } -bool CBaseBaseDef::Can( dword dwCan ) const +bool CBaseBaseDef::Can( uint64 uiCan ) const { - return (m_Can & dwCan); + return (m_Can & uiCan); } void CBaseBaseDef::UnLink() @@ -196,7 +196,7 @@ bool CBaseBaseDef::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * p sVal = g_Cfg.ResourceGetName( GetResourceID()); break; case OBC_CAN: - sVal.FormatHex(m_Can); + sVal.FormatULLHex(m_Can); break; case OBC_HASCOMPONENTPROPS: @@ -374,7 +374,7 @@ bool CBaseBaseDef::r_LoadVal( CScript & s ) case OBC_BASEID: return false; case OBC_CAN: - m_Can = s.GetArgDWVal(); // | ( m_Can & ( CAN_C_INDOORS|CAN_C_EQUIP|CAN_C_USEHANDS|CAN_C_NONHUMANOID )); //Fixed #2326 ? + m_Can = s.GetArgULLVal(); // | ( m_Can & ( CAN_C_INDOORS|CAN_C_EQUIP|CAN_C_USEHANDS|CAN_C_NONHUMANOID )); //Fixed #2326 ? return true; case OBC_DEFNAME: diff --git a/src/game/CBase.h b/src/game/CBase.h index 8dbbf24cd..a390f9dd4 100644 --- a/src/game/CBase.h +++ b/src/game/CBase.h @@ -52,7 +52,7 @@ struct CBaseBaseDef : public CResourceLink, public CEntityProps word m_defenseBase; // base defense bonus given by this (items)/having (chars). word m_defenseRange; // variable range of defense. - dword m_Can; // Base attribute flags. CAN_C_GHOST, etc + uint64 m_Can; // Base attribute flags. CAN_C_GHOST, etc RESDISPLAY_VERSION _iEraLimitProps; // Don't allow to have properties newer than the given era. CCFaction _pFaction; @@ -238,10 +238,10 @@ struct CBaseBaseDef : public CResourceLink, public CEntityProps /** * @brief Has the given Can flag. - * @param dwCan The can flags. + * @param uiCan The can flags. * @return true if it succeeds, false if it fails. */ - bool Can( dword dwCan ) const; + bool Can( uint64 uiCan ) const; /** * @brief Un link. diff --git a/src/game/CObjBase.cpp b/src/game/CObjBase.cpp index 50e6cc8dc..3ab2b37ab 100644 --- a/src/game/CObjBase.cpp +++ b/src/game/CObjBase.cpp @@ -1014,10 +1014,10 @@ bool CObjBase::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc, } } break; case OC_CAN: - sVal.FormatHex( GetCanFlags() ); + sVal.FormatULLHex( GetCanFlags() ); break; case OC_CANMASK: - sVal.FormatHex( m_CanMask ); + sVal.FormatULLHex( m_CanMask ); break; case OC_MODMAXWEIGHT: sVal.FormatVal(m_ModMaxWeight); @@ -1805,7 +1805,7 @@ bool CObjBase::r_LoadVal( CScript & s ) return false; case OC_CANMASK: { - m_CanMask = s.GetArgDWVal(); + m_CanMask = s.GetArgULLVal(); if (IsItem()) { CItem* pItem = static_cast(this); diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index 5ff8923f6..c73595956 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -54,7 +54,7 @@ class CObjBase : public CObjBaseTemplate, public CScriptObj, public CEntity, pub CVarDefMap m_TagDefs; // attach extra tags here. CVarDefMap m_BaseDefs; // New Variable storage system - dword m_CanMask; // Mask to be XORed to Can: enable or disable some Can Flags + uint64 m_CanMask; // Mask to be XORed to Can: enable or disable some Can Flags word m_attackBase; // dam for weapons word m_attackRange; // variable range of attack damage. @@ -115,12 +115,12 @@ public: virtual bool IsDeleted() const override; */ CBaseBaseDef* Base_GetDef() const noexcept; - inline dword GetCanFlagsBase() const noexcept + inline uint64 GetCanFlagsBase() const noexcept { return Base_GetDef()->m_Can; } - inline dword GetCanFlags() const noexcept + inline uint64 GetCanFlags() const noexcept { // m_CanMask is XORed to m_Can: // If a flag in m_CanMask is enabled in m_Can, it is ignored in this Can check @@ -129,14 +129,14 @@ public: virtual bool IsDeleted() const override; return (GetCanFlagsBase() ^ m_CanMask); } - bool Can(dword dwCan) const noexcept + bool Can(uint64 uiCan) const noexcept { - return (GetCanFlags() & dwCan); + return (GetCanFlags() & uiCan); } - inline bool Can(dword dwCan, dword dwObjCanFlags) const noexcept + inline bool Can(uint64 uiCan, uint64 uiObjCanFlags) const noexcept { - return (dwObjCanFlags & dwCan); + return (uiObjCanFlags & uiCan); } bool IsRunningTrigger() const; diff --git a/src/game/CWorldMap.cpp b/src/game/CWorldMap.cpp index 1549f3326..7ddf51b6f 100644 --- a/src/game/CWorldMap.cpp +++ b/src/game/CWorldMap.cpp @@ -907,7 +907,7 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) CItemBase * pItemDef = nullptr; CItemBaseDupe * pDupeDef = nullptr; CItem * pItem = nullptr; - dword dwBlockThis = 0; + uint64 uiBlockThis = 0; char z = 0; int x2 = 0, y2 = 0; @@ -940,8 +940,8 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) { if (pItemDef->GetID() == iDispID) //parent item { - dwBlockThis = (pItemDef->m_Can & CAN_I_MOVEMASK); - z += ((dwBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); + uiBlockThis = (pItemDef->m_Can & CAN_I_MOVEMASK); + z += ((uiBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); } else //non-parent item { @@ -949,33 +949,33 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) if ( ! pDupeDef ) { g_Log.EventDebug("Failed to get non-parent reference (static) (DispID 0%x) (X: %d Y: %d Z: %d)\n",iDispID,pStatic->m_x+pMapBlock->m_x,pStatic->m_y+pMapBlock->m_y,pStatic->m_z); - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); - z += ((dwBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); + uiBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); + z += ((uiBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); } else { - dwBlockThis = (pDupeDef->m_Can & CAN_I_MOVEMASK); - z += ((dwBlockThis & CAN_I_CLIMB) ? pDupeDef->GetHeight()/2 : pDupeDef->GetHeight()); + uiBlockThis = (pDupeDef->m_Can & CAN_I_MOVEMASK); + z += ((uiBlockThis & CAN_I_CLIMB) ? pDupeDef->GetHeight()/2 : pDupeDef->GetHeight()); } } } else if ( iDispID ) { - CItemBase::GetItemTiledataFlags(&dwBlockThis, iDispID); + CItemBase::GetItemTiledataFlags(&uiBlockThis, iDispID); } if (block.m_Bottom.m_z < z) { - if ((z < pt.m_z + PLAYER_HEIGHT) && (dwBlockThis & (CAN_I_PLATFORM|CAN_I_CLIMB|CAN_I_WATER))) + if ((z < pt.m_z + PLAYER_HEIGHT) && (uiBlockThis & (CAN_I_PLATFORM|CAN_I_CLIMB|CAN_I_WATER))) { - block.m_Bottom.m_dwBlockFlags = dwBlockThis; + block.m_Bottom.m_uiBlockFlags = uiBlockThis; block.m_Bottom.m_dwTile = iDispID + (ITEMID_TYPE)TERRAIN_QTY; block.m_Bottom.m_z = z; // Leave block->...->m_height unchanged, since it already has the height of the char/item } else if (block.m_Top.m_z > z) { - block.m_Top.m_dwBlockFlags = dwBlockThis; + block.m_Top.m_uiBlockFlags = uiBlockThis; block.m_Top.m_dwTile = iDispID + (ITEMID_TYPE)TERRAIN_QTY; block.m_Top.m_z = z; // Leave block->...->m_height unchanged, since it already has the height of the char/item @@ -987,7 +987,7 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) pItemDef = nullptr; pDupeDef = nullptr; pItem = nullptr; - dwBlockThis = 0; + uiBlockThis = 0; z = 0; x2 = y2 = 0; iQty = 0; @@ -1042,8 +1042,8 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) { if ( pItemDef->GetID() == iDispID ) //parent item { - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); - z += ((dwBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); + uiBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); + z += ((uiBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); } else //non-parent item { @@ -1051,33 +1051,33 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) if ( pDupeDef == nullptr ) { g_Log.EventDebug("Failed to get non-parent reference (multi) (DispID 0%x) (X: %d Y: %d Z: %d)\n",iDispID,pMultiItem->m_dx+pItem->GetTopPoint().m_x,pMultiItem->m_dy+pItem->GetTopPoint().m_y,pMultiItem->m_dz+pItem->GetTopPoint().m_z); - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); - z += ((dwBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); + uiBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); + z += ((uiBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); } else { - dwBlockThis = ( pDupeDef->m_Can & CAN_I_MOVEMASK ); - z += ((dwBlockThis & CAN_I_CLIMB) ? pDupeDef->GetHeight()/2 : pDupeDef->GetHeight()); + uiBlockThis = ( pDupeDef->m_Can & CAN_I_MOVEMASK ); + z += ((uiBlockThis & CAN_I_CLIMB) ? pDupeDef->GetHeight()/2 : pDupeDef->GetHeight()); } } } else if ( iDispID ) { - CItemBase::GetItemTiledataFlags(&dwBlockThis, iDispID); + CItemBase::GetItemTiledataFlags(&uiBlockThis, iDispID); } if (block.m_Bottom.m_z < z) { - if ((z < pt.m_z + PLAYER_HEIGHT) && (dwBlockThis & (CAN_I_PLATFORM|CAN_I_CLIMB|CAN_I_WATER))) + if ((z < pt.m_z + PLAYER_HEIGHT) && (uiBlockThis & (CAN_I_PLATFORM|CAN_I_CLIMB|CAN_I_WATER))) { - block.m_Bottom.m_dwBlockFlags = dwBlockThis; + block.m_Bottom.m_uiBlockFlags = uiBlockThis; block.m_Bottom.m_dwTile = iDispID + (ITEMID_TYPE)TERRAIN_QTY; block.m_Bottom.m_z = z; // Leave block->...->m_height unchanged, since it already has the height of the char/item } else if (block.m_Top.m_z > z) { - block.m_Top.m_dwBlockFlags = dwBlockThis; + block.m_Top.m_uiBlockFlags = uiBlockThis; block.m_Top.m_dwTile = iDispID + (ITEMID_TYPE)TERRAIN_QTY; block.m_Top.m_z = z; // Leave block->...->m_height unchanged, since it already has the height of the char/item @@ -1092,7 +1092,7 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) pItemDef = nullptr; pDupeDef = nullptr; pItem = nullptr; - dwBlockThis = 0; + uiBlockThis = 0; x2 = y2 = 0; iQty = 0; z = 0; @@ -1117,8 +1117,8 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) { if ( pItemDef->GetDispID() == iDispID )//parent item { - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); - z += ((dwBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); + uiBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); + z += ((uiBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); } else //non-parent item { @@ -1126,28 +1126,28 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) if ( ! pDupeDef ) { g_Log.EventDebug("Failed to get non-parent reference (dynamic) (DispID 0%x) (X: %d Y: %d Z: %d)\n",iDispID,pItem->GetTopPoint().m_x,pItem->GetTopPoint().m_y,pItem->GetTopPoint().m_z); - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); - z += ((dwBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); + uiBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); + z += ((uiBlockThis & CAN_I_CLIMB) ? pItemDef->GetHeight()/2 : pItemDef->GetHeight()); } else { - dwBlockThis = ( pDupeDef->m_Can & CAN_I_MOVEMASK ); - z += ((dwBlockThis & CAN_I_CLIMB) ? pDupeDef->GetHeight()/2 : pDupeDef->GetHeight()); + uiBlockThis = ( pDupeDef->m_Can & CAN_I_MOVEMASK ); + z += ((uiBlockThis & CAN_I_CLIMB) ? pDupeDef->GetHeight()/2 : pDupeDef->GetHeight()); } } if ( block.m_Bottom.m_z < z ) { - if ( (z < pt.m_z + PLAYER_HEIGHT) && (dwBlockThis & (CAN_I_PLATFORM|CAN_I_CLIMB|CAN_I_WATER)) ) + if ( (z < pt.m_z + PLAYER_HEIGHT) && (uiBlockThis & (CAN_I_PLATFORM|CAN_I_CLIMB|CAN_I_WATER)) ) { - block.m_Bottom.m_dwBlockFlags = dwBlockThis; + block.m_Bottom.m_uiBlockFlags = uiBlockThis; block.m_Bottom.m_dwTile = pItemDef->GetDispID() + (ITEMID_TYPE)TERRAIN_QTY; block.m_Bottom.m_z = z; // Leave block->...->m_height unchanged, since it already has the height of the char/item } else if ( block.m_Top.m_z > z ) { - block.m_Top.m_dwBlockFlags = dwBlockThis; + block.m_Top.m_uiBlockFlags = uiBlockThis; block.m_Top.m_dwTile = pItemDef->GetDispID() + (ITEMID_TYPE)TERRAIN_QTY; block.m_Top.m_z = z; // Leave block->...->m_height unchanged, since it already has the height of the char/item @@ -1156,11 +1156,11 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) } else if (iDispID) { - CItemBase::GetItemTiledataFlags(&dwBlockThis, pItem->GetDispID()); + CItemBase::GetItemTiledataFlags(&uiBlockThis, pItem->GetDispID()); } } - dwBlockThis = 0; + uiBlockThis = 0; // Terrain height is screwed. Since it is related to all the terrain around it. const CUOMapMeter * pMeter = pMapBlock->GetTerrain( UO_BLOCK_OFFSET(pt.m_x), UO_BLOCK_OFFSET(pt.m_y) ); if ( ! pMeter ) @@ -1168,38 +1168,38 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) if ( pMeter->m_wTerrainIndex == TERRAIN_HOLE ) { - dwBlockThis = 0; + uiBlockThis = 0; } else if ( CUOMapMeter::IsTerrainNull( pMeter->m_wTerrainIndex ) ) // inter dungeon type. { - dwBlockThis = CAN_I_BLOCK; + uiBlockThis = CAN_I_BLOCK; } else { CUOTerrainInfo land( pMeter->m_wTerrainIndex ); //DEBUG_ERR(("Terrain flags - land.m_flags 0%x dwBlockThis (0%x)\n",land.m_flags,dwBlockThis)); if ( land.m_flags & UFLAG1_WATER ) - dwBlockThis |= CAN_I_WATER; + uiBlockThis |= CAN_I_WATER; if ( land.m_flags & UFLAG1_DAMAGE ) - dwBlockThis |= CAN_I_FIRE; + uiBlockThis |= CAN_I_FIRE; if ( land.m_flags & UFLAG1_BLOCK ) - dwBlockThis |= CAN_I_BLOCK; - if (( ! dwBlockThis ) || ( land.m_flags & UFLAG2_PLATFORM )) // Platform items should take precendence over non-platforms. - dwBlockThis = CAN_I_PLATFORM; + uiBlockThis |= CAN_I_BLOCK; + if ((!uiBlockThis) || ( land.m_flags & UFLAG2_PLATFORM )) // Platform items should take precendence over non-platforms. + uiBlockThis = CAN_I_PLATFORM; } if (block.m_Bottom.m_z < pMeter->m_z) { - if (((pMeter->m_z < pt.m_z + PLAYER_HEIGHT) && (dwBlockThis & (CAN_I_PLATFORM|CAN_I_CLIMB|CAN_I_WATER))) || (block.m_Bottom.m_z == UO_SIZE_MIN_Z)) + if (((pMeter->m_z < pt.m_z + PLAYER_HEIGHT) && (uiBlockThis & (CAN_I_PLATFORM|CAN_I_CLIMB|CAN_I_WATER))) || (block.m_Bottom.m_z == UO_SIZE_MIN_Z)) { - block.m_Bottom.m_dwBlockFlags = dwBlockThis; + block.m_Bottom.m_uiBlockFlags = uiBlockThis; block.m_Bottom.m_dwTile = pMeter->m_wTerrainIndex; block.m_Bottom.m_z = pMeter->m_z; // Leave block->...->m_height unchanged, since it already has the height of the char/item } else if (block.m_Top.m_z > pMeter->m_z) { - block.m_Top.m_dwBlockFlags = dwBlockThis; + block.m_Top.m_uiBlockFlags = uiBlockThis; block.m_Top.m_dwTile = pMeter->m_wTerrainIndex; block.m_Top.m_z = pMeter->m_z; // Leave block->...->m_height unchanged, since it already has the height of the char/item @@ -1209,11 +1209,11 @@ void CWorldMap::GetFixPoint( const CPointMap & pt, CServerMapBlockState & block) if ( block.m_Bottom.m_z == UO_SIZE_MIN_Z ) { //Fail safe... Reset to 0z with no top block; - block.m_Bottom.m_dwBlockFlags = 0; + block.m_Bottom.m_uiBlockFlags = 0; block.m_Bottom.m_dwTile = 0; block.m_Bottom.m_z = 0; // Leave block->...->m_height unchanged, since it already has the height of the char/item - block.m_Top.m_dwBlockFlags = 0; + block.m_Top.m_uiBlockFlags = 0; block.m_Top.m_dwTile = 0; block.m_Top.m_z = UO_SIZE_Z; } @@ -1225,7 +1225,7 @@ void CWorldMap::GetHeightPoint(const CPointMap & pt, CServerMapBlockState & bloc const CItemBase * pItemDef = nullptr; const CItemBaseDupe * pDupeDef = nullptr; CItem * pItem = nullptr; - dword dwBlockThis = 0; + uint64 uiBlockThis = 0; char z = 0; height_t zHeight = 0; int x2 = 0, y2 = 0; @@ -1261,7 +1261,7 @@ void CWorldMap::GetHeightPoint(const CPointMap & pt, CServerMapBlockState & bloc if ( pItemDef->GetID() == iDispID ) //parent item { zHeight = pItemDef->GetHeight(); - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); //Use only Block flags, other remove + uiBlockThis = (pItemDef->m_Can & CAN_I_MOVEMASK); //Use only Block flags, other remove } else //non-parent item { @@ -1270,32 +1270,32 @@ void CWorldMap::GetHeightPoint(const CPointMap & pt, CServerMapBlockState & bloc { g_Log.EventDebug("Failed to get non-parent reference (static) (DispID 0%x) (X: %d Y: %d Z: %d)\n",iDispID,pStatic->m_x+pMapBlock->m_x,pStatic->m_y+pMapBlock->m_y,pStatic->m_z); zHeight = pItemDef->GetHeight(); - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); + uiBlockThis = (pItemDef->m_Can & CAN_I_MOVEMASK); } else { zHeight = pDupeDef->GetHeight(); - dwBlockThis = ( pDupeDef->m_Can & CAN_I_MOVEMASK ); //Use only Block flags, other remove - CAN flags cannot be inherited from the parent item due to bad script pack... + uiBlockThis = (pDupeDef->m_Can & CAN_I_MOVEMASK); //Use only Block flags, other remove - CAN flags cannot be inherited from the parent item due to bad script pack... } } } else if ( iDispID ) { - CItemBase::GetItemTiledataFlags(&dwBlockThis, iDispID); + CItemBase::GetItemTiledataFlags(&uiBlockThis, iDispID); } //DEBUG_ERR(("z (%d) block.m_iHeight (%d) block.m_Bottom.m_z (%d)\n",z,block.m_iHeight,block.m_Bottom.m_z)); // This static is at the coordinates in question. // enough room for me to stand here ? - block.CheckTile_Item( dwBlockThis, z, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY ); + block.CheckTile_Item(uiBlockThis, z, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY); } } pItemDef = nullptr; pDupeDef = nullptr; pItem = nullptr; - dwBlockThis = 0; + uiBlockThis = 0; z = 0; zHeight = 0; x2 = y2 = 0; @@ -1355,7 +1355,7 @@ void CWorldMap::GetHeightPoint(const CPointMap & pt, CServerMapBlockState & bloc if ( pItemDef->GetID() == iDispID ) //parent item { zHeight = pItemDef->GetHeight(); - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); //Use only Block flags, other remove + uiBlockThis = (pItemDef->m_Can & CAN_I_MOVEMASK); //Use only Block flags, other remove } else //non-parent item { @@ -1365,21 +1365,21 @@ void CWorldMap::GetHeightPoint(const CPointMap & pt, CServerMapBlockState & bloc g_Log.EventDebug("Failed to get non-parent reference (multi) (DispID 0%x) (X: %d Y: %d Z: %d)\n", iDispID, pMultiItem->m_dx + ptItemTop.m_x, pMultiItem->m_dy + ptItemTop.m_y, pMultiItem->m_dz + ptItemTop.m_z); zHeight = pItemDef->GetHeight(); - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); + uiBlockThis = (pItemDef->m_Can & CAN_I_MOVEMASK); } else { zHeight = pDupeDef->GetHeight(); - dwBlockThis = ( pDupeDef->m_Can & CAN_I_MOVEMASK ); //Use only Block flags, other remove - CAN flags cannot be inherited from the parent item due to bad script pack... + uiBlockThis = (pDupeDef->m_Can & CAN_I_MOVEMASK); //Use only Block flags, other remove - CAN flags cannot be inherited from the parent item due to bad script pack... } } } else if ( iDispID ) { - CItemBase::GetItemTiledataFlags(&dwBlockThis, iDispID); + CItemBase::GetItemTiledataFlags(&uiBlockThis, iDispID); } - block.CheckTile_Item( dwBlockThis, z, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY ); + block.CheckTile_Item(uiBlockThis, z, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY); } } } @@ -1390,7 +1390,7 @@ void CWorldMap::GetHeightPoint(const CPointMap & pt, CServerMapBlockState & bloc pItemDef = nullptr; pDupeDef = nullptr; pItem = nullptr; - dwBlockThis = 0; + uiBlockThis = 0; x2 = y2 = 0; iQty = 0; zHeight = 0; @@ -1417,7 +1417,7 @@ void CWorldMap::GetHeightPoint(const CPointMap & pt, CServerMapBlockState & bloc if ( pItemDef->GetDispID() == iDispID )//parent item { zHeight = pItemDef->GetHeight(); - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); //Use only Block flags, other remove + uiBlockThis = (pItemDef->m_Can & CAN_I_MOVEMASK); //Use only Block flags, other remove } else //non-parent item { @@ -1426,24 +1426,24 @@ void CWorldMap::GetHeightPoint(const CPointMap & pt, CServerMapBlockState & bloc { g_Log.EventDebug("Failed to get non-parent reference (dynamic) (DispID 0%x) (X: %d Y: %d Z: %d)\n",iDispID,pItem->GetTopPoint().m_x,pItem->GetTopPoint().m_y,pItem->GetTopPoint().m_z); zHeight = pItemDef->GetHeight(); - dwBlockThis = ( pItemDef->m_Can & CAN_I_MOVEMASK ); + uiBlockThis = (pItemDef->m_Can & CAN_I_MOVEMASK); } else { zHeight = pDupeDef->GetHeight(); - dwBlockThis = ( pDupeDef->m_Can & CAN_I_MOVEMASK ); //Use only Block flags, other remove - CAN flags cannot be inherited from the parent item due to bad script pack... + uiBlockThis = (pDupeDef->m_Can & CAN_I_MOVEMASK); //Use only Block flags, other remove - CAN flags cannot be inherited from the parent item due to bad script pack... } } } else if (iDispID) { - CItemBase::GetItemTiledataFlags(&dwBlockThis, iDispID); + CItemBase::GetItemTiledataFlags(&uiBlockThis, iDispID); } - block.CheckTile_Item(dwBlockThis, z, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY); + block.CheckTile_Item(uiBlockThis, z, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY); } - dwBlockThis = 0; + uiBlockThis = 0; // Terrain height is screwed. Since it is related to all the terrain around it. std::optional pMapTop = GetMapMeterAdjusted(pt); //Get pMapTop Z Adjusted. //const CUOMapMeter* pMapTop = pMapBlock->GetTerrain(UO_BLOCK_OFFSET(pt.m_x), UO_BLOCK_OFFSET(pt.m_y)); @@ -1452,35 +1452,35 @@ void CWorldMap::GetHeightPoint(const CPointMap & pt, CServerMapBlockState & bloc //DEBUG_ERR(("pMeter->m_wTerrainIndex 0%x dwBlockThis (0%x)\n",pMeter->m_wTerrainIndex,dwBlockThis)); if (pMapTop->m_wTerrainIndex == TERRAIN_HOLE) { - dwBlockThis = 0; + uiBlockThis = 0; } else if (CUOMapMeter::IsTerrainNull(pMapTop->m_wTerrainIndex)) // inter dungeon type. { - dwBlockThis = CAN_I_BLOCK; + uiBlockThis = CAN_I_BLOCK; } else { const CUOTerrainInfo land(pMapTop->m_wTerrainIndex); //DEBUG_ERR(("Terrain flags - land.m_flags 0%x dwBlockThis (0%x)\n",land.m_flags,dwBlockThis)); if (land.m_flags & UFLAG1_WATER) - dwBlockThis |= CAN_I_WATER; + uiBlockThis |= CAN_I_WATER; if (land.m_flags & UFLAG1_DAMAGE) - dwBlockThis |= CAN_I_FIRE; + uiBlockThis |= CAN_I_FIRE; if (land.m_flags & UFLAG1_BLOCK) - dwBlockThis |= CAN_I_BLOCK; - if ((! dwBlockThis) || (land.m_flags & UFLAG2_PLATFORM)) // Platform items should take precendence over non-platforms. - dwBlockThis = CAN_I_PLATFORM; + uiBlockThis |= CAN_I_BLOCK; + if ((!uiBlockThis) || (land.m_flags & UFLAG2_PLATFORM)) // Platform items should take precendence over non-platforms. + uiBlockThis = CAN_I_PLATFORM; } //DEBUG_ERR(("TERRAIN dwBlockThis (0%x)\n",dwBlockThis)); - block.CheckTile_Terrain(dwBlockThis, pMapTop->m_z, pMapTop->m_wTerrainIndex); + block.CheckTile_Terrain(uiBlockThis, pMapTop->m_z, pMapTop->m_wTerrainIndex); if ( block.m_Bottom.m_z == UO_SIZE_MIN_Z ) { block.m_Bottom = block.m_Lowest; if ( block.m_Top.m_z == block.m_Bottom.m_z ) { - block.m_Top.m_dwBlockFlags = 0; + block.m_Top.m_uiBlockFlags = 0; block.m_Top.m_dwTile = 0; block.m_Top.m_z = UO_SIZE_Z; } @@ -1526,34 +1526,34 @@ CUOMapMeter CWorldMap::CheckMapTerrain(CUOMapMeter pDefault, short x, short y, u return *pMeter; } -char CWorldMap::GetHeightPoint(const CPointMap & pt, dword & dwBlockFlags, bool fHouseCheck) // static +char CWorldMap::GetHeightPoint(const CPointMap & pt, uint64 & uiBlockFlags, bool fHouseCheck) // static { ADDTOCALLSTACK_INTENSIVE("CWorldMap::GetHeightPoint"); - const dword dwCan = dwBlockFlags; - CServerMapBlockState block( dwBlockFlags, pt.m_z + (PLAYER_HEIGHT / 2), pt.m_z + PLAYER_HEIGHT ); + const uint64 uiCan = uiBlockFlags; + CServerMapBlockState block( uiBlockFlags, pt.m_z + (PLAYER_HEIGHT / 2), pt.m_z + PLAYER_HEIGHT ); GetHeightPoint(pt, block, fHouseCheck); // Pass along my results. - dwBlockFlags = block.m_Bottom.m_dwBlockFlags; - if ( block.m_Top.m_dwBlockFlags ) - dwBlockFlags |= CAN_I_ROOF; // we are covered by something. + uiBlockFlags = block.m_Bottom.m_uiBlockFlags; + if ( block.m_Top.m_uiBlockFlags ) + uiBlockFlags |= CAN_I_ROOF; // we are covered by something. - if (( block.m_Lowest.m_dwBlockFlags & CAN_I_HOVER ) || ( block.m_Bottom.m_dwBlockFlags & CAN_I_HOVER ) || ( block.m_Top.m_dwBlockFlags & CAN_I_HOVER )) + if ((block.m_Lowest.m_uiBlockFlags & CAN_I_HOVER) || (block.m_Bottom.m_uiBlockFlags & CAN_I_HOVER) || (block.m_Top.m_uiBlockFlags & CAN_I_HOVER)) { - if ( dwCan & CAN_C_HOVER ) - dwBlockFlags = 0; // we can hover over this + if (uiCan & CAN_C_HOVER) + uiBlockFlags = 0; // we can hover over this else - dwBlockFlags &= ~CAN_I_HOVER; // we don't have the ability to fly + uiBlockFlags &= ~CAN_I_HOVER; // we don't have the ability to fly } - if (( dwBlockFlags & ( CAN_I_CLIMB|CAN_I_PLATFORM) ) && ( dwCan & CAN_C_WALK )) + if ((uiBlockFlags & ( CAN_I_CLIMB|CAN_I_PLATFORM)) && (uiCan & CAN_C_WALK)) { - dwBlockFlags &= ~CAN_I_CLIMB; - dwBlockFlags |= CAN_I_PLATFORM; // not really true but hack it anyhow. + uiBlockFlags &= ~CAN_I_CLIMB; + uiBlockFlags |= CAN_I_PLATFORM; // not really true but hack it anyhow. //DEBUG_MSG(("block.m_Bottom.m_z (%d)\n",block.m_Bottom.m_z)); return block.m_Bottom.m_z; } - if ( dwCan & CAN_C_FLY ) + if (uiCan & CAN_C_FLY) return pt.m_z; return block.m_Bottom.m_z; @@ -1572,7 +1572,7 @@ void CWorldMap::GetHeightPoint2( const CPointMap & pt, CServerMapBlockState & bl return; } - dword dwBlockThis = 0; + uint64 uiBlockThis = 0; const uint iStaticQty = pMapBlock->m_Statics.GetStaticQty(); if ( iStaticQty > 0 ) // no static items here. { @@ -1585,13 +1585,13 @@ void CWorldMap::GetHeightPoint2( const CPointMap & pt, CServerMapBlockState & bl const CUOStaticItemRec * pStatic = pMapBlock->m_Statics.GetStatic( i ); char z = pStatic->m_z; - dwBlockThis = 0; + uiBlockThis = 0; const ITEMID_TYPE iDispID = pStatic->GetDispID(); - height_t zHeight = CItemBase::GetItemHeight( iDispID, &dwBlockThis ); + height_t zHeight = CItemBase::GetItemHeight(iDispID, &uiBlockThis); // This static is at the coordinates in question. // enough room for me to stand here ? - block.CheckTile( dwBlockThis, z, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY ); + block.CheckTile(uiBlockThis, z, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY); } } @@ -1627,11 +1627,11 @@ void CWorldMap::GetHeightPoint2( const CPointMap & pt, CServerMapBlockState & bl continue; char zitem = (char)( pItem->GetTopZ() + pMultiItem->m_dz ); - dwBlockThis = 0; + uiBlockThis = 0; const ITEMID_TYPE iDispID = pMultiItem->GetDispID(); - height_t zHeight = CItemBase::GetItemHeight( iDispID, &dwBlockThis ); + height_t zHeight = CItemBase::GetItemHeight( iDispID, &uiBlockThis ); - block.CheckTile( dwBlockThis, zitem, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY ); + block.CheckTile(uiBlockThis, zitem, zHeight, iDispID + (ITEMID_TYPE)TERRAIN_QTY); } } } @@ -1656,18 +1656,18 @@ void CWorldMap::GetHeightPoint2( const CPointMap & pt, CServerMapBlockState & bl ASSERT(pItemDef); // Get Attributes from ItemDef. If they are not set, get them from the static object (DISPID) - dwBlockThis = pItemDef->Can(CAN_I_DOOR | CAN_I_WATER | CAN_I_CLIMB | CAN_I_BLOCK | CAN_I_PLATFORM); + uiBlockThis = pItemDef->Can(CAN_I_DOOR | CAN_I_WATER | CAN_I_CLIMB | CAN_I_BLOCK | CAN_I_PLATFORM); height_t zHeight = pItemDef->GetHeight(); - dword dwStaticBlockThis = 0; - height_t zStaticHeight = CItemBase::GetItemHeight(pItem->GetDispID(), &dwStaticBlockThis); + uint64 uiStaticBlockThis = 0; + height_t zStaticHeight = CItemBase::GetItemHeight(pItem->GetDispID(), &uiStaticBlockThis); - if (dwBlockThis == 0) - dwBlockThis = dwStaticBlockThis; + if (uiBlockThis == 0) + uiBlockThis = uiStaticBlockThis; if (zHeight == 0) zHeight = zStaticHeight; - if ( !block.CheckTile(dwBlockThis, zitem, zHeight, pItemDef->GetDispID() + (ITEMID_TYPE)TERRAIN_QTY ) ) + if ( !block.CheckTile(uiBlockThis, zitem, zHeight, pItemDef->GetDispID() + (ITEMID_TYPE)TERRAIN_QTY ) ) { } } @@ -1681,24 +1681,24 @@ void CWorldMap::GetHeightPoint2( const CPointMap & pt, CServerMapBlockState & bl ASSERT(pMeter); if (pMeter->m_wTerrainIndex == TERRAIN_HOLE) - dwBlockThis = 0; + uiBlockThis = 0; else if (pMeter->m_wTerrainIndex == TERRAIN_NULL) // inter dungeon type. - dwBlockThis = CAN_I_BLOCK; + uiBlockThis = CAN_I_BLOCK; else { const CUOTerrainInfo land(pMeter->m_wTerrainIndex); if (land.m_flags & UFLAG2_PLATFORM) // Platform items should take precendence over non-platforms. - dwBlockThis = CAN_I_PLATFORM; + uiBlockThis = CAN_I_PLATFORM; else if (land.m_flags & UFLAG1_WATER) - dwBlockThis = CAN_I_WATER; + uiBlockThis = CAN_I_WATER; else if (land.m_flags & UFLAG1_DAMAGE) - dwBlockThis = CAN_I_FIRE; + uiBlockThis = CAN_I_FIRE; else if (land.m_flags & UFLAG1_BLOCK) - dwBlockThis = CAN_I_BLOCK; + uiBlockThis = CAN_I_BLOCK; else - dwBlockThis = CAN_I_PLATFORM; + uiBlockThis = CAN_I_PLATFORM; } - block.CheckTile(dwBlockThis, pMeter->m_z, 0, pMeter->m_wTerrainIndex); + block.CheckTile(uiBlockThis, pMeter->m_z, 0, pMeter->m_wTerrainIndex); } if ( block.m_Bottom.m_z == UO_SIZE_MIN_Z ) @@ -1708,7 +1708,7 @@ void CWorldMap::GetHeightPoint2( const CPointMap & pt, CServerMapBlockState & bl } // Height of player who walked to X/Y/OLDZ -char CWorldMap::GetHeightPoint2( const CPointMap & pt, dword & dwBlockFlags, bool fHouseCheck ) // static +char CWorldMap::GetHeightPoint2( const CPointMap & pt, uint64 & uiBlockFlags, bool fHouseCheck ) // static { ADDTOCALLSTACK_INTENSIVE("CWorldMap::GetHeightPoint2"); // Given our coords at pt including pt.m_z @@ -1733,44 +1733,44 @@ char CWorldMap::GetHeightPoint2( const CPointMap & pt, dword & dwBlockFlags, boo // ??? NOTE: some creatures should be taller than others !!! - const dword dwCan = dwBlockFlags; - CServerMapBlockState block(dwBlockFlags, pt.m_z, PLAYER_HEIGHT); + const uint64 uiCan = uiBlockFlags; + CServerMapBlockState block(uiBlockFlags, pt.m_z, PLAYER_HEIGHT); GetHeightPoint2( pt, block, fHouseCheck ); // Pass along my results. - dwBlockFlags = block.m_Bottom.m_dwBlockFlags; - if (block.m_Top.m_dwBlockFlags) + uiBlockFlags = block.m_Bottom.m_uiBlockFlags; + if (block.m_Top.m_uiBlockFlags) { - dwBlockFlags |= CAN_I_ROOF; // we are covered by something. + uiBlockFlags |= CAN_I_ROOF; // we are covered by something. // Do not check for landtiles to block me. We pass through if statics are under them if (block.m_Top.m_dwTile > TERRAIN_QTY) { // If this tile possibly blocks me, roof cannot block me - if (block.m_Top.m_dwBlockFlags & (~CAN_I_ROOF)) + if (block.m_Top.m_uiBlockFlags & (~CAN_I_ROOF)) { if (block.m_Top.m_z < block.m_Bottom.m_z + PLAYER_HEIGHT) - dwBlockFlags |= CAN_I_BLOCK; // we can't fit under this! + uiBlockFlags |= CAN_I_BLOCK; // we can't fit under this! } } } - if (( block.m_Lowest.m_dwBlockFlags & CAN_I_HOVER ) || ( block.m_Bottom.m_dwBlockFlags & CAN_I_HOVER ) || ( block.m_Top.m_dwBlockFlags & CAN_I_HOVER )) + if ((block.m_Lowest.m_uiBlockFlags & CAN_I_HOVER) || (block.m_Bottom.m_uiBlockFlags & CAN_I_HOVER) || (block.m_Top.m_uiBlockFlags & CAN_I_HOVER)) { - if ( dwCan & CAN_C_HOVER ) - dwBlockFlags = 0; // we can hover over this + if (uiCan & CAN_C_HOVER) + uiBlockFlags = 0; // we can hover over this else - dwBlockFlags &= ~CAN_I_HOVER; // we don't have the ability to fly + uiBlockFlags &= ~CAN_I_HOVER; // we don't have the ability to fly } - if (( dwBlockFlags & ( CAN_I_CLIMB|CAN_I_PLATFORM) ) && ( dwCan & CAN_C_WALK )) + if ((uiBlockFlags & (CAN_I_CLIMB|CAN_I_PLATFORM)) && (uiCan & CAN_C_WALK)) { - dwBlockFlags &= ~CAN_I_CLIMB; - dwBlockFlags |= CAN_I_PLATFORM; // not really true but hack it anyhow. + uiBlockFlags &= ~CAN_I_CLIMB; + uiBlockFlags |= CAN_I_PLATFORM; // not really true but hack it anyhow. return( block.m_Bottom.m_z ); } - if ( dwCan & CAN_C_FLY ) + if (uiCan & CAN_C_FLY) return( pt.m_z ); return( block.m_Bottom.m_z ); diff --git a/src/game/CWorldMap.h b/src/game/CWorldMap.h index 794668416..40f700e25 100644 --- a/src/game/CWorldMap.h +++ b/src/game/CWorldMap.h @@ -48,10 +48,10 @@ class CWorldMap // Height checks static void GetHeightPoint2( const CPointMap & pt, CServerMapBlockState & block, bool fHouseCheck = false ); - static char GetHeightPoint2(const CPointMap & pt, dword & dwBlockFlags, bool fHouseCheck = false); // Height of player who walked to X/Y/OLDZ + static char GetHeightPoint2(const CPointMap & pt, uint64 & uiBlockFlags, bool fHouseCheck = false); // Height of player who walked to X/Y/OLDZ static void GetHeightPoint( const CPointMap & pt, CServerMapBlockState & block, bool fHouseCheck = false ); - static char GetHeightPoint( const CPointMap & pt, dword & dwBlockFlags, bool fHouseCheck = false ); + static char GetHeightPoint( const CPointMap & pt, uint64 & uiBlockFlags, bool fHouseCheck = false ); static void GetFixPoint( const CPointMap & pt, CServerMapBlockState & block); diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 2f897b539..49bec9761 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -713,18 +713,18 @@ int CChar::IsWeird() const } // Get the Z we should be at -char CChar::GetFixZ( const CPointMap& pt, dword dwBlockFlags) +char CChar::GetFixZ( const CPointMap& pt, uint64 uiBlockFlags) { - const dword dwCanFlags = GetCanFlags(); - const dword dwCanMoveFlags = GetCanMoveFlags(dwCanFlags); + const uint64 uiCanFlags = GetCanFlags(); + const uint64 uiCanMoveFlags = GetCanMoveFlags(uiCanFlags); - if ( !dwBlockFlags ) - dwBlockFlags = dwCanMoveFlags; + if (!uiBlockFlags) + uiBlockFlags = uiCanMoveFlags; - if (dwCanMoveFlags == 0xFFFFFFFF) + if (uiCanMoveFlags == UINT64_MAX) return pt.m_z; - if (dwCanMoveFlags & CAN_C_WALK ) - dwBlockFlags |= CAN_I_CLIMB; // If we can walk than we can climb. Ignore CAN_C_FLY at all here + if (uiCanMoveFlags & CAN_C_WALK ) + uiBlockFlags |= CAN_I_CLIMB; // If we can walk than we can climb. Ignore CAN_C_FLY at all here const short iZClimbed = pt.m_z + m_zClimbHeight; const height_t uiHeightMount = GetHeightMount( false ); @@ -732,27 +732,27 @@ char CChar::GetFixZ( const CPointMap& pt, dword dwBlockFlags) const int iBlockMaxHeight = std::max(int(iZClimbed + uiHeightMount), int(INT8_MAX)); const height_t uiClimbHeight = height_t(std::max(short(iZClimbed + 2), short(UINT8_MAX))); - CServerMapBlockState block( dwBlockFlags, pt.m_z, iBlockMaxHeight, uiClimbHeight, uiHeightMount ); - CWorldMap::GetFixPoint( pt, block ); + CServerMapBlockState block(uiBlockFlags, pt.m_z, iBlockMaxHeight, uiClimbHeight, uiHeightMount); + CWorldMap::GetFixPoint(pt, block); - dwBlockFlags = block.m_Bottom.m_dwBlockFlags; - if ( block.m_Top.m_dwBlockFlags ) + uiBlockFlags = block.m_Bottom.m_uiBlockFlags; + if (block.m_Top.m_uiBlockFlags) { - dwBlockFlags |= CAN_I_ROOF; // we are covered by something. + uiBlockFlags |= CAN_I_ROOF; // we are covered by something. if ( block.m_Top.m_z < (iZClimbed + ((block.m_Top.m_dwTile > TERRAIN_QTY) ? uiHeightMount : uiHeightMount/2 )) ) - dwBlockFlags |= CAN_I_BLOCK; // we can't fit under this! + uiBlockFlags |= CAN_I_BLOCK; // we can't fit under this! } - if ( dwBlockFlags != 0x0 ) + if ( uiBlockFlags != 0x0 ) { - if ( (dwBlockFlags & CAN_I_DOOR) && Can(CAN_C_GHOST, dwCanFlags) ) - dwBlockFlags &= ~CAN_I_BLOCK; + if ((uiBlockFlags & CAN_I_DOOR) && Can(CAN_C_GHOST, uiCanFlags)) + uiBlockFlags &= ~CAN_I_BLOCK; - if ( (dwBlockFlags & CAN_I_WATER) && Can(CAN_C_SWIM, dwCanFlags) ) - dwBlockFlags &= ~CAN_I_BLOCK; + if ((uiBlockFlags & CAN_I_WATER) && Can(CAN_C_SWIM, uiCanFlags)) + uiBlockFlags &= ~CAN_I_BLOCK; - if ( !Can(CAN_C_FLY, dwCanFlags) ) + if ( !Can(CAN_C_FLY, uiCanFlags) ) { - if ( ! ( dwBlockFlags & CAN_I_CLIMB ) ) // we can climb anywhere + if (!(uiBlockFlags & CAN_I_CLIMB)) // we can climb anywhere { if ( block.m_Bottom.m_dwTile > TERRAIN_QTY ) { @@ -766,10 +766,10 @@ char CChar::GetFixZ( const CPointMap& pt, dword dwBlockFlags) } } } - if ( (dwBlockFlags & CAN_I_BLOCK) && !Can(CAN_C_PASSWALLS, dwCanFlags) ) + if ((uiBlockFlags & CAN_I_BLOCK) && !Can(CAN_C_PASSWALLS, uiCanFlags)) return pt.m_z; - if ( block.m_Bottom.m_z >= UO_SIZE_Z ) + if (block.m_Bottom.m_z >= UO_SIZE_Z) return pt.m_z; } @@ -2794,10 +2794,10 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo CPointMap ptDst = GetTopPoint(); DIR_TYPE dir = GetDirStr(ptcKey); ptDst.Move( dir ); - dword dwBlockFlags = 0; + uint64 uiBlockFlags = 0; CRegion * pArea; - pArea = CheckValidMove( ptDst, &dwBlockFlags, dir, nullptr ); - sVal.FormatHex( pArea ? pArea->GetResourceID().IsValidUID() : 0 ); + pArea = CheckValidMove(ptDst, &uiBlockFlags, dir, nullptr); + sVal.FormatHex(pArea ? pArea->GetResourceID().IsValidUID() : 0); } return true; @@ -2819,12 +2819,12 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo ptDst.Move( GetDirStr( ptcKey ) ); CRegion * pArea = ptDst.GetRegion( REGION_TYPE_MULTI | REGION_TYPE_AREA ); if ( !pArea ) - sVal.FormatHex( UINT32_MAX ); + sVal.FormatULLHex( UINT64_MAX ); else { - dword dwBlockFlags = 0; - CWorldMap::GetHeightPoint2( ptDst, dwBlockFlags, true ); - sVal.FormatHex( dwBlockFlags ); + uint64 uiBlockFlags = 0Ui64; + CWorldMap::GetHeightPoint2(ptDst, uiBlockFlags, true); + sVal.FormatULLHex(uiBlockFlags); } } return true; diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index be892ce65..333719a57 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -341,7 +341,7 @@ public: void StatFlag_Clear(uint64 uiStatFlag) noexcept; //protected: void _StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; - char GetFixZ(const CPointMap& pt, dword dwBlockFlags = 0); + char GetFixZ(const CPointMap& pt, uint64 uiBlockFlags = 0Ui64); bool IsPriv( word flag ) const; virtual PLEVEL_TYPE GetPrivLevel() const override; @@ -456,7 +456,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; bool TeleportToCli( int iType, int iArgs ); bool TeleportToObj( int iType, tchar * pszArgs ); private: - CRegion * CheckValidMove( CPointMap & ptDest, dword * pdwBlockFlags, DIR_TYPE dir, height_t * ClimbHeight, bool fPathFinding = false ) const; + CRegion * CheckValidMove( CPointMap & ptDest, uint64 * uiBlockFlags, DIR_TYPE dir, height_t * ClimbHeight, bool fPathFinding = false ) const; void FixClimbHeight(); bool MoveToRoom( CRegion * pNewRoom, bool fAllowReject); bool IsVerticalSpace( const CPointMap& ptDest, bool fForceMount = false ) const; @@ -533,7 +533,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; lpctstr GetPossessPronoun() const; // his byte GetModeFlag( const CClient *pViewer = nullptr ) const; byte GetDirFlag(bool fSquelchForwardStep = false) const; - dword GetCanMoveFlags(dword dwCanFlags, bool fIgnoreGM = false) const; + uint64 GetCanMoveFlags(uint64 uiCanFlags, bool fIgnoreGM = false) const; virtual int FixWeirdness() override; void CreateNewCharCheck(); @@ -1167,7 +1167,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; bool OnFreezeCheck() const; bool IsStuck(bool fFreezeCheck); - void DropAll( CItemContainer * pCorpse = nullptr, uint64 dwAttr = 0 ); + void DropAll(CItemContainer * pCorpse = nullptr, uint64 uiAttr = 0); void UnEquipAllItems( CItemContainer * pCorpse = nullptr, bool fLeaveHands = false ); void Wake(); void SleepStart( bool fFrontFall ); diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index c0712a39d..a8b314a45 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -558,7 +558,7 @@ void CChar::OnRemoveObj( CSObjContRec* pObRec ) // Override this = called when r } // shrunk or died. (or sleeping) -void CChar::DropAll( CItemContainer * pCorpse, uint64 iAttr ) +void CChar::DropAll(CItemContainer * pCorpse, uint64 uiAttr) { ADDTOCALLSTACK("CChar::DropAll"); if ( IsStatFlag( STATF_CONJURED )) @@ -569,11 +569,11 @@ void CChar::DropAll( CItemContainer * pCorpse, uint64 iAttr ) { if ( pCorpse == nullptr ) { - pPack->ContentsDump( GetTopPoint(), iAttr ); + pPack->ContentsDump(GetTopPoint(), uiAttr); } else { - pPack->ContentsTransfer( pCorpse, true ); + pPack->ContentsTransfer(pCorpse, true); } } @@ -3401,14 +3401,14 @@ CRegion * CChar::CanMoveWalkTo( CPointMap & ptDst, bool fCheckChars, bool fCheck } // ok to go here ? physical blocking objects ? - dword dwBlockFlags = 0; + uint64 uiBlockFlags = 0Ui64; height_t ClimbHeight = 0; CRegion *pArea = nullptr; EXC_TRY("CanMoveWalkTo"); EXC_SET_BLOCK("Check Valid Move"); - pArea = CheckValidMove(ptDst, &dwBlockFlags, DIR_TYPE(dir & ~DIR_MASK_RUNNING), &ClimbHeight, fPathFinding); + pArea = CheckValidMove(ptDst, &uiBlockFlags, DIR_TYPE(dir & ~DIR_MASK_RUNNING), &ClimbHeight, fPathFinding); if ( !pArea ) { if (g_Cfg.m_iDebugFlags & DEBUGF_WALK) @@ -3561,8 +3561,8 @@ CRegion * CChar::CanMoveWalkTo( CPointMap & ptDst, bool fCheckChars, bool fCheck if ( uiStamReq > 0 ) UpdateStatVal(STAT_DEX, -uiStamReq); - StatFlag_Mod(STATF_INDOORS, (dwBlockFlags & CAN_I_ROOF) || pArea->IsFlag(REGION_FLAG_UNDERGROUND)); - m_zClimbHeight = (dwBlockFlags & CAN_I_CLIMB) ? ClimbHeight : 0; + StatFlag_Mod(STATF_INDOORS, (uiBlockFlags & CAN_I_ROOF) || pArea->IsFlag(REGION_FLAG_UNDERGROUND)); + m_zClimbHeight = (uiBlockFlags & CAN_I_CLIMB) ? ClimbHeight : 0; } EXC_CATCH; return pArea; @@ -4047,7 +4047,7 @@ bool CChar::MoveToValidSpot(DIR_TYPE dir, int iDist, int iDistStart, bool fFromS pt.m_z += PLAYER_HEIGHT; char startZ = pt.m_z; - dword dwCan = GetCanMoveFlags(GetCanFlags(), true); // CAN_C_SWIM + uint64 uiCan = GetCanMoveFlags(GetCanFlags(), true); // CAN_C_SWIM for ( int i=0; i startZ) ) + if (fFromShip && (uiBlockFlags & CAN_I_BLOCK) && !(uiCan & CAN_C_PASSWALLS) && (pt.m_z > startZ)) { break; } - if ( ! ( dwBlockFlags &~ dwCan )) + if (!(uiBlockFlags &~ uiCan)) { // we can go here. (maybe) if ( Spell_Teleport(pt, true, !fFromShip, false) ) diff --git a/src/game/chars/CCharLOS.cpp b/src/game/chars/CCharLOS.cpp index 1b7ebae16..5eec81031 100644 --- a/src/game/chars/CCharLOS.cpp +++ b/src/game/chars/CCharLOS.cpp @@ -36,7 +36,7 @@ bool CChar::CanSeeLOS( const CPointMap &ptDst, CPointMap *pptBlock, int iMaxDist while ( --iDist >= 0 ) { const DIR_TYPE dir = ptSrc.GetDir(ptDst); - dword dwBlockFlags; + uint64 uiBlockFlags; if ( dir % 2 && !IsSetEF(EF_NoDiagonalCheckLOS) ) // test only diagonal dirs { CPointMap ptTest(ptSrc); @@ -46,22 +46,22 @@ bool CChar::CanSeeLOS( const CPointMap &ptDst, CPointMap *pptBlock, int iMaxDist dirTest2 = DIR_N; ptTest.Move(dirTest1); - dwBlockFlags = CAN_C_SWIM|CAN_C_WALK|CAN_C_FLY; - char z = CWorldMap::GetHeightPoint2(ptTest, dwBlockFlags, true); + uiBlockFlags = CAN_C_SWIM|CAN_C_WALK|CAN_C_FLY; + char z = CWorldMap::GetHeightPoint2(ptTest, uiBlockFlags, true); short zDiff = (short)(abs(z - ptTest.m_z)); - if ( (zDiff > PLAYER_HEIGHT) || (dwBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR)) ) // blocked + if ( (zDiff > PLAYER_HEIGHT) || (uiBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR)) ) // blocked { ptTest = ptSrc; ptTest.Move(dirTest2); { - dwBlockFlags = CAN_C_SWIM|CAN_C_WALK|CAN_C_FLY; - z = CWorldMap::GetHeightPoint2(ptTest, dwBlockFlags, true); + uiBlockFlags = CAN_C_SWIM|CAN_C_WALK|CAN_C_FLY; + z = CWorldMap::GetHeightPoint2(ptTest, uiBlockFlags, true); zDiff = (short)(abs(z - ptTest.m_z)); if ( zDiff > PLAYER_HEIGHT ) goto blocked; - if ( dwBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR) ) + if (uiBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR)) { ptSrc = ptTest; goto blocked; @@ -74,11 +74,11 @@ bool CChar::CanSeeLOS( const CPointMap &ptDst, CPointMap *pptBlock, int iMaxDist if ( iDist ) { ptSrc.Move(dir); // NOTE: The dir is very coarse and can change slightly. - dwBlockFlags = CAN_C_SWIM|CAN_C_WALK|CAN_C_FLY; - char z = CWorldMap::GetHeightPoint2(ptSrc, dwBlockFlags, true); + uiBlockFlags = CAN_C_SWIM|CAN_C_WALK|CAN_C_FLY; + char z = CWorldMap::GetHeightPoint2(ptSrc, uiBlockFlags, true); short zDiff = (short)(abs(z - ptSrc.m_z)); - if ( (zDiff > PLAYER_HEIGHT) || (dwBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR)) || (iDistTry > iMaxDist) ) + if ( (zDiff > PLAYER_HEIGHT) || (uiBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR)) || (iDistTry > iMaxDist) ) goto blocked; ptSrc.m_z = z; @@ -681,4 +681,4 @@ bool CChar::CanSeeLOS( const CObjBaseTemplate *pObj, word wFlags, bool bCombatCh } else return CanSeeLOS(pObj->GetTopPoint(), nullptr, pObj->GetVisualRange(), wFlags, bCombatCheck); -} \ No newline at end of file +} diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 37d07a957..ef1ef0105 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -2162,9 +2162,9 @@ void CChar::Spell_Field(CPointMap pntTarg, ITEMID_TYPE idEW, ITEMID_TYPE idNS, u ptg.m_y += (short)(iy); } - dword dwBlockFlags = 0; - CWorldMap::GetHeightPoint2(ptg, dwBlockFlags, true); - if ( dwBlockFlags & ( CAN_I_BLOCK | CAN_I_DOOR ) ) + uint64 uiBlockFlags = 0Ui64; + CWorldMap::GetHeightPoint2(ptg, uiBlockFlags, true); + if (uiBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR)) { if (ix < 0) // field cannot extend fully to the left minX = ix + 1; @@ -2588,11 +2588,11 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE i { if (IsSetMagicFlags(MAGICF_SUMMONWALKCHECK)) // check if the target location is valid { - const dword dwCan = pChar->GetCanFlags() & CAN_C_MOVEMASK; - dword dwBlockFlags = 0; - CWorldMap::GetHeightPoint2(ptTarg, dwBlockFlags, true); + const uint64 uiCan = pChar->GetCanFlags() & CAN_C_MOVEMASK; + uint64 uiBlockFlags = 0Ui64; + CWorldMap::GetHeightPoint2(ptTarg, uiBlockFlags, true); - if (dwBlockFlags & ~dwCan) + if (uiBlockFlags & ~uiCan) { SysMessageDefault(DEFMSG_MSG_SUMMON_INVALIDTARG); pChar->Delete(); diff --git a/src/game/chars/CCharStatus.cpp b/src/game/chars/CCharStatus.cpp index 21ac547ce..6267a0cca 100644 --- a/src/game/chars/CCharStatus.cpp +++ b/src/game/chars/CCharStatus.cpp @@ -506,9 +506,9 @@ bool CChar::IsSwimming() const return false; // Is there a solid surface under us? - dword dwBlockFlags = GetCanMoveFlags(GetCanFlags()); - char iSurfaceZ = CWorldMap::GetHeightPoint2(ptTop, dwBlockFlags, true); - if ( (iSurfaceZ == pt.m_z) && (dwBlockFlags & CAN_I_WATER) ) + uint64 uiBlockFlags = GetCanMoveFlags(GetCanFlags()); + char iSurfaceZ = CWorldMap::GetHeightPoint2(ptTop, uiBlockFlags, true); + if ((iSurfaceZ == pt.m_z) && (uiBlockFlags & CAN_I_WATER)) return true; return false; @@ -715,19 +715,19 @@ byte CChar::GetDirFlag(bool fSquelchForwardStep) const return dir; } -dword CChar::GetCanMoveFlags(dword dwCanFlags, bool fIgnoreGM) const +uint64 CChar::GetCanMoveFlags(uint64 uiCanFlags, bool fIgnoreGM) const { // What things do not block us ? if ( IsPriv(PRIV_GM|PRIV_ALLMOVE) && !fIgnoreGM ) - return 0xFFFFFFFF; // nothing blocks us: we are able to move onto everything. + return UINT64_MAX; // nothing blocks us: we are able to move onto everything. if ( IsStatFlag(STATF_DEAD) ) - dwCanFlags |= CAN_C_GHOST; + uiCanFlags |= CAN_C_GHOST; if ( IsStatFlag(STATF_HOVERING) ) - dwCanFlags |= CAN_C_HOVER; + uiCanFlags |= CAN_C_HOVER; - return ( dwCanFlags & CAN_C_MOVEMASK ); + return ( uiCanFlags & CAN_C_MOVEMASK ); } byte CChar::GetLightLevel() const @@ -1802,12 +1802,12 @@ bool CChar::IsVerticalSpace( const CPointMap& ptDest, bool fForceMount ) const if ( IsPriv(PRIV_GM | PRIV_ALLMOVE) || !ptDest.IsValidPoint() ) return true; - dword dwBlockFlags = GetCanMoveFlags(GetCanFlags()); - if ( dwBlockFlags & CAN_C_WALK ) - dwBlockFlags |= CAN_I_CLIMB; + uint64 uiBlockFlags = GetCanMoveFlags(GetCanFlags()); + if (uiBlockFlags & CAN_C_WALK) + uiBlockFlags |= CAN_I_CLIMB; const height_t iHeightMount = GetHeightMount(); - CServerMapBlockState block(dwBlockFlags, ptDest.m_z, ptDest.m_z + m_zClimbHeight + iHeightMount, ptDest.m_z + m_zClimbHeight + 2, iHeightMount); + CServerMapBlockState block(uiBlockFlags, ptDest.m_z, ptDest.m_z + m_zClimbHeight + iHeightMount, ptDest.m_z + m_zClimbHeight + 2, iHeightMount); CWorldMap::GetHeightPoint(ptDest, block, true); if ( iHeightMount + ptDest.m_z + (fForceMount ? 4 : 0) >= block.m_Top.m_z ) // 4 is the mount height @@ -1815,7 +1815,7 @@ bool CChar::IsVerticalSpace( const CPointMap& ptDest, bool fForceMount ) const return true; } -CRegion *CChar::CheckValidMove( CPointMap &ptDest, dword *pdwBlockFlags, DIR_TYPE dir, height_t *pClimbHeight, bool fPathFinding ) const +CRegion *CChar::CheckValidMove( CPointMap &ptDest, uint64 *uiBlockFlags, DIR_TYPE dir, height_t *pClimbHeight, bool fPathFinding ) const { ADDTOCALLSTACK("CChar::CheckValidMove"); // Is it ok to move here ? is it blocked ? @@ -1836,12 +1836,12 @@ CRegion *CChar::CheckValidMove( CPointMap &ptDest, dword *pdwBlockFlags, DIR_TYP CPointMap ptTest(ptOld); ptTest.Move(dirTest1); - if ( !CheckValidMove(ptTest, pdwBlockFlags, DIR_QTY, pClimbHeight) ) + if ( !CheckValidMove(ptTest, uiBlockFlags, DIR_QTY, pClimbHeight) ) return nullptr; ptTest = ptOld; ptTest.Move(dirTest2); - if ( !CheckValidMove(ptTest, pdwBlockFlags, DIR_QTY, pClimbHeight) ) + if ( !CheckValidMove(ptTest, uiBlockFlags, DIR_QTY, pClimbHeight) ) return nullptr; } @@ -1864,38 +1864,38 @@ CRegion *CChar::CheckValidMove( CPointMap &ptDest, dword *pdwBlockFlags, DIR_TYP return nullptr; } - const dword dwCanFlags = GetCanFlags(); - const dword dwMovementCan = GetCanMoveFlags(dwCanFlags); // actions i can perform to step on a tile (some tiles require a specific ability, like to swim for the water) + const uint64 uiCanFlags = GetCanFlags(); + const uint64 uiMovementCan = GetCanMoveFlags(uiCanFlags); // actions i can perform to step on a tile (some tiles require a specific ability, like to swim for the water) if (g_Cfg.m_iDebugFlags & DEBUGF_WALK) - g_Log.EventWarn("GetCanMoveFlags() (0x%" PRIx32 ").\n", dwMovementCan); - if ( !(dwMovementCan & CAN_C_MOVEMENTCAPABLEMASK) ) + g_Log.EventWarn("GetCanMoveFlags() (0x%" PRIx32 ").\n", uiMovementCan); + if (!(uiMovementCan & CAN_C_MOVEMENTCAPABLEMASK)) return nullptr; // cannot move at all, so WTF? - dword dwMapMoveFlags = dwMovementCan; - if (dwMovementCan & CAN_C_WALK ) + uint64 uiMapMoveFlags = uiMovementCan; + if (uiMovementCan & CAN_C_WALK ) { - dwMapMoveFlags |= CAN_C_FLY; // if we can walk than we can CLIMB. The char flag for doing that is FLY. + uiMapMoveFlags |= CAN_C_FLY; // if we can walk than we can CLIMB. The char flag for doing that is FLY. } const height_t iHeight = IsSetEF(EF_WalkCheckHeightMounted) ? GetHeightMount() : GetHeight(); - CServerMapBlockState block(dwMapMoveFlags, ptDest.m_z, ptDest.m_z + m_zClimbHeight + iHeight, ptDest.m_z + m_zClimbHeight + 3, iHeight); + CServerMapBlockState block(uiMapMoveFlags, ptDest.m_z, ptDest.m_z + m_zClimbHeight + iHeight, ptDest.m_z + m_zClimbHeight + 3, iHeight); if (g_Cfg.m_iDebugFlags & DEBUGF_WALK) { g_Log.EventWarn("\t\tCServerMapBlockState block( 0%x, %d, %d, %d ); ptDest.m_z(%d) m_zClimbHeight(%d).\n", - dwMapMoveFlags, ptDest.m_z, ptDest.m_z + m_zClimbHeight + iHeight, ptDest.m_z + m_zClimbHeight + 2, ptDest.m_z, m_zClimbHeight); + uiMapMoveFlags, ptDest.m_z, ptDest.m_z + m_zClimbHeight + iHeight, ptDest.m_z + m_zClimbHeight + 2, ptDest.m_z, m_zClimbHeight); } CWorldMap::GetHeightPoint(ptDest, block, true); // Pass along my results. - dwMapMoveFlags = block.m_Bottom.m_dwBlockFlags; + uiMapMoveFlags = block.m_Bottom.m_uiBlockFlags; uint uiBlockedBy = 0; // need to check also for UFLAG1_FLOOR? - if ( block.m_Top.m_dwBlockFlags ) + if ( block.m_Top.m_uiBlockFlags ) { const bool fTopLandTile = (block.m_Top.m_dwTile <= TERRAIN_QTY); - if (!fTopLandTile && (block.m_Top.m_dwBlockFlags & (CAN_I_ROOF|CAN_I_PLATFORM|CAN_I_BLOCK)) && Can(CAN_C_NOINDOORS)) + if (!fTopLandTile && (block.m_Top.m_uiBlockFlags & (CAN_I_ROOF|CAN_I_PLATFORM|CAN_I_BLOCK)) && Can(CAN_C_NOINDOORS)) return nullptr; const short iHeightDiff = (block.m_Top.m_z - block.m_Bottom.m_z); @@ -1911,68 +1911,68 @@ CRegion *CChar::CheckValidMove( CPointMap &ptDest, dword *pdwBlockFlags, DIR_TYP // Two cases possible: // 1) On the dest P we would be covered by something and we wouldn't fit under this! // 2) On the dest P there's an item but we can pass through it (this special case will be handled with fPassTrough late - dwMapMoveFlags |= CAN_I_BLOCK; + uiMapMoveFlags |= CAN_I_BLOCK; uiBlockedBy |= CAN_I_ROOF; } else if (iHeightDiff < (m_zClimbHeight + uiHeightReq) ) { // i'm trying to walk on a point over my head, it's possible to climb it but there isn't enough room for me to fit between Top and Bottom tile // (i'd bang my head against the ceiling!) - dwMapMoveFlags |= CAN_I_BLOCK; + uiMapMoveFlags |= CAN_I_BLOCK; uiBlockedBy |= CAN_I_CLIMB; } } const bool fLandTile = (block.m_Bottom.m_dwTile <= TERRAIN_QTY); bool fPassTrough = false; - if ( (dwMovementCan != 0xFFFFFFFF) && (dwMapMoveFlags != 0x0) ) + if ((uiMovementCan != UINT64_MAX) && (uiMapMoveFlags != 0x0)) { // It IS in my way and HAS a flag set, check further if (g_Cfg.m_iDebugFlags & DEBUGF_WALK) g_Log.EventWarn("BOTTOMitemID (0%" PRIx32 ") TOPitemID (0%" PRIx32 ").\n", (block.m_Bottom.m_dwTile - TERRAIN_QTY), (block.m_Top.m_dwTile - TERRAIN_QTY)); - if (dwMapMoveFlags & CAN_I_WATER) + if (uiMapMoveFlags & CAN_I_WATER) { - if (Can(CAN_C_SWIM, dwCanFlags)) + if (Can(CAN_C_SWIM, uiCanFlags)) { // I can swim, and water tiles have the impassable flag, so let's remove it - dwMapMoveFlags &= ~CAN_I_BLOCK; + uiMapMoveFlags &= ~CAN_I_BLOCK; } else { // Item is water and i can't swim - dwMapMoveFlags |= CAN_I_BLOCK; // it should be already added in the tiledata, but we better make that sure + uiMapMoveFlags |= CAN_I_BLOCK; // it should be already added in the tiledata, but we better make that sure uiBlockedBy |= CAN_I_WATER; } } - if ( (dwMapMoveFlags & CAN_I_PLATFORM) && !Can(CAN_C_WALK, dwCanFlags) ) + if ((uiMapMoveFlags & CAN_I_PLATFORM) && !Can(CAN_C_WALK, uiCanFlags)) { // Item is walkable (land, not water) and i can't walk - dwMapMoveFlags |= CAN_I_BLOCK; + uiMapMoveFlags |= CAN_I_BLOCK; uiBlockedBy |= CAN_I_PLATFORM; } - if ( (dwMapMoveFlags & CAN_I_DOOR) ) + if ((uiMapMoveFlags & CAN_I_DOOR)) { - if (Can(CAN_C_GHOST, dwCanFlags)) + if (Can(CAN_C_GHOST, uiCanFlags)) { fPassTrough = true; } else { // Item is a door and i'm not a ghost - dwMapMoveFlags |= CAN_I_BLOCK; + uiMapMoveFlags |= CAN_I_BLOCK; uiBlockedBy |= CAN_I_DOOR; } } - if ( (dwMapMoveFlags & CAN_I_HOVER) ) + if ( (uiMapMoveFlags & CAN_I_HOVER) ) { - if (Can(CAN_C_HOVER, dwCanFlags) || IsStatFlag(STATF_HOVERING)) + if (Can(CAN_C_HOVER, uiCanFlags) || IsStatFlag(STATF_HOVERING)) { ; //fPassTrough = true; } else { - dwMapMoveFlags |= CAN_I_BLOCK; + uiMapMoveFlags |= CAN_I_BLOCK; uiBlockedBy |= CAN_I_HOVER; } } @@ -1986,7 +1986,7 @@ CRegion *CChar::CheckValidMove( CPointMap &ptDest, dword *pdwBlockFlags, DIR_TYP if (fLandTile) { // It's a land tile - if ((dwMapMoveFlags & CAN_I_BLOCK) && !(uiBlockedBy & CAN_I_CLIMB)) + if ((uiMapMoveFlags & CAN_I_BLOCK) && !(uiBlockedBy & CAN_I_CLIMB)) return nullptr; if (block.m_Bottom.m_z > ptDest.m_z + m_zClimbHeight + iHeight + 3) return nullptr; @@ -1994,24 +1994,24 @@ CRegion *CChar::CheckValidMove( CPointMap &ptDest, dword *pdwBlockFlags, DIR_TYP else { // It's an item - if (!fPassTrough && (dwMapMoveFlags & CAN_I_BLOCK)) + if (!fPassTrough && (uiMapMoveFlags & CAN_I_BLOCK)) { // It's a blocking item. I should need special capabilities to pass through (or over) it. if (!(uiBlockedBy & CAN_I_CLIMB)) return nullptr; - if (!Can(CAN_C_PASSWALLS, dwCanFlags)) + if (!Can(CAN_C_PASSWALLS, uiCanFlags)) { // I can't pass through it, but can i climb or fly on it? - if (Can(CAN_C_FLY, dwCanFlags)) + if (Can(CAN_C_FLY, uiCanFlags)) { - if (block.m_Top.m_dwBlockFlags & CAN_I_ROOF) + if (block.m_Top.m_uiBlockFlags & CAN_I_ROOF) { // Roof tiles usually don't have the impassable/block tiledata flag, but i don't want flying chars to pass over the wall (bottom tile) // and through roof (top tile) and enter a building in this way return nullptr; } } - else if (dwMapMoveFlags & CAN_I_CLIMB) + else if (uiMapMoveFlags & CAN_I_CLIMB) { // If dwBlockFlags & CAN_I_CLIMB, then it's a "climbable" item (and i can climb it, // since i don't have CAN_I_CLIMB in uiBlockedBy) @@ -2036,9 +2036,9 @@ CRegion *CChar::CheckValidMove( CPointMap &ptDest, dword *pdwBlockFlags, DIR_TYP return nullptr; } - if ( pdwBlockFlags ) - *pdwBlockFlags = dwMapMoveFlags; - if ( pClimbHeight && (dwMapMoveFlags & CAN_I_CLIMB) ) + if (uiBlockFlags) + *uiBlockFlags = uiMapMoveFlags; + if ( pClimbHeight && (uiMapMoveFlags & CAN_I_CLIMB) ) *pClimbHeight = block.m_zClimbHeight; // Be wary that now block.m_Bottom isn't just the "tile with lowest (p.z + height)", because if you are stepping on an item with height != 0, @@ -2062,7 +2062,7 @@ void CChar::FixClimbHeight() CServerMapBlockState block(CAN_I_CLIMB, pt.m_z, pt.m_z + iHeightMount + 3, pt.m_z + 2, iHeightMount); CWorldMap::GetHeightPoint(pt, block, true); - if ( (block.m_Bottom.m_z == pt.m_z) && (block.m_dwBlockFlags & CAN_I_CLIMB) ) // we are standing on stairs + if ( (block.m_Bottom.m_z == pt.m_z) && (block.m_uiBlockFlags & CAN_I_CLIMB) ) // we are standing on stairs m_zClimbHeight = block.m_zClimbHeight; else m_zClimbHeight = 0; diff --git a/src/game/clients/CClient.cpp b/src/game/clients/CClient.cpp index 7a5dd2426..12dde8321 100644 --- a/src/game/clients/CClient.cpp +++ b/src/game/clients/CClient.cpp @@ -1289,8 +1289,8 @@ bool CClient::r_Verb( CScript & s, CTextConsole * pSrc ) // Execute command from const CPointMap po(pObj->GetTopLevelObj()->GetTopPoint()); CPointMap pnt = po; pnt.MoveN( DIR_W, 3 ); - dword dwBlockFlags = m_pChar->GetCanMoveFlags(m_pChar->GetCanFlags()); - pnt.m_z = CWorldMap::GetHeightPoint2( pnt, dwBlockFlags ); // ??? Get Area + uint64 uiBlockFlags = m_pChar->GetCanMoveFlags(m_pChar->GetCanFlags()); + pnt.m_z = CWorldMap::GetHeightPoint2( pnt, uiBlockFlags ); // ??? Get Area m_pChar->m_dirFace = pnt.GetDir( po, m_pChar->m_dirFace ); // Face the player m_pChar->Spell_Teleport( pnt, true, false ); } diff --git a/src/game/components/CCMultiMovable.cpp b/src/game/components/CCMultiMovable.cpp index a0bd762c3..623517778 100644 --- a/src/game/components/CCMultiMovable.cpp +++ b/src/game/components/CCMultiMovable.cpp @@ -479,10 +479,9 @@ bool CCMultiMovable::CanMoveTo(const CPointMap & pt) const if (pItemThis->IsAttr(ATTR_MAGIC)) return true; - dword dwBlockFlags = CAN_I_WATER; - - CWorldMap::GetHeightPoint2(pt, dwBlockFlags, true); - if (dwBlockFlags & CAN_I_WATER) + uint64 uiBlockFlags = CAN_I_WATER; + CWorldMap::GetHeightPoint2(pt, uiBlockFlags, true); + if (uiBlockFlags & CAN_I_WATER) return true; return false; @@ -1212,8 +1211,8 @@ bool CCMultiMovable::r_Verb(CScript & s, CTextConsole * pSrc) // Execute command CPointMap pt = pItemThis->GetTopPoint(); pt.m_z = zold; pItemThis->SetTopZ(-UO_SIZE_Z); // bottom of the world where i won't get in the way. - dword dwBlockFlags = CAN_I_WATER; - char z = CWorldMap::GetHeightPoint2(pt, dwBlockFlags); + uint64 uiBlockFlags = CAN_I_WATER; + char z = CWorldMap::GetHeightPoint2(pt, uiBlockFlags); pItemThis->SetTopZ(zold); // restore z for now. pt.InitPoint(); pt.m_z = z - zold; diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 32e31cda1..785e2aeaa 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -781,11 +781,11 @@ int CItem::IsWeird() const return( ( ptCont == nullptr ) ? 0x2106 : ptCont->IsWeird() ); } -char CItem::GetFixZ( CPointMap pt, dword dwBlockFlags ) +char CItem::GetFixZ( CPointMap pt, uint64 uiBlockFlags ) { - height_t zHeight = CItemBase::GetItemHeight( GetDispID(), &dwBlockFlags ); - CServerMapBlockState block( dwBlockFlags, pt.m_z, pt.m_z + zHeight, pt.m_z + 2, zHeight ); - CWorldMap::GetFixPoint( pt, block ); + height_t zHeight = CItemBase::GetItemHeight( GetDispID(), &uiBlockFlags ); + CServerMapBlockState block(uiBlockFlags, pt.m_z, pt.m_z + zHeight, pt.m_z + 2, zHeight); + CWorldMap::GetFixPoint(pt, block); return block.m_Bottom.m_z; } @@ -3154,7 +3154,7 @@ bool CItem::r_LoadVal( CScript & s ) // Load an item Script m_weight = s.GetArgWVal(); break; case IC_CANUSE: - m_CanUse = s.GetArgVal(); + m_CanUse = s.GetArgULLVal(); break; case IC_CONT: // needs special processing. { diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index 61e0849af..a14b40dbd 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -58,7 +58,7 @@ class CItem : public CObjBase word m_wAmount; // Amount of items in pile. 64K max (or corpse type) IT_TYPE m_type; // What does this item do when dclicked ? defines dynamic_cast type uchar m_containedGridIndex; // Which grid have i been placed in ? (when in a container) - dword m_CanUse; // Base attribute flags. can_u_all/male/female.. + uint64 m_CanUse; // Base attribute flags. can_u_all/male/female.. word m_weight; public: @@ -597,7 +597,7 @@ class CItem : public CObjBase void SetAnim( ITEMID_TYPE id, int64 iTicksTimeout); // time in ticks virtual int IsWeird() const override; - char GetFixZ(CPointMap pt, dword dwBlockFlags = 0); + char GetFixZ(CPointMap pt, uint64 uiBlockFlags = 0Ui64); CCFaction* GetSlayer() const; byte GetSpeed() const; diff --git a/src/game/items/CItemBase.cpp b/src/game/items/CItemBase.cpp index 6fa15987a..5278db39d 100644 --- a/src/game/items/CItemBase.cpp +++ b/src/game/items/CItemBase.cpp @@ -698,61 +698,61 @@ bool CItemBase::GetItemData( ITEMID_TYPE id, CUOItemTypeRec_HS * pData ) // stat return true; } -void CItemBase::GetItemSpecificFlags( const CUOItemTypeRec_HS & tiledata, dword *pdwBlockFlags, IT_TYPE type, ITEMID_TYPE id ) // static +void CItemBase::GetItemSpecificFlags( const CUOItemTypeRec_HS & tiledata, uint64 *uiBlockFlags, IT_TYPE type, ITEMID_TYPE id ) // static { ADDTOCALLSTACK("CItemBase::GetItemSpecificFlags"); if ( type == IT_DOOR ) { - *pdwBlockFlags &= ~CAN_I_BLOCK; + *uiBlockFlags &= ~CAN_I_BLOCK; if ( IsID_DoorOpen(id)) - *pdwBlockFlags &= ~CAN_I_DOOR; + *uiBlockFlags &= ~CAN_I_DOOR; else - *pdwBlockFlags |= CAN_I_DOOR; + *uiBlockFlags |= CAN_I_DOOR; } if ( tiledata.m_flags & UFLAG3_LIGHT ) // this may actually be a moon gate or fire ? - *pdwBlockFlags |= CAN_I_LIGHT; // normally of type IT_LIGHT_LIT; + *uiBlockFlags |= CAN_I_LIGHT; // normally of type IT_LIGHT_LIT; if ( (tiledata.m_flags & UFLAG2_STACKABLE) || type == IT_REAGENT || id == ITEMID_EMPTY_BOTTLE ) - *pdwBlockFlags |= CAN_I_PILE; + *uiBlockFlags |= CAN_I_PILE; } -void CItemBase::GetItemTiledataFlags( dword *pdwCanFlags, ITEMID_TYPE id ) // static +void CItemBase::GetItemTiledataFlags( uint64 *uiCanFlags, ITEMID_TYPE id ) // static { ADDTOCALLSTACK("CItemBase::GetItemTiledataFlags"); CUOItemTypeRec_HS tiledata{}; if ( ! CItemBase::GetItemData( id, &tiledata )) { - *pdwCanFlags = 0; + *uiCanFlags = 0Ui64; return; } if ( tiledata.m_flags & UFLAG4_DOOR ) - *pdwCanFlags |= CAN_I_DOOR; + *uiCanFlags |= CAN_I_DOOR; if ( tiledata.m_flags & UFLAG1_WATER ) - *pdwCanFlags |= CAN_I_WATER; + *uiCanFlags |= CAN_I_WATER; if ( tiledata.m_flags & UFLAG2_PLATFORM ) - *pdwCanFlags |= CAN_I_PLATFORM; + *uiCanFlags |= CAN_I_PLATFORM; if ( tiledata.m_flags & UFLAG1_BLOCK ) - *pdwCanFlags |= CAN_I_BLOCK; + *uiCanFlags |= CAN_I_BLOCK; if ( tiledata.m_flags & UFLAG2_CLIMBABLE ) - *pdwCanFlags |= CAN_I_CLIMB; + *uiCanFlags |= CAN_I_CLIMB; if ( tiledata.m_flags & UFLAG1_DAMAGE ) - *pdwCanFlags |= CAN_I_FIRE; + *uiCanFlags |= CAN_I_FIRE; if ( tiledata.m_flags & UFLAG4_ROOF ) - *pdwCanFlags |= CAN_I_ROOF; + *uiCanFlags |= CAN_I_ROOF; if ( tiledata.m_flags & UFLAG4_HOVEROVER ) - *pdwCanFlags |= CAN_I_HOVER; + *uiCanFlags |= CAN_I_HOVER; } -height_t CItemBase::GetItemHeightFlags( const CUOItemTypeRec_HS & tiledata, dword *pdwCanFlags ) // static +height_t CItemBase::GetItemHeightFlags( const CUOItemTypeRec_HS & tiledata, uint64 *uiCanFlags ) // static { ADDTOCALLSTACK("CItemBase::GetItemHeightFlags"); // Chairs are marked as blocking for some reason ? if ( tiledata.m_flags & UFLAG4_DOOR ) // door { - *pdwCanFlags = CAN_I_DOOR; + *uiCanFlags = CAN_I_DOOR; return tiledata.m_height; } @@ -760,36 +760,36 @@ height_t CItemBase::GetItemHeightFlags( const CUOItemTypeRec_HS & tiledata, dwor { if ( tiledata.m_flags & UFLAG1_WATER ) // water { - *pdwCanFlags = CAN_I_WATER; + *uiCanFlags = CAN_I_WATER; return tiledata.m_height; } - *pdwCanFlags = CAN_I_BLOCK; + *uiCanFlags = CAN_I_BLOCK; } else { //DEBUG_ERR(("tiledata.m_flags 0x%x\n",tiledata.m_flags)); - *pdwCanFlags = 0; + *uiCanFlags = 0; if ( ! ( tiledata.m_flags & (UFLAG2_PLATFORM|UFLAG4_ROOF|UFLAG4_HOVEROVER) )) return 0; // have no effective height if it doesn't block. } if ( tiledata.m_flags & UFLAG4_ROOF) - *pdwCanFlags |= CAN_I_ROOF; + *uiCanFlags |= CAN_I_ROOF; else if ( tiledata.m_flags & UFLAG2_PLATFORM ) - *pdwCanFlags |= CAN_I_PLATFORM; + *uiCanFlags |= CAN_I_PLATFORM; if ( tiledata.m_flags & UFLAG2_CLIMBABLE ) { // actual standing height is height/2 - *pdwCanFlags |= CAN_I_CLIMB; + *uiCanFlags |= CAN_I_CLIMB; } if ( tiledata.m_flags & UFLAG4_HOVEROVER ) - *pdwCanFlags |= CAN_I_HOVER; + *uiCanFlags |= CAN_I_HOVER; //DEBUG_WARN(("tiledata.m_height(%d)\n",tiledata.m_height)); return tiledata.m_height; } -height_t CItemBase::GetItemHeight( ITEMID_TYPE id, dword *pdwBlockFlags ) // static +height_t CItemBase::GetItemHeight( ITEMID_TYPE id, uint64 *uiBlockFlags ) // static { ADDTOCALLSTACK_INTENSIVE("CItemBase::GetItemHeight"); // Get just the height and the blocking flags for the item by id. @@ -804,7 +804,7 @@ height_t CItemBase::GetItemHeight( ITEMID_TYPE id, dword *pdwBlockFlags ) // sta CItemBase * pBase = dynamic_cast (pBaseStub); if ( pBase ) { - *pdwBlockFlags = pBase->m_Can & CAN_I_MOVEMASK; + *uiBlockFlags = pBase->m_Can & CAN_I_MOVEMASK; return pBase->GetHeight(); } } @@ -813,15 +813,15 @@ height_t CItemBase::GetItemHeight( ITEMID_TYPE id, dword *pdwBlockFlags ) // sta CUOItemTypeRec_HS tiledata = {}; if ( ! GetItemData( id, &tiledata )) { - *pdwBlockFlags = CAN_I_MOVEMASK; + *uiBlockFlags = CAN_I_MOVEMASK; return UO_SIZE_Z; } if ( IsID_Chair( id ) ) { - *pdwBlockFlags = 0; + *uiBlockFlags = 0; return 0; // have no effective height if they don't block. } - return GetItemHeightFlags( tiledata, pdwBlockFlags ); + return GetItemHeightFlags( tiledata, uiBlockFlags ); } IT_TYPE CItemBase::GetTypeBase( ITEMID_TYPE id, const CUOItemTypeRec_HS &tiledata ) // static @@ -1186,7 +1186,7 @@ bool CItemBase::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc } break; case IBC_CANUSE: - sVal.FormatHex( m_CanUse ); + sVal.FormatULLHex( m_CanUse ); break; case IBC_DYE: sVal.FormatVal( m_Can & CAN_I_DYE ); @@ -1508,7 +1508,7 @@ bool CItemBase::r_LoadVal( CScript &s ) } break; case IBC_CANUSE: - m_CanUse = s.GetArgVal(); + m_CanUse = s.GetArgULLVal(); break; case IBC_DISPID: // Can't set this. diff --git a/src/game/items/CItemBase.h b/src/game/items/CItemBase.h index bbb5c2faa..19774c5e8 100644 --- a/src/game/items/CItemBase.h +++ b/src/game/items/CItemBase.h @@ -34,7 +34,7 @@ class CItemBase : public CBaseBaseDef static const char *m_sClassName; SKILL_TYPE m_iSkill; - dword m_CanUse; // CanUse flags. + uint64 m_CanUse; // CanUse flags. // Not applicable to all. CResourceQtyArray m_SkillMake; // what skills to create this ? (and non-consumed items) @@ -227,9 +227,9 @@ class CItemBase : public CBaseBaseDef protected: static void ReplaceItemBase( CItemBase * pOld, CResourceDef * pNew ); public: - static void GetItemTiledataFlags( dword *pdwCanFlags, ITEMID_TYPE id ); - static height_t GetItemHeightFlags( const CUOItemTypeRec_HS & tile, dword *pdwCanFlags ); - static void GetItemSpecificFlags( const CUOItemTypeRec_HS & tile, dword *pdwCanFlags, IT_TYPE type, ITEMID_TYPE id ); + static void GetItemTiledataFlags( uint64 *uiCanFlags, ITEMID_TYPE id ); + static height_t GetItemHeightFlags( const CUOItemTypeRec_HS & tile, uint64 *uiCanFlags ); + static void GetItemSpecificFlags( const CUOItemTypeRec_HS & tile, uint64 *uiCanFlags, IT_TYPE type, ITEMID_TYPE id ); static bool IsTypeArmor( IT_TYPE type ) noexcept; static bool IsTypeWeapon( IT_TYPE type ) noexcept; static bool IsTypeSpellbook( IT_TYPE type ) noexcept; @@ -261,7 +261,7 @@ class CItemBase : public CBaseBaseDef static tchar * GetNamePluralize( lpctstr pszNameBase, bool fPluralize ); static bool GetItemData( ITEMID_TYPE id, CUOItemTypeRec_HS * ptile ); - static height_t GetItemHeight( ITEMID_TYPE id, dword *pdwBlockFlags ); + static height_t GetItemHeight( ITEMID_TYPE id, uint64 *uiBlockFlags ); static CREID_TYPE FindCharTrack( ITEMID_TYPE trackID ); @@ -364,7 +364,7 @@ class CItemBaseDupe : public CResourceDef height_t m_Height; public: - dword m_Can; + uint64 m_Can; static const char *m_sClassName; CItemBaseDupe(ITEMID_TYPE id, CItemBase* pMasterItem); diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index 367318b36..484e070a1 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -3308,14 +3308,14 @@ CItem *CItemMulti::Multi_Create(CChar *pChar, const CItemBase * pItemDef, CPoint return nullptr; } - dword dwBlockFlags = (fShip) ? CAN_C_SWIM : CAN_C_WALK; // Flags to check: Ships should check for swimable tiles. + uint64 uiBlockFlags = (fShip) ? CAN_C_SWIM : CAN_C_WALK; // Flags to check: Ships should check for swimable tiles. /* * Intensive check returning the top Z point of the given X, Y coords * It uses the dwBlockBlacks passed to check the new Z level. * Also update those dwBlockFlags with all the flags found at the given location. * 3rd param is set to also update Z with any house component found in the proccess. */ - ptn.m_z = CWorldMap::GetHeightPoint2(ptn, dwBlockFlags, true); + ptn.m_z = CWorldMap::GetHeightPoint2(ptn, uiBlockFlags, true); if (abs(ptn.m_z - pt.m_z) > 4) // Difference of Z > 4? so much, stop. { pChar->SysMessageDefault(DEFMSG_ITEMUSE_MULTI_BUMP); @@ -3323,13 +3323,13 @@ CItem *CItemMulti::Multi_Create(CChar *pChar, const CItemBase * pItemDef, CPoint } if (fShip) { - if (!(dwBlockFlags & CAN_I_WATER)) // Ships must be placed on water. + if (!(uiBlockFlags & CAN_I_WATER)) // Ships must be placed on water. { pChar->SysMessageDefault(DEFMSG_ITEMUSE_MULTI_SHIPW); return nullptr; } } - else if (dwBlockFlags & (CAN_I_WATER | CAN_I_BLOCK | CAN_I_CLIMB)) // Did the intensive check find some undesired flags? Stop. + else if (uiBlockFlags & (CAN_I_WATER | CAN_I_BLOCK | CAN_I_CLIMB)) // Did the intensive check find some undesired flags? Stop. { pChar->SysMessageDefault(DEFMSG_ITEMUSE_MULTI_BLOCKED); return nullptr; diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index 6b1bf5e7d..7275ef219 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -231,8 +231,8 @@ void CItemMultiCustom::EndCustomize(bool fForce) CPointMap ptDest = Multi_GetSign()->GetTopPoint(); // find ground height, since the signpost is usually raised - dword dwBlockFlags = 0; - ptDest.m_z = CWorldMap::GetHeightPoint2(ptDest, dwBlockFlags, true); + uint64 uiBlockFlags = 0Ui64; + ptDest.m_z = CWorldMap::GetHeightPoint2(ptDest, uiBlockFlags, true); pChar->MoveToChar(ptDest); pChar->UpdateMove(ptOld); diff --git a/src/network/send.cpp b/src/network/send.cpp index 34972a869..0be915222 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -5407,4 +5407,4 @@ PacketGlobalChat::PacketGlobalChat(const CClient* target, byte unknown, byte act trim(); push(target); -} \ No newline at end of file +} From f7c948a92efa1f6825bba1024532db14d65e18ab Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 2 Apr 2024 18:39:00 +0100 Subject: [PATCH 37/90] Build Fix --- src/game/chars/CChar.cpp | 2 +- src/game/chars/CChar.h | 2 +- src/game/chars/CCharAct.cpp | 2 +- src/game/chars/CCharSpell.cpp | 4 ++-- src/game/items/CItem.h | 2 +- src/game/items/CItemBase.cpp | 2 +- src/game/items/CItemMultiCustom.cpp | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 49bec9761..724e1d587 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -2822,7 +2822,7 @@ bool CChar::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc, bo sVal.FormatULLHex( UINT64_MAX ); else { - uint64 uiBlockFlags = 0Ui64; + uint64 uiBlockFlags = 0; CWorldMap::GetHeightPoint2(ptDst, uiBlockFlags, true); sVal.FormatULLHex(uiBlockFlags); } diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 333719a57..b38ddddc4 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -341,7 +341,7 @@ public: void StatFlag_Clear(uint64 uiStatFlag) noexcept; //protected: void _StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; - char GetFixZ(const CPointMap& pt, uint64 uiBlockFlags = 0Ui64); + char GetFixZ(const CPointMap& pt, uint64 uiBlockFlags = 0); bool IsPriv( word flag ) const; virtual PLEVEL_TYPE GetPrivLevel() const override; diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index a8b314a45..9cf9d7cb8 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -3401,7 +3401,7 @@ CRegion * CChar::CanMoveWalkTo( CPointMap & ptDst, bool fCheckChars, bool fCheck } // ok to go here ? physical blocking objects ? - uint64 uiBlockFlags = 0Ui64; + uint64 uiBlockFlags = 0; height_t ClimbHeight = 0; CRegion *pArea = nullptr; diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index ef1ef0105..0d5b4278b 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -2162,7 +2162,7 @@ void CChar::Spell_Field(CPointMap pntTarg, ITEMID_TYPE idEW, ITEMID_TYPE idNS, u ptg.m_y += (short)(iy); } - uint64 uiBlockFlags = 0Ui64; + uint64 uiBlockFlags = 0; CWorldMap::GetHeightPoint2(ptg, uiBlockFlags, true); if (uiBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR)) { @@ -2589,7 +2589,7 @@ CChar * CChar::Spell_Summon_Try(SPELL_TYPE spell, CPointMap ptTarg, CREID_TYPE i if (IsSetMagicFlags(MAGICF_SUMMONWALKCHECK)) // check if the target location is valid { const uint64 uiCan = pChar->GetCanFlags() & CAN_C_MOVEMASK; - uint64 uiBlockFlags = 0Ui64; + uint64 uiBlockFlags = 0; CWorldMap::GetHeightPoint2(ptTarg, uiBlockFlags, true); if (uiBlockFlags & ~uiCan) diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index a14b40dbd..3c1ae2718 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -597,7 +597,7 @@ class CItem : public CObjBase void SetAnim( ITEMID_TYPE id, int64 iTicksTimeout); // time in ticks virtual int IsWeird() const override; - char GetFixZ(CPointMap pt, uint64 uiBlockFlags = 0Ui64); + char GetFixZ(CPointMap pt, uint64 uiBlockFlags = 0); CCFaction* GetSlayer() const; byte GetSpeed() const; diff --git a/src/game/items/CItemBase.cpp b/src/game/items/CItemBase.cpp index 5278db39d..5d285aff9 100644 --- a/src/game/items/CItemBase.cpp +++ b/src/game/items/CItemBase.cpp @@ -724,7 +724,7 @@ void CItemBase::GetItemTiledataFlags( uint64 *uiCanFlags, ITEMID_TYPE id ) // st CUOItemTypeRec_HS tiledata{}; if ( ! CItemBase::GetItemData( id, &tiledata )) { - *uiCanFlags = 0Ui64; + *uiCanFlags = 0; return; } diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index 7275ef219..a5e19d9f8 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -231,7 +231,7 @@ void CItemMultiCustom::EndCustomize(bool fForce) CPointMap ptDest = Multi_GetSign()->GetTopPoint(); // find ground height, since the signpost is usually raised - uint64 uiBlockFlags = 0Ui64; + uint64 uiBlockFlags = 0; ptDest.m_z = CWorldMap::GetHeightPoint2(ptDest, uiBlockFlags, true); pChar->MoveToChar(ptDest); From 33db9306b55f5cce3e56fad4d822374921f5b06b Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 2 Apr 2024 19:43:22 +0100 Subject: [PATCH 38/90] Chat Debug Possible Fix Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/channels/354358315373035542/483721253773901824/1224030729906815077) --- Changelog.txt | 3 ++- src/game/clients/CChat.cpp | 9 ++++++--- src/game/clients/CChatChanMember.cpp | 11 ++++++++--- src/game/clients/CChatChannel.cpp | 18 +++++++++--------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 064f0a786..1a305f09c 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3532,4 +3532,5 @@ Added: ARGO to get bit uid under @ResourceGather and @RegionResourceGather trigg Fixed: Possible fix for the OnRegionTrigger getting called on invalid region while multi creating/removing. 02-04-2024, xwerswoodx -Changed: dword CAN flags changed with uint64 to increase limits. \ No newline at end of file +Changed: dword CAN flags changed with uint64 to increase limits. +Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/channels/354358315373035542/483721253773901824/1224030729906815077) \ No newline at end of file diff --git a/src/game/clients/CChat.cpp b/src/game/clients/CChat.cpp index 257eb9964..cc60350ce 100644 --- a/src/game/clients/CChat.cpp +++ b/src/game/clients/CChat.cpp @@ -382,9 +382,12 @@ void CChat::QuitChat(CChatChanMember* pClient) ADDTOCALLSTACK("CChat::QuitChat"); // Remove from old channel (if any) - CChatChannel* pCurrentChannel = pClient->GetChannel(); - if (pCurrentChannel) - pCurrentChannel->RemoveMember(pClient); + if (!pClient) + return; + + CChatChannel* pCurrentChannel = pClient->GetChannel(); + if (pCurrentChannel) + pCurrentChannel->RemoveMember(pClient); } void CChat::FormatName(CSString& sName, const CChatChanMember* pMember, bool fSystem) diff --git a/src/game/clients/CChatChanMember.cpp b/src/game/clients/CChatChanMember.cpp index 3034953ab..476e6a7de 100644 --- a/src/game/clients/CChatChanMember.cpp +++ b/src/game/clients/CChatChanMember.cpp @@ -196,12 +196,17 @@ const CClient * CChatChanMember::GetClientActive() const lpctstr CChatChanMember::GetChatName() const { ADDTOCALLSTACK("CChatChanMember::GetChatName"); - return( GetClientActive()->GetAccount()->m_sChatName ); + const CClient *pClient = GetClientActive(); + + if (pClient) + return(pClient->GetAccount()->m_sChatName); + return ""; } bool CChatChanMember::IsIgnoring(lpctstr pszName) const { - return( FindIgnoringIndex( pszName ) != sl::scont_bad_index() ); + ADDTOCALLSTACK("CChatChanMember::IsIgnoring"); + return( FindIgnoringIndex(pszName) != sl::scont_bad_index() ); } void CChatChanMember::HideCharacterName() @@ -247,4 +252,4 @@ void CChatChanMember::RemoveIgnore(lpctstr pszName) SendChatMsg(CHATMSG_NotIgnoring, pszName); else ToggleIgnore(pszName); -} \ No newline at end of file +} diff --git a/src/game/clients/CChatChannel.cpp b/src/game/clients/CChatChannel.cpp index 571c7d769..96caf2f98 100644 --- a/src/game/clients/CChatChannel.cpp +++ b/src/game/clients/CChatChannel.cpp @@ -161,6 +161,9 @@ void CChatChannel::RenameChannel(CChatChanMember* pBy, lpctstr pszName) void CChatChannel::SendMember(CChatChanMember* pMember, CChatChanMember* pToMember) { ADDTOCALLSTACK("CChatChannel::SendMember"); + if (!pMember) + return; + CSString sName; g_Serv.m_Chats.FormatName(sName, pMember); @@ -193,30 +196,27 @@ void CChatChannel::SendMember(CChatChanMember* pMember, CChatChanMember* pToMemb void CChatChannel::RemoveMember(CChatChanMember * pMember) { ADDTOCALLSTACK("CChatChannel::RemoveMember"); - - for ( size_t i = 0; i < m_Members.size(); ) + for ( size_t i = 0; i < m_Members.size(); ++i) { // Tell the other clients in this channel (if any) you are leaving (including yourself) CClient * pClient = m_Members[i]->GetClientActive(); - if ( pClient == nullptr ) // auto-remove offline clients + if (!pClient) // auto-remove offline clients { m_Members[i]->SetChannel(nullptr); - m_Members.erase(m_Members.begin() + i); + m_Members.erase_index(i); continue; } - if (!pClient->m_fUseNewChatSystem) + if (!pClient->m_fUseNewChatSystem && pMember) pClient->addChatSystemMessage(CHATCMD_RemoveMemberFromChannel, pMember->GetChatName()); - if (m_Members[i] == pMember) // disjoin + if (pMember && m_Members[i] == pMember) // disjoin { pClient->addChatSystemMessage(pClient->m_fUseNewChatSystem ? CHATCMD_LeftChannel : CHATCMD_ClearMembers, static_cast(m_sName)); - m_Members.erase(m_Members.begin() + i); + m_Members.erase_index(i); break; } - - ++i; } // Delete the channel if there's no members left From 7b806e6e531e6336764c031e04eeb29e44c4c9f4 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 2 Apr 2024 19:48:17 +0100 Subject: [PATCH 39/90] Added Missing Data to sphere.ini --- src/sphere.ini | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/sphere.ini b/src/sphere.ini index 051d7bcb2..940cd99f6 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -447,22 +447,23 @@ DisplayArmorAsPercent = 0 DisplayElementalResistance = 0 // Extra magic flags to control magic/magery behaviour (default:0, 0.55i compatible) -// MAGICF_NODIRCHANGE 00001 // Not rotate player when casting/targeting -// MAGICF_PRECAST 00002 // Precasting (cast spell before target prompt) -// MAGICF_IGNOREAR 00004 // Magic damage ignore ar -// MAGICF_CANHARMSELF 00008 // Magic can do damage on self -// MAGICF_STACKSTATS 00010 // Different stat spells don't cancel each other out -// MAGICF_FREEZEONCAST 00020 // No movement whilst casting -// MAGICF_SUMMONWALKCHECK 00040 // Summoned creatures should be able to walk on the target location (e.g. water creatures to be summoned on water) -// MAGICF_NOFIELDSOVERWALLS 00080 // Field spells cannot cross over blocking objects -// MAGICF_NOANIM 00100 // Auto SPELLFLAG_NO_ANIM in every spell -// MAGICF_OSIFORMULAS 00200 // Calculate spell damage and duration based on OSI formulas -// MAGICF_NOCASTFROZENHANDS 00400 // Can't cast spells if got paralyzed holding something on hands -// MAGICF_POLYMORPHSTATS 00800 // Polymorph spells give out stats based on base chars (old behaviour backwards) -// MAGICF_OVERRIDEFIELDS 01000 // Prevent cast multiple field spells on the same tile, making the new field tile remove the previous field -// MAGICF_CASTPARALYZED 02000 // Can cast even if paralyzed -// MAGICF_NOREFLECTOWN 04000 // Do not reflect own spell if the spell has already reflected from the target. -// MAGICF_DELREFLECTOWN 08000 // Remove reflection instead of damage himself when NOREFLECTOWN active if the spell reflected from another target. +// MAGICF_NODIRCHANGE 000001 // Not rotate player when casting/targeting +// MAGICF_PRECAST 000002 // Precasting (cast spell before target prompt) +// MAGICF_IGNOREAR 000004 // Magic damage ignore ar +// MAGICF_CANHARMSELF 000008 // Magic can do damage on self +// MAGICF_STACKSTATS 000010 // Different stat spells don't cancel each other out +// MAGICF_FREEZEONCAST 000020 // No movement whilst casting +// MAGICF_SUMMONWALKCHECK 000040 // Summoned creatures should be able to walk on the target location (e.g. water creatures to be summoned on water) +// MAGICF_NOFIELDSOVERWALLS 000080 // Field spells cannot cross over blocking objects +// MAGICF_NOANIM 000100 // Auto SPELLFLAG_NO_ANIM in every spell +// MAGICF_OSIFORMULAS 000200 // Calculate spell damage and duration based on OSI formulas +// MAGICF_NOCASTFROZENHANDS 000400 // Can't cast spells if got paralyzed holding something on hands +// MAGICF_POLYMORPHSTATS 000800 // Polymorph spells give out stats based on base chars (old behaviour backwards) +// MAGICF_OVERRIDEFIELDS 001000 // Prevent cast multiple field spells on the same tile, making the new field tile remove the previous field +// MAGICF_CASTPARALYZED 002000 // Can cast even if paralyzed +// MAGICF_NOREFLECTOWN 004000 // Do not reflect own spell if the spell has already reflected from the target. +// MAGICF_DELREFLECTOWN 008000 // Remove reflection instead of damage himself when NOREFLECTOWN active if the spell reflected from another target. +// MAGICF_REACTIVEARMORTH 010000 // Increases Reactive Armor spell range from 1 block to 2. //MagicFlags=0 // Max amount of each Stat gained through Polymorph spell. This affects separatelly to each stat. @@ -569,6 +570,9 @@ ItemsMaxAmount=60000 // Set to 1 to allow players to take equipment from their pets' paperdoll CanUndressPets=1 +// Set to 1 to allow players to heal their pets by dropping potion on them. +CanPetsDrinkPotion=1 + // Monsters run when scared of death MonsterFear=0 From a36e87980238050510660f6f78a890bc08665386 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 3 Apr 2024 16:02:02 +0100 Subject: [PATCH 40/90] t_crop update Added: "MOREX" key to set amount of fruit given when the crop ripped. --- Changelog.txt | 5 ++++- src/game/items/CItem.h | 1 + src/game/items/CItemPlant.cpp | 11 ++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 1a305f09c..2a805c4c4 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3533,4 +3533,7 @@ Fixed: Possible fix for the OnRegionTrigger getting called on invalid region whi 02-04-2024, xwerswoodx Changed: dword CAN flags changed with uint64 to increase limits. -Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/channels/354358315373035542/483721253773901824/1224030729906815077) \ No newline at end of file +Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/channels/354358315373035542/483721253773901824/1224030729906815077) + +03-04-2024, xwerswoodx +Added: "MOREX" key to set amount of fruit given when the crop ripped. \ No newline at end of file diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index 3c1ae2718..20d616cb5 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -345,6 +345,7 @@ class CItem : public CObjBase { int32 m_Respawn_Sec; // more1 = plant respawn time in seconds. (for faster growth plants) CResourceIDBase m_ridFruitOverride; // more2 = Override for TDATA2 = What is the fruit of this plant + word m_ridAmount; // morex = amount of fruit. } m_itCrop; // IT_TREE diff --git a/src/game/items/CItemPlant.cpp b/src/game/items/CItemPlant.cpp index d4a96ca8a..859f1d8dd 100644 --- a/src/game/items/CItemPlant.cpp +++ b/src/game/items/CItemPlant.cpp @@ -27,7 +27,8 @@ bool CItem::Plant_Use(CChar *pChar) ITEMID_TYPE iGrowID = (ITEMID_TYPE)pItemDef->m_ttCrops.m_ridGrow.GetResIndex(); ITEMID_TYPE iFruitIDOverride = (ITEMID_TYPE)m_itCrop.m_ridFruitOverride.GetResIndex(); - if ( (iGrowID == ITEMID_NOTHING) && (iFruitIDOverride != ITEMID_NOTHING) ) // If we set an override, we can reap this at every stage + word iAmount = std::max(m_itCrop.m_ridAmount, (word)1); + if (iGrowID != ITEMID_NOTHING) // If we set an override, we can reap this at every stage { // not ripe. (but we could just eat it if we are herbivorous ?) pChar->SysMessageDefault(DEFMSG_CROPS_NOT_RIPE); @@ -45,8 +46,12 @@ bool CItem::Plant_Use(CChar *pChar) else { CItem *pItemFruit = CItem::CreateScript(iFruitID, pChar); - if ( pItemFruit ) - pChar->ItemBounce(pItemFruit); + if (pItemFruit) + { + if (pItemFruit->IsStackableType()) + pItemFruit->SetAmount(iAmount); + pChar->ItemBounce(pItemFruit); + } } Plant_CropReset(); From 592f0a6f4099958084875a341ceafc2a143f0b46 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 3 Apr 2024 17:54:19 +0100 Subject: [PATCH 41/90] Crop update Changed: Now @Create trigger called when crop grow to let people to change MORE values in stages if needed. Added: @ResourceTest trigger added for crops. (This trigger works seperately for every stage) Added: @ResourceGather trigger added for crops. (This trigger works seperately for every stage) --- Changelog.txt | 19 +++++++++++- src/game/CObjBase.h | 2 ++ src/game/items/CItem.cpp | 2 ++ src/game/items/CItem.h | 1 + src/game/items/CItemPlant.cpp | 57 +++++++++++++++++++++++++++++------ 5 files changed, 71 insertions(+), 10 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 2a805c4c4..7e76f1c0b 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3536,4 +3536,21 @@ Changed: dword CAN flags changed with uint64 to increase limits. Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/channels/354358315373035542/483721253773901824/1224030729906815077) 03-04-2024, xwerswoodx -Added: "MOREX" key to set amount of fruit given when the crop ripped. \ No newline at end of file +Added: "MOREX" key to set amount of fruit given when the crop ripped. +Changed: Now @Create trigger called when crop grow to let people to change MORE values in stages if needed. +Added: @ResourceTest trigger added for crops. (This trigger works seperately for every stage) + I: Crop UID + SRC: Player who uses plant. + ARGN1: Next state item ID [Writeable] + ARGN2: Fruit ID (if exists) [Writeable] + ARGN3: Fruit ID Override (if exists) [Writeable] + - Returns: + 1: Stop the fruit checks. +Added: @ResourceGather trigger added for crops. (This trigger works seperately for every stage) + I: Crop UID + SRC: Player who is gathering plant. + ARGN1: Amount of fruit. [Writeable] + ARGO: Fruit UID + - Returns: + 1: Prevent player to gather fruit. + 6: Let player to gather fruit but it will drop to the ground instead of backpack. \ No newline at end of file diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index c73595956..c25695806 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -1048,6 +1048,8 @@ enum ITRIG_TYPE ITRIG_Redeed, // Redeeding a multi. ITRIG_RegionEnter, // Ship entering a new region. ITRIG_RegionLeave, // Ship leaving the region. + ITRIG_ResourceGather, + ITRIG_ResourceTest, ITRIG_Sell, // I'm being sold. ITRIG_Ship_Move, // I'm a ship and i'm move around. ITRIG_Ship_Stop, // I'm a ship and i'm stop around. diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 785e2aeaa..c270deb5d 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -77,6 +77,8 @@ lpctstr const CItem::sm_szTrigName[ITRIG_QTY+1] = // static "@Redeed", "@RegionEnter", "@RegionLeave", + "@ResourceGather", + "@ResourceTest", "@SELL", "@Ship_Move", "@Ship_Stop", diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index 20d616cb5..a5a81d1d2 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -840,6 +840,7 @@ protected: virtual void _SetTimeout(int64 iMsecs) override final; bool Plant_OnTick(); void Plant_CropReset(); bool Plant_Use( CChar * pChar ); + bool Plant_SetID(ITEMID_TYPE id); virtual void DupeCopy( const CObjBase * pItem ) override; CItem * UnStackSplit( word amount, CChar * pCharSrc = nullptr ); diff --git a/src/game/items/CItemPlant.cpp b/src/game/items/CItemPlant.cpp index 859f1d8dd..9923e04e7 100644 --- a/src/game/items/CItemPlant.cpp +++ b/src/game/items/CItemPlant.cpp @@ -1,7 +1,11 @@ +#include "CItem.h" #include "../chars/CChar.h" +#include "../triggers.h" #include "../CWorldMap.h" -#include "CItem.h" +#include "../../common/CScriptTriggerArgs.h" +#include "../../common/resource/CResourceID.h" +#include "../CServer.h" void CItem::Plant_SetTimer() { @@ -26,8 +30,20 @@ bool CItem::Plant_Use(CChar *pChar) const CItemBase* pItemDef = Item_GetDef(); ITEMID_TYPE iGrowID = (ITEMID_TYPE)pItemDef->m_ttCrops.m_ridGrow.GetResIndex(); - ITEMID_TYPE iFruitIDOverride = (ITEMID_TYPE)m_itCrop.m_ridFruitOverride.GetResIndex(); + ITEMID_TYPE iFruitID = (ITEMID_TYPE)pItemDef->m_ttCrops.m_ridFruit.GetResIndex(); + ITEMID_TYPE iFruitIDOverride = (ITEMID_TYPE)m_itCrop.m_ridFruitOverride.GetResIndex(); word iAmount = std::max(m_itCrop.m_ridAmount, (word)1); + if (IsTrigUsed(TRIGGER_RESOURCETEST)) + { + CScriptTriggerArgs args(iGrowID, iFruitID, iFruitIDOverride); + TRIGRET_TYPE iRet = OnTrigger(ITRIG_ResourceTest, pChar, &args); + iGrowID = (ITEMID_TYPE)(RES_GET_INDEX(args.m_iN1)); + iFruitID = (ITEMID_TYPE)(RES_GET_INDEX(args.m_iN2)); + iFruitIDOverride = (ITEMID_TYPE)(RES_GET_INDEX(args.m_iN3)); + if (iRet == TRIGRET_RET_TRUE) + return true; + } + if (iGrowID != ITEMID_NOTHING) // If we set an override, we can reap this at every stage { // not ripe. (but we could just eat it if we are herbivorous ?) @@ -35,25 +51,41 @@ bool CItem::Plant_Use(CChar *pChar) return true; } - ITEMID_TYPE iFruitID = ITEMID_NOTHING; if ( iFruitIDOverride != ITEMID_NOTHING ) iFruitID = iFruitIDOverride; - else - iFruitID = (ITEMID_TYPE)pItemDef->m_ttCrops.m_ridFruit.GetResIndex(); if ( iFruitID == ITEMID_NOTHING ) pChar->SysMessageDefault(DEFMSG_CROPS_NO_FRUIT); else { CItem *pItemFruit = CItem::CreateScript(iFruitID, pChar); + iAmount = (pItemFruit->IsStackableType() ? iAmount : 1); if (pItemFruit) { - if (pItemFruit->IsStackableType()) - pItemFruit->SetAmount(iAmount); + if (IsTrigUsed(TRIGGER_RESOURCEGATHER)) + { + CScriptTriggerArgs args(iAmount); + args.m_pO1 = pItemFruit; + TRIGRET_TYPE iRet = OnTrigger(ITRIG_ResourceGather, pChar, &args); + iAmount = (word)(args.m_iN1 > 0 ? args.m_iN1 : 1); + if (iRet == TRIGRET_RET_TRUE) + { + pItemFruit->Delete(true); + return true; + } + else if (iRet == TRIGRET_RET_HALFBAKED) + { + pItemFruit->SetAmount(iAmount); + pItemFruit->MoveToDecay(GetTopPoint(), g_Cfg.m_iDecay_Item); + goto cropReset; + } + } + pItemFruit->SetAmount(iAmount); pChar->ItemBounce(pItemFruit); } } + cropReset: Plant_CropReset(); pChar->UpdateAnimate(ANIM_BOW); pChar->Sound(0x13e); @@ -118,13 +150,20 @@ bool CItem::Plant_OnTick() } else if ( iGrowID ) { - SetID(iGrowID); + Plant_SetID(iGrowID); Update(); } return true; } +bool CItem::Plant_SetID(ITEMID_TYPE id) +{ + bool iRet = SetID(id); + OnTrigger(ITRIG_Create, &g_Serv, nullptr); + return iRet; +} + // Animals will eat crops before they are ripe, so we need a way to reset them prematurely void CItem::Plant_CropReset() { @@ -140,7 +179,7 @@ void CItem::Plant_CropReset() const CItemBase *pItemDef = Item_GetDef(); ITEMID_TYPE iResetID = (ITEMID_TYPE)pItemDef->m_ttCrops.m_ridReset.GetResIndex(); if ( iResetID != ITEMID_NOTHING ) - SetID(iResetID); + Plant_SetID(iResetID); Plant_SetTimer(); RemoveFromView(); // remove from most screens. From e080570d7623805d59dd034485c0d58d0749f553 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 3 Apr 2024 21:12:49 +0100 Subject: [PATCH 42/90] Invalid Resource ID Fixed: Possible fix for invalid ResourceID warnings. (Issue: #1071) --- Changelog.txt | 7 ++++--- src/common/resource/CResourceHolder.cpp | 9 ++++++--- src/game/chars/CChar.cpp | 4 ++-- src/game/chars/CCharSkill.cpp | 3 +++ src/game/clients/CClientMsg.cpp | 9 ++++++--- 5 files changed, 21 insertions(+), 11 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 7e76f1c0b..ee53cc4c1 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3538,7 +3538,7 @@ Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/ 03-04-2024, xwerswoodx Added: "MOREX" key to set amount of fruit given when the crop ripped. Changed: Now @Create trigger called when crop grow to let people to change MORE values in stages if needed. -Added: @ResourceTest trigger added for crops. (This trigger works seperately for every stage) +Added: @ResourceTest trigger added for crops. (This trigger works separately for every stage) I: Crop UID SRC: Player who uses plant. ARGN1: Next state item ID [Writeable] @@ -3546,11 +3546,12 @@ Added: @ResourceTest trigger added for crops. (This trigger works seperately for ARGN3: Fruit ID Override (if exists) [Writeable] - Returns: 1: Stop the fruit checks. -Added: @ResourceGather trigger added for crops. (This trigger works seperately for every stage) +Added: @ResourceGather trigger added for crops. (This trigger works separately for every stage) I: Crop UID SRC: Player who is gathering plant. ARGN1: Amount of fruit. [Writeable] ARGO: Fruit UID - Returns: 1: Prevent player to gather fruit. - 6: Let player to gather fruit but it will drop to the ground instead of backpack. \ No newline at end of file + 6: Let player to gather fruit but it will drop to the ground instead of backpack. +Fixed: Possible fix for invalid ResourceID warnings. (Issue: #1071) \ No newline at end of file diff --git a/src/common/resource/CResourceHolder.cpp b/src/common/resource/CResourceHolder.cpp index ae1928e6f..43072b1b1 100644 --- a/src/common/resource/CResourceHolder.cpp +++ b/src/common/resource/CResourceHolder.cpp @@ -287,9 +287,12 @@ lpctstr CResourceHolder::ResourceGetName( const CResourceID& rid ) const ADDTOCALLSTACK("CResourceHolder::ResourceGetName"); // Get a portable name for the resource id type. - const CResourceDef * pResourceDef = ResourceGetDef( rid ); - if ( pResourceDef ) - return pResourceDef->GetResourceName(); + if (rid.IsValidResource()) + { + const CResourceDef* pResourceDef = ResourceGetDef(rid); + if (pResourceDef) + return pResourceDef->GetResourceName(); + } tchar * pszTmp = Str_GetTemp(); ASSERT(pszTmp); diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 724e1d587..32649c80c 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -4277,8 +4277,8 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc if ( !Arg_Qty ) return false; return UpdateAnimate((ANIM_TYPE)(Arg_piCmd[0]), true, false, - (Arg_Qty > 1) ? (uchar)(Arg_piCmd[1]) : 1, - (Arg_Qty > 2) ? (uchar)(Arg_piCmd[2]) : 1); + (Arg_Qty > 1) ? (uchar)(Arg_piCmd[1]) : (byte)0, + (Arg_Qty > 2) ? (uchar)(Arg_piCmd[2]) : (byte)7); } break; case CHV_ATTACK: diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index e7c72a1c1..cc89208c6 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -990,6 +990,9 @@ CItem * CChar::Skill_NaturalResource_Create( CItem * pResBit, SKILL_TYPE skill ) ASSERT(pResBit); // Find the ore type located here based on color. + if (!pResBit->m_itResource.m_ridRes.IsValidResource()) + return nullptr; + CRegionResourceDef * pOreDef = dynamic_cast(g_Cfg.ResourceGetDef(pResBit->m_itResource.m_ridRes)); if ( !pOreDef ) return nullptr; diff --git a/src/game/clients/CClientMsg.cpp b/src/game/clients/CClientMsg.cpp index 9b826cf92..285dc801f 100644 --- a/src/game/clients/CClientMsg.cpp +++ b/src/game/clients/CClientMsg.cpp @@ -1267,9 +1267,12 @@ void CClient::addItemName( CItem * pItem ) case IT_ROCK: case IT_WATER: { - CResourceDef *pResDef = g_Cfg.RegisteredResourceGetDef(pItem->m_itResource.m_ridRes); - if ( pResDef ) - len += snprintf(szName + len, sizeof(szName) - len, " (%s)", pResDef->GetName()); + if (pItem->m_itResource.m_ridRes.IsValidResource()) + { + CResourceDef* pResDef = g_Cfg.RegisteredResourceGetDef(pItem->m_itResource.m_ridRes); + if (pResDef) + len += snprintf(szName + len, sizeof(szName) - len, " (%s)", pResDef->GetName()); + } } break; From 0248026c97e8c394e8778fb53b4e64edce51840d Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Mon, 8 Apr 2024 19:26:39 +0100 Subject: [PATCH 43/90] Multi Region Fixed: Missing REGION reference for multis. (Issue: #1228) --- Changelog.txt | 5 ++++- src/game/items/CItemMulti.cpp | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Changelog.txt b/Changelog.txt index ee53cc4c1..36e5b3719 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3554,4 +3554,7 @@ Added: @ResourceGather trigger added for crops. (This trigger works separately f - Returns: 1: Prevent player to gather fruit. 6: Let player to gather fruit but it will drop to the ground instead of backpack. -Fixed: Possible fix for invalid ResourceID warnings. (Issue: #1071) \ No newline at end of file +Fixed: Possible fix for invalid ResourceID warnings. (Issue: #1071) + +08-04-2024, xwerswoodx +Fixed: Missing REGION reference for multis. (Issue: #1228) \ No newline at end of file diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index 484e070a1..6533b47ac 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -2686,6 +2686,23 @@ bool CItemMulti::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc sVal.FormatVal(0); break; } + case SHL_REGION: + { + if (m_pRegion != nullptr) + { + if (!IsStrEmpty(ptcKey)) + { + if (m_pRegion) + return m_pRegion->r_WriteVal(ptcKey, sVal, pSrc); + } + + if (m_pRegion) + sVal.FormatHex(m_pRegion->GetResourceID().GetObjUID()); + else + sVal.FormatHex(0); + } + break; + } case SHL_OWNER: { CChar *pOwner = GetOwner().CharFind(); From 3c8cfb81e08621d9d7bd74801860f8436d06efdf Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Mon, 8 Apr 2024 22:44:16 +0100 Subject: [PATCH 44/90] Elemental Engine Flags Added: ElementalEngineFlags variable added to sphere.ini to let servers to filter elemental engine. (Issue: #1230) --- Changelog.txt | 13 +- src/game/CServerConfig.cpp | 153 +++++++++++---------- src/game/CServerConfig.h | 19 +++ src/game/chars/CCharFight.cpp | 2 +- src/game/chars/CCharSpell.cpp | 78 +++++++---- src/game/clients/CClientMsg.cpp | 11 +- src/game/clients/CClientMsg_AOSTooltip.cpp | 2 +- src/network/send.cpp | 2 +- src/sphere.ini | 14 ++ 9 files changed, 182 insertions(+), 112 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 36e5b3719..3b14c686e 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3557,4 +3557,15 @@ Added: @ResourceGather trigger added for crops. (This trigger works separately f Fixed: Possible fix for invalid ResourceID warnings. (Issue: #1071) 08-04-2024, xwerswoodx -Fixed: Missing REGION reference for multis. (Issue: #1228) \ No newline at end of file +Fixed: Missing REGION reference for multis. (Issue: #1228) +Added: ElementalEngineFlags variable added to sphere.ini to let servers to filter elemental engine. (Issue: #1230) + EE_CURSE = 0x1, // Adds Elemental buff/defuff to curse spell. + EE_MASS_CURSE = 0x2, // Adds Elemental buff/defuff to mass curse spell. + EE_REACTIVE_ARMOR = 0x4, // Adds Elemental buff/defuff to reactive armor spell. + EE_MAGIC_REFLECT = 0x8, // Adds Elemental buff/defuff to magic reflect spell. + EE_PROTECTION = 0x10, // Adds Elemental buff/defuff to protection spell. + EE_ARCH_PROTECTION = 0x20, // Adds Elemental buff/defuff to arch protection spell. + EE_STONESKIN = 0x40, // Adds Elemental buff/defuff to stone skin spell. + EE_STEELSKIN = 0x80, // Adds Elemental buff/defuff to steel skin spell. + EE_RESPHYSICAL = 0x100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. + \ No newline at end of file diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 00da9910f..588554496 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -174,6 +174,7 @@ CServerConfig::CServerConfig() m_iHitsUpdateRate = MSECS_PER_SEC; m_iSpeedScaleFactor = 80000; m_iCombatFlags = 0; + m_iElementalEngineFlags = UINT64_MAX; //In default, all Elemental Engine flags are active, also I put UINT64_MAX to let sphere active new flags (if added) automatically. m_iCombatArcheryMovementDelay = 10; m_iCombatDamageEra = 0; m_iCombatHitChanceEra = 0; @@ -515,6 +516,7 @@ enum RC_TYPE RC_DUMPPACKETSFORACC, #endif RC_DUNGEONLIGHT, + RC_ELEMENTALENGINEFLAGS, RC_EMOTEFLAGS, // m_iEmoteFlags RC_EQUIPPEDCAST, // m_fEquippedCast RC_ERALIMITGEAR, // _iEraLimitGear @@ -706,87 +708,88 @@ enum RC_TYPE // NOTE: Need to be alphabetized order const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY+1] { - { "ACCTFILES", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sAcctBaseDir) }}, - { "ADVANCEDLOS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAdvancedLos) }}, - { "AGREE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAgree) }}, - { "ALLOWBUYSELLAGENT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAllowBuySellAgent) }}, - { "ALLOWLIGHTOVERRIDE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAllowLightOverride) }}, - { "ALLOWNEWBTRANSFER", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAllowNewbTransfer) }}, - { "ARCHERYMAXDIST", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iArcheryMaxDist) }}, - { "ARCHERYMINDIST", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iArcheryMinDist) }}, - { "AREAFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiAreaFlags) }}, - { "ARRIVEDEPARTMSG", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iArriveDepartMsg) }}, - { "ATTACKERTIMEOUT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAttackerTimeout) }}, - { "ATTACKINGISACRIME", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAttackingIsACrime) }}, + { "ACCTFILES", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sAcctBaseDir) }}, + { "ADVANCEDLOS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAdvancedLos) }}, + { "AGREE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAgree) }}, + { "ALLOWBUYSELLAGENT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAllowBuySellAgent) }}, + { "ALLOWLIGHTOVERRIDE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAllowLightOverride) }}, + { "ALLOWNEWBTRANSFER", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAllowNewbTransfer) }}, + { "ARCHERYMAXDIST", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iArcheryMaxDist) }}, + { "ARCHERYMINDIST", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iArcheryMinDist) }}, + { "AREAFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiAreaFlags) }}, + { "ARRIVEDEPARTMSG", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iArriveDepartMsg) }}, + { "ATTACKERTIMEOUT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAttackerTimeout) }}, + { "ATTACKINGISACRIME", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAttackingIsACrime) }}, { "AUTOHOUSEKEYS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,_fAutoHouseKeys) }}, - { "AUTONEWBIEKEYS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAutoNewbieKeys) }}, - { "AUTOPRIVFLAGS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAutoPrivFlags) }}, + { "AUTONEWBIEKEYS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAutoNewbieKeys) }}, + { "AUTOPRIVFLAGS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAutoPrivFlags) }}, { "AUTOPROCESSPRIORITY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAutoProcessPriority) }}, - { "AUTORESDISP", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAutoResDisp) }}, + { "AUTORESDISP", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAutoResDisp) }}, { "AUTOSHIPKEYS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,_fAutoShipKeys) }}, - { "BACKPACKOVERLOAD", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iBackpackOverload) }}, - { "BACKUPLEVELS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iSaveBackupLevels) }}, - { "BANKMAXITEMS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iBankIMax) }}, - { "BANKMAXWEIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iBankWMax) }}, - { "BUILD", { ELEM_VOID, 0 }}, + { "BACKPACKOVERLOAD", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iBackpackOverload) }}, + { "BACKUPLEVELS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iSaveBackupLevels) }}, + { "BANKMAXITEMS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iBankIMax) }}, + { "BANKMAXWEIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iBankWMax) }}, + { "BUILD", { ELEM_VOID, 0 }}, { "CANPETSDRINKPOTION", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCanPetsDrinkPotion) }}, - { "CANSEESAMEPLEVEL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCanSeeSamePLevel) }}, - { "CANUNDRESSPETS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCanUndressPets) }}, - { "CHARTAGS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCharTags) }}, - { "CHATFLAGS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iChatFlags) }}, - { "CHATSTATICCHANNELS", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sChatStaticChannels) }}, - { "CLIENTLINGER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientLingerTime) }}, - { "CLIENTLOGINMAXTRIES", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientLoginMaxTries) }}, - { "CLIENTLOGINTEMPBAN", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientLoginTempBan) }}, - { "CLIENTMAX", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientsMax) }}, - { "CLIENTMAXIP", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientsMaxIP) }}, - { "CLIENTS", { ELEM_VOID, 0 }}, // duplicate - { "COLORHIDDEN", { ELEM_VOID, static_castOFFSETOF(CServerConfig,m_iColorHidden) }}, - { "COLORINVIS", { ELEM_VOID, static_castOFFSETOF(CServerConfig,m_iColorInvis) }}, - { "COLORINVISITEM", { ELEM_VOID, static_castOFFSETOF(CServerConfig,m_iColorInvisItem) }}, - { "COLORINVISSPELL", { ELEM_VOID, static_castOFFSETOF(CServerConfig,m_iColorInvisSpell) }}, - { "COLORNOTOCRIMINAL", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoCriminal) }}, - { "COLORNOTODEFAULT", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoDefault) }}, - { "COLORNOTOEVIL", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoEvil) }}, - { "COLORNOTOGOOD", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoGood) }}, - { "COLORNOTOGOODNPC", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoGoodNPC) }}, - { "COLORNOTOGUILDSAME", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoGuildSame) }}, - { "COLORNOTOGUILDWAR", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoGuildWar) }}, - { "COLORNOTOINVUL", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoInvul) }}, - { "COLORNOTOINVULGAMEMASTER",{ ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoInvulGameMaster) }}, - { "COLORNOTONEUTRAL", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoNeutral) }}, - { "COMBATARCHERYMOVEMENTDELAY",{ ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCombatArcheryMovementDelay) }}, - { "COMBATDAMAGEERA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCombatDamageEra) }}, - { "COMBATFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iCombatFlags) }}, - { "COMBATHITCHANCEERA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCombatHitChanceEra) }}, + { "CANSEESAMEPLEVEL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCanSeeSamePLevel) }}, + { "CANUNDRESSPETS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCanUndressPets) }}, + { "CHARTAGS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCharTags) }}, + { "CHATFLAGS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iChatFlags) }}, + { "CHATSTATICCHANNELS", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sChatStaticChannels) }}, + { "CLIENTLINGER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientLingerTime) }}, + { "CLIENTLOGINMAXTRIES", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientLoginMaxTries) }}, + { "CLIENTLOGINTEMPBAN", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientLoginTempBan) }}, + { "CLIENTMAX", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientsMax) }}, + { "CLIENTMAXIP", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iClientsMaxIP) }}, + { "CLIENTS", { ELEM_VOID, 0 }}, // duplicate + { "COLORHIDDEN", { ELEM_VOID, static_castOFFSETOF(CServerConfig,m_iColorHidden) }}, + { "COLORINVIS", { ELEM_VOID, static_castOFFSETOF(CServerConfig,m_iColorInvis) }}, + { "COLORINVISITEM", { ELEM_VOID, static_castOFFSETOF(CServerConfig,m_iColorInvisItem) }}, + { "COLORINVISSPELL", { ELEM_VOID, static_castOFFSETOF(CServerConfig,m_iColorInvisSpell) }}, + { "COLORNOTOCRIMINAL", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoCriminal) }}, + { "COLORNOTODEFAULT", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoDefault) }}, + { "COLORNOTOEVIL", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoEvil) }}, + { "COLORNOTOGOOD", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoGood) }}, + { "COLORNOTOGOODNPC", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoGoodNPC) }}, + { "COLORNOTOGUILDSAME", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoGuildSame) }}, + { "COLORNOTOGUILDWAR", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoGuildWar) }}, + { "COLORNOTOINVUL", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoInvul) }}, + { "COLORNOTOINVULGAMEMASTER",{ ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoInvulGameMaster) }}, + { "COLORNOTONEUTRAL", { ELEM_WORD, static_castOFFSETOF(CServerConfig,m_iColorNotoNeutral) }}, + { "COMBATARCHERYMOVEMENTDELAY",{ ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCombatArcheryMovementDelay) }}, + { "COMBATDAMAGEERA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCombatDamageEra) }}, + { "COMBATFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iCombatFlags) }}, + { "COMBATHITCHANCEERA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCombatHitChanceEra) }}, { "COMBATPARRYINGERA", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iCombatParryingEra) }}, - { "COMBATSPEEDERA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCombatSpeedEra) }}, - { "COMMANDLOG", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCommandLog) }}, - { "COMMANDPREFIX", { ELEM_BYTE, static_castOFFSETOF(CServerConfig,m_cCommandPrefix) }}, - { "COMMANDTRIGGER", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sCommandTrigger) }}, - { "CONNECTINGMAX", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iConnectingMax) }}, - { "CONNECTINGMAXIP", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iConnectingMaxIP) }}, + { "COMBATSPEEDERA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCombatSpeedEra) }}, + { "COMMANDLOG", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCommandLog) }}, + { "COMMANDPREFIX", { ELEM_BYTE, static_castOFFSETOF(CServerConfig,m_cCommandPrefix) }}, + { "COMMANDTRIGGER", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sCommandTrigger) }}, + { "CONNECTINGMAX", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iConnectingMax) }}, + { "CONNECTINGMAXIP", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iConnectingMaxIP) }}, { "CONTAINERMAXITEMS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iContainerMaxItems) }}, - { "CONTEXTMENULIMIT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iContextMenuLimit) }}, - { "CORPSENPCDECAY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDecay_CorpseNPC) }}, - { "CORPSEPLAYERDECAY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDecay_CorpsePlayer) }}, - { "CRIMINALTIMER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCriminalTimer) }}, - { "CUOSTATUS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCUOStatus) }}, - { "DEADCANNOTSEELIVING", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_fDeadCannotSeeLiving) }}, - { "DEADSOCKETTIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDeadSocketTime) }}, - { "DEBUGFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iDebugFlags) }}, - { "DECAYTIMER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDecay_Item) }}, - { "DEFAULTCOMMANDLEVEL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDefaultCommandLevel) }}, - { "DISPLAYARMORASPERCENT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fDisplayPercentAr) }}, - { "DISPLAYELEMENTALRESISTANCE",{ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fDisplayElementalResistance)}}, - { "DISTANCETALK", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDistanceTalk ) }}, - { "DISTANCEWHISPER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDistanceWhisper ) }}, - { "DISTANCEYELL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDistanceYell ) }}, - { "DRAGWEIGHTMAX", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDragWeightMax) }}, + { "CONTEXTMENULIMIT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iContextMenuLimit) }}, + { "CORPSENPCDECAY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDecay_CorpseNPC) }}, + { "CORPSEPLAYERDECAY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDecay_CorpsePlayer) }}, + { "CRIMINALTIMER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iCriminalTimer) }}, + { "CUOSTATUS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fCUOStatus) }}, + { "DEADCANNOTSEELIVING", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_fDeadCannotSeeLiving) }}, + { "DEADSOCKETTIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDeadSocketTime) }}, + { "DEBUGFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iDebugFlags) }}, + { "DECAYTIMER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDecay_Item) }}, + { "DEFAULTCOMMANDLEVEL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDefaultCommandLevel) }}, + { "DISPLAYARMORASPERCENT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fDisplayPercentAr) }}, + { "DISPLAYELEMENTALRESISTANCE",{ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fDisplayElementalResistance)}}, + { "DISTANCETALK", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDistanceTalk) }}, + { "DISTANCEWHISPER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDistanceWhisper) }}, + { "DISTANCEYELL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDistanceYell) }}, + { "DRAGWEIGHTMAX", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDragWeightMax) }}, #ifdef _DUMPSUPPORT - { "DUMPPACKETSFORACC", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sDumpAccPackets) }}, + { "DUMPPACKETSFORACC", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sDumpAccPackets) }}, #endif - { "DUNGEONLIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightDungeon) }}, + { "DUNGEONLIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightDungeon) }}, + { "ELEMENTALENGINEFLAGS", { ELEM_MASK_INT64, static_castOFFSETOF(CServerConfig, m_iElementalEngineFlags) }}, { "EMOTEFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iEmoteFlags) }}, { "EQUIPPEDCAST", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fEquippedCast) }}, { "ERALIMITGEAR", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iEraLimitGear) }}, @@ -1371,6 +1374,10 @@ bool CServerConfig::r_LoadVal( CScript &s ) m_cCommandPrefix = *s.GetArgStr(); break; + case RC_ELEMENTALENGINEFLAGS: + m_iElementalEngineFlags = s.GetArg64Val(); + break; + case RC_EXPERIMENTAL: _uiExperimentalFlags = s.GetArgUVal(); //PrintEFOFFlags(true, false); diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index b6955c19e..284e3ad1c 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -129,6 +129,23 @@ enum COMBATFLAGS_TYPE COMBAT_PARALYZE_CANSWING = 0x80000 // Characters can continue attacking while paralyzed. (Old sphere behaviour) }; +/** +* @enum ELEMENTALENGINEFLAGS_TYPE +* @brief ElementalEngineFlags (sphere.ini) +*/ +enum ELEMENTALENGINEFLAGS_TYPE +{ + EE_CURSE = 0x1, // Adds Elemental buff/defuff to curse spell. + EE_MASS_CURSE = 0x2, // Adds Elemental buff/defuff to mass curse spell. + EE_REACTIVE_ARMOR = 0x4, // Adds Elemental buff/defuff to reactive armor spell. + EE_MAGIC_REFLECT = 0x8, // Adds Elemental buff/defuff to magic reflect spell. + EE_PROTECTION = 0x10, // Adds Elemental buff/defuff to protection spell. + EE_ARCH_PROTECTION = 0x20, // Adds Elemental buff/defuff to arch protection spell. + EE_STONESKIN = 0x40, // Adds Elemental buff/defuff to stone skin spell. + EE_STEELSKIN = 0x80, // Adds Elemental buff/defuff to steel skin spell. + EE_RESPHYSICAL = 0x100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. +}; + /** * @enum PARRYFLAGS_TYPE * @brief ParryEra (sphere.ini): Parrying behaviour @@ -374,6 +391,7 @@ extern class CServerConfig : public CResourceHolder // Flags for controlling pvp/pvm behaviour of players uint m_iCombatFlags; // combat flags uint m_iMagicFlags; // magic flags + uint64 m_iElementalEngineFlags; //Elemental engine flags uint m_iRacialFlags; // racial traits flags uint m_iRevealFlags; // reveal flags used for SPELL_REVEAL (mostly for backwards). uint m_iEmoteFlags; // emote flags @@ -1111,6 +1129,7 @@ typedef std::map KRGumpsMap; #define IsSetOF(of) ((g_Cfg._uiOptionFlags & of) != 0) #define IsSetCombatFlags(of) ((g_Cfg.m_iCombatFlags & of) != 0) #define IsSetMagicFlags(of) ((g_Cfg.m_iMagicFlags & of) != 0) +#define IsSetEEFlags(of) ((g_Cfg.m_iElementalEngineFlags & of) != 0) #endif // _INC_CSERVERCONFIG_H diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 574da963f..640978787 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -416,7 +416,7 @@ int CChar::CalcArmorDefense() const ADDTOCALLSTACK("CChar::CalcArmorDefense"); // If Combat Elemental Engine is enabled, we don't need to calculate the AC because RESPHYSICAL is used. - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_RESPHYSICAL)) return 0; int iDefenseTotal = 0; diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 0d5b4278b..a5b9a29f9 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -808,7 +808,7 @@ void CChar::Spell_Effect_Remove(CItem * pSpell) case SPELL_Curse: case SPELL_Mass_Curse: { - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && m_pPlayer ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags((spell == SPELL_Mass_Curse ? EE_MASS_CURSE : EE_CURSE)) && m_pPlayer) { CCPropsChar* pCCPChar = GetComponentProps(); CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); @@ -855,7 +855,7 @@ void CChar::Spell_Effect_Remove(CItem * pSpell) UpdateStatVal( STAT_INT, +uiStatEffect ); return; case SPELL_Reactive_Armor: - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_REACTIVE_ARMOR)) { CCPropsChar* pCCPChar = GetComponentProps(); CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); @@ -874,7 +874,7 @@ void CChar::Spell_Effect_Remove(CItem * pSpell) return; case SPELL_Magic_Reflect: StatFlag_Clear(STATF_REFLECTION); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_MAGIC_REFLECT)) { CCPropsChar* pCCPChar = GetComponentProps(); CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); @@ -891,27 +891,37 @@ void CChar::Spell_Effect_Remove(CItem * pSpell) case SPELL_Stoneskin: // 115 // turns your skin into stone, giving a boost to your AR. case SPELL_Protection: case SPELL_Arch_Prot: - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) - { - CCPropsChar* pCCPChar = GetComponentProps(); - CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); - ModPropNum(pCCPChar, PROPCH_RESPHYSICAL, + pSpell->m_itSpell.m_PolyStr, pBaseCCPChar); + { + ELEMENTALENGINEFLAGS_TYPE iType = EE_PROTECTION; + if (spell == SPELL_Steelskin) + iType = EE_STEELSKIN; + else if (spell == SPELL_Stoneskin) + iType = EE_STONESKIN; + else if (spell == SPELL_Arch_Prot) + iType = EE_ARCH_PROTECTION; + + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(iType)) + { + CCPropsChar* pCCPChar = GetComponentProps(); + CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); + ModPropNum(pCCPChar, PROPCH_RESPHYSICAL, +pSpell->m_itSpell.m_PolyStr, pBaseCCPChar); ModPropNum(pCCPChar, PROPCH_FASTERCASTING, +2, pBaseCCPChar); _CheckLimitEffectSkill(pSpell->m_itSpell.m_PolyDex, this, SKILL_MAGICRESISTANCE); - Skill_AddBase(SKILL_MAGICRESISTANCE, pSpell->m_itSpell.m_PolyDex - Skill_GetBase(SKILL_MAGICRESISTANCE)); - } - else - { - m_defense = (word)CalcArmorDefense(); - } - if (pClient) - { - if (spell == SPELL_Protection) - pClient->removeBuff(BI_PROTECTION); - else if (spell == SPELL_Arch_Prot) - pClient->removeBuff(BI_ARCHPROTECTION); - } - return; + Skill_AddBase(SKILL_MAGICRESISTANCE, pSpell->m_itSpell.m_PolyDex - Skill_GetBase(SKILL_MAGICRESISTANCE)); + } + else + { + m_defense = (word)CalcArmorDefense(); + } + if (pClient) + { + if (spell == SPELL_Protection) + pClient->removeBuff(BI_PROTECTION); + else if (spell == SPELL_Arch_Prot) + pClient->removeBuff(BI_ARCHPROTECTION); + } + return; + } /*case SPELL_Chameleon: // 106 // makes your skin match the colors of whatever is behind you. return;*/ case SPELL_Trance: // 111 // temporarily increases your meditation skill. @@ -1366,7 +1376,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) switch ( spell ) { case SPELL_Reactive_Armor: - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_REACTIVE_ARMOR)) { wStatEffectRef = 15 + (pCaster->Skill_GetBase(SKILL_INSCRIPTION) / 200); @@ -1389,7 +1399,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) if (pClient && IsSetOF(OF_Buffs)) { pClient->removeBuff(BI_REACTIVEARMOR); - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_REACTIVE_ARMOR)) { Str_FromI(wStatEffectRef, NumBuff[0], sizeof(NumBuff[0]), 10); for ( int idx = 1; idx < 5; ++idx ) @@ -1475,7 +1485,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) { wStatEffectRef = 8 + (pCaster->Skill_GetBase(SKILL_EVALINT) / 100) - (Skill_GetBase(SKILL_MAGICRESISTANCE) / 100); } - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && m_pPlayer ) // Curse also decrease max resistances on players + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags((spell == SPELL_Mass_Curse ? EE_MASS_CURSE : EE_CURSE)) && m_pPlayer) // Curse also decrease max resistances on players { CCPropsChar* pCCPChar = GetComponentProps(); CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); @@ -1502,7 +1512,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) for ( int idx = STAT_STR; idx < STAT_BASE_QTY; ++idx ) Str_FromI(wStatEffectRef, NumBuff[idx], sizeof(NumBuff[0]), 10); - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags((spell == SPELL_Mass_Curse ? EE_MASS_CURSE : EE_CURSE))) { for ( int idx = 3; idx < 7; ++idx ) Str_FromI(10, NumBuff[idx], sizeof(NumBuff[0]), 10); @@ -1603,7 +1613,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) return; case SPELL_Magic_Reflect: StatFlag_Set( STATF_REFLECTION ); - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_MAGIC_REFLECT)) { wStatEffectRef = 25 - (pCaster->Skill_GetBase(SKILL_INSCRIPTION) / 200); @@ -1618,7 +1628,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) if (pClient && IsSetOF(OF_Buffs)) { pClient->removeBuff(BI_MAGICREFLECTION); - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_MAGIC_REFLECT)) { Str_FromI(-wStatEffectRef, NumBuff[0], sizeof(NumBuff[0]), 10); for ( int idx = 1; idx < 5; ++idx ) @@ -1639,7 +1649,15 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) { int iPhysicalResist = 0; int iMagicResist = 0; - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + ELEMENTALENGINEFLAGS_TYPE iType = EE_PROTECTION; + if (spell == SPELL_Steelskin) + iType = EE_STEELSKIN; + else if (spell == SPELL_Stoneskin) + iType = EE_STONESKIN; + else if (spell == SPELL_Arch_Prot) + iType = EE_ARCH_PROTECTION; + + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(iType)) { ushort uiCasterEvalInt = pCaster->Skill_GetBase(SKILL_EVALINT), uiCasterMeditation = pCaster->Skill_GetBase(SKILL_MEDITATION); ushort uiCasterInscription = pCaster->Skill_GetBase(SKILL_INSCRIPTION); @@ -1680,7 +1698,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) } pClient->removeBuff(BuffIcon); - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(iType)) { Str_FromI(-iPhysicalResist, NumBuff[0], sizeof(NumBuff[0]), 10); Str_FromI(-iMagicResist/10, NumBuff[1], sizeof(NumBuff[0]), 10); diff --git a/src/game/clients/CClientMsg.cpp b/src/game/clients/CClientMsg.cpp index 285dc801f..0dd16f1f0 100644 --- a/src/game/clients/CClientMsg.cpp +++ b/src/game/clients/CClientMsg.cpp @@ -65,8 +65,9 @@ void CClient::resendBuffs() const wStatEffect = pItem->m_itSpell.m_spelllevel; int64 iTimerEffectSigned = pItem->GetTimerSAdjusted(); wTimerEffect = (word)(maximum(iTimerEffectSigned, 0)); + SPELL_TYPE spell = (SPELL_TYPE)(RES_GET_INDEX(pItem->m_itSpell.m_spell)); - switch ( pItem->m_itSpell.m_spell ) + switch (spell) { case SPELL_Night_Sight: removeBuff(BI_NIGHTSIGHT); @@ -134,7 +135,7 @@ void CClient::resendBuffs() const case SPELL_Reactive_Armor: { removeBuff(BI_REACTIVEARMOR); - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_REACTIVE_ARMOR)) { Str_FromI(wStatEffect, NumBuff[0], sizeof(NumBuff[0]), 10); for ( int idx = 1; idx < 5; ++idx ) @@ -153,14 +154,14 @@ void CClient::resendBuffs() const { BUFF_ICONS BuffIcon = BI_PROTECTION; dword BuffCliloc = 1075814; - if ( pItem->m_itSpell.m_spell == SPELL_Arch_Prot ) + if (spell == SPELL_Arch_Prot) { BuffIcon = BI_ARCHPROTECTION; BuffCliloc = 1075816; } removeBuff(BuffIcon); - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags((spell == SPELL_Arch_Prot ? EE_ARCH_PROTECTION : EE_PROTECTION))) { Str_FromI(-pItem->m_itSpell.m_PolyStr, NumBuff[0], sizeof(NumBuff[0]), 10); Str_FromI(-pItem->m_itSpell.m_PolyDex / 10, NumBuff[1], sizeof(NumBuff[0]), 10); @@ -187,7 +188,7 @@ void CClient::resendBuffs() const case SPELL_Magic_Reflect: { removeBuff(BI_MAGICREFLECTION); - if ( IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) ) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_MAGIC_REFLECT)) { Str_FromI(-wStatEffect, NumBuff[0], sizeof(NumBuff[0]), 10); for ( int idx = 1; idx < 5; ++idx ) diff --git a/src/game/clients/CClientMsg_AOSTooltip.cpp b/src/game/clients/CClientMsg_AOSTooltip.cpp index 724199531..dd54f77bb 100644 --- a/src/game/clients/CClientMsg_AOSTooltip.cpp +++ b/src/game/clients/CClientMsg_AOSTooltip.cpp @@ -475,7 +475,7 @@ void CClient::AOSTooltip_addDefaultItemData(CItem * pItem) case IT_CLOTHING: case IT_SHIELD: { - if (!IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) + if (!IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) || (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !IsSetEEFlags(EE_RESPHYSICAL))) { int iArmorRating = pItem->Armor_GetDefense(); int iPercentArmorRating = 0; diff --git a/src/network/send.cpp b/src/network/send.cpp index 0be915222..7bcc5486f 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -237,7 +237,7 @@ void PacketObjectStatus::WriteVersionSpecific(const CClient* target, CChar* othe writeInt32(other->ContentCount(CResourceID(RES_TYPEDEF, IT_GOLD))); } - if (fElemental) + if (fElemental && IsSetEEFlags(EE_RESPHYSICAL)) writeInt16((word)other->GetPropNum(pCCPChar, PROPCH_RESPHYSICAL, pBaseCCPChar)); else writeInt16(other->m_defense + otherDefinition->m_defense); diff --git a/src/sphere.ini b/src/sphere.ini index 940cd99f6..2b74ac111 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -397,6 +397,20 @@ SuppressCapitals=0 // COMBAT_PARALYZE_CANSWING 080000 // Characters can continue attacking while paralyzed. (Old sphere behaviour) //CombatFlags=0 +// Elemental Engine flags that can be used to filter COMBAT_ELEMENTAL_ENGINE +// EE_CURSE 0001 // Adds Elemental buff/defuff to curse spell. +// EE_MASS_CURSE 0002 // Adds Elemental buff/defuff to mass curse spell. +// EE_REACTIVE_ARMOR 0004 // Adds Elemental buff/defuff to reactive armor spell. +// EE_MAGIC_REFLECT 0008 // Adds Elemental buff/defuff to magic reflect spell. +// EE_PROTECTION 0010 // Adds Elemental buff/defuff to protection spell. +// EE_ARCH_PROTECTION 0020 // Adds Elemental buff/defuff to arch protection spell. +// EE_STONESKIN 0040 // Adds Elemental buff/defuff to stone skin spell. +// EE_STEELSKIN 0080 // Adds Elemental buff/defuff to steel skin spell. +// EE_RESPHYSICAL 0100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. +// ALL 01FF // Includes all from 01 to 0100. +// MAX 0FFFFFFFFFFFFFFFF // Includes all flag values for UINT64. +//ElementalEngineFlags=0FFFFFFFFFFFFFFFF + // If COMBAT_ARCHERYCANMOVE is not enabled, wait this much tenth of seconds (minimum=0) after the player // stopped moving before starting a new attack // (Values changed between expansions. SE:2~3 / AOS:5 / pre-AOS:10) From ec132ced86885c75078e644888f8bf7ec7f3fd21 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Mon, 8 Apr 2024 23:03:01 +0100 Subject: [PATCH 45/90] Increased CElementDef structure from uint to uint64 as some flags in sphere.ini close to the max value of uint. --- src/common/sphere_library/CSAssoc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/sphere_library/CSAssoc.h b/src/common/sphere_library/CSAssoc.h index 058ad8779..69aad08fa 100644 --- a/src/common/sphere_library/CSAssoc.h +++ b/src/common/sphere_library/CSAssoc.h @@ -62,7 +62,7 @@ struct CElementDef { static const int sm_Lengths[ELEM_QTY]; ELEM_TYPE m_type; - uint m_offset; // The offset into the class instance for this item. + uint64 m_offset; // The offset into the class instance for this item. // get structure value. void * GetValPtr( const void * pBaseInst ) const; From 642c0312b8409d9b299fa68b70c4c65ed0d673e6 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 9 Apr 2024 17:14:04 +0100 Subject: [PATCH 46/90] Custom Multi Count Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) --- Changelog.txt | 4 +++- src/game/items/CItemMulti.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 3b14c686e..61715bd40 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3568,4 +3568,6 @@ Added: ElementalEngineFlags variable added to sphere.ini to let servers to filte EE_STONESKIN = 0x40, // Adds Elemental buff/defuff to stone skin spell. EE_STEELSKIN = 0x80, // Adds Elemental buff/defuff to steel skin spell. EE_RESPHYSICAL = 0x100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. - \ No newline at end of file + +09-04-2024, xwerswoodx +Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) \ No newline at end of file diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index 6533b47ac..90b3da0b8 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -3654,7 +3654,7 @@ HOUSE_PRIV CMultiStorage::GetPriv(const CUID& uidMulti) { ADDTOCALLSTACK("CMultiStorage::GetPrivMulti"); const CItemMulti *pMulti = static_cast(uidMulti.ItemFind()); - if (pMulti->IsType(IT_MULTI)) + if (pMulti->IsType(IT_MULTI) || pMulti->IsType(IT_MULTI_CUSTOM)) { return _lHouses[uidMulti]; } From e1859c188c9385cddb89e9bc7ad079a4d7bda204 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 9 Apr 2024 17:58:18 +0100 Subject: [PATCH 47/90] Bonded Pet Cannot See Master Fixed: Bonded pets cannot see their master while DeadCannotSeeLiving equals to 2. (Issue: #1225) --- Changelog.txt | 3 ++- src/game/chars/CCharStatus.cpp | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 61715bd40..35b394918 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3570,4 +3570,5 @@ Added: ElementalEngineFlags variable added to sphere.ini to let servers to filte EE_RESPHYSICAL = 0x100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. 09-04-2024, xwerswoodx -Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) \ No newline at end of file +Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) +Fixed: Bonded pets cannot see their master while DeadCannotSeeLiving equals to 2. (Issue: #1225) \ No newline at end of file diff --git a/src/game/chars/CCharStatus.cpp b/src/game/chars/CCharStatus.cpp index 6267a0cca..e43f77726 100644 --- a/src/game/chars/CCharStatus.cpp +++ b/src/game/chars/CCharStatus.cpp @@ -1027,8 +1027,11 @@ bool CChar::CanSeeAsDead( const CChar *pChar) const { if ( pChar->m_pPlayer ) { - if ( iDeadCannotSee == 2 ) - return false; + if (IsNPC() && NPC_PetGetOwner() != pChar) //NPCs should see their owners even if iDeadCannotSee equals to 2. + { + if (iDeadCannotSee == 2) + return false; + } } else { From 000c555b959abd2a304359b6a9dec0b5bb858dc0 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 9 Apr 2024 18:53:13 +0100 Subject: [PATCH 48/90] Standart Guild Align Fix Fixed: The issue that causes Guilds without align shown enemy to the players with a guild with align. (Issue: #1208) --- Changelog.txt | 3 ++- src/game/chars/CCharNotoriety.cpp | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 35b394918..4b29d3b4c 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3571,4 +3571,5 @@ Added: ElementalEngineFlags variable added to sphere.ini to let servers to filte 09-04-2024, xwerswoodx Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) -Fixed: Bonded pets cannot see their master while DeadCannotSeeLiving equals to 2. (Issue: #1225) \ No newline at end of file +Fixed: Bonded pets cannot see their master while DeadCannotSeeLiving equals to 2. (Issue: #1225) +Fixed: The issue that causes Guilds without align shown enemy to the players with a guild with align. (Issue: #1208) \ No newline at end of file diff --git a/src/game/chars/CCharNotoriety.cpp b/src/game/chars/CCharNotoriety.cpp index 491e5f6f3..2f6629ace 100644 --- a/src/game/chars/CCharNotoriety.cpp +++ b/src/game/chars/CCharNotoriety.cpp @@ -212,15 +212,13 @@ NOTO_TYPE CChar::Noto_CalcFlag(const CChar * pCharViewer, bool fAllowIncog, bool { if (IsSetOF(OF_EnableGuildAlignNotoriety)) { - if (pViewerGuild->GetAlignType() != STONEALIGN_STANDARD) + if (pViewerGuild->GetAlignType() != STONEALIGN_STANDARD && pMyGuild->GetAlignType() != STONEALIGN_STANDARD) //We have to check if my guild is also not STONEALIGN_STANDART. { if (pViewerGuild->GetAlignType() == pMyGuild->GetAlignType()) { return NOTO_GUILD_SAME; } - return NOTO_GUILD_WAR; - } } From 787fbfd5defff868b1237ec35ad86dc47b8fdfa6 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 9 Apr 2024 21:29:36 +0100 Subject: [PATCH 49/90] Console Warnings Fixed: Invalid ResourceID console warnings. (Issue: #1071) --- Changelog.txt | 3 ++- src/game/items/CItem.cpp | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 4b29d3b4c..09a709332 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3572,4 +3572,5 @@ Added: ElementalEngineFlags variable added to sphere.ini to let servers to filte 09-04-2024, xwerswoodx Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) Fixed: Bonded pets cannot see their master while DeadCannotSeeLiving equals to 2. (Issue: #1225) -Fixed: The issue that causes Guilds without align shown enemy to the players with a guild with align. (Issue: #1208) \ No newline at end of file +Fixed: The issue that causes Guilds without an align shown enemy to the players with a guild with an align. (Issue: #1208) +Fixed: Another fix for Invalid ResourceID console warnings. (Issue: #1071) \ No newline at end of file diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index c270deb5d..fd867cc62 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2271,14 +2271,14 @@ void CItem::r_WriteMore1(CSString & sVal) case IT_GRASS: case IT_ROCK: case IT_WATER: - sVal = g_Cfg.ResourceGetName(m_itResource.m_ridRes); + sVal = g_Cfg.ResourceGetName(CResourceID(RES_REGIONRESOURCE, m_itResource.m_ridRes.GetResIndex())); //Changed to fix issue but it is not implemented. return; case IT_FRUIT: case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: - sVal = g_Cfg.ResourceGetName(m_itFood.m_ridCook); + sVal = g_Cfg.ResourceGetName(CResourceID(RES_ITEMDEF, m_itFood.m_ridCook.GetResIndex())); return; case IT_TRAP: @@ -2326,13 +2326,13 @@ void CItem::r_WriteMore2( CSString & sVal ) case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: - sVal = g_Cfg.ResourceGetName( CResourceID( RES_CHARDEF, m_itFood.m_MeatType )); + sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, m_itFood.m_MeatType)); return; case IT_CROPS: case IT_FOLIAGE: - sVal = g_Cfg.ResourceGetName( m_itCrop.m_ridFruitOverride ); - return; + sVal = g_Cfg.ResourceGetName(CResourceID(RES_ITEMDEF, m_itCrop.m_ridFruitOverride.GetResIndex())); + return; case IT_LEATHER: case IT_HIDE: @@ -2340,13 +2340,13 @@ void CItem::r_WriteMore2( CSString & sVal ) case IT_FUR: case IT_WOOL: case IT_BLOOD: - case IT_BONE: - sVal = g_Cfg.ResourceGetName( CResourceID( RES_CHARDEF, m_itNormal.m_more2 )); - return; + case IT_BONE: + sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, m_itNormal.m_more2)); + return; case IT_ANIM_ACTIVE: - sVal = g_Cfg.ResourceGetName( CResourceID( RES_TYPEDEF, m_itAnim.m_PrevType )); - return; + sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, m_itAnim.m_PrevType)); + return; default: if (CResourceIDBase::IsValidResource(m_itNormal.m_more2)) From 262f4e4de5a4d72f2f2339d170ff3d92311de0c8 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 10 Apr 2024 04:37:29 +0100 Subject: [PATCH 50/90] GMs Dress Players Fixed: GMs cannot dress up players. (Issue: #901) --- Changelog.txt | 3 ++- src/game/chars/CChar.h | 1 + src/game/chars/CCharStatus.cpp | 11 ++++++++++- src/network/receive.cpp | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 09a709332..8d030478b 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3573,4 +3573,5 @@ Added: ElementalEngineFlags variable added to sphere.ini to let servers to filte Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) Fixed: Bonded pets cannot see their master while DeadCannotSeeLiving equals to 2. (Issue: #1225) Fixed: The issue that causes Guilds without an align shown enemy to the players with a guild with an align. (Issue: #1208) -Fixed: Another fix for Invalid ResourceID console warnings. (Issue: #1071) \ No newline at end of file +Fixed: Another fix for Invalid ResourceID console warnings. (Issue: #1071) +Fixed: GMs cannot dress up players. (Issue: #901) \ No newline at end of file diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index b38ddddc4..4bf1b62e6 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -1112,6 +1112,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; CChar* Horse_GetValidMountChar(); public: + bool CanDress(const CChar* pChar) const; bool IsOwnedBy( const CChar * pChar, bool fAllowGM = true ) const; CChar * GetOwner() const; CChar * Use_Figurine( CItem * pItem, bool fCheckFollowerSlots = true ); diff --git a/src/game/chars/CCharStatus.cpp b/src/game/chars/CCharStatus.cpp index e43f77726..395171b75 100644 --- a/src/game/chars/CCharStatus.cpp +++ b/src/game/chars/CCharStatus.cpp @@ -899,6 +899,15 @@ CChar * CChar::GetOwner() const return nullptr; } +bool CChar::CanDress(const CChar* pChar) const +{ + if (IsPriv(PRIV_GM) && (GetPrivLevel() > pChar->GetPrivLevel() || GetPrivLevel() == PLEVEL_Owner)) + return true; + else if (pChar->IsOwnedBy(this)) + return true; + return false; +} + bool CChar::IsOwnedBy( const CChar * pChar, bool fAllowGM ) const { ADDTOCALLSTACK("CChar::IsOwnedBy"); @@ -1388,7 +1397,7 @@ bool CChar::CanTouch( const CObjBase *pObj ) const if ( pChar == this ) return true; if ( IsPriv(PRIV_GM) ) - return (GetPrivLevel() >= pChar->GetPrivLevel()); + return (GetPrivLevel() > pChar->GetPrivLevel() || GetPrivLevel() == PLEVEL_Owner); //The check below is needed otherwise, you cannot resurrect a player ghost by using bandages (unless you are a GM), maybe there is a better way? if (pChar->IsStatFlag(STATF_DEAD) && (Skill_GetActive() == SKILL_HEALING || Skill_GetActive() == SKILL_VETERINARY)) return true; diff --git a/src/network/receive.cpp b/src/network/receive.cpp index f28b46e8b..04aca7a37 100644 --- a/src/network/receive.cpp +++ b/src/network/receive.cpp @@ -540,7 +540,7 @@ bool PacketItemEquipReq::onReceive(CNetState* net) CChar* target = targetSerial.CharFind(); bool fSuccess = false; - if (target && (itemLayer < LAYER_HORSE) && target->IsOwnedBy(source) && target->CanTouch(item)) + if (target && (itemLayer < LAYER_HORSE) && source->CanDress(target) && source->CanTouch(item)) { //if (target->CanCarry(item)) //Since Weight behavior rework, we want avoid don't be able to equip an item if overweight fSuccess = target->ItemEquip(item, source); From dcaf0af54a7a4941213f5b679aff20603586b1ad Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 10 Apr 2024 20:41:59 +0100 Subject: [PATCH 51/90] GM unequip fix Fixed: Wrong check block GMs to unequip item from players. --- Changelog.txt | 5 ++++- src/game/chars/CCharStatus.cpp | 2 +- src/network/send.cpp | 5 ++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 8d030478b..5cc12ba2b 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3574,4 +3574,7 @@ Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232 Fixed: Bonded pets cannot see their master while DeadCannotSeeLiving equals to 2. (Issue: #1225) Fixed: The issue that causes Guilds without an align shown enemy to the players with a guild with an align. (Issue: #1208) Fixed: Another fix for Invalid ResourceID console warnings. (Issue: #1071) -Fixed: GMs cannot dress up players. (Issue: #901) \ No newline at end of file +Fixed: GMs cannot dress up players. (Issue: #901) + +10-04-2024, xwerswoodx +Fixed: Wrong check block GMs to unequip item from players. \ No newline at end of file diff --git a/src/game/chars/CCharStatus.cpp b/src/game/chars/CCharStatus.cpp index 395171b75..a43c99e97 100644 --- a/src/game/chars/CCharStatus.cpp +++ b/src/game/chars/CCharStatus.cpp @@ -903,7 +903,7 @@ bool CChar::CanDress(const CChar* pChar) const { if (IsPriv(PRIV_GM) && (GetPrivLevel() > pChar->GetPrivLevel() || GetPrivLevel() == PLEVEL_Owner)) return true; - else if (pChar->IsOwnedBy(this)) + else if (g_Cfg.m_fCanUndressPets && pChar->IsOwnedBy(this)) return true; return false; } diff --git a/src/network/send.cpp b/src/network/send.cpp index 7bcc5486f..40af17891 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -2610,9 +2610,8 @@ PacketPaperdoll::PacketPaperdoll(const CClient* target, const CChar* character) mode |= (target->GetNetState()->isClientVersion(MINCLIVER_ML)) ? 0x1 : 0x40; if (target->GetNetState()->isClientVersion(MINCLIVER_ML)) { - if (character == target->GetChar() || - (g_Cfg.m_fCanUndressPets ? (character->IsOwnedBy(target->GetChar())) : (target->IsPriv(PRIV_GM) && target->GetPrivLevel() > character->GetPrivLevel())) ) - mode |= 0x2; + if (character == target->GetChar() || target->GetChar()->CanDress(character)) + mode |= 0x2; } writeInt32(character->GetUID()); From 9a091a796fb38e0a88f1e6708c87b5fff812afe8 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Fri, 12 Apr 2024 15:58:15 +0100 Subject: [PATCH 52/90] Some Review Changes --- Changelog.txt | 2 +- src/common/sphere_library/CSAssoc.h | 2 +- src/game/CServerConfig.cpp | 6 +++--- src/game/CServerConfig.h | 3 +-- src/game/chars/CCharFight.cpp | 2 +- src/game/chars/CCharSpell.cpp | 2 +- src/game/game_macros.h | 2 +- src/sphere.ini | 5 ++--- 8 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 5cc12ba2b..1f022d809 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3513,7 +3513,7 @@ Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReduction LOCAL.ItemPoisonReductionChance = Is the chance that weapon reduce poison morez. (Default 100%) LOCAL.ItemPoisonReductionAmount = Is the amount that weapon reduce. (Default: CurrentPoisonAmount/ 2) Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) -Added: MAGICF_REACTIVEARMORTH (010000) MAGICF flag to Sphere.ini to let people decide if reactive armor should reflect two handed weapons. +Added: Reactive armor range increased from 1 to 2 in default. 27-03-2024, xwerswoodx Fixed: Possible fix for accesses and bans not loading for multis. (Issue: #1223) diff --git a/src/common/sphere_library/CSAssoc.h b/src/common/sphere_library/CSAssoc.h index 69aad08fa..5e584a285 100644 --- a/src/common/sphere_library/CSAssoc.h +++ b/src/common/sphere_library/CSAssoc.h @@ -62,7 +62,7 @@ struct CElementDef { static const int sm_Lengths[ELEM_QTY]; ELEM_TYPE m_type; - uint64 m_offset; // The offset into the class instance for this item. + size_t m_offset; // The offset into the class instance for this item. // get structure value. void * GetValPtr( const void * pBaseInst ) const; diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 588554496..a0c092be9 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -174,7 +174,7 @@ CServerConfig::CServerConfig() m_iHitsUpdateRate = MSECS_PER_SEC; m_iSpeedScaleFactor = 80000; m_iCombatFlags = 0; - m_iElementalEngineFlags = UINT64_MAX; //In default, all Elemental Engine flags are active, also I put UINT64_MAX to let sphere active new flags (if added) automatically. + m_iElementalEngineFlags = UINT32_MAX; //In default, all Elemental Engine flags are active, also I put UINT32_MAX to let sphere active new flags (if added) automatically. m_iCombatArcheryMovementDelay = 10; m_iCombatDamageEra = 0; m_iCombatHitChanceEra = 0; @@ -789,7 +789,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY+1] { "DUMPPACKETSFORACC", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sDumpAccPackets) }}, #endif { "DUNGEONLIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightDungeon) }}, - { "ELEMENTALENGINEFLAGS", { ELEM_MASK_INT64, static_castOFFSETOF(CServerConfig, m_iElementalEngineFlags) }}, + { "ELEMENTALENGINEFLAGS", { ELEM_MASK_INT, static_castOFFSETOF(CServerConfig, m_iElementalEngineFlags) }}, { "EMOTEFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iEmoteFlags) }}, { "EQUIPPEDCAST", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fEquippedCast) }}, { "ERALIMITGEAR", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iEraLimitGear) }}, @@ -1375,7 +1375,7 @@ bool CServerConfig::r_LoadVal( CScript &s ) break; case RC_ELEMENTALENGINEFLAGS: - m_iElementalEngineFlags = s.GetArg64Val(); + m_iElementalEngineFlags = s.GetArgUVal(); break; case RC_EXPERIMENTAL: diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 284e3ad1c..634a7b06f 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -178,7 +178,6 @@ enum MAGICFLAGS_TYPE MAGICF_CASTPARALYZED = 0x0002000, // Can cast even if paralyzed MAGICF_NOREFLECTOWN = 0x0004000, // Do not reflect the own spells if the spell reflected from the target. MAGICF_DELREFLECTOWN = 0x0008000, // Remove reflection instead of damaging himself when NOREFLECTOWN active if the spell reflected from another target. - MAGICF_REACTIVEARMORTH = 0x0010000 // Reactive armor reflect two handed weapons. }; enum REVEALFLAGS_TYPE @@ -391,7 +390,7 @@ extern class CServerConfig : public CResourceHolder // Flags for controlling pvp/pvm behaviour of players uint m_iCombatFlags; // combat flags uint m_iMagicFlags; // magic flags - uint64 m_iElementalEngineFlags; //Elemental engine flags + uint m_iElementalEngineFlags; //Elemental engine flags uint m_iRacialFlags; // racial traits flags uint m_iRevealFlags; // reveal flags used for SPELL_REVEAL (mostly for backwards). uint m_iEmoteFlags; // emote flags diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 640978787..716aef6ea 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -923,7 +923,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys // Preventing recurrent reflection with DAMAGE_REACTIVE. if ( IsStatFlag(STATF_REACTIVE) && !((uType & DAMAGE_GOD) || (uType & DAMAGE_REACTIVE)) ) { - if (GetTopDist3D(pSrc) < 2 || (IsSetMagicFlags(MAGICF_REACTIVEARMORTH) && GetTopDist3D(pSrc) <= 2)) + if (GetTopDist3D(pSrc) <= 2) { CItem* pReactive = LayerFind(LAYER_SPELL_Reactive); diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index a5b9a29f9..957d4750c 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -2281,7 +2281,7 @@ void CChar::Spell_Field(CPointMap pntTarg, ITEMID_TYPE idEW, ITEMID_TYPE idNS, u pSpell->SetHue(iColor); pSpell->GenerateScript(this); - if (pSpellDef->IsSpellType(SPELLFLAG_ASYNC)) // If the spell has ASYNC flag, the timers should be randomized. + if (pSpellDef->IsSpellType(SPELLFLAG_FIELD_RANDOMDECAY)) // If the spell has ASYNC flag, the timers should be randomized. iDuration += Calc_GetRandLLVal(iDuration / 2); pSpell->MoveToDecay( ptg, iDuration * MSECS_PER_TENTH, true); diff --git a/src/game/game_macros.h b/src/game/game_macros.h index 416ceb67a..c84ce2e70 100644 --- a/src/game/game_macros.h +++ b/src/game/game_macros.h @@ -105,7 +105,7 @@ typedef dword DAMAGE_TYPE; // describe a type of damage. #define SPELLFLAG_CURSE 0x20000000 // Curses just like Weaken,Purge Magic,Curse,etc. #define SPELLFLAG_HEAL 0x40000000 // Healing spell #define SPELLFLAG_TICK 0x80000000 // A ticking spell like Poison. -#define SPELLFLAG_ASYNC 0x100000000 // Make the field items have random timers. +#define SPELLFLAG_FIELD_RANDOMDECAY 0x100000000 // Make the field items have random timers. #define SPELLFLAG_TARG_ONLYSELF 0x200000000 // You can only target yourself. #endif // _INC_GAME_MACROS_H diff --git a/src/sphere.ini b/src/sphere.ini index 2b74ac111..86630907c 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -408,8 +408,8 @@ SuppressCapitals=0 // EE_STEELSKIN 0080 // Adds Elemental buff/defuff to steel skin spell. // EE_RESPHYSICAL 0100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. // ALL 01FF // Includes all from 01 to 0100. -// MAX 0FFFFFFFFFFFFFFFF // Includes all flag values for UINT64. -//ElementalEngineFlags=0FFFFFFFFFFFFFFFF +// MAX 0FFFFFFFF // Includes all flag values for UINT. +//ElementalEngineFlags=0FFFFFFFF // If COMBAT_ARCHERYCANMOVE is not enabled, wait this much tenth of seconds (minimum=0) after the player // stopped moving before starting a new attack @@ -477,7 +477,6 @@ DisplayElementalResistance = 0 // MAGICF_CASTPARALYZED 002000 // Can cast even if paralyzed // MAGICF_NOREFLECTOWN 004000 // Do not reflect own spell if the spell has already reflected from the target. // MAGICF_DELREFLECTOWN 008000 // Remove reflection instead of damage himself when NOREFLECTOWN active if the spell reflected from another target. -// MAGICF_REACTIVEARMORTH 010000 // Increases Reactive Armor spell range from 1 block to 2. //MagicFlags=0 // Max amount of each Stat gained through Polymorph spell. This affects separatelly to each stat. From bebbf59701cf24870a0be5a66b9f01278699ee36 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 14 Apr 2024 21:20:04 +0100 Subject: [PATCH 53/90] Custom Hosing Fix Fixed: An issue that causes a visual bug to remove all tiles while removing a tile in higher floors. (Issue: #345) --- Changelog.txt | 7 +++++-- src/game/items/CItemMultiCustom.cpp | 15 ++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 1f022d809..1a11000e6 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3513,7 +3513,7 @@ Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReduction LOCAL.ItemPoisonReductionChance = Is the chance that weapon reduce poison morez. (Default 100%) LOCAL.ItemPoisonReductionAmount = Is the amount that weapon reduce. (Default: CurrentPoisonAmount/ 2) Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) -Added: Reactive armor range increased from 1 to 2 in default. +Changed: Reactive armor range increased from 1 to 2 in default. 27-03-2024, xwerswoodx Fixed: Possible fix for accesses and bans not loading for multis. (Issue: #1223) @@ -3577,4 +3577,7 @@ Fixed: Another fix for Invalid ResourceID console warnings. (Issue: #1071) Fixed: GMs cannot dress up players. (Issue: #901) 10-04-2024, xwerswoodx -Fixed: Wrong check block GMs to unequip item from players. \ No newline at end of file +Fixed: Wrong check block GMs to unequip item from players. + +14-04-2024, xwerswoodx +Fixed: An issue that causes a visual bug to remove all tiles while removing a tile in higher floors. (Issue: #345) \ No newline at end of file diff --git a/src/game/items/CItemMultiCustom.cpp b/src/game/items/CItemMultiCustom.cpp index a5e19d9f8..1de47c1bf 100644 --- a/src/game/items/CItemMultiCustom.cpp +++ b/src/game/items/CItemMultiCustom.cpp @@ -931,17 +931,14 @@ void CItemMultiCustom::SendStructureTo(CClient * pClientSrc) if (!pDesign->m_vectorComponents.empty()) { - if (_iMaxPlane < 0) + // find the highest plane/floor + for (const CMultiComponent *pComp : pDesign->m_vectorComponents) { - // find the highest plane/floor - for (const CMultiComponent *pComp : pDesign->m_vectorComponents) - { - const uchar uiPlane = GetPlane(pComp); - if (uiPlane <= _iMaxPlane) - continue; + const uchar uiPlane = GetPlane(pComp); + if (uiPlane <= _iMaxPlane) + continue; - _iMaxPlane = uiPlane; - } + _iMaxPlane = uiPlane; } // determine the dimensions of the building From af32ecce4592a4ba57b7f9a2086491d23396a162 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 16 Apr 2024 18:25:26 +0100 Subject: [PATCH 54/90] Merged Jhobean's Pr Merged Jhobean's EMOTEF_EAT PR and split EAT flag for npcs and players. (PR: #1207) --- Changelog.txt | 15 +++++++++++++-- src/game/CServerConfig.h | 11 +++++++---- src/game/chars/CChar.h | 2 +- src/game/chars/CCharAct.cpp | 20 +++++++++++++------- src/game/chars/CCharNPCAct.cpp | 10 ++++++---- src/game/chars/CCharUse.cpp | 2 +- src/sphere.ini | 8 +++++--- src/tables/defmessages.tbl | 3 ++- 8 files changed, 48 insertions(+), 23 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 1a11000e6..3755703b7 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3448,6 +3448,11 @@ Additionally, the problem of zig-zag issue following in the South direction has 13-03-2024, Jhobean - Added: Item properties functionnality:HITAREAPHYSICAL,HITAREAFIRE,HITAREACOLD,HITAREAPOISON,HITAREAENERGY,HITFIREBALL,HITHARM,HITLIGHTNING,HITMAGICARROW,REFLECTPHYSICALDAM +16-03-2024, Jhobean +- Added: Flag EMOTEF_EAT is added on the ini to avoid see the emote when eating. +- Added: NPC_EAT_GRASS MSG to be able change the hardcode name of "grass" when an animal eat grass +- Added: Item been eaten can now be read on the ARGO parameter of the trigger @Eat. + 24-03-2024, xwerswoodx Fixed: The issue that causes more1/2 not saved correctly for spellbook. (Issue: #1221) Fixed: Players automatically become criminal to everyone when attack someone. (Issue: #1213) @@ -3510,8 +3515,9 @@ Added: New function trigger f_onserver_broadcast. (Issue: #1145) - Returns: 1: Prevents server to send broadcast message. Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReductionAmount to @Hit trigger. (Issue: #1159) + This LOCALs changes default behaviour of poisoned weapons while removing poison. LOCAL.ItemPoisonReductionChance = Is the chance that weapon reduce poison morez. (Default 100%) - LOCAL.ItemPoisonReductionAmount = Is the amount that weapon reduce. (Default: CurrentPoisonAmount/ 2) + LOCAL.ItemPoisonReductionAmount = Is the amount of poison that weapon reduce. (Default: CurrentPoisonAmount/ 2) Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) Changed: Reactive armor range increased from 1 to 2 in default. @@ -3580,4 +3586,9 @@ Fixed: GMs cannot dress up players. (Issue: #901) Fixed: Wrong check block GMs to unequip item from players. 14-04-2024, xwerswoodx -Fixed: An issue that causes a visual bug to remove all tiles while removing a tile in higher floors. (Issue: #345) \ No newline at end of file +Fixed: An issue that causes a visual bug to remove all tiles while removing a tile in higher floors. (Issue: #345) + +16-04-2024, xwerswoodx +Changed: EMOTEF_EAT name changed to EMOTEF_HIDE_EAT_PLAYER and limited to only player emotes. + EMOTEF_EAT is from the merge of Jhobean's pr so it wasn't in sphere at all. +Added: EMOTEF_HIDE_EAT_NPC to hide emotes while eating only for npcs. \ No newline at end of file diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 634a7b06f..0d1673e21 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -198,7 +198,9 @@ enum EMOTEFLAGS_TYPE { EMOTEF_ATTACKER = 0x01, // Only show %s is attacking %s! emote to attacked character. EMOTEF_POISON = 0x02, // Only show poison emote to affected character. - EMOTEF_DESTROY = 0x04 // Only show item destroy emote to the owner of the item. + EMOTEF_DESTROY = 0x04, // Only show item destroy emote to the owner of the item. + EMOTEF_HIDE_EAT_PLAYER = 0x08, // Do not show emote while players eating. + EMOTEF_HIDE_EAT_NPC = 0x010 // Do not show emote while npcs eating. }; enum TOOLTIPMODE_TYPE @@ -1126,9 +1128,10 @@ typedef std::map KRGumpsMap; #define IsSetEF(ef) ((g_Cfg._uiExperimentalFlags & ef) != 0) #define IsSetOF(of) ((g_Cfg._uiOptionFlags & of) != 0) -#define IsSetCombatFlags(of) ((g_Cfg.m_iCombatFlags & of) != 0) -#define IsSetMagicFlags(of) ((g_Cfg.m_iMagicFlags & of) != 0) -#define IsSetEEFlags(of) ((g_Cfg.m_iElementalEngineFlags & of) != 0) +#define IsSetCombatFlags(cf) ((g_Cfg.m_iCombatFlags & cf) != 0) +#define IsSetMagicFlags(mf) ((g_Cfg.m_iMagicFlags & mf) != 0) +#define IsSetEEFlags(eef) ((g_Cfg.m_iElementalEngineFlags & eef) != 0) +#define IsSetEmoteFlag(ef) ((g_Cfg.m_iEmoteFlags & ef) != 0) #endif // _INC_CSERVERCONFIG_H diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 4bf1b62e6..0c410641e 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -1138,7 +1138,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; bool Death(); bool Reveal( uint64 iFlags = 0 ); void Jail( CTextConsole * pSrc, bool fSet, int iCell ); - void EatAnim( lpctstr pszName, ushort uiQty ); + void EatAnim(CItem* pItem, ushort uiQty); /** * @Brief I'm calling guards (Player speech) * diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index 9cf9d7cb8..b76519662 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -2230,32 +2230,38 @@ bool CChar::ItemEquip( CItem * pItem, CChar * pCharMsg, bool fFromDClick ) // OnEat() // Generating eating animation // also calling @Eat and setting food's level (along with other possible stats 'local.hits',etc?) -void CChar::EatAnim( lpctstr pszName, ushort uiQty ) +void CChar::EatAnim(CItem* pItem, ushort uiQty) { ADDTOCALLSTACK("CChar::EatAnim"); + ASSERT(pItem); //Should never happen, but make sure item is valid. + static const SOUND_TYPE sm_EatSounds[] = { 0x03a, 0x03b, 0x03c }; Sound(sm_EatSounds[Calc_GetRandVal(ARRAY_COUNT(sm_EatSounds))]); if ( !IsStatFlag(STATF_ONHORSE) ) UpdateAnimate(ANIM_EAT); - tchar * pszMsg = Str_GetTemp(); - snprintf(pszMsg, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_MSG_EATSOME), pszName); - Emote(pszMsg); + EMOTEFLAGS_TYPE eFlag = (IsPlayer() ? EMOTEF_HIDE_EAT_PLAYER : EMOTEF_HIDE_EAT_NPC); + if (!IsSetEmoteFlag(eFlag)) + { + tchar* pszMsg = Str_GetTemp(); + snprintf(pszMsg, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_MSG_EATSOME), pItem->GetName()); + Emote(pszMsg); + } ushort uiHits = 0; ushort uiMana = 0; ushort uiStam = (ushort)( Calc_GetRandVal2(3, 6) + (uiQty / 5) ); ushort uiFood = uiQty; ushort uiStatsLimit = 0; - if ( IsTrigUsed(TRIGGER_EAT) ) + if (IsTrigUsed(TRIGGER_EAT)) { - CScriptTriggerArgs Args; + CScriptTriggerArgs Args(uiStatsLimit); Args.m_VarsLocal.SetNumNew("Hits", uiHits); Args.m_VarsLocal.SetNumNew("Mana", uiMana); Args.m_VarsLocal.SetNumNew("Stam", uiStam); Args.m_VarsLocal.SetNumNew("Food", uiFood); - Args.m_iN1 = uiStatsLimit; + Args.m_pO1 = pItem; if ( OnTrigger(CTRIG_Eat, this, &Args) == TRIGRET_RET_TRUE ) return; diff --git a/src/game/chars/CCharNPCAct.cpp b/src/game/chars/CCharNPCAct.cpp index d123ce766..f01074478 100644 --- a/src/game/chars/CCharNPCAct.cpp +++ b/src/game/chars/CCharNPCAct.cpp @@ -1782,7 +1782,7 @@ bool CChar::NPC_Act_Food() { // can take and eat just in place ushort uiEaten = (ushort)(pClosestFood->ConsumeAmount(uiEatAmount)); - EatAnim(pClosestFood->GetName(), uiEaten); + EatAnim(pClosestFood, uiEaten); if ( !pClosestFood->GetAmount() ) { pClosestFood->Plant_CropReset(); // set growth if this is a plant @@ -1847,7 +1847,8 @@ bool CChar::NPC_Act_Food() if ( pResBit && pResBit->GetAmount() && ( pResBit->GetTopPoint().m_z == iMyZ ) ) { ushort uiEaten = pResBit->ConsumeAmount(10); - EatAnim("grass", uiEaten/10); + pResBit->SetName(g_Cfg.GetDefaultMsg(DEFMSG_NPC_EAT_GRASS)); + EatAnim(pResBit, uiEaten/10); // the bit is not needed in a worldsave, timeout of 10 minutes pResBit->m_TagDefs.SetNum("NOSAVE", 1); @@ -2485,7 +2486,7 @@ void CChar::NPC_Food() // can take and eat just in place EXC_SET_BLOCK("eating nearby"); ushort uiEaten = pClosestFood->ConsumeAmount(uiEatAmount); - EatAnim(pClosestFood->GetName(), uiEaten); + EatAnim(pClosestFood, uiEaten); if ( !pClosestFood->GetAmount() ) { pClosestFood->Plant_CropReset(); // set growth if this is a plant @@ -2542,7 +2543,8 @@ void CChar::NPC_Food() { EXC_SET_BLOCK("eating grass"); const ushort uiEaten = pResBit->ConsumeAmount(15); - EatAnim("grass", uiEaten/10); + pResBit->SetName(g_Cfg.GetDefaultMsg(DEFMSG_NPC_EAT_GRASS)); + EatAnim(pResBit, uiEaten/10); // the bit is not needed in a worldsave, timeout of 10 minutes pResBit->m_TagDefs.SetNum("NOSAVE", 1); diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index f988e331a..890acc632 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -903,7 +903,7 @@ void CChar::Use_EatQty( CItem * pFood, ushort uiQty ) } UpdateDir(pFood); - EatAnim(pFood->GetName(), uiRestore * uiQty); + EatAnim(pFood, uiRestore * uiQty); pFood->ConsumeAmount(uiQty); } diff --git a/src/sphere.ini b/src/sphere.ini index 86630907c..b41e9633c 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -511,9 +511,11 @@ RacialFlags=0 RevealFlags=01|02|04|08|010|040|080|0200 // Emote flags -// EMOTEF_ATTACKER 01 // Only show %s is attacking %s! emote to attacked character. -// EMOTEF_POISON 02 // Only show poison emotes to the affected character. -// EMOTEF_DESTROY 04 // Only show item destroyed emote to the owner of the item. +// EMOTEF_ATTACKER 001 // Only show %s is attacking %s! emote to attacked character. +// EMOTEF_POISON 002 // Only show poison emotes to the affected character. +// EMOTEF_DESTROY 004 // Only show item destroyed emote to the owner of the item. +// EMOTEF_HIDE_EAT_PLAYER 008 // Do not show emote while players eating. +// EMOTEF_HIDE_EAT_NPC 010 // Do not show emote while npcs eating. EmoteFlags=0 // Length of time (in seconds) for a char to remember his attacker (used for attacker keyword) diff --git a/src/tables/defmessages.tbl b/src/tables/defmessages.tbl index 885d0353b..6467574fe 100644 --- a/src/tables/defmessages.tbl +++ b/src/tables/defmessages.tbl @@ -587,7 +587,8 @@ MSG(MUSICANSHIP_POOR, "You play poorly.") MSG(NPC_VENDOR_GUARDS, "Ahh, Guards my goods are gone !!") MSG(NPC_VENDOR_SELL_TY, "Here you are, %d gold coin%s. I thank thee for thy business.") MSG(NON_ALIVE, "That does not appear to be a living being.") -MSG(NPC_BANKER_DEPOSIT, "I shall deposit %d gold in your account") +MSG(NPC_BANKER_DEPOSIT, "I shall deposit %d gold in your account") +MSG(NPC_EAT_GRASS, "grass") MSG(NPC_GENERIC_CRIM, "Help! Guards a Criminal!") MSG(NPC_GENERIC_DONTWANT, "They don't appear to want the item") MSG(NPC_GENERIC_GONE_1, "Well it was nice speaking to you %s but I must go about my business") From 33dba6c71ad90e2b7aa0bc91abb6cacb9288136b Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 16 Apr 2024 21:30:32 +0100 Subject: [PATCH 55/90] @Hit and @GetHit as Item Triggers Added: Trigger @Hit is added as an item trigger. Added: Trigger @GetHit is added as an item trigger. --- Changelog.txt | 39 ++++++++++++++++++++++++++++++++++- src/game/CObjBase.h | 2 ++ src/game/chars/CCharFight.cpp | 29 ++++++++++++++++++++++++-- src/game/items/CItem.cpp | 2 ++ 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 3755703b7..322cc1e86 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3591,4 +3591,41 @@ Fixed: An issue that causes a visual bug to remove all tiles while removing a ti 16-04-2024, xwerswoodx Changed: EMOTEF_EAT name changed to EMOTEF_HIDE_EAT_PLAYER and limited to only player emotes. EMOTEF_EAT is from the merge of Jhobean's pr so it wasn't in sphere at all. -Added: EMOTEF_HIDE_EAT_NPC to hide emotes while eating only for npcs. \ No newline at end of file +Added: EMOTEF_HIDE_EAT_NPC to hide emotes while eating only for npcs. +Added: Trigger @Hit is added as an item trigger. + This trigger nows trigger before @Damage but after character @Hit trigger. + Args are same as the character @Hit trigger, but I and ARGO switch the values. + Args: + - I: The weapon being used. + - SRC: The character being hit. + - ARGO: The character doing the hitting. + - ARGN1: The amount of damage being dealt. + - ARGN2: The type(s) of damage. + - LOCAL.ARROW: UID of the arrow used (Archery only) [Read Only] + - LOCAL.ARROWHANDLED: If set true (1), clears the ammo stack variable. + - LOCAL.ITEMDAMAGECHANCE: Sets the damage chance for the weapon. (Default: 25%) + - LOCAL.ITEMPOISONREDUCTIONCHANCE: Sets the poison reduction chance for poisoned weapons. + - LOCAL.ITEMPOISONREDUCTIONAMOUNT: Sets the amount of poison that reduced from morez value. + Returns: + 1: Cancels the combat swing of the character. +Added: Trigger @GetHit is added as an item trigger. + This trigger nows trigger before @Damage but after character @GetHit trigger. + Args are same as the character @GetHit trigger, but I changed to the item, and the character saves on ARGO. + Also LOCAL.ITEMDAMAGELAYER only works under character @GetHit trigger, it is only readable under item trigger. + Args: + - I: The clothing part take a hit. + - SRC: The character responsible for the damage. + - ARGO: The character being damaged. + - ARGN1: The amount of damage being applied. (Before slayer calculation if applicable) + - ARGN2: The type(s) of damage being applied. + - ARGN3: Hits will be fixed to this amount after the hit if the value is greaten than it (default: 0) + - LOCAL.ITEMDAMAGECHANCE: Sets the damage chance for the hitted part of the body. (Armor or shield, if any) (Default: 25%) + - LOCAL.DAMAGEPERCENTPHYSICAL: The amount in % of the physical damage received, only set if Elemental Engine is enabled. [Read Only] + - LOCAL.DAMAGEPERCENTPHYSICAL: The amount in % of the physical damage received, only set if Elemental Engine is enabled. [Read Only] + - LOCAL.DAMAGEPERCENTFIRE: The amount in % of the fire damage received, only set if Elemental Engine is enabled. [Read Only] + - LOCAL.DAMAGEPERCENTCOLD: The amount in % of the cold damage received, only set if Elemental Engine is enabled. [Read Only] + - LOCAL.DAMAGEPERCENTPOISON: The amount in % of the poison damage received, only set if Elemental Engine is enabled. [Read Only] + - LOCAL.DAMAGEPERCENTENERGY: The amount in % of the energy damage received, only set if Elemental Engine is enabled. [Read Only] + - LOCAL.ITEMDAMAGELAYER: The layer of the item being damaged. [Read Only] + Returns: + 1: Prevents damage from being applied to the character. \ No newline at end of file diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index c25695806..2187b23b2 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -1039,6 +1039,8 @@ enum ITRIG_TYPE ITRIG_DYE, ITRIG_EQUIP, // I have been equipped. ITRIG_EQUIPTEST, // I'm not yet equiped, but checking if I can. + ITRIG_GetHit, // Triggers when this clothing part get hit from characters. + ITRIG_Hit, // Triggers when this item used to make a damage on characters. ITRIG_MemoryEquip, // I'm a memory and I'm being equiped. ITRIG_PICKUP_GROUND, // I'm being picked up from ground. ITRIG_PICKUP_PACK, // picked up from inside some container. diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 716aef6ea..9e6d8f008 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -748,19 +748,31 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys Args.m_VarsLocal.SetNum("DamagePercentEnergy", iDmgEnergy); } + CItem* pItemHit = nullptr; if ( IsTrigUsed(TRIGGER_GETHIT) ) { if ( OnTrigger( CTRIG_GetHit, pSrc, &Args ) == TRIGRET_RET_TRUE ) return 0; iDmg = (int)(Args.m_iN1); uType = (DAMAGE_TYPE)(Args.m_iN2); + + LAYER_TYPE iHitLayer = (LAYER_TYPE)(Args.m_VarsLocal.GetKeyNum("ItemDamageLayer")); + pItemHit = LayerFind(iHitLayer); + if (pItemHit) + { + Args.m_pO1 = this; + // "ItemDamageLayer" will only be readable. + if (pItemHit->OnTrigger(ITRIG_GetHit, pSrc, &Args) == TRIGRET_RET_TRUE) + return 0; + iDmg = (int)(Args.m_iN1); //Update damage amount and type again after @Hit trigger under item. + uType = (DAMAGE_TYPE)(Args.m_iN2); + // We don't need to update iHitLayer as it's already called on item + } } int iItemDamageChance = (int)(Args.m_VarsLocal.GetKeyNum("ItemDamageChance")); if ( (iItemDamageChance > Calc_GetRandVal(100)) && !Can(CAN_C_NONHUMANOID) ) { - LAYER_TYPE iHitLayer = (LAYER_TYPE)(Args.m_VarsLocal.GetKeyNum("ItemDamageLayer")); - CItem *pItemHit = LayerFind(iHitLayer); if ( pItemHit ) pItemHit->OnTakeDamage(iDmg, pSrc, uType); } @@ -2113,6 +2125,19 @@ WAR_SWING_TYPE CChar::Fight_Hit( CChar * pCharTarg ) iDmg = (int)(Args.m_iN1); iDmgType = (DAMAGE_TYPE)(Args.m_iN2); + + if (pWeapon) + { + Args.m_pO1 = this; + if (pWeapon->OnTrigger(ITRIG_Hit, pCharTarg, &Args) == TRIGRET_RET_TRUE) + return WAR_SWING_EQUIPPING; + + if (Args.m_VarsLocal.GetKeyNum("ArrowHandled") != 0) // if arrow is handled by script, do nothing with it further + pAmmo = nullptr; + + iDmg = (int)(Args.m_iN1); + iDmgType = (DAMAGE_TYPE)(Args.m_iN2); + } } // BAD BAD Healing fix.. Cant think of something else -- Radiant diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index fd867cc62..e23ef4daa 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -68,6 +68,8 @@ lpctstr const CItem::sm_szTrigName[ITRIG_QTY+1] = // static "@Dye", // My color has been changed "@EQUIP", // I have been unequipped "@EQUIPTEST", + "@GetHit", + "@Hit", "@MemoryEquip", "@PICKUP_GROUND", // I was picked up off the ground. "@PICKUP_PACK", // picked up from inside some container. From 7d887da72793e4975dfcdf80e387b9aba4b78458 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 16 Apr 2024 22:50:04 +0100 Subject: [PATCH 56/90] Visual Range Update Added: MAPVIEWRADAR, MAPVIEWSIZE and MAPVIEWSIZEMAX to sphere.ini that overrides default visual range values. (Issue: #1144) --- Changelog.txt | 7 +- src/common/CScriptObj.cpp | 2 +- src/game/CObjBaseTemplate.cpp | 5 +- src/game/CServerConfig.cpp | 136 +++++++++++++-------- src/game/CServerConfig.h | 4 + src/game/chars/CChar.cpp | 4 +- src/game/chars/CCharAct.cpp | 4 +- src/game/chars/CCharFight.cpp | 4 +- src/game/chars/CCharMemory.cpp | 2 +- src/game/chars/CCharNPCAct.cpp | 8 +- src/game/chars/CCharUse.cpp | 2 +- src/game/clients/CClientMsg.cpp | 8 +- src/game/clients/CClientMsg_AOSTooltip.cpp | 2 +- src/game/components/CCItemDamageable.cpp | 4 +- src/game/items/CItem.cpp | 19 +-- src/network/send.cpp | 6 +- src/sphere.ini | 9 ++ 17 files changed, 137 insertions(+), 89 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 322cc1e86..1d247896c 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3628,4 +3628,9 @@ Added: Trigger @GetHit is added as an item trigger. - LOCAL.DAMAGEPERCENTENERGY: The amount in % of the energy damage received, only set if Elemental Engine is enabled. [Read Only] - LOCAL.ITEMDAMAGELAYER: The layer of the item being damaged. [Read Only] Returns: - 1: Prevents damage from being applied to the character. \ No newline at end of file + 1: Prevents damage from being applied to the character. +Added: MAPVIEWRADAR, MAPVIEWSIZE and MAPVIEWSIZEMAX to sphere.ini that overrides default visual range values. (Issue: #1144) + Defaults: + MapViewRadar=31 + MapViewSize=18 + MapViewSizeMax=24 \ No newline at end of file diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index 3c20c387c..02978f202 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -2454,7 +2454,7 @@ TRIGRET_TYPE CScriptObj::OnTriggerLoopGeneric(CScript& s, int iType, CTextConsol if (s.HasArgs()) iDist = s.GetArgVal(); else - iDist = UO_MAP_VIEW_SIZE_DEFAULT; + iDist = g_Cfg.m_iMapViewSize; CObjBaseTemplate* pObj = dynamic_cast (this); if (pObj == nullptr) diff --git a/src/game/CObjBaseTemplate.cpp b/src/game/CObjBaseTemplate.cpp index 1cdb34073..92517d7d0 100644 --- a/src/game/CObjBaseTemplate.cpp +++ b/src/game/CObjBaseTemplate.cpp @@ -1,6 +1,7 @@ #include "../sphere/threads.h" #include "uo_files/uofiles_macros.h" #include "CObjBaseTemplate.h" +#include "CServerConfig.h" CObjBaseTemplate::CObjBaseTemplate() : @@ -163,7 +164,7 @@ DIR_TYPE CObjBaseTemplate::GetDir( const CObjBaseTemplate * pObj, DIR_TYPE DirDe int CObjBaseTemplate::GetVisualRange() const // virtual { - return UO_MAP_VIEW_SIZE_DEFAULT; + return g_Cfg.m_iMapViewSize; } @@ -191,4 +192,4 @@ bool CObjBaseTemplate::SetName( lpctstr pszName ) return false; m_sName = pszName; return true; -} \ No newline at end of file +} diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index a0c092be9..77b8922f0 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -200,6 +200,10 @@ CServerConfig::CServerConfig() _uiAreaFlags = AREAF_RoomInheritsFlags; _fMeditationMovementAbort = false; + m_iMapViewSize = UO_MAP_VIEW_SIZE_DEFAULT; + m_iMapViewSizeMax = UO_MAP_VIEW_SIZE_MAX; + m_iMapViewRadar = UO_MAP_VIEW_RADAR; + m_iMaxSkill = SKILL_QTY; m_iWalkBuffer = 15; m_iWalkRegen = 25; @@ -573,6 +577,9 @@ enum RC_TYPE RC_MANALOSSFAIL, // m_fManaLossFail RC_MANALOSSPERCENT, // m_fManaLossPercent RC_MAPCACHETIME, + RC_MAPVIEWRADAR, + RC_MAPVIEWSIZE, + RC_MAPVIEWSIZEMAX, RC_MAXBASESKILL, // m_iMaxBaseSkill RC_MAXCHARSPERACCOUNT, // RC_MAXCOMPLEXITY, // m_iMaxCharComplexity @@ -790,62 +797,65 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY+1] #endif { "DUNGEONLIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightDungeon) }}, { "ELEMENTALENGINEFLAGS", { ELEM_MASK_INT, static_castOFFSETOF(CServerConfig, m_iElementalEngineFlags) }}, - { "EMOTEFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iEmoteFlags) }}, - { "EQUIPPEDCAST", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fEquippedCast) }}, - { "ERALIMITGEAR", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iEraLimitGear) }}, - { "ERALIMITLOOT", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iEraLimitLoot) }}, - { "ERALIMITPROPS", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iEraLimitProps) }}, - { "EVENTSITEM", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sEventsItem) }}, - { "EVENTSPET", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sEventsPet) }}, - { "EVENTSPLAYER", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sEventsPlayer) }}, - { "EVENTSREGION", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sEventsRegion) }}, - { "EXPERIENCEKOEFPVM", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iExperienceKoefPVM) }}, - { "EXPERIENCEKOEFPVP", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iExperienceKoefPVP) }}, - { "EXPERIENCEMODE", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iExperienceMode) }}, - { "EXPERIENCESYSTEM", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bExperienceSystem) }}, - { "EXPERIMENTAL", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiExperimentalFlags) }}, - { "FEATUREAOS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureAOS) }}, - { "FEATUREEXTRA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureExtra) }}, - { "FEATUREKR", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureKR) }}, - { "FEATURELBR", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureLBR) }}, - { "FEATUREML", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureML) }}, - { "FEATURESA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureSA) }}, - { "FEATURESE", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureSE) }}, - { "FEATURET2A", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureT2A) }}, - { "FEATURETOL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureTOL) }}, - { "FLIPDROPPEDITEMS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fFlipDroppedItems) }}, - { "FORCEGARBAGECOLLECT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fSaveGarbageCollect) }}, - { "FREEZERESTARTTIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFreezeRestartTime) }}, - { "GAMEMINUTELENGTH", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iGameMinuteLength) }}, - { "GENERICSOUNDS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fGenericSounds) }}, - { "GUARDLINGER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iGuardLingerTime) }}, - { "GUARDSINSTANTKILL", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fGuardsInstantKill) }}, - { "GUARDSONMURDERERS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fGuardsOnMurderers) }}, - { "GUESTSMAX", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iGuestsMax) }}, - { "GUILDS", { ELEM_VOID, 0 }}, - { "HEARALL", { ELEM_VOID, 0 }}, - { "HELPINGCRIMINALSISACRIME",{ ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fHelpingCriminalsIsACrime) }}, - { "HITPOINTPERCENTONREZ", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iHitpointPercentOnRez) }}, - { "HITSHUNGERLOSS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iHitsHungerLoss) }}, - { "HITSUPDATERATE", { ELEM_VOID, 0 }}, + { "EMOTEFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iEmoteFlags) }}, + { "EQUIPPEDCAST", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fEquippedCast) }}, + { "ERALIMITGEAR", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iEraLimitGear) }}, + { "ERALIMITLOOT", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iEraLimitLoot) }}, + { "ERALIMITPROPS", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iEraLimitProps) }}, + { "EVENTSITEM", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sEventsItem) }}, + { "EVENTSPET", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sEventsPet) }}, + { "EVENTSPLAYER", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sEventsPlayer) }}, + { "EVENTSREGION", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sEventsRegion) }}, + { "EXPERIENCEKOEFPVM", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iExperienceKoefPVM) }}, + { "EXPERIENCEKOEFPVP", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iExperienceKoefPVP) }}, + { "EXPERIENCEMODE", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iExperienceMode) }}, + { "EXPERIENCESYSTEM", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bExperienceSystem) }}, + { "EXPERIMENTAL", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiExperimentalFlags) }}, + { "FEATUREAOS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureAOS) }}, + { "FEATUREEXTRA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureExtra) }}, + { "FEATUREKR", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureKR) }}, + { "FEATURELBR", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureLBR) }}, + { "FEATUREML", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureML) }}, + { "FEATURESA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureSA) }}, + { "FEATURESE", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureSE) }}, + { "FEATURET2A", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureT2A) }}, + { "FEATURETOL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureTOL) }}, + { "FLIPDROPPEDITEMS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fFlipDroppedItems) }}, + { "FORCEGARBAGECOLLECT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fSaveGarbageCollect) }}, + { "FREEZERESTARTTIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFreezeRestartTime) }}, + { "GAMEMINUTELENGTH", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iGameMinuteLength) }}, + { "GENERICSOUNDS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fGenericSounds) }}, + { "GUARDLINGER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iGuardLingerTime) }}, + { "GUARDSINSTANTKILL", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fGuardsInstantKill) }}, + { "GUARDSONMURDERERS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fGuardsOnMurderers) }}, + { "GUESTSMAX", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iGuestsMax) }}, + { "GUILDS", { ELEM_VOID, 0 }}, + { "HEARALL", { ELEM_VOID, 0 }}, + { "HELPINGCRIMINALSISACRIME",{ ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fHelpingCriminalsIsACrime) }}, + { "HITPOINTPERCENTONREZ", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iHitpointPercentOnRez) }}, + { "HITSHUNGERLOSS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iHitsHungerLoss) }}, + { "HITSUPDATERATE", { ELEM_VOID, 0 }}, { "ITEMHITPOINTSUPDATE", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_iItemHitpointsUpdate), }}, - { "ITEMSMAXAMOUNT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iItemsMaxAmount), }}, - { "LEVELMODE", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLevelMode), }}, - { "LEVELNEXTAT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLevelNextAt), }}, - { "LEVELSYSTEM", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bLevelSystem), }}, - { "LIGHTDAY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightDay), }}, - { "LIGHTNIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightNight), }}, - { "LOCALIPADMIN", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fLocalIPAdmin), }}, // The local ip is assumed to be the admin. - { "LOG", { ELEM_VOID, 0 }}, - { "LOGMASK", { ELEM_VOID, 0 }}, // GetLogMask - { "LOOTINGISACRIME", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fLootingIsACrime) }}, - { "LOSTNPCTELEPORT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLostNPCTeleport) }}, - { "MAGICFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iMagicFlags) }}, - { "MAGICUNLOCKDOOR", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iMagicUnlockDoor) }}, - { "MANALOSSABORT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fManaLossAbort) }}, + { "ITEMSMAXAMOUNT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iItemsMaxAmount), }}, + { "LEVELMODE", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLevelMode), }}, + { "LEVELNEXTAT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLevelNextAt), }}, + { "LEVELSYSTEM", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bLevelSystem), }}, + { "LIGHTDAY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightDay), }}, + { "LIGHTNIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightNight), }}, + { "LOCALIPADMIN", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fLocalIPAdmin), }}, // The local ip is assumed to be the admin. + { "LOG", { ELEM_VOID, 0 }}, + { "LOGMASK", { ELEM_VOID, 0 }}, // GetLogMask + { "LOOTINGISACRIME", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fLootingIsACrime) }}, + { "LOSTNPCTELEPORT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLostNPCTeleport) }}, + { "MAGICFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iMagicFlags) }}, + { "MAGICUNLOCKDOOR", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iMagicUnlockDoor) }}, + { "MANALOSSABORT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fManaLossAbort) }}, { "MANALOSSFAIL", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fManaLossFail) }}, - { "MANALOSSPERCENT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_fManaLossPercent) }}, - { "MAPCACHETIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iMapCacheTime) }}, + { "MANALOSSPERCENT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_fManaLossPercent) }}, + { "MAPCACHETIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iMapCacheTime) }}, + { "MAPVIEWRADAR", { ELEM_BYTE, static_castOFFSETOF(CServerConfig,m_iMapViewRadar) }}, + { "MAPVIEWSIZE", { ELEM_BYTE, static_castOFFSETOF(CServerConfig,m_iMapViewSize) }}, + { "MAPVIEWSIZEMAX", { ELEM_BYTE, static_castOFFSETOF(CServerConfig,m_iMapViewSizeMax) }}, { "MAXBASESKILL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iMaxBaseSkill) }}, { "MAXCHARSPERACCOUNT", { ELEM_BYTE, static_castOFFSETOF(CServerConfig,m_iMaxCharsPerAccount) }}, { "MAXCOMPLEXITY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iMaxCharComplexity) }}, @@ -1238,6 +1248,15 @@ bool CServerConfig::r_LoadVal( CScript &s ) case RC_MAPCACHETIME: _iMapCacheTime = s.GetArgLLVal() * MSECS_PER_SEC; break; + case RC_MAPVIEWRADAR: + m_iMapViewRadar = s.GetArgBVal(); + break; + case RC_MAPVIEWSIZE: + m_iMapViewSize = s.GetArgBVal(); + break; + case RC_MAPVIEWSIZEMAX: + m_iMapViewSizeMax = s.GetArgBVal(); + break; case RC_MAXCHARSPERACCOUNT: m_iMaxCharsPerAccount = (uchar)(s.GetArgVal()); if ( m_iMaxCharsPerAccount > MAX_CHARS_PER_ACCT ) @@ -2050,6 +2069,15 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * case RC_MAPCACHETIME: sVal.FormatLLVal( _iMapCacheTime / MSECS_PER_SEC ); break; + case RC_MAPVIEWRADAR: + sVal.FormatBVal(m_iMapViewRadar); + break; + case RC_MAPVIEWSIZE: + sVal.FormatBVal(m_iMapViewSize); + break; + case RC_MAPVIEWSIZEMAX: + sVal.FormatBVal(m_iMapViewSizeMax); + break; case RC_NOTOTIMEOUT: sVal.FormatVal(m_iNotoTimeout); break; diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 0d1673e21..1b2cae326 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -433,6 +433,10 @@ extern class CServerConfig : public CResourceHolder int m_iDistanceTalk; // Max distance at which Talking can be readed. int m_iNPCDistanceHear; // Max distance at which NPCs can hear. + byte m_iMapViewSize; // Visibility for normal items (on old clients it's always 18) + byte m_iMapViewSizeMax; // Max visibility for normal items, default 24. + byte m_iMapViewRadar; // Visibility for castles, keeps and boats, default 31. + CSString m_sSpeechSelf; // [SPEECH ] associated to players. CSString m_sSpeechPet; // [SPEECH ] associated to pets. CSString m_sSpeechOther; // unused? diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 32649c80c..06a0a91ee 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -285,7 +285,7 @@ CChar::CChar( CREID_TYPE baseID ) : _uiRange = RANGE_MAKE(1, 0); // RangeH = 1; RangeL = 0 m_StepStealth = 0; - m_iVisualRange = UO_MAP_VIEW_SIZE_DEFAULT; + m_iVisualRange = g_Cfg.m_iMapViewSize; m_virtualGold = 0; _iTimePeriodicTick = 0; @@ -877,7 +877,7 @@ void CChar::SetVisualRange(byte newSight) { THREAD_UNIQUE_LOCK_SET; // max value is 18 on classic clients prior 7.0.55.27 version and 24 on enhanced clients and latest classic clients - m_iVisualRange = minimum(newSight, UO_MAP_VIEW_SIZE_MAX); + m_iVisualRange = minimum(newSight, g_Cfg.m_iMapViewSizeMax); pClient = GetClientActive(); } if (pClient) diff --git a/src/game/chars/CCharAct.cpp b/src/game/chars/CCharAct.cpp index b76519662..f62afb579 100644 --- a/src/game/chars/CCharAct.cpp +++ b/src/game/chars/CCharAct.cpp @@ -2996,7 +2996,7 @@ bool CChar::SetPoison( int iSkill, int iHits, CChar * pCharSrc ) int iPoisonLevel = 0; int iDist = GetDist(pCharSrc); - if (iDist <= UO_MAP_VIEW_SIZE_MAX) + if (iDist <= g_Cfg.m_iMapViewSizeMax) { if (iSkill >= 1000) //Lethal-Deadly iPoisonLevel = 3 + !bool(Calc_GetRandVal(10)); @@ -3295,7 +3295,7 @@ bool CChar::Death() // Remove the characters which I can't see as dead from the screen if (g_Cfg.m_fDeadCannotSeeLiving) { - CWorldSearch AreaChars(GetTopPoint(), UO_MAP_VIEW_SIZE_MAX); + CWorldSearch AreaChars(GetTopPoint(), g_Cfg.m_iMapViewSizeMax); AreaChars.SetSearchSquare(true); for (;;) { diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index 9e6d8f008..a0944db45 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -101,7 +101,7 @@ bool CChar::CheckCrimeSeen( SKILL_TYPE SkillToSee, CChar * pCharMark, const CObj if (m_pNPC && m_pNPC->m_Brain == NPCBRAIN_GUARD) // guards only fight for justice, they can't commit a crime!!? return false; - CWorldSearch AreaChars( GetTopPoint(), UO_MAP_VIEW_SIZE_DEFAULT ); + CWorldSearch AreaChars( GetTopPoint(), g_Cfg.m_iMapViewSize ); for (;;) { CChar * pChar = AreaChars.GetChar(); @@ -183,7 +183,7 @@ void CChar::CallGuards() // We don't have any target yet, let's check everyone nearby CChar * pCriminal; - CWorldSearch AreaCrime(GetTopPoint(), UO_MAP_VIEW_SIZE_DEFAULT); + CWorldSearch AreaCrime(GetTopPoint(), g_Cfg.m_iMapViewSize); while ((pCriminal = AreaCrime.GetChar()) != nullptr) { if (pCriminal == this) diff --git a/src/game/chars/CCharMemory.cpp b/src/game/chars/CCharMemory.cpp index b52b64ff5..5e643b8f6 100644 --- a/src/game/chars/CCharMemory.cpp +++ b/src/game/chars/CCharMemory.cpp @@ -424,7 +424,7 @@ bool CChar::Memory_Fight_OnTick( CItemMemory * pMemory ) // Attacker.Elapsed = -1 means no combat end for this attacker. // g_Cfg.m_iAttackerTimeout = 0 means attackers doesnt decay. (but cleared when the attacker is killed or the char dies) - if (GetDist(pTarg) > UO_MAP_VIEW_RADAR || ((g_Cfg.m_iAttackerTimeout != 0) && (elapsed >= 0) && (elapsed > g_Cfg.m_iAttackerTimeout)) ) + if (GetDist(pTarg) > g_Cfg.m_iMapViewRadar || ((g_Cfg.m_iAttackerTimeout != 0) && (elapsed >= 0) && (elapsed > g_Cfg.m_iAttackerTimeout)) ) { Memory_Fight_Retreat( pTarg, pMemory ); clearit: diff --git a/src/game/chars/CCharNPCAct.cpp b/src/game/chars/CCharNPCAct.cpp index f01074478..a1010ce11 100644 --- a/src/game/chars/CCharNPCAct.cpp +++ b/src/game/chars/CCharNPCAct.cpp @@ -1069,12 +1069,12 @@ bool CChar::NPC_LookAround( bool fForceCheckItems ) return false; // Call the rand function once, since repeated calls can be expensive (and this function is called a LOT of times, if there are lots of active NPCs) - const int iRand = Calc_GetRandVal(UO_MAP_VIEW_RADAR); + const int iRand = Calc_GetRandVal(g_Cfg.m_iMapViewRadar); const CPointMap& ptTop = GetTopPoint(); int iRange = GetVisualRange(); - if (iRange > UO_MAP_VIEW_RADAR) - iRange = UO_MAP_VIEW_RADAR; + if (iRange > g_Cfg.m_iMapViewRadar) + iRange = g_Cfg.m_iMapViewRadar; int iRangeBlur = UO_MAP_VIEW_SIGHT; // If I can't move don't look too far. @@ -1331,7 +1331,7 @@ bool CChar::NPC_Act_Follow(bool fFlee, int maxDistance, bool fMoveAway) EXC_SET_BLOCK("Distance checks"); const CPointMap& ptMe = GetTopPoint(); int dist = ptMe.GetDist(m_Act_p); - if (dist > UO_MAP_VIEW_RADAR) // too far away ? + if (dist > g_Cfg.m_iMapViewRadar) // too far away ? { return false; } diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 890acc632..02f14577e 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -205,7 +205,7 @@ void CChar::Use_MoonGate( CItem * pItem ) const CPointMap& ptTop = GetTopPoint(); for ( ; i < iCount; ++i ) { - if ( ptTop.GetDist(g_Cfg.m_MoonGates[i]) <= UO_MAP_VIEW_SIZE_DEFAULT ) + if ( ptTop.GetDist(g_Cfg.m_MoonGates[i]) <= g_Cfg.m_iMapViewSize ) break; } diff --git a/src/game/clients/CClientMsg.cpp b/src/game/clients/CClientMsg.cpp index 0dd16f1f0..e0fee85db 100644 --- a/src/game/clients/CClientMsg.cpp +++ b/src/game/clients/CClientMsg.cpp @@ -308,7 +308,7 @@ void CClient::addRemoveAll( bool fItems, bool fChars ) if ( fItems ) { // Remove any multi objects first ! or client will hang - CWorldSearch AreaItems(GetChar()->GetTopPoint(), UO_MAP_VIEW_RADAR); + CWorldSearch AreaItems(GetChar()->GetTopPoint(), g_Cfg.m_iMapViewRadar); AreaItems.SetSearchSquare(true); for (;;) { @@ -1932,7 +1932,7 @@ void CClient::addPlayerSee( const CPointMap & ptOld ) // ptOld: the point from where i moved (i can call this method when i'm moving to a new position), // If ptOld is an invalid point, just send every object i can see. - CWorldSearch AreaItems(ptCharThis, UO_MAP_VIEW_RADAR * 2); // *2 to catch big multis + CWorldSearch AreaItems(ptCharThis, g_Cfg.m_iMapViewRadar * 2); // *2 to catch big multis AreaItems.SetSearchSquare(true); for (;;) { @@ -1959,9 +1959,9 @@ void CClient::addPlayerSee( const CPointMap & ptOld ) /* const CPointMap ptMultiCorner = pMulti->GetRegion()->GetRegionCorner(dirFace); - if ( ptOld.GetDistSight(ptMultiCorner) > UO_MAP_VIEW_RADAR ) + if ( ptOld.GetDistSight(ptMultiCorner) > g_Cfg.m_iMapViewRadar ) { - if (ptCharThis.GetDistSight(ptMultiCorner) <= UO_MAP_VIEW_RADAR ) + if (ptCharThis.GetDistSight(ptMultiCorner) <= g_Cfg.m_iMapViewRadar ) { // this just came into view vecMultis.emplace_back(pItem); diff --git a/src/game/clients/CClientMsg_AOSTooltip.cpp b/src/game/clients/CClientMsg_AOSTooltip.cpp index dd54f77bb..ff7307059 100644 --- a/src/game/clients/CClientMsg_AOSTooltip.cpp +++ b/src/game/clients/CClientMsg_AOSTooltip.cpp @@ -48,7 +48,7 @@ bool CClient::addAOSTooltip(CObjBase * pObj, bool fRequested, bool fShop) // we do not need to send tooltips for items not in LOS (multis/ships) //DEBUG_MSG(("(( m_pChar->GetTopPoint().GetDistSight(pObj->GetTopPoint()) (%x) > UO_MAP_VIEW_SIZE_DEFAULT (%x) ) && ( !bShop ) (%x) )", m_pChar->GetTopPoint().GetDistSight(pObj->GetTopPoint()), UO_MAP_VIEW_SIZE_DEFAULT, ( !bShop ))); int iDist = GetChar()->GetTopPoint().GetDistSight(pObj->GetTopPoint()); - if ( (iDist > GetChar()->GetVisualRange()) && (iDist <= UO_MAP_VIEW_RADAR) && !fShop ) //(iDist <= UO_MAP_VIEW_RADAR) fShop is needed because items equipped or in a container have invalid GetTopPoint (and a very high iDist) + if ( (iDist > GetChar()->GetVisualRange()) && (iDist <= g_Cfg.m_iMapViewRadar) && !fShop ) //(iDist <= UO_MAP_VIEW_RADAR) fShop is needed because items equipped or in a container have invalid GetTopPoint (and a very high iDist) return false; // We check here if we are sending a tooltip for a static/non-movable items diff --git a/src/game/components/CCItemDamageable.cpp b/src/game/components/CCItemDamageable.cpp index 0620ac473..d638f7263 100644 --- a/src/game/components/CCItemDamageable.cpp +++ b/src/game/components/CCItemDamageable.cpp @@ -70,7 +70,7 @@ void CCItemDamageable::OnTickStatsUpdate() _iTimeLastUpdate = iCurtime; CItem *pItem = static_cast(GetLink()); - CWorldSearch AreaChars(pItem->GetTopPoint(), UO_MAP_VIEW_SIZE_DEFAULT); + CWorldSearch AreaChars(pItem->GetTopPoint(), g_Cfg.m_iMapViewSize); AreaChars.SetSearchSquare(true); CChar *pChar = nullptr; for (;;) @@ -212,4 +212,4 @@ CCRET_TYPE CCItemDamageable::OnTickComponent() { ADDTOCALLSTACK("CCItemDamageable::_OnTick"); return CCRET_CONTINUE; // Skip code here, _OnTick is done separately from OnTickStatsUpdate -} \ No newline at end of file +} diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index e23ef4daa..b054bd392 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -716,8 +716,8 @@ bool CItem::IsMovable() const int CItem::GetVisualRange() const // virtual { if ( GetDispID() >= ITEMID_MULTI ) // ( IsTypeMulti() ) why not this? - return UO_MAP_VIEW_RADAR; - return UO_MAP_VIEW_SIZE_DEFAULT; + return g_Cfg.m_iMapViewRadar; + return g_Cfg.m_iMapViewSize; } // Retrieve tag.override.speed for this CItem @@ -5013,17 +5013,18 @@ lpctstr CItem::Use_SpyGlass( CChar * pUser ) const CPointMap ptCoords = pUser->GetTopPoint(); -#define BASE_SIGHT 26 // 32 (UO_MAP_VIEW_RADAR) is the edge of the radar circle (for the most part) + // #define BASE_SIGHT 26 // 32 (UO_MAP_VIEW_RADAR) is the edge of the radar circle (for the most part) + byte bSight = (g_Cfg.m_iMapViewRadar > 5 ? g_Cfg.m_iMapViewRadar - 5 : 26); //m_iMapViewRadar is 31 in default. WEATHER_TYPE wtWeather = ptCoords.GetSector()->GetWeather(); byte iLight = ptCoords.GetSector()->GetLight(); CSString sSearch; tchar *pResult = Str_GetTemp(); // Weather bonus - double rWeatherSight = wtWeather == WEATHER_RAIN ? (0.25 * BASE_SIGHT) : 0.0; + double rWeatherSight = wtWeather == WEATHER_RAIN ? (0.25 * bSight) : 0.0; // Light level bonus - double rLightSight = (1.0 - (static_cast(iLight) / 25.0)) * BASE_SIGHT * 0.25; - int iVisibility = (int) (BASE_SIGHT + rWeatherSight + rLightSight); + double rLightSight = (1.0 - (static_cast(iLight) / 25.0)) * bSight * 0.25; + int iVisibility = (int) (bSight + rWeatherSight + rLightSight); // Check for the nearest land, only check every 4th square for speed const CUOMapMeter * pMeter = CWorldMap::GetMapMeter( ptCoords ); // Are we at sea? @@ -5113,7 +5114,7 @@ lpctstr CItem::Use_SpyGlass( CChar * pUser ) const } // Track boats separately from other items - if ( iDist <= UO_MAP_VIEW_RADAR && // if it's visible in the radar window as a boat, report it + if ( iDist <= g_Cfg.m_iMapViewRadar && // if it's visible in the radar window as a boat, report it pItem->m_type == IT_SHIP ) { ++iBoatSighted; // Keep a tally of how many we see @@ -5147,14 +5148,14 @@ lpctstr CItem::Use_SpyGlass( CChar * pUser ) const DIR_TYPE dir = ptCoords.GetDir(pItemSighted->GetTopPoint()); if (iItemSighted == 1) { - if ( iDist > UO_MAP_VIEW_RADAR) // if beyond ship visibility in the radar window, don't be specific + if ( iDist > g_Cfg.m_iMapViewRadar) // if beyond ship visibility in the radar window, don't be specific sSearch.Format(g_Cfg.GetDefaultMsg(DEFMSG_SHIP_SEEN_STH_DIR), static_cast(CPointBase::sm_szDirs[ dir ]) ); else sSearch.Format(g_Cfg.GetDefaultMsg(DEFMSG_SHIP_SEEN_ITEM_DIR), static_cast(pItemSighted->GetNameFull(false)), static_cast(CPointBase::sm_szDirs[ dir ]) ); } else { - if ( iDist > UO_MAP_VIEW_RADAR) // if beyond ship visibility in the radar window, don't be specific + if ( iDist > g_Cfg.m_iMapViewRadar) // if beyond ship visibility in the radar window, don't be specific sSearch.Format(g_Cfg.GetDefaultMsg(DEFMSG_SHIP_SEEN_ITEM_DIR_MANY), CPointBase::sm_szDirs[ dir ] ); else sSearch.Format(g_Cfg.GetDefaultMsg(DEFMSG_SHIP_SEEN_SPECIAL_DIR), static_cast(pItemSighted->GetNameFull(false)), static_cast(CPointBase::sm_szDirs[ dir ])); diff --git a/src/network/send.cpp b/src/network/send.cpp index 40af17891..1a041f3ac 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -4051,7 +4051,7 @@ bool PacketPropertyListVersionOld::onSend(const CClient* client) const CObjBase* object = m_object.ObjFind(); int iCharVisualRange = character->GetVisualRange(); - if (object == nullptr || character->GetTopDistSight(object->GetTopLevelObj()) > maximum(iCharVisualRange, UO_MAP_VIEW_SIZE_DEFAULT)) + if (object == nullptr || character->GetTopDistSight(object->GetTopLevelObj()) > maximum(iCharVisualRange, g_Cfg.m_iMapViewSize)) return false; return true; @@ -4690,7 +4690,7 @@ bool PacketPropertyList::onSend(const CClient* client) const CObjBase* object = m_object.ObjFind(); int iCharVisualRange = character->GetVisualRange(); - if (!object || character->GetTopDistSight(object->GetTopLevelObj()) > maximum(iCharVisualRange, UO_MAP_VIEW_SIZE_DEFAULT) && !character->IsPriv(PRIV_ALLSHOW)) + if (!object || character->GetTopDistSight(object->GetTopLevelObj()) > maximum(iCharVisualRange, g_Cfg.m_iMapViewSize) && !character->IsPriv(PRIV_ALLSHOW)) return false; if (hasExpired(30 * MSECS_PER_SEC)) @@ -4909,7 +4909,7 @@ bool PacketPropertyListVersion::onSend(const CClient* client) const CObjBase* object = m_object.ObjFind(); int iCharVisualRange = character->GetVisualRange(); - if (object == nullptr || character->GetTopDistSight(object->GetTopLevelObj()) > maximum(iCharVisualRange, UO_MAP_VIEW_SIZE_DEFAULT)) + if (object == nullptr || character->GetTopDistSight(object->GetTopLevelObj()) > maximum(iCharVisualRange, g_Cfg.m_iMapViewSize)) return false; return true; diff --git a/src/sphere.ini b/src/sphere.ini index b41e9633c..475d24c7c 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -106,6 +106,15 @@ Map5=1280,4096,-1,5,5 // To enable the use of MapDif*.mul and StaDif*.mul files, set this to 1. Note: these files were removed on clients 6+. UseMapDiffs=0 +// Visibility for castles, keeps and boats, default 31. +MapViewRadar=31 + +// Visibility range for normal items (on old clients it's always 18) +MapViewSize=18 + +// Max visibility for normal items, default 24. +MapViewSizeMax=24 + /////////////////////////////////////////////////////////////// //////// World Save Information /////////////////////////////////////////////////////////////// From 3d86b3655f84ab7354e5b989523da6aa18dac751 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 17 Apr 2024 03:17:34 +0100 Subject: [PATCH 57/90] H keyword for Hexadecimal returns Added: 'H' shortcut for variables to get the value as hexadecimal. --- Changelog.txt | 6 +++++- src/common/CScriptObj.cpp | 12 +++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 1d247896c..5876c49b4 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3633,4 +3633,8 @@ Added: MAPVIEWRADAR, MAPVIEWSIZE and MAPVIEWSIZEMAX to sphere.ini that overrides Defaults: MapViewRadar=31 MapViewSize=18 - MapViewSizeMax=24 \ No newline at end of file + MapViewSizeMax=24 +Added: 'H' shortcut for variables to get the value as hexadecimal. + For example, if you use .tag.test 100 + returns 100 + returns 064 \ No newline at end of file diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index 02978f202..5bc148a3d 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -538,7 +538,17 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc return true; } - } + } + else if ((*ptcKey == 'h') || (*ptcKey == 'H')) // same as > to get hex from the val + { + lpctstr sArgs = ptcKey + 1; + if (r_WriteVal(sArgs, sVal, pSrc)) + { + if (*sVal != '-') + sVal.FormatLLHex(ahextoi64(sVal)); + return true; + } + } // , , are shortcuts to rand(), rand(15) and rand(3,15) else if (( *ptcKey == 'r' ) || ( *ptcKey == 'R' )) { From 4ad60abfd79dddd81a18d9768e682b40892394b5 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 17 Apr 2024 04:32:13 +0100 Subject: [PATCH 58/90] raydienull's LAYER_STABLE PR merge - Merged: raydienull's LAYER_STABLE build merged, but LAYER_AUCTION keep same as LAYER_STABLE added as a new layer. (PR: #1201) - Fixed: raydienull's LAYER_STABLE follower triggers doesn't called while taking pet out of stable. - Fixed: raydienull's LAYER_STABLE doesn't work with the new follower system. - Removed: Unnecessary LINK == PLAYER checks as figurines will be stocked on the owned player. --- Changelog.txt | 107 ++++++++++++++------------ src/game/chars/CCharNPCAct_Vendor.cpp | 40 ++++------ src/game/chars/CCharStatus.cpp | 6 ++ src/game/clients/CClientTarg.cpp | 6 +- src/game/uo_files/uofiles_enums.h | 1 + src/tables/defmessages.tbl | 1 - 6 files changed, 84 insertions(+), 77 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 5876c49b4..a020e7d8d 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3442,6 +3442,9 @@ Additionally, the problem of zig-zag issue following in the South direction has 13-12-2023, Nolok - Fixed: Rare crash occurring when a NPC is selecting an attackable target, but there's only one target (not attackable) in sight. +15-12-2023, raydienull +- Changed: LAYER_AUCTION to LAYER_STABLE and now is used to store the stabled pets on the player. + 12-02-2024, Drk84 - Updated SphereCrypt.ini. @@ -3454,31 +3457,31 @@ Additionally, the problem of zig-zag issue following in the South direction has - Added: Item been eaten can now be read on the ARGO parameter of the trigger @Eat. 24-03-2024, xwerswoodx -Fixed: The issue that causes more1/2 not saved correctly for spellbook. (Issue: #1221) -Fixed: Players automatically become criminal to everyone when attack someone. (Issue: #1213) -Fixed: CallGuard not working correctly on the players that only criminal for target. (Issue: #1213, #1040) -Fixed: The wrong input of Kill trigger, to make it compatible with older sphere versions. (Issue: #1210) -Added: New Layer LAYER_STORAGE (80) to let scripters create their own storage system. (Issue: #1209) +- Fixed: The issue that causes more1/2 not saved correctly for spellbook. (Issue: #1221) +- Fixed: Players automatically become criminal to everyone when attack someone. (Issue: #1213) +- Fixed: CallGuard not working correctly on the players that only criminal for target. (Issue: #1213, #1040) +- Fixed: The wrong input of Kill trigger, to make it compatible with older sphere versions. (Issue: #1210) +- Added: New Layer LAYER_STORAGE (80) to let scripters create their own storage system. (Issue: #1209) Only t_container and t_container_locked can be equipped to this layer. -Changed: Decay time removed from spawned items, as Sphere gives tons of invalid link errors when items decayed. (Issue: #1218) -Added: New spellflag SPELLFLAG_ASYNC (0100000000) to randomize field timers like old sphere versions. (Issue: #1169) +- Changed: Decay time removed from spawned items, as Sphere gives tons of invalid link errors when items decayed. (Issue: #1218) +- Added: New spellflag SPELLFLAG_ASYNC (0100000000) to randomize field timers like old sphere versions. (Issue: #1169) SPELLFLAG_ASYNC should be added to defs. -Added: New spellflag SPELLFLAG_TARG_ONLYSELF (0200000000) to make spell only be used on character himself. (Issue: #1171) +- Added: New spellflag SPELLFLAG_TARG_ONLYSELF (0200000000) to make spell only be used on character himself. (Issue: #1171) SPELLFLAG_TARG_ONLYSELF should be added to defs. //magery_9 "You can only use this spell on yourself." could be added to defmessages. -Changed: SERV.LOG command changed to support console colors. (Issue: [Feature Request] Colored Serv & Src Log System #1158) +- Changed: SERV.LOG command changed to support console colors. (Issue: [Feature Request] Colored Serv & Src Log System #1158) SERV.LOG works same as before. Usage of custom color system is: SERV.LOG @color,type,mask message Example: SERV.LOG @CTCOL_RED,LOGL_EVENT,LOGM_NOCONTEXT|LOGM_KILLS message LOGM, LOGL and CTCOL values should be added to defs. 25-03-2024, xwerswoodx -Added: Sphere.ini setting CanPetsDrinkPotion (true in default) to make pets drink potion when their owner drop it on it. (Issue: #1147) +- Added: Sphere.ini setting CanPetsDrinkPotion (true in default) to make pets drink potion when their owner drop it on it. (Issue: #1147) CanPetsDrinkPotion = 0 can be added to sphere.ini to disable that. -Fixed: Missing fCheckOnly checks block the taming skill. (Issue: #1219) +- Fixed: Missing fCheckOnly checks block the taming skill. (Issue: #1219) 26-03-2024, xwerswoodx -Added: New trigger @Drink added for characters. (Issue: #1162) +- Added: New trigger @Drink added for characters. (Issue: #1162) I: The character drinking the item. SRC: The character drinking the item. ARGO = the item that drank @@ -3491,60 +3494,60 @@ Added: New trigger @Drink added for characters. (Issue: #1162) 6: Let character to drink but will not give any empty bottle. - Messages: DRINK_NOT_ENOUGH, "You don't have enough %s to drink this." -Added: New trigger @AfkMode added for characters. (Issue: #1161) +- Added: New trigger @AfkMode added for characters. (Issue: #1161) I: The character changing AFK status. SRC: The character changing AFK status. ARGN1 = Current Afk Status ARGN2 = Next Afk Status - Returns: 1: Stops character from switching afk status. -Added: New trigger @Reveal added for characters. (Issue: #1157) +- Added: New trigger @Reveal added for characters. (Issue: #1157) I: The character who is revealing. SRC: The character who is revealing. - Returns: 1: Prevents character from being revealed. -Added: New triggers @ArrowQuest_Add and @ArrowQuest_Close added for characters. (Issue: #1116) +- Added: New triggers @ArrowQuest_Add and @ArrowQuest_Close added for characters. (Issue: #1116) I: The character who activating/deactivating arrow quest. SRC: The character who activating/deactivating arrow quest. -Added: New function triggers f_onaccount_block and f_onaccount_unblock. (Issue: #1156) +- Added: New function triggers f_onaccount_block and f_onaccount_unblock. (Issue: #1156) ARGS = Account name. - Returns: 1: Prevents account from blocking/unblocking. -Added: New function trigger f_onserver_broadcast. (Issue: #1145) +- Added: New function trigger f_onserver_broadcast. (Issue: #1145) ARGS = message - Returns: 1: Prevents server to send broadcast message. -Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReductionAmount to @Hit trigger. (Issue: #1159) +- Added: Two new LOCAL variables ItemPoisonReductionChance and ItemPoisonReductionAmount to @Hit trigger. (Issue: #1159) This LOCALs changes default behaviour of poisoned weapons while removing poison. LOCAL.ItemPoisonReductionChance = Is the chance that weapon reduce poison morez. (Default 100%) LOCAL.ItemPoisonReductionAmount = Is the amount of poison that weapon reduce. (Default: CurrentPoisonAmount/ 2) -Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) -Changed: Reactive armor range increased from 1 to 2 in default. +- Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) +- Changed: Reactive armor range increased from 1 to 2 in default. 27-03-2024, xwerswoodx -Fixed: Possible fix for accesses and bans not loading for multis. (Issue: #1223) -Fixed: Possible fix for wrong damage calculation of slayer bonus damage. (Issue: #1179) +- Fixed: Possible fix for accesses and bans not loading for multis. (Issue: #1223) +- Fixed: Possible fix for wrong damage calculation of slayer bonus damage. (Issue: #1179) 28-03-2024, xwerswoodx -Added: REGION_FLAG_HOUSE (0x0100) for houses. (Issue: #1154) +- Added: REGION_FLAG_HOUSE (0x0100) for houses. (Issue: #1154) REGION_FLAG_HOUSE 0100 should be added defs. 30-03-2024, xwerswoodx -Added: ARGO object for @MurderMark trigger to get killed character. -Fixed: ARGN1 (reap amount) doesn't updated depends on the amount left on bit. (Issue: #1224) -Added: ARGO to get bit uid under @ResourceGather and @RegionResourceGather triggers. +- Added: ARGO object for @MurderMark trigger to get killed character. +- Fixed: ARGN1 (reap amount) doesn't updated depends on the amount left on bit. (Issue: #1224) +- Added: ARGO to get bit uid under @ResourceGather and @RegionResourceGather triggers. 31-03-2024, xwerswoodx -Fixed: Possible fix for the OnRegionTrigger getting called on invalid region while multi creating/removing. +- Fixed: Possible fix for the OnRegionTrigger getting called on invalid region while multi creating/removing. 02-04-2024, xwerswoodx -Changed: dword CAN flags changed with uint64 to increase limits. -Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/channels/354358315373035542/483721253773901824/1224030729906815077) +- Changed: dword CAN flags changed with uint64 to increase limits. +- Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/channels/354358315373035542/483721253773901824/1224030729906815077) 03-04-2024, xwerswoodx -Added: "MOREX" key to set amount of fruit given when the crop ripped. -Changed: Now @Create trigger called when crop grow to let people to change MORE values in stages if needed. -Added: @ResourceTest trigger added for crops. (This trigger works separately for every stage) +- Added: "MOREX" key to set amount of fruit given when the crop ripped. +- Changed: Now @Create trigger called when crop grow to let people to change MORE values in stages if needed. +- Added: @ResourceTest trigger added for crops. (This trigger works separately for every stage) I: Crop UID SRC: Player who uses plant. ARGN1: Next state item ID [Writeable] @@ -3552,7 +3555,7 @@ Added: @ResourceTest trigger added for crops. (This trigger works separately for ARGN3: Fruit ID Override (if exists) [Writeable] - Returns: 1: Stop the fruit checks. -Added: @ResourceGather trigger added for crops. (This trigger works separately for every stage) +- Added: @ResourceGather trigger added for crops. (This trigger works separately for every stage) I: Crop UID SRC: Player who is gathering plant. ARGN1: Amount of fruit. [Writeable] @@ -3560,11 +3563,11 @@ Added: @ResourceGather trigger added for crops. (This trigger works separately f - Returns: 1: Prevent player to gather fruit. 6: Let player to gather fruit but it will drop to the ground instead of backpack. -Fixed: Possible fix for invalid ResourceID warnings. (Issue: #1071) +- Fixed: Possible fix for invalid ResourceID warnings. (Issue: #1071) 08-04-2024, xwerswoodx -Fixed: Missing REGION reference for multis. (Issue: #1228) -Added: ElementalEngineFlags variable added to sphere.ini to let servers to filter elemental engine. (Issue: #1230) +- Fixed: Missing REGION reference for multis. (Issue: #1228) +- Added: ElementalEngineFlags variable added to sphere.ini to let servers to filter elemental engine. (Issue: #1230) EE_CURSE = 0x1, // Adds Elemental buff/defuff to curse spell. EE_MASS_CURSE = 0x2, // Adds Elemental buff/defuff to mass curse spell. EE_REACTIVE_ARMOR = 0x4, // Adds Elemental buff/defuff to reactive armor spell. @@ -3576,23 +3579,23 @@ Added: ElementalEngineFlags variable added to sphere.ini to let servers to filte EE_RESPHYSICAL = 0x100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. 09-04-2024, xwerswoodx -Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) -Fixed: Bonded pets cannot see their master while DeadCannotSeeLiving equals to 2. (Issue: #1225) -Fixed: The issue that causes Guilds without an align shown enemy to the players with a guild with an align. (Issue: #1208) -Fixed: Another fix for Invalid ResourceID console warnings. (Issue: #1071) -Fixed: GMs cannot dress up players. (Issue: #901) +- Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) +- Fixed: Bonded pets cannot see their master while DeadCannotSeeLiving equals to 2. (Issue: #1225) +- Fixed: The issue that causes Guilds without an align shown enemy to the players with a guild with an align. (Issue: #1208) +- Fixed: Another fix for Invalid ResourceID console warnings. (Issue: #1071) +- Fixed: GMs cannot dress up players. (Issue: #901) 10-04-2024, xwerswoodx -Fixed: Wrong check block GMs to unequip item from players. +- Fixed: Wrong check block GMs to unequip item from players. 14-04-2024, xwerswoodx -Fixed: An issue that causes a visual bug to remove all tiles while removing a tile in higher floors. (Issue: #345) +- Fixed: An issue that causes a visual bug to remove all tiles while removing a tile in higher floors. (Issue: #345) 16-04-2024, xwerswoodx -Changed: EMOTEF_EAT name changed to EMOTEF_HIDE_EAT_PLAYER and limited to only player emotes. +- Changed: EMOTEF_EAT name changed to EMOTEF_HIDE_EAT_PLAYER and limited to only player emotes. EMOTEF_EAT is from the merge of Jhobean's pr so it wasn't in sphere at all. -Added: EMOTEF_HIDE_EAT_NPC to hide emotes while eating only for npcs. -Added: Trigger @Hit is added as an item trigger. +- Added: EMOTEF_HIDE_EAT_NPC to hide emotes while eating only for npcs. +- Added: Trigger @Hit is added as an item trigger. This trigger nows trigger before @Damage but after character @Hit trigger. Args are same as the character @Hit trigger, but I and ARGO switch the values. Args: @@ -3608,7 +3611,7 @@ Added: Trigger @Hit is added as an item trigger. - LOCAL.ITEMPOISONREDUCTIONAMOUNT: Sets the amount of poison that reduced from morez value. Returns: 1: Cancels the combat swing of the character. -Added: Trigger @GetHit is added as an item trigger. +- Added: Trigger @GetHit is added as an item trigger. This trigger nows trigger before @Damage but after character @GetHit trigger. Args are same as the character @GetHit trigger, but I changed to the item, and the character saves on ARGO. Also LOCAL.ITEMDAMAGELAYER only works under character @GetHit trigger, it is only readable under item trigger. @@ -3629,12 +3632,16 @@ Added: Trigger @GetHit is added as an item trigger. - LOCAL.ITEMDAMAGELAYER: The layer of the item being damaged. [Read Only] Returns: 1: Prevents damage from being applied to the character. -Added: MAPVIEWRADAR, MAPVIEWSIZE and MAPVIEWSIZEMAX to sphere.ini that overrides default visual range values. (Issue: #1144) +- Added: MAPVIEWRADAR, MAPVIEWSIZE and MAPVIEWSIZEMAX to sphere.ini that overrides default visual range values. (Issue: #1144) Defaults: MapViewRadar=31 MapViewSize=18 MapViewSizeMax=24 -Added: 'H' shortcut for variables to get the value as hexadecimal. +- Added: 'H' shortcut for variables to get the value as hexadecimal. For example, if you use .tag.test 100 returns 100 - returns 064 \ No newline at end of file + returns 064 +- Merged: raydienull's LAYER_STABLE build merged, but LAYER_AUCTION keep same as LAYER_STABLE added as a new layer. +- Fixed: raydienull's LAYER_STABLE follower triggers doesn't called while taking pet out of stable. +- Fixed: raydienull's LAYER_STABLE doesn't work with the new follower system. +- Removed: Unnecessary LINK == PLAYER checks as figurines will be stocked on the owned player. \ No newline at end of file diff --git a/src/game/chars/CCharNPCAct_Vendor.cpp b/src/game/chars/CCharNPCAct_Vendor.cpp index caa79a5cc..6775991f7 100644 --- a/src/game/chars/CCharNPCAct_Vendor.cpp +++ b/src/game/chars/CCharNPCAct_Vendor.cpp @@ -105,12 +105,12 @@ bool CChar::NPC_StablePetSelect( CChar * pCharPlayer ) if ( ! pCharPlayer->IsClientActive()) return false; - // Might have too many pets already ? - int iCount = 0; - CItemContainer * pBank = GetBank(); - if ( pBank->GetContentCount() >= g_Cfg.m_iContainerMaxItems ) + CItemContainer *pStableContainer = pCharPlayer->GetBank(LAYER_STABLE); + ASSERT(pStableContainer); //Should never terminate + + if (pStableContainer->GetContentCount() >= g_Cfg.m_iContainerMaxItems) { - Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_STABLEMASTER_FULL ) ); + Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_STABLEMASTER_TOOMANY)); return false; } @@ -161,18 +161,6 @@ bool CChar::NPC_StablePetSelect( CChar * pCharPlayer ) } } - for (CSObjContRec* pObjRec : *pBank) - { - CItem* pItem = static_cast(pObjRec); - if ( pItem->IsType(IT_FIGURINE) && pItem->m_uidLink == pCharPlayer->GetUID() ) - ++iCount; - } - if ( iCount >= iPetMax ) - { - Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_STABLEMASTER_TOOMANY ) ); - return false; - } - pCharPlayer->m_pClient->m_Targ_Prv_UID = GetUID(); pCharPlayer->m_pClient->addTarget( CLIMODE_TARG_PET_STABLE, g_Cfg.GetDefaultMsg( DEFMSG_NPC_STABLEMASTER_TARG ) ); return true; @@ -188,16 +176,17 @@ bool CChar::NPC_StablePetRetrieve( CChar * pCharPlayer ) if ( m_pNPC->m_Brain != NPCBRAIN_STABLE ) return false; - CItemContainer* pBank = GetBank(); - ASSERT(pBank); + CItemContainer* pStableContainer = pCharPlayer->GetBank(LAYER_STABLE); + ASSERT(pStableContainer); int iCount = 0; - for (CSObjContRec* pObjRec : pBank->GetIterationSafeCont()) + for (CSObjContRec* pObjRec : pStableContainer->GetIterationSafeCont()) { CItem* pItem = static_cast(pObjRec); - if ( pItem->IsType(IT_FIGURINE) && (pItem->m_uidLink == pCharPlayer->GetUID()) ) + if (pItem->IsType(IT_FIGURINE)) { - if ( !pCharPlayer->Use_Figurine(pItem) ) + CChar* pPet = pCharPlayer->Use_Figurine(pItem); + if (!pPet) { tchar *pszTemp = Str_GetTemp(); snprintf(pszTemp, Str_TempLength(), g_Cfg.GetDefaultMsg(DEFMSG_NPC_STABLEMASTER_CLAIM_FOLLOWER), pItem->GetName()); @@ -205,7 +194,12 @@ bool CChar::NPC_StablePetRetrieve( CChar * pCharPlayer ) return true; } - pItem->Delete(); + pItem->Delete(); + if (IsSetOF(OF_PetSlots)) + { + const short iFollowerSlots = (short)pPet->GetDefNum("FOLLOWERSLOTS", true, 1); + pCharPlayer->FollowersUpdate(pPet, (maximum(0, iFollowerSlots)), false); + } ++iCount; } } diff --git a/src/game/chars/CCharStatus.cpp b/src/game/chars/CCharStatus.cpp index a43c99e97..6102877a4 100644 --- a/src/game/chars/CCharStatus.cpp +++ b/src/game/chars/CCharStatus.cpp @@ -129,6 +129,10 @@ CItemContainer *CChar::GetBank( LAYER_TYPE layer ) id = ITEMID_BACKPACK; break; + case LAYER_STABLE: + id = ITEMID_POUCH; + break; + case LAYER_VENDOR_STOCK: case LAYER_VENDOR_EXTRA: case LAYER_VENDOR_BUYS: @@ -344,6 +348,7 @@ LAYER_TYPE CChar::CanEquipLayer( CItem *pItem, LAYER_TYPE layer, CChar *pCharMsg { case LAYER_PACK: case LAYER_AUCTION: + case LAYER_STABLE: if ( !pItem->IsType(IT_CONTAINER) ) fCantEquip = true; break; @@ -442,6 +447,7 @@ LAYER_TYPE CChar::CanEquipLayer( CItem *pItem, LAYER_TYPE layer, CChar *pCharMsg { case LAYER_AUCTION: case LAYER_PACK: + case LAYER_STABLE: return LAYER_NONE; // this should not happen case LAYER_HORSE: case LAYER_DRAGGING: diff --git a/src/game/clients/CClientTarg.cpp b/src/game/clients/CClientTarg.cpp index 6136896a7..94656352f 100644 --- a/src/game/clients/CClientTarg.cpp +++ b/src/game/clients/CClientTarg.cpp @@ -1610,12 +1610,12 @@ bool CClient::OnTarg_Pet_Stable( CChar * pCharPet ) if ( IsSetOF(OF_PetSlots) ) { - short iFollowerSlots = (short)pCharPet->GetDefNum("FOLLOWERSLOTS", true); + short iFollowerSlots = (short)pCharPet->GetDefNum("FOLLOWERSLOTS", true, 1); m_pChar->FollowersUpdate(pCharPet,(-maximum(0, iFollowerSlots))); } - pCharMaster->GetBank()->ContentAdd( pPetItem ); - pCharMaster->Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_STABLEMASTER_CLAIM ) ); + m_pChar->GetBank(LAYER_STABLE)->ContentAdd(pPetItem); + pCharMaster->Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_STABLEMASTER_CLAIM)); return true; } diff --git a/src/game/uo_files/uofiles_enums.h b/src/game/uo_files/uofiles_enums.h index 39e56c30f..de3493853 100644 --- a/src/game/uo_files/uofiles_enums.h +++ b/src/game/uo_files/uofiles_enums.h @@ -556,6 +556,7 @@ enum LAYER_TYPE // defined by UO. Only one item can be in a slot. LAYER_SPELL_Mana_Drain, LAYER_STORAGE, //80 New Storage layer, can equip t_container and t_container_locked. + LAYER_STABLE, //81 New stable layer, now stabled pets will be stored in this layer of the player instead of npc's itself. LAYER_QTY }; diff --git a/src/tables/defmessages.tbl b/src/tables/defmessages.tbl index 6467574fe..d638763d4 100644 --- a/src/tables/defmessages.tbl +++ b/src/tables/defmessages.tbl @@ -677,7 +677,6 @@ MSG(NPC_PET_TARG_TRANSFER_SUMMONED, "You cannot transfer ownership of a summone MSG(NPC_PET_WAGE_COST, "I will work for %d gold") MSG(NPC_PET_WEAK, "I'm too weak to carry that. ") MSG(NPC_STABLEMASTER_FEED, "feed the %s") -MSG(NPC_STABLEMASTER_FULL, "I'm sorry the stables are full") MSG(NPC_STABLEMASTER_TOOMANY, "You have too many pets in the stables!") MSG(NPC_STABLEMASTER_TARG, "Which animal wouldst thou like to stable here?") MSG(NPC_STABLEMASTER_TARG_SUCCESS, "Your pet has been stabled.") From 753ff28fc6dbe651c2605f9dd105ff6e323e5153 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 17 Apr 2024 04:36:22 +0100 Subject: [PATCH 59/90] Update Changelog.txt --- Changelog.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index a020e7d8d..aac0291d9 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3641,7 +3641,7 @@ Additionally, the problem of zig-zag issue following in the South direction has For example, if you use .tag.test 100 returns 100 returns 064 -- Merged: raydienull's LAYER_STABLE build merged, but LAYER_AUCTION keep same as LAYER_STABLE added as a new layer. -- Fixed: raydienull's LAYER_STABLE follower triggers doesn't called while taking pet out of stable. +- Merged: raydienull's LAYER_STABLE build merged, but LAYER_AUCTION keep same while LAYER_STABLE added as a new layer. (PR: #1201) +- Fixed: raydienull's LAYER_STABLE follower triggers isn't called while taking pet out of stable. - Fixed: raydienull's LAYER_STABLE doesn't work with the new follower system. - Removed: Unnecessary LINK == PLAYER checks as figurines will be stocked on the owned player. \ No newline at end of file From b1ba663880bd05ac794ab6c166588769a53bfb97 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Thu, 18 Apr 2024 16:19:51 +0100 Subject: [PATCH 60/90] c_man_gm - Fixed: Setting GMs dispid to c_man_gm in-game, prevents GMs to use in-game commands. --- Changelog.txt | 5 ++++- src/game/clients/CClientEvent.cpp | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index aac0291d9..4f79c0e03 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3644,4 +3644,7 @@ Additionally, the problem of zig-zag issue following in the South direction has - Merged: raydienull's LAYER_STABLE build merged, but LAYER_AUCTION keep same while LAYER_STABLE added as a new layer. (PR: #1201) - Fixed: raydienull's LAYER_STABLE follower triggers isn't called while taking pet out of stable. - Fixed: raydienull's LAYER_STABLE doesn't work with the new follower system. -- Removed: Unnecessary LINK == PLAYER checks as figurines will be stocked on the owned player. \ No newline at end of file +- Removed: Unnecessary LINK == PLAYER checks as figurines will be stocked on the owned player. + +18-04-2024, xwerswoodx +- Fixed: Setting GMs dispid to c_man_gm in-game, prevents GMs to use in-game commands. \ No newline at end of file diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index f410b4e79..c5ee3c1b9 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -1035,13 +1035,13 @@ void CClient::Event_CombatMode( bool fWar ) // Only for switching to combat mode bool CClient::Event_Command(lpctstr pszCommand, TALKMODE_TYPE mode) { ADDTOCALLSTACK("CClient::Event_Command"); - if ( mode == 13 || mode == 14 ) // guild and alliance don't pass this. + if ( mode == TALKMODE_GUILD || mode == TALKMODE_ALLIANCE ) // guild and alliance don't pass this. return false; if ( pszCommand[0] == 0 ) return true; // should not be said if ( Str_Check(pszCommand) ) return true; // should not be said - if ( ( ( m_pChar->GetID() == 0x3db ) && ( pszCommand[0] == '=' ) ) || ( pszCommand[0] == g_Cfg.m_cCommandPrefix ) ) + if (((m_pChar->GetDispID() == CREID_EQUIP_GM_ROBE) && (pszCommand[0] == '=')) || (pszCommand[0] == g_Cfg.m_cCommandPrefix)) //Should be dispid, or it's bugged when you change character's dispid to c_man_gm. { // Lazy :P } From 82e59ee037983f3e10a3da879c40618966f016c9 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Thu, 18 Apr 2024 19:29:17 +0100 Subject: [PATCH 61/90] NPC Hear Distance - Changed: Default NPC hear range reverted back to the 14 from 4, as it was 14 in older versions, as there was no reason for changing it. (Issue: #1215) --- Changelog.txt | 3 ++- src/game/CServerConfig.cpp | 8 +++++++- src/game/clients/CClientEvent.cpp | 2 +- src/sphere.ini | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 4f79c0e03..8cb51263e 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3647,4 +3647,5 @@ Additionally, the problem of zig-zag issue following in the South direction has - Removed: Unnecessary LINK == PLAYER checks as figurines will be stocked on the owned player. 18-04-2024, xwerswoodx -- Fixed: Setting GMs dispid to c_man_gm in-game, prevents GMs to use in-game commands. \ No newline at end of file +- Fixed: Setting GMs dispid to c_man_gm in-game, prevents GMs to use in-game commands. +- Changed: Default NPC hear range reverted back to the 14 from 4, as it was 14 in older versions, as there was no reason for changing it. (Issue: #1215) diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 77b8922f0..684e6dc7b 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -194,7 +194,7 @@ CServerConfig::CServerConfig() m_iDistanceWhisper = 3; m_iDistanceTalk = UO_MAP_VIEW_SIZE_DEFAULT; m_iDragWeightMax = 300; - m_iNPCDistanceHear = 4; + m_iNPCDistanceHear = UO_MAP_VIEW_SIGHT; // Why it was 4? Default range must match with the default value under CClient::Event_Talk_Common. _uiExperimentalFlags= 0; _uiOptionFlags = (OF_Command_Sysmsgs|OF_NoHouseMuteSpeech); _uiAreaFlags = AREAF_RoomInheritsFlags; @@ -1298,6 +1298,9 @@ bool CServerConfig::r_LoadVal( CScript &s ) case RC_NOTOTIMEOUT: m_iNotoTimeout = s.GetArgVal(); break; + case RC_NPCDISTANCEHEAR: + m_iNPCDistanceHear = s.GetArgVal(); + break; case RC_WOOLGROWTHTIME: m_iWoolGrowthTime = s.GetArgLLVal() * 60 * MSECS_PER_SEC; break; @@ -2081,6 +2084,9 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * case RC_NOTOTIMEOUT: sVal.FormatVal(m_iNotoTimeout); break; + case RC_NPCDISTANCEHEAR: + sVal.FormatVal(m_iNPCDistanceHear); + break; case RC_MAXHOUSESACCOUNT: sVal.FormatUCVal(_iMaxHousesAccount); break; diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index c5ee3c1b9..d14f14269 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -1885,7 +1885,7 @@ void CClient::Event_Talk_Common(lpctstr pszText) // PC speech //Reduce NPC hear distance for non pets int iAltDist = iFullDist; - CWorldSearch AreaChars(m_pChar->GetTopPoint(), UO_MAP_VIEW_SIGHT); + CWorldSearch AreaChars(m_pChar->GetTopPoint(), iFullDist); // Search for the iFullDist, as it can be overriden in sphere.ini for (;;) { diff --git a/src/sphere.ini b/src/sphere.ini index 475d24c7c..741d28a7e 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -282,7 +282,7 @@ EraLimitProps = 9 // Maximum distance for NPCs to hear // Setting value to negative will set a distance of abs(value) with no LOS check -//NPCDistanceHear=4 +//NPCDistanceHear=14 // Do not allow entering under roof being on horse? MountHeight=0 From 75e5be9ccb8386f7d11fabbd082ae731c4856c02 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sat, 20 Apr 2024 18:03:45 +0100 Subject: [PATCH 62/90] CCChampion Rework - Rework: Champion system fully reworked. - Fixed: Candles keep stuck while killing npcs. (Issue: #564) - Fixed: LEVELMAX doesn't affect the max level of champion system, and keep spawn npcs for default max level. - Changed: Spawn system changed and now it automatically calculate the percentage of spawns per level in descending order. - Changed: Candle calculation is now depend on max level, instead of static 4 level. - Added: SRC added in @Start trigger. SRC is a reference of player that starts champion spawner. - Added: @Complete trigger that triggers when champion completed. (Issue: #477) - Added: @DelRedCandle trigger that triggers while red candle removing. - Added: @DelWhiteCandle trigger that triggers while white candle removing. - Added: @Level trigger that triggers when champion level up. - Added: @Stop trigger that triggers when champion stopped. --- Changelog.txt | 44 ++ src/game/CObjBase.h | 9 +- src/game/components/CCChampion.cpp | 1088 ++++++++++++++-------------- src/game/components/CCChampion.h | 92 ++- src/game/components/CCSpawn.cpp | 17 +- src/game/items/CItem.cpp | 9 +- src/tables/triggers.tbl | 17 +- 7 files changed, 709 insertions(+), 567 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 8cb51263e..39a575727 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3649,3 +3649,47 @@ Additionally, the problem of zig-zag issue following in the South direction has 18-04-2024, xwerswoodx - Fixed: Setting GMs dispid to c_man_gm in-game, prevents GMs to use in-game commands. - Changed: Default NPC hear range reverted back to the 14 from 4, as it was 14 in older versions, as there was no reason for changing it. (Issue: #1215) + +20-04-2024, xwerswoodx +- Rework: Champion system fully reworked. +- Fixed: Candles keep stuck while killing npcs. (Issue: #564) +- Fixed: LEVELMAX doesn't affect the max level of champion system, and keep spawn npcs for default max level. +- Changed: Spawn system changed and now it automatically calculate the percentage of spawns per level in descending order. +- Changed: Candle calculation is now depend on max level, instead of static 4 level. +- Added: SRC added in @Start trigger. SRC is a reference of player that starts champion spawner. +- Added: @Complete trigger that triggers when champion completed. (Issue: #477) + Args: + - I: Champion spawner uid. + TODO: Will add attacker list in this trigger. +- Added: @DelRedCandle trigger that triggers while red candle removing. + Args: + - I: Champion spawner uid. + - ARGO: Candle uid. + - ARGN1: Reason of removing. [Read Only] + 1: Timeout + 2: User Command + 3: Clearing all candles + Returns: + - 1: Cancel the delete action. +- Added: @DelWhiteCandle trigger that triggers while white candle removing. + Args: + - I: Champion spawner uid. + - ARGO: Candle uid. + - ARGN1: Reason of removing. [Read Only] + 1: Timeout + 2: User Command + 3: Clearing all candles + Returns: + - 1: Cancel the delete action. +- Added: @Level trigger that triggers when champion level up. + Args: + - I: Champion spawner uid. + - ARGN1: Level [Read Only] + - ARGN2: Total monster count for current level. [Read Only] + - ARGN3: Needed red candle count for current level. [Read Only] +- Added: @Stop trigger that triggers when champion stopped. + Args: + - I: Champion spawner uid. + - SRC: The player that stopped spawner. + Returns: + - 1: Cancel stopping action. \ No newline at end of file diff --git a/src/game/CObjBase.h b/src/game/CObjBase.h index 2187b23b2..071ff4ee1 100644 --- a/src/game/CObjBase.h +++ b/src/game/CObjBase.h @@ -1015,8 +1015,8 @@ enum STONEALIGN_TYPE // Types of Guild/Town stones enum ITRIG_TYPE { // XTRIG_UNKNOWN = some named trigger not on this list. - ITRIG_ADDREDCANDLE = 1, - ITRIG_ADDOBJ, // For t_spawn when obj is add to list + ITRIG_ADDOBJ = 1, // For t_spawn when obj is add to list + ITRIG_ADDREDCANDLE, ITRIG_ADDWHITECANDLE, ITRIG_AfterClick, ITRIG_Buy, @@ -1024,12 +1024,15 @@ enum ITRIG_TYPE ITRIG_Click, ITRIG_CLIENTTOOLTIP, // Sending tooltip to client for this item ITRIG_CLIENTTOOLTIP_AFTERDEFAULT, + ITRIG_COMPLETE, ITRIG_ContextMenuRequest, // A context menu was requested over me. ITRIG_ContextMenuSelect, // A context menu option was selected, perform actions. ITRIG_Create, // Item is being created. ITRIG_DAMAGE, // I have been damaged in some way. ITRIG_DCLICK, // I have been dclicked. ITRIG_DELOBJ, // For t_spawn when obj is remove from list + ITRIG_DELREDCANDLE, + ITRIG_DELWHITECANDLE, ITRIG_DESTROY, //+I am nearly destroyed. ITRIG_DROPON_CHAR, // I have been dropped on this char. ITRIG_DROPON_GROUND, // I have been dropped on the ground here. @@ -1041,6 +1044,7 @@ enum ITRIG_TYPE ITRIG_EQUIPTEST, // I'm not yet equiped, but checking if I can. ITRIG_GetHit, // Triggers when this clothing part get hit from characters. ITRIG_Hit, // Triggers when this item used to make a damage on characters. + ITRIG_LEVEL, ITRIG_MemoryEquip, // I'm a memory and I'm being equiped. ITRIG_PICKUP_GROUND, // I'm being picked up from ground. ITRIG_PICKUP_PACK, // picked up from inside some container. @@ -1061,6 +1065,7 @@ enum ITRIG_TYPE ITRIG_SPELLEFFECT, // cast some spell on me. ITRIG_Start, // Start trigger, right now used only on Champions. ITRIG_STEP, // I have been walked on. (or shoved) + ITRIG_STOP, ITRIG_TARGON_CANCEL, // Someone requested me (item) to target, now the targeting was canceled. ITRIG_TARGON_CHAR, // I'm targeting a char. ITRIG_TARGON_GROUND, // I'm targeting the ground. diff --git a/src/game/components/CCChampion.cpp b/src/game/components/CCChampion.cpp index bc2ff82aa..c123fc521 100644 --- a/src/game/components/CCChampion.cpp +++ b/src/game/components/CCChampion.cpp @@ -24,17 +24,68 @@ #include #define CANDLESNEXTRED 4 +#define MAXSPAWN 2400 +#define MAXLEVEL 5 -CCChampion::CCChampion(CItem *pLink) : CComponent(COMP_CHAMPION) +lpctstr const CCChampion::sm_szLoadKeys[ICHMPL_QTY + 1] = +{ + "ACTIVE", + "ADDREDCANDLE", + "ADDWHITECANDLE", + "CANDLESNEXTLEVEL", + "CHAMPIONID", + "CHAMPIONSPAWN", + "CHAMPIONSUMMONED", + "DEATHCOUNT", + "KILLSNEXTRED", + "KILLSNEXTWHITE", + "LASTACTIVATIONTIME", + "LEVEL", + "LEVELMAX", + "MORE", + "MORE1", + "NPCGROUP", + "REDCANDLES", + "SPAWNSCUR", + "SPAWNSMAX", + "WHITECANDLES", + nullptr +}; + +lpctstr const CCChampion::sm_szVerbKeys[ICHMPV_QTY + 1] = +{ + "ADDOBJ", + "ADDSPAWN", + "DELOBJ", + "DELREDCANDLE", + "DELWHITECANDLE", + "INIT", + "MULTICREATE", + "START", + "STOP", + nullptr +}; + +CCChampion::CCChampion(CItem* pLink) : CComponent(COMP_CHAMPION) { ADDTOCALLSTACK("CCChampion::CCChampion"); _pLink = pLink; - _iLevelMax = 4; - _iSpawnsMax = 2400; + _iLevelMax = MAXLEVEL; + _iSpawnsMax = MAXSPAWN; + ClearData(); _idChampion = CREID_INVALID; + _iLastActivationTime = 0; Init(); } +void CCChampion::Copy(const CComponent* target) +{ + ADDTOCALLSTACK("CCChampion::Copy"); + UnreferencedParameter(target); + //I don't see the point of duping a Champion, its insane and makes no sense, + // if someone wants to totally dupe a champion it can be done from scripts. +} + CCChampion::~CCChampion() { ADDTOCALLSTACK("CCChampion::~CCChampion"); @@ -42,7 +93,7 @@ CCChampion::~CCChampion() ClearRedCandles(); } -CItem * CCChampion::GetLink() const +CItem* CCChampion::GetLink() const { return _pLink; } @@ -52,14 +103,17 @@ CCRET_TYPE CCChampion::OnTickComponent() ADDTOCALLSTACK("CCChampion::_OnTick"); if (!_pRedCandles.empty()) { - _iSpawnsMax += _iSpawnsNextRed; - DelRedCandle(); + // TODO: Check + // DONE + _iSpawnsCur -= minimum(_iSpawnsCur, _iSpawnsNextRed); + _iDeathCount -= minimum(_iDeathCount, _iSpawnsNextRed); + DelRedCandle(CANDLEDELREASON_TIMEOUT); } else { Stop(); } - GetLink()->SetTimeoutS(60 * 10); //10 minutes + GetLink()->SetTimeoutS(60 * 10); return CCRET_CONTINUE; } @@ -71,104 +125,133 @@ CCSpawn* CCChampion::GetSpawnItem() void CCChampion::Init() { ADDTOCALLSTACK("CCChampion::Init"); - _fActive = false; - _iLevel = 0; - _iSpawnsCur = 0; - _iDeathCount = 0; - _iSpawnsNextWhite = 2; - _iSpawnsNextRed = 10; - _iCandlesNextRed = CANDLESNEXTRED; - _iCandlesNextLevel = 0; - _iLastActivationTime = 0; - _fChampionSummoned = false; - if (_idSpawn.IsValidResource() == false) - { - return; - } - const int resId = _idSpawn.GetResIndex(); - const CResourceIDBase rid(RES_CHAMPION, resId); - CResourceDef* pResDef = g_Cfg.RegisteredResourceGetDef(rid); - const CCChampionDef* pChampDef = static_cast(pResDef); - if (pChampDef == nullptr) - { - return; - } - _iLevelMax = pChampDef->_iLevelMax; - _iSpawnsMax = pChampDef->_iSpawnsMax; - _idChampion = pChampDef->_idChampion; - _spawnGroupsId.clear(); - if (pChampDef->_idSpawn.size()) + + if (_idSpawn.IsValidResource()) { - _spawnGroupsId.insert(pChampDef->_idSpawn.begin(), pChampDef->_idSpawn.end()); + /* + const CResourceIDBase rid(RES_CHAMPION, _idSpawn.GetResIndex()); + CResourceDef* pResDef = g_Cfg.RegisteredResourceGetDef(rid); + const CCChampionDef* pChampDef = static_cast(pResDef); + */ + + const int resId = _idSpawn.GetResIndex(); + const CResourceIDBase rid(RES_CHAMPION, resId); + CResourceDef* pResDef = g_Cfg.RegisteredResourceGetDef(rid); + const CCChampionDef* pChampDef = static_cast(pResDef); + + if (pChampDef != nullptr) + { + _iLevelMax = pChampDef->_iLevelMax; + _iSpawnsMax = pChampDef->_iSpawnsMax; + _idChampion = pChampDef->_idChampion; + _spawnGroupsId.clear(); + + if (!pChampDef->_idSpawn.empty()) + _spawnGroupsId.insert(pChampDef->_idSpawn.begin(), pChampDef->_idSpawn.end()); + InitializeLists(); // Initialize lists. + } } } -void CCChampion::Start() +void CCChampion::Start(CChar *pChar) { ADDTOCALLSTACK("CCChampion::Start"); // TODO store light in the area - if (_fActive == true) - { - Stop(); - } + if (_fActive) + return; _fActive = true; _iLastActivationTime = CWorldGameTime::GetCurrentTime().GetTimeRaw(); - _iSpawnsNextRed = GetCandlesPerLevel(); - _iCandlesNextRed = CANDLESNEXTRED; + // TODO: Check + // DONE + _iSpawnsNextRed = GetCandlesCount(); SetLevel(1); - if (IsTrigUsed(TRIGGER_START)) + if (pChar && IsTrigUsed(TRIGGER_START)) { - if (OnTrigger(ITRIG_Start, &g_Serv, nullptr) == TRIGRET_RET_TRUE) - { - return;// Do not spawn anything if the trigger returns 1 - } + // TODO: add source? + // DONE + if (OnTrigger(ITRIG_Start, pChar, nullptr) == TRIGRET_RET_TRUE) + return; } - for (ushort i = 0; i < _iSpawnsNextWhite; ++i) // Spawn all the monsters required to get the next White candle. // TODO: a way to prevent this from script. + + for (ushort i = 0; i < _iSpawnsNextWhite; ++i) SpawnNPC(); } -void CCChampion::Stop() +void CCChampion::Stop(CChar* pChar) { + // TODO: stop trigger ADDTOCALLSTACK("CCChampion::Stop"); + if (pChar) + { + if (IsTrigUsed(TRIGGER_STOP)) + { + if (OnTrigger(ITRIG_STOP, pChar, nullptr) == TRIGRET_RET_TRUE) + return; + } + } + KillChildren(); + ClearData(); + GetLink()->SetTimeout(-1); + ClearWhiteCandles(); + ClearRedCandles(); +} + +void CCChampion::ClearData() +{ _fActive = false; + _iLevel = 1; _iSpawnsCur = 0; _iDeathCount = 0; - _iLevel = 0; - _iCandlesNextRed = 0; _iCandlesNextLevel = 0; - _fChampionSummoned = false; - GetLink()->SetTimeout(_iLastActivationTime - CWorldGameTime::GetCurrentTime().GetTimeRaw()); - ClearWhiteCandles(); - ClearRedCandles(); + m_ChampionSummoned.InitUID(); + _MonstersList.clear(); + _CandleList.clear(); } void CCChampion::Complete() { ADDTOCALLSTACK("CCChampion::Complete"); - Stop(); //Cleaning everything, just to be sure. - // TODO: Add rewards, titles, etc + if (_fActive) + Stop(); + + // TODO: add new trigger + // DONE + // TODO: Add attacker list in trigger. + if (IsTrigUsed(TRIGGER_COMPLETE)) + { + OnTrigger(ITRIG_COMPLETE, &g_Serv, nullptr); + } + // TODO: add rewards, titles, etc? } -void CCChampion::OnKill() +void CCChampion::OnKill(const CUID& uid) { ADDTOCALLSTACK("CCChampion::OnKill"); - if (_iSpawnsNextWhite == 0) + // TODO: code for on kill, also add trigger? + if (uid.IsValidUID()) { - AddWhiteCandle(); + if (uid == m_ChampionSummoned) + { + Complete(); + return; + } } + + // TODO: addwhite candle + // DONE + if (!_iSpawnsNextWhite) + AddWhiteCandle(); + ++_iDeathCount; - if (_iDeathCount >= _iSpawnsMax) + if (_iDeathCount >= _iSpawnsMax && !m_ChampionSummoned.IsChar()) { - ClearWhiteCandles(); - ClearRedCandles(); - if (_fChampionSummoned == false) - { - SetLevel(UCHAR_MAX); - } + // Is player death count exceed _iSpawnMax? + // Force start the boss fight. + SetLevel(_iLevelMax); } SpawnNPC(); } @@ -176,41 +259,36 @@ void CCChampion::OnKill() void CCChampion::SpawnNPC() { ADDTOCALLSTACK("CCChampion::SpawnNPC"); - CREID_TYPE pNpc = CREID_INVALID; CResourceIDBase rid; - if (_iLevel == UCHAR_MAX)// Completed the champion's minor spawns, summon the boss (once). + bool _fChampionSummoned = false; + if (_iLevel >= _iLevelMax) { - if (_fChampionSummoned == true)// Already summoned the Champion, stop - { + // Max level? Time for boss challenge! + if (m_ChampionSummoned.IsChar()) //Is boss already spawned? return; - } - if (_iDeathCount >= _iSpawnsMax) // Killed all npcs, summon the boss. - { - pNpc = _idChampion; - _fChampionSummoned = true; - } + _iSpawnsNextWhite = 1; + _iSpawnsCur = _iSpawnsMax - 1; + _fChampionSummoned = true; + pNpc = _idChampion; } - else if (_iSpawnsCur < _iSpawnsMax) + else { - int iSize = (int)_spawnGroupsId[_iLevel].size(); - idSpawn spawngroup; - if ( iSize > 0) - { - spawngroup = _spawnGroupsId; - } + // Not ready for boss fight yet? + size_t uiSize = _spawnGroupsId[_iLevel].size(); + idSpawn idGroup; + if (uiSize > 0) + idGroup = _spawnGroupsId; else { CResourceDef* pRes = g_Cfg.RegisteredResourceGetDef(_idSpawn); CCChampionDef* pChampDef = static_cast(pRes); - if (pChampDef != nullptr) + if (pChampDef) { - iSize = (int)pChampDef->_idSpawn[_iLevel].size(); - if ( iSize > 0) - { - spawngroup = pChampDef->_idSpawn; - } + uiSize = pChampDef->_idSpawn[_iLevel].size(); + if (uiSize > 0) + idGroup = pChampDef->_idSpawn; else { g_Log.EventError("CCChampion:: Trying to create NPCs from undefined NPCGROUP[%d]\n", _iLevel); @@ -218,94 +296,108 @@ void CCChampion::SpawnNPC() } } } - if (_iSpawnsNextWhite > 0) - { - --_iSpawnsNextWhite; - } - if (iSize > 0 && iSize <= UCHAR_MAX) + + if (uiSize > 0 && uiSize <= UCHAR_MAX) { - uchar iRand = (uchar)Calc_GetRandVal2(0, (int)iSize -1); - pNpc = spawngroup[_iLevel][iRand]; //Find out the random npc. + uchar ucRand = (uchar)Calc_GetRandVal((int)uiSize); + pNpc = idGroup[_iLevel][ucRand]; // Get the npc randomly from the list. } else { - g_Log.EventError("Champion bad group index %d.\n", _iLevel); + g_Log.EventError("CCChampion:: Champion bad group index %d.\n", _iLevel); + return; } } - else - { + + if (_iSpawnsNextWhite == 0) // Do not spawn anymore if _iSpawnNextWhite equals to 0, should never happen but just for avoid any unnecessary loop. return; - } - rid = CResourceIDBase(RES_CHARDEF, pNpc); - CResourceDef* pDef = g_Cfg.RegisteredResourceGetDef(rid); - if (!pDef) + + if (_iSpawnsCur >= _iSpawnsMax) // Total spawn amount should never be higher than max. { + _iSpawnsNextWhite = 0; // Set Next White spawn rate to 0 to make sure not bugged. return; } - //ASSERT(dynamic_cast(pDef)); - if (!pNpc) // At least one NPC per level should be added, check just in case. - { + + if (!pNpc) return; - } + + rid = CResourceIDBase(RES_CHARDEF, pNpc); + CResourceDef* pRes = g_Cfg.RegisteredResourceGetDef(rid); + if (!pRes) + return; + CCSpawn* pSpawn = GetSpawnItem(); if (pSpawn) { - CChar* spawn = pSpawn->GenerateChar(rid); - if (spawn != nullptr) + CChar* pChar = pSpawn->GenerateChar(rid); + if (pChar) { - AddObj(spawn->GetUID()); + AddObj(pChar->GetUID()); + if (_fChampionSummoned) + m_ChampionSummoned = pChar->GetUID(); } } + // TODO: code spawn system. + // DONE ++_iSpawnsCur; + --_iSpawnsNextWhite; + } void CCChampion::AddWhiteCandle(const CUID& uid) { ADDTOCALLSTACK("CCChampion::AddWhiteCandle"); - if (_iLevel == UCHAR_MAX) - { + // TODO: code add white candle system. + // DONE + if (_iLevel >= _iLevelMax) return; - } - if (_pWhiteCandles.size() >= _iCandlesNextRed) + + if (_pWhiteCandles.size() >= CANDLESNEXTRED) { AddRedCandle(); return; } else - _iSpawnsNextWhite = _iSpawnsNextRed / 5; + _iSpawnsNextWhite = _iSpawnsNextRed / (CANDLESNEXTRED + 1); - CItem * pCandle = nullptr; - CItem *pLink = static_cast(GetLink()); + CItem* pCandle = nullptr; + CItem* pLink = static_cast(GetLink()); if (uid.IsValidUID()) { - pCandle = uid.ItemFind(); + _pWhiteCandles.emplace_back(uid); + return; } if (!pCandle) { pCandle = pLink->CreateBase(ITEMID_SKULL_CANDLE); if (!pCandle) + { + // If cannot create candle, force boss to spawn to be able to finish. + SetLevel(_iLevelMax); return; + } CPointMap pt = pLink->GetTopPoint(); - switch (_pWhiteCandles.size() + 1) // +1 here because the candle is post placed. + switch (_pWhiteCandles.size()) { - case 1: - pt.MoveN(DIR_SW, 1); - break; - case 2: - pt.MoveN(DIR_SE, 1); - break; - case 3: - pt.MoveN(DIR_NW, 1); - break; - case 4: - pt.MoveN(DIR_NE, 1); - break; - default: - break; + case 0: + pt.MoveN(DIR_SW, 1); + break; + case 1: + pt.MoveN(DIR_SE, 1); + break; + case 2: + pt.MoveN(DIR_NW, 1); + break; + case 3: + pt.MoveN(DIR_NE, 1); + break; + default: + break; } + pCandle->SetTopPoint(pt); - if (g_Serv.IsLoading() == false) + if (!g_Serv.IsLoading()) { if (IsTrigUsed(TRIGGER_ADDWHITECANDLE)) { @@ -323,31 +415,33 @@ void CCChampion::AddWhiteCandle(const CUID& uid) pCandle->Update(); pCandle->GenerateScript(nullptr); } + _pWhiteCandles.emplace_back(pCandle->GetUID()); - pCandle->m_uidLink = pLink->GetUID(); // Link it to the champion, so if it gets removed the candle will be removed too + pCandle->m_uidLink = pLink->GetUID(); } void CCChampion::AddRedCandle(const CUID& uid) { ADDTOCALLSTACK("CCChampion::AddRedCandle"); - CItem * pCandle = nullptr; + // TODO: code add red candle system. + // DONE + + CItem* pCandle = nullptr; + CItem* pLink = static_cast(GetLink()); if (uid.IsValidUID()) { - pCandle = uid.ItemFind(); + _pRedCandles.emplace_back(uid); + return; } - CItem *pLink = static_cast(GetLink()); - size_t uiRedCandlesAmount = _pRedCandles.size(); - if (uiRedCandlesAmount >= _iCandlesNextLevel) - { + if (_pRedCandles.size() >= _iCandlesNextLevel) SetLevel(_iLevel + 1); - } + if (_iLevel >= _iLevelMax) - { return; - } - _iSpawnsNextWhite = _iSpawnsNextRed / 5; - if (!g_Serv.IsLoading()) // White candles may be created before red ones when restoring items from worldsave we must not remove them. + + _iSpawnsNextWhite = _iSpawnsNextRed / (CANDLESNEXTRED + 1); + if (!g_Serv.IsLoading()) // Do not remove white candles, while server is loading them from save. { ClearWhiteCandles(); } @@ -356,202 +450,263 @@ void CCChampion::AddRedCandle(const CUID& uid) { pCandle = pLink->CreateBase(ITEMID_SKULL_CANDLE); if (!pCandle) - return; - _iCandlesNextRed = CANDLESNEXTRED; - CPointMap pt = pLink->GetTopPoint(); - if (g_Serv.IsLoading() == false) { - if (IsTrigUsed(TRIGGER_ADDREDCANDLE)) - { - CScriptTriggerArgs args(pCandle); - if (OnTrigger(ITRIG_ADDREDCANDLE, &g_Serv, &args) == TRIGRET_RET_TRUE) - { - pCandle->Delete(); - return; - } - } + // If cannot create candle, force boss to spawn to be able to finish. + SetLevel(_iLevelMax); + return; } - switch (uiRedCandlesAmount+1) // +1 here because the candle is post placed. + + CPointMap pt = pLink->GetTopPoint(); + switch (_pRedCandles.size()) { - case 1: + case 0: pt.MoveN(DIR_NW, 2); break; - case 2: + case 1: pt.MoveN(DIR_N, 2); pt.MoveN(DIR_W, 1); break; - case 3: + case 2: pt.MoveN(DIR_N, 2); break; - case 4: + case 3: pt.MoveN(DIR_N, 2); pt.MoveN(DIR_E, 1); break; - case 5: + case 4: pt.MoveN(DIR_NE, 2); break; - case 6: + case 5: pt.MoveN(DIR_E, 2); pt.MoveN(DIR_N, 1); break; - case 7: + case 6: pt.MoveN(DIR_E, 2); break; - case 8: + case 7: pt.MoveN(DIR_E, 2); pt.MoveN(DIR_S, 1); break; - case 9: + case 8: pt.MoveN(DIR_SE, 2); break; - case 10: + case 9: pt.MoveN(DIR_S, 2); pt.MoveN(DIR_E, 1); break; - case 11: + case 10: pt.MoveN(DIR_S, 2); break; - case 12: + case 11: pt.MoveN(DIR_S, 2); pt.MoveN(DIR_W, 1); break; - case 13: + case 12: pt.MoveN(DIR_SW, 2); break; - case 14: + case 13: pt.MoveN(DIR_W, 2); pt.MoveN(DIR_S, 1); break; - case 15: + case 14: pt.MoveN(DIR_W, 2); break; - case 16: + case 15: pt.MoveN(DIR_W, 2); pt.MoveN(DIR_N, 1); break; default: break; } - //TODO Trigger @AddRedCandle (pCandle, pt, _iCandlesNextRed,) - + if (!g_Serv.IsLoading()) + { + if (IsTrigUsed(TRIGGER_ADDREDCANDLE)) + { + CScriptTriggerArgs args(pCandle); + if (OnTrigger(ITRIG_ADDREDCANDLE, &g_Serv, &args) == TRIGRET_RET_TRUE) + { + pCandle->Delete(); + return; + } + } + } pCandle->SetAttr(ATTR_MOVE_NEVER); pCandle->MoveTo(pt); pCandle->SetTopZ(pCandle->GetTopZ() + 4); - pCandle->SetHue( (HUE_TYPE)33 ); + pCandle->SetHue((HUE_TYPE)33); pCandle->Update(); pCandle->GenerateScript(nullptr); ClearWhiteCandles(); } + _pRedCandles.emplace_back(pCandle->GetUID()); - pCandle->m_uidLink = pLink->GetUID(); // Link it to the champion, so if it gets removed the candle will be removed too + pCandle->m_uidLink = pLink->GetUID(); } void CCChampion::SetLevel(byte iLevel) { ADDTOCALLSTACK("CCChampion::SetLevel"); + if (g_Serv.IsLoading()) + return; + _iLevel = iLevel; - if (g_Serv.IsLoading() == true) + if (_iLevel < 1) + _iLevel = 1; + + ushort iLevelMonsters = GetMonstersCount(); + _iCandlesNextLevel += GetCandlesCount(); + // TODO: Trigger @Level (level, GetMonstersPerLevel, _iCandlesNextLevel) + // DONE + if (IsTrigUsed(TRIGGER_LEVEL)) { - return; + CScriptTriggerArgs args(_iLevel, iLevelMonsters, _iCandlesNextLevel); + OnTrigger(ITRIG_LEVEL, &g_Serv, &args); } - if (_iLevel < 1) + + if (_iLevel >= _iLevelMax) // Start boss fight when level maxed. { - _iLevel = 1; + KillChildren(); + ClearWhiteCandles(); + ClearRedCandles(); + SpawnNPC(); + return; } - ushort iLevelMonsters = GetMonstersPerLevel(_iSpawnsMax); - //Get the current candles required - last required candles (if current level = 1, then gets 6-0 = 6, level 2 = 10 - 6 = 4, and so on). - _iCandlesNextLevel = GetCandlesPerLevel(); - _iCandlesNextRed = 4; - ushort iRedMonsters = iLevelMonsters / _iCandlesNextLevel; - ushort iWhiteMonsters = iRedMonsters / _iCandlesNextRed; - // TODO: Trigger @Level (old level, new level, GetMonstersPerLevel, _iCandlesNextLevel) + // TODO: check and code + // DONE // TODO: As the level increases, the light on the area decreases. - + ushort iRedMonsters = iLevelMonsters / _iCandlesNextLevel; + ushort iWhiteMonsters = iRedMonsters / (CANDLESNEXTRED + 1); _iSpawnsNextWhite = iWhiteMonsters; _iSpawnsNextRed = iRedMonsters; - GetLink()->SetTimeoutS(60 * 10); //10 minutes + GetLink()->SetTimeoutS(60 * 10); } -byte CCChampion::GetCandlesPerLevel(byte iLevel) const +void CCChampion::InitializeLists() { - ADDTOCALLSTACK("CCChampion::GetCandlesPerLevel"); - if (iLevel == 255) + ADDTOCALLSTACK("CCChampion::InitializeLists"); + + /* + * As we have _iLevelMax overrideable, we can't use static switch for it. + * The closest algorithm I could fine for it is; + * [(100 / _iLevelMax) / (_iLevel - 1)] + (_iLevelMax - _iLevel) + */ + _MonstersList.clear(); + _CandleList.clear(); + + uchar ucPerc = 100 / _iLevelMax; + uchar ucMonsterTotal = 0; + uchar ucCandleTotal = 0; + for (uchar i = (_iLevelMax - 2); i > 0; --i) { - iLevel = _iLevel; + uchar ucMonster = (ucPerc / i) + (_iLevelMax - (i + 1)); + _MonstersList.insert(_MonstersList.begin(), ucMonster); // Push the value from beginning. + ucMonsterTotal += ucMonster; } - switch (iLevel) + _MonstersList.insert(_MonstersList.begin(), (100 - ucMonsterTotal)); // Push the left over as first element. + + for (uchar i = (_iLevelMax - 1); i > 1; --i) { - case 4: - return 16; - case 3: - return 14; - case 2: - return 10; - case 1: - return 6; - default: - return 1; + uchar ucCandle = ((16 - ucCandleTotal) / i); + _CandleList.insert(_CandleList.begin(), ucCandle); + ucCandleTotal += ucCandle; } + _CandleList.insert(_CandleList.begin(), (16 - ucCandleTotal)); } -ushort CCChampion::GetMonstersPerLevel(ushort iMonsters) const +// TODO: as we have hardcoded switch base level system, _iLevelMax should always equals to 5! Shouldn't be overrideable. +// DONE +uchar CCChampion::GetCandlesCount() +{ + ADDTOCALLSTACK("CCChampion::GetCandlesPerLevel"); + if (_iLevel == UCHAR_MAX) + return 16; + + if (_iLevel < 1) // Should never happen but put here to make sure avoid invalid index. + _iLevel = 1; + + if (_CandleList.empty()) + InitializeLists(); + + if (_CandleList.empty()) // Should never be empty after InitializeLists() but added to avoid any bug + return 16; + + if (_iLevel <= _CandleList.size()) + return _CandleList[_iLevel - 1]; + return 16; + +} + +// TODO: iMonsters? Change to something specific or remove? +// DONE +ushort CCChampion::GetMonstersCount() { ADDTOCALLSTACK("CCChampion::GetMonstersPerLevel"); - ushort iTotal = 0; - switch (_iLevel) + if (_iLevel < 1) // Should never happen but put here to make sure avoid invalid index. + _iLevel = 1; + + if (_MonstersList.empty()) + InitializeLists(); + + if (_MonstersList.empty()) // Should never be empty after InitializeLists() but added to avoid any bug + return 1; + + if (_iLevel <= _MonstersList.size()) { - case 4: - iTotal = (7 * iMonsters) / 100; // 7% of monsters are spawned in level 4. - break; - case 3: - iTotal = (13 * iMonsters) / 100; // 13% of monsters are spawned in level 3. - break; - case 2: - iTotal = (27 * iMonsters) / 100; // 27% of monsters are spawned in level 2. - break; - default: - case 1: - iTotal = (53 * iMonsters) / 100; // 53% of monster are spawned in level 1. - break; + ushort ucPerc = (ushort)_MonstersList[_iLevel - 1]; + return (ucPerc * _iSpawnsMax) / 100; } - return iTotal; + return 1; } // Delete the last created white candle. -void CCChampion::DelWhiteCandle() +void CCChampion::DelWhiteCandle(CANDLEDELREASON_TYPE reason) { ADDTOCALLSTACK("CCChampion::DelWhiteCandle"); if (_pWhiteCandles.empty()) - { return; - } - - //TODO Trigger @DelWhiteCandle - CItem * pCandle = _pWhiteCandles.back().ItemFind(); + CItem* pCandle = _pWhiteCandles.back().ItemFind(); if (pCandle) { - pCandle->Delete(); + // TODO: trigger: @DelWhiteCandle + // DONE + if (IsTrigUsed(TRIGGER_DELWHITECANDLE)) + { + CScriptTriggerArgs args(reason); + args.m_pO1 = pCandle; + if (OnTrigger(ITRIG_DELWHITECANDLE, &g_Serv, &args) == TRIGRET_RET_TRUE) + return; + } + + if (pCandle) // Is candle still exists after trigger? + pCandle->Delete(); } _pWhiteCandles.pop_back(); } // Delete the last created red candle. -void CCChampion::DelRedCandle() +void CCChampion::DelRedCandle(CANDLEDELREASON_TYPE reason) { ADDTOCALLSTACK("CCChampion::DelRedCandle"); if (_pRedCandles.empty()) - { return; - } - //TODO Trigger @DelRedCandle - - CItem * pCandle = _pRedCandles.back().ItemFind(); + CItem* pCandle = _pRedCandles.back().ItemFind(); if (pCandle) { - pCandle->Delete(); + // TODO: trigger: @DelRedCandle + // DONE + if (IsTrigUsed(TRIGGER_DELREDCANDLE)) + { + CScriptTriggerArgs args(reason); + args.m_pO1 = pCandle; + if (OnTrigger(ITRIG_DELREDCANDLE, &g_Serv, &args) == TRIGRET_RET_TRUE) + return; + } + + if (pCandle) // Is candle still exists after trigger? + pCandle->Delete(); } _pRedCandles.pop_back(); } @@ -559,41 +714,30 @@ void CCChampion::DelRedCandle() // Clear all white candles. void CCChampion::ClearWhiteCandles() { - ADDTOCALLSTACK("CCChampion::ClearWhiteCandles"); if (_pWhiteCandles.empty()) - { return; - } - for (size_t i = 0, uiTotal = _pWhiteCandles.size(); i < uiTotal; ++i) - { + for (size_t i = 0, iTotal = _pWhiteCandles.size(); i < iTotal; ++i) DelWhiteCandle(); - } } // Clear all red candles. void CCChampion::ClearRedCandles() { - ADDTOCALLSTACK("CCChampion::ClearRedCandles"); if (_pRedCandles.empty()) - { return; - } - for (size_t i = 0, uiTotal = _pRedCandles.size(); i < uiTotal; ++i) - { - DelRedCandle(); - } + + for (size_t i = 0, iTotal = _pRedCandles.size(); i < iTotal; ++i) + DelRedCandle(CANDLEDELREASON_CLEAR); } // kill everything spawned from this spawn ! void CCChampion::KillChildren() { ADDTOCALLSTACK("CCChampion:KillChildren"); - CCSpawn *pSpawn = static_cast(GetLink()->GetComponent(COMP_SPAWN)); + CCSpawn *pSpawn = GetSpawnItem(); if (pSpawn) - { pSpawn->KillChildren(); - } } // Deleting one object from Spawn's memory, reallocating memory automatically. @@ -604,159 +748,56 @@ void CCChampion::DelObj(const CUID& uid) { return; } - CCSpawn *pSpawn = static_cast(GetLink()->GetComponent(COMP_SPAWN)); + CCSpawn* pSpawn = static_cast(GetLink()->GetComponent(COMP_SPAWN)); ASSERT(pSpawn); pSpawn->DelObj(uid); - CChar *pChar = uid.CharFind(); + CChar* pChar = uid.CharFind(); if (pChar) { + // Should it called in any time? As DelObj called when obj deleting? CScript s("-e_spawn_champion");//Removing it here just for safety, preventing any additional DelObj being called from the trigger and causing an infinite loop. pChar->m_OEvents.r_LoadVal(s, RES_EVENTS); //removing event from the char. + OnKill(uid); } //Not checking HP or anything else, an NPC was created and counted so killing, removing or just taking it out of the lists counts towards the progression. - OnKill(); + OnKill(uid); } // Storing one UID in Spawn's _pObj[] void CCChampion::AddObj(const CUID& uid) { ADDTOCALLSTACK("CCChampion:AddObj"); - CChar *pChar = uid.CharFind(); + CChar* pChar = uid.CharFind(); if (pChar) { - CScript s("events +e_spawn_champion"); - pChar->r_LoadVal(s); + // TODO: check if event exists. + // DONE + if (IsValidResourceDef("e_spawn_champion")) + { + CScript s("events +e_spawn_champion"); + pChar->r_LoadVal(s); + } } } -// Returns the monster's 'level' according to the champion's level (red candles). -/*byte CCChampion::GetPercentMonsters() -{ - switch (_iLevel) - { - default: - case 1: - return 38; - case 2: - case 3: - return 25; - case 4: - return 12; - } -}*/ - -// Returns the percentaje of monsters killed. -/*byte CCChampion::GetCompletionMonsters() -{ - byte iPercent = (m_iDeathCount * 100) / _iSpawnsMax; - - if (iPercent <= 53) - return 1; - else if ( iPercent <= 80 ) // 53 + 27 - return 2; - else if ( iPercent <= 93 ) // 53 + 27 + 13 - return 3; - else if ( iPercent <= 100 ) - return 4; - return 1; -}*/ - -enum ICHMPL_TYPE -{ - ICHMPL_ACTIVE, - ICHMPL_ADDREDCANDLE, - ICHMPL_ADDWHITECANDLE, - ICHMPL_CANDLESNEXTLEVEL, - ICHMPL_CANDLESNEXTRED, - ICHMPL_CHAMPIONID, - ICHMPL_CHAMPIONSPAWN, - ICHMPL_CHAMPIONSUMMONED, - ICHMPL_DEATHCOUNT, - ICHMPL_KILLSNEXTRED, - ICHMPL_KILLSNEXTWHITE, - ICHMPL_LASTACTIVATIONTIME, - ICHMPL_LEVEL, - ICHMPL_LEVELMAX, - ICHMPL_MORE, - ICHMPL_MORE1, - ICHMPL_NPCGROUP, - ICHMPL_REDCANDLES, - ICHMPL_SPAWNSCUR, - ICHMPL_SPAWNSMAX, - ICHMPL_WHITECANDLES, - ICHMPL_QTY -}; - -lpctstr const CCChampion::sm_szLoadKeys[ICHMPL_QTY + 1] = -{ - "ACTIVE", - "ADDREDCANDLE", - "ADDWHITECANDLE", - "CANDLESNEXTLEVEL", - "CANDLESNEXTRED", - "CHAMPIONID", - "CHAMPIONSPAWN", - "CHAMPIONSUMMONED", - "DEATHCOUNT", - "KILLSNEXTRED", - "KILLSNEXTWHITE", - "LASTACTIVATIONTIME", - "LEVEL", - "LEVELMAX", - "MORE", - "MORE1", - "NPCGROUP", - "REDCANDLES", - "SPAWNSCUR", - "SPAWNSMAX", - "WHITECANDLES", - nullptr -}; - -enum ICHMPV_TYPE -{ - ICHMPV_ADDOBJ, - ICHMPV_ADDSPAWN, - ICHMPV_DELOBJ, - ICHMPV_DELREDCANDLE, - ICHMPV_DELWHITECANDLE, - ICHMPV_INIT, - ICHMPV_MULTICREATE, - ICHMPV_START, - ICHMPV_STOP, - ICHMPV_QTY -}; - - -lpctstr const CCChampion::sm_szVerbKeys[ICHMPV_QTY + 1] = -{ - "ADDOBJ", - "ADDSPAWN", - "DELOBJ", - "DELREDCANDLE", - "DELWHITECANDLE", - "INIT", - "MULTICREATE", - "START", - "STOP", - nullptr -}; -void CCChampion::r_Write(CScript & s) +void CCChampion::r_Write(CScript& s) { ADDTOCALLSTACK("CCChampion::r_Write"); + CResourceDef* pRes = g_Cfg.RegisteredResourceGetDef(_idSpawn); CCChampionDef* pChampDef = static_cast(pRes); + if (!pChampDef) { g_Log.EventDebug("Trying to save a champion spawn 0%" PRIx32 " with bad id 0%" PRIx32 ".\n", (dword)GetLink()->GetUID(), _idSpawn.GetPrivateUID()); return; } + s.WriteKeyVal("ACTIVE", _fActive); s.WriteKeyStr("CHAMPIONID", g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, _idChampion))); - s.WriteKeyVal("CHAMPIONSUMMONED", _fChampionSummoned); + s.WriteKeyVal("CHAMPIONSUMMONED", m_ChampionSummoned.GetObjUID()); s.WriteKeyVal("CANDLESNEXTLEVEL", _iCandlesNextLevel); - s.WriteKeyVal("CANDLESNEXTRED", _iCandlesNextRed); s.WriteKeyVal("DEATHCOUNT", _iDeathCount); s.WriteKeyVal("KILLSNEXTRED", _iSpawnsNextRed); s.WriteKeyVal("KILLSNEXTWHITE", _iSpawnsNextWhite); @@ -767,23 +808,22 @@ void CCChampion::r_Write(CScript & s) s.WriteKeyVal("SPAWNSMAX", _iSpawnsMax); if (_idSpawn.IsValidResource()) - { s.WriteKeyStr("CHAMPIONSPAWN", g_Cfg.ResourceGetName(_idSpawn)); - } + for (const CUID& uidCandle : _pRedCandles) { - const CItem * pCandle = uidCandle.ItemFind(); + const CObjBase* pCandle = uidCandle.ObjFind(); if (!pCandle) - continue; // ?? - s.WriteKeyHex("ADDREDCANDLE", (dword)uidCandle); + continue; + s.WriteKeyHex("ADDREDCANDLE", uidCandle.GetObjUID()); } for (const CUID& uidCandle : _pWhiteCandles) { - const CItem * pCandle = uidCandle.ItemFind(); + const CObjBase* pCandle = uidCandle.ObjFind(); if (!pCandle) - continue; // ?? - s.WriteKeyHex("ADDWHITECANDLE", (dword)uidCandle); + continue; + s.WriteKeyHex("ADDWHITECANDLE", uidCandle.GetObjUID()); } if (!_spawnGroupsId.empty()) @@ -806,14 +846,13 @@ void CCChampion::r_Write(CScript & s) std::stringstream finalStream; finalStream << "npcgroup[" << (int)group.first << "]"; - s.WriteKeyStr(finalStream.str().c_str(), groupString.c_str()); } } return; } -bool CCChampion::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc) +bool CCChampion::r_WriteVal(lpctstr ptcKey, CSString& sVal, CTextConsole* pSrc) { UnreferencedParameter(pSrc); ADDTOCALLSTACK("CCChampion::r_WriteVal"); @@ -829,40 +868,37 @@ bool CCChampion::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc } switch (iCmd) { - case ICHMPL_ACTIVE: - sVal.FormatBVal(_fActive); - break; - case ICHMPL_CANDLESNEXTLEVEL: - sVal.FormatUCVal(_iCandlesNextLevel); - break; - case ICHMPL_CANDLESNEXTRED: - sVal.FormatUCVal(_iCandlesNextRed); - break; - case ICHMPL_LASTACTIVATIONTIME: - sVal.FormatLLVal(_iLastActivationTime); - break; - case ICHMPL_LEVEL: - sVal.FormatUCVal(_iLevel); - break; - case ICHMPL_LEVELMAX: - sVal.FormatUCVal(_iLevelMax); - break; - case ICHMPL_KILLSNEXTRED: - sVal.FormatUSVal(_iSpawnsNextRed); - break; - case ICHMPL_KILLSNEXTWHITE: - sVal.FormatUSVal(_iSpawnsNextWhite); - break; - case ICHMPL_REDCANDLES: - sVal.FormatVal((int)_pRedCandles.size()); - break; - case ICHMPL_WHITECANDLES: - sVal.FormatVal((int)_pWhiteCandles.size()); - break; - case ICHMPL_DEATHCOUNT: - sVal.FormatUSVal(_iDeathCount); - break; - case ICHMPL_NPCGROUP: + case ICHMPL_ACTIVE: + sVal.FormatBVal(_fActive); + break; + case ICHMPL_CANDLESNEXTLEVEL: + sVal.FormatUCVal(_iCandlesNextLevel); + break; + case ICHMPL_LASTACTIVATIONTIME: + sVal.FormatLLVal(_iLastActivationTime); + break; + case ICHMPL_LEVEL: + sVal.FormatUCVal(_iLevel); + break; + case ICHMPL_LEVELMAX: + sVal.FormatUCVal(_iLevelMax); + break; + case ICHMPL_KILLSNEXTRED: + sVal.FormatUSVal(_iSpawnsNextRed); + break; + case ICHMPL_KILLSNEXTWHITE: + sVal.FormatUSVal(_iSpawnsNextWhite); + break; + case ICHMPL_REDCANDLES: + sVal.FormatVal((int)_pRedCandles.size()); + break; + case ICHMPL_WHITECANDLES: + sVal.FormatVal((int)_pWhiteCandles.size()); + break; + case ICHMPL_DEATHCOUNT: + sVal.FormatUSVal(_iDeathCount); + break; + case ICHMPL_NPCGROUP: { uchar uiGroup = (uchar)Exp_GetSingle(ptcKey); int iSize = (int)_spawnGroupsId[uiGroup].size(); //Try to get custom spawngroups for this champion spawn. @@ -905,17 +941,17 @@ bool CCChampion::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc sVal.FormatVal(-1); //Bad format? break; } - case ICHMPL_CHAMPIONID: + case ICHMPL_CHAMPIONID: { - sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, _idChampion)); + sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, _idChampion)); break; } - case ICHMPL_CHAMPIONSUMMONED: - sVal.FormatCVal(_fChampionSummoned); - break; - case ICHMPL_CHAMPIONSPAWN: - case ICHMPL_MORE: - case ICHMPL_MORE1: + case ICHMPL_CHAMPIONSUMMONED: + sVal.FormatDWVal(m_ChampionSummoned.GetObjUID()); + break; + case ICHMPL_CHAMPIONSPAWN: + case ICHMPL_MORE: + case ICHMPL_MORE1: { if (_idSpawn.IsValidResource()) { @@ -927,24 +963,24 @@ bool CCChampion::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc } break; } - case ICHMPL_SPAWNSCUR: - sVal.FormatUSVal(_iSpawnsCur); - break; - case ICHMPL_SPAWNSMAX: - sVal.FormatUSVal(_iSpawnsMax); - break; - default: - return false; + case ICHMPL_SPAWNSCUR: + sVal.FormatUSVal(_iSpawnsCur); + break; + case ICHMPL_SPAWNSMAX: + sVal.FormatUSVal(_iSpawnsMax); + break; + default: + return false; } return true; } -bool CCChampion::r_LoadVal(CScript & s) +bool CCChampion::r_LoadVal(CScript& s) { ADDTOCALLSTACK("CCChampion::r_LoadVal"); int iCmd = FindTableSorted(s.GetKey(), sm_szLoadKeys, (int)ARRAY_COUNT(sm_szLoadKeys) - 1); lpctstr ptcKey = s.GetKey(); - + if (iCmd < 0) { if (!strnicmp(ptcKey, "NPCGROUP", 8)) @@ -955,7 +991,7 @@ bool CCChampion::r_LoadVal(CScript & s) } switch (iCmd) { - case ICHMPL_ACTIVE: + case ICHMPL_ACTIVE: { if (g_Serv.IsLoading() == true) //Only when the server is loading. { @@ -963,35 +999,32 @@ bool CCChampion::r_LoadVal(CScript & s) } break; } - case ICHMPL_ADDREDCANDLE: + case ICHMPL_ADDREDCANDLE: { - AddRedCandle(CUID(s.GetArgVal())); + AddRedCandle(CUID(s.GetArgDWVal())); break; } - case ICHMPL_ADDWHITECANDLE: + case ICHMPL_ADDWHITECANDLE: { - AddWhiteCandle(CUID(s.GetArgVal())); + AddWhiteCandle(CUID(s.GetArgDWVal())); break; } - case ICHMPL_CANDLESNEXTLEVEL: - _iCandlesNextLevel = s.GetArgUCVal(); - break; - case ICHMPL_CANDLESNEXTRED: - _iCandlesNextRed = s.GetArgUCVal(); - break; - case ICHMPL_DEATHCOUNT: - _iDeathCount = s.GetArgUSVal(); - break; - case ICHMPL_LASTACTIVATIONTIME: - _iLastActivationTime = s.GetArgLLVal(); - break; - case ICHMPL_LEVEL: - _iLevel = s.GetArgUCVal(); - break; - case ICHMPL_LEVELMAX: - _iLevelMax = s.GetArgUCVal(); - break; - case ICHMPL_NPCGROUP: + case ICHMPL_CANDLESNEXTLEVEL: + _iCandlesNextLevel = s.GetArgUCVal(); + break; + case ICHMPL_DEATHCOUNT: + _iDeathCount = s.GetArgUSVal(); + break; + case ICHMPL_LASTACTIVATIONTIME: + _iLastActivationTime = s.GetArgLLVal(); + break; + case ICHMPL_LEVEL: + _iLevel = s.GetArgUCVal(); + break; + case ICHMPL_LEVELMAX: + _iLevelMax = s.GetArgUCVal(); + break; + case ICHMPL_NPCGROUP: { uchar iGroup = Exp_GetUCVal(ptcKey); tchar* piCmd[UCHAR_MAX]; @@ -1007,59 +1040,49 @@ bool CCChampion::r_LoadVal(CScript & s) } break; } - case ICHMPL_KILLSNEXTRED: - _iSpawnsNextRed = s.GetArgUCVal(); - break; - case ICHMPL_KILLSNEXTWHITE: - _iSpawnsNextWhite = s.GetArgUCVal(); - break; - case ICHMPL_SPAWNSCUR: - _iSpawnsCur = s.GetArgUSVal(); - break; - case ICHMPL_SPAWNSMAX: - _iSpawnsMax = s.GetArgUSVal(); - break; - case ICHMPL_CHAMPIONID: - _idChampion = (CREID_TYPE)g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr()); - break; - case ICHMPL_CHAMPIONSUMMONED: - _fChampionSummoned = s.GetArgCVal(); - break; - case ICHMPL_CHAMPIONSPAWN: - case ICHMPL_MORE: - case ICHMPL_MORE1: + case ICHMPL_KILLSNEXTRED: + _iSpawnsNextRed = s.GetArgUCVal(); + break; + case ICHMPL_KILLSNEXTWHITE: + _iSpawnsNextWhite = s.GetArgUCVal(); + break; + case ICHMPL_SPAWNSCUR: + _iSpawnsCur = s.GetArgUSVal(); + break; + case ICHMPL_SPAWNSMAX: + _iSpawnsMax = s.GetArgUSVal(); + break; + case ICHMPL_CHAMPIONID: + _idChampion = (CREID_TYPE)g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr()); + break; + case ICHMPL_CHAMPIONSUMMONED: + m_ChampionSummoned.SetObjUID(s.GetArgDWVal()); + break; + case ICHMPL_CHAMPIONSPAWN: + case ICHMPL_MORE: + case ICHMPL_MORE1: { - Stop(); - const dword dwPrivateUID = s.GetArgDWVal(); - if (!CUID::IsValidUID(dwPrivateUID)) - { - break; - } - CResourceIDBase ridArg(dwPrivateUID); // Not using CResourceID because res_chardef, spawn, itemdef, template do not use the "page" arg - const int iRidIndex = ridArg.GetResIndex(); - const int iRidType = ridArg.GetResType(); - - if ((iRidType == RES_CHAMPION)) - { - // If i have the ResType probably i passed a Defname - _idSpawn = ridArg; - } - else - { - _idSpawn = CResourceIDBase(RES_CHAMPION, iRidIndex); - } - if (_idSpawn.IsValidUID() == false) - { - g_Log.EventDebug("Invalid champion id"); //todo better log - } - else + const CUID uid(s.GetArgDWVal()); + if (!uid.IsValidUID()) + return true; // Should return true because we don't want to see undefined keyword exception. + + if (!uid.IsValidResource()) + return true; + + CResourceIDBase rid(uid.GetPrivateUID()); + _idSpawn = (rid.GetResType() == RES_CHAMPION ? rid : CResourceIDBase(RES_CHAMPION, rid.GetResIndex())); + + if (!_idSpawn.IsValidUID()) { - Init(); + g_Log.EventDebug("Invalid champion id, champion spawn stopped. uid=0%x\n", (dword)uid); + Stop(); + return true; } + Init(); break; } - default: - return false; + default: + return false; } return true; } @@ -1068,7 +1091,6 @@ void CCChampion::Delete(bool fForce) { ADDTOCALLSTACK("CCChampion::Delete"); UnreferencedParameter(fForce); - // KillChildren is being called from CCSpawn, must not call it twice. ClearWhiteCandles(); ClearRedCandles(); } @@ -1119,8 +1141,10 @@ bool CCChampion::r_GetRef(lpctstr & ptcKey, CScriptObj * & pRef) bool CCChampion::r_Verb(CScript & s, CTextConsole * pSrc) { ADDTOCALLSTACK("CCChampion::r_Verb"); - UnreferencedParameter(pSrc); + //UnreferencedParameter(pSrc); int iCmd = FindTableSorted(s.GetKey(), sm_szVerbKeys, (int)ARRAY_COUNT(sm_szVerbKeys) - 1); + CChar* pCharSrc = pSrc->GetChar(); + switch (iCmd) { case ICHMPV_ADDOBJ: @@ -1141,39 +1165,31 @@ bool CCChampion::r_Verb(CScript & s, CTextConsole * pSrc) return true; } case ICHMPV_DELREDCANDLE: - DelRedCandle(); + DelRedCandle(CANDLEDELREASON_COMMAND); return true; case ICHMPV_DELWHITECANDLE: - DelWhiteCandle(); + DelWhiteCandle(CANDLEDELREASON_COMMAND); return true; case ICHMPV_INIT: Init(); return true; case ICHMPV_MULTICREATE: { - /*CUID uid( s.GetArgVal() ); // FIXME: ECS link with CItemMulti. - CChar * pCharSrc = uid.CharFind(); - Multi_Setup( pCharSrc, 0 );*/ + //CUID uid( s.GetArgVal() ); // FIXME: ECS link with CItemMulti. + //CChar * pCharSrc = uid.CharFind(); + //Multi_Setup( pCharSrc, 0 ); return true; } case ICHMPV_START: - Start(); + Start(pCharSrc); return true; case ICHMPV_STOP: - Stop(); + Stop(pCharSrc); return true; } return false; } -void CCChampion::Copy(const CComponent * target) -{ - ADDTOCALLSTACK("CCChampion::Copy"); - UnreferencedParameter(target); - /*I don't see the point of duping a Champion, its insane and makes no sense, - * if someone wants to totally dupe a champion it can be done from scripts. - */ -} TRIGRET_TYPE CCChampion::OnTrigger(ITRIG_TYPE trig, CTextConsole* pSrc, CScriptTriggerArgs* pArgs) { @@ -1199,18 +1215,6 @@ TRIGRET_TYPE CCChampion::OnTrigger(ITRIG_TYPE trig, CTextConsole* pSrc, CScriptT return iRet; } - -enum CHAMPIONDEF_TYPE -{ - CHAMPIONDEF_CHAMPIONID, ///< Champion ID: _iChampion. - CHAMPIONDEF_DEFNAME, ///< Champion's DEFNAME. - CHAMPIONDEF_LEVELMAX, ///< Max Level for this champion. - CHAMPIONDEF_NAME, ///< Champion name: m_sName. - CHAMPIONDEF_NPCGROUP, ///< Monster level / group: _iSpawn[n][n]. - CHAMPIONDEF_SPAWNSMAX , ///< Total amount of monsters: _iSpawnsMax. - CHAMPIONDEF_QTY -}; - lpctstr const CCChampionDef::sm_szLoadKeys[CHAMPIONDEF_QTY + 1] = { "CHAMPIONID", @@ -1226,8 +1230,8 @@ lpctstr const CCChampionDef::sm_szLoadKeys[CHAMPIONDEF_QTY + 1] = CCChampionDef::CCChampionDef(CResourceID rid) : CResourceLink(rid) { ADDTOCALLSTACK("CCChampionDef::CCChampionDef"); - _iSpawnsMax = 2400; - _iLevelMax = 4; + _iSpawnsMax = MAXSPAWN; + _iLevelMax = MAXLEVEL; _idChampion = CREID_INVALID; } diff --git a/src/game/components/CCChampion.h b/src/game/components/CCChampion.h index bbdacc3e1..9a4982570 100644 --- a/src/game/components/CCChampion.h +++ b/src/game/components/CCChampion.h @@ -37,6 +37,69 @@ enum CHAMPION_ID CHAMPION_QTY // End of OSI defined Champion spawns. }; + +enum ICHMPL_TYPE +{ + ICHMPL_ACTIVE, + ICHMPL_ADDREDCANDLE, + ICHMPL_ADDWHITECANDLE, + ICHMPL_CANDLESNEXTLEVEL, + ICHMPL_CHAMPIONID, + ICHMPL_CHAMPIONSPAWN, + ICHMPL_CHAMPIONSUMMONED, + ICHMPL_DEATHCOUNT, + ICHMPL_KILLSNEXTRED, + ICHMPL_KILLSNEXTWHITE, + ICHMPL_LASTACTIVATIONTIME, + ICHMPL_LEVEL, + ICHMPL_LEVELMAX, + ICHMPL_MORE, + ICHMPL_MORE1, + ICHMPL_NPCGROUP, + ICHMPL_REDCANDLES, + ICHMPL_SPAWNSCUR, + ICHMPL_SPAWNSMAX, + ICHMPL_WHITECANDLES, + ICHMPL_QTY +}; + +enum ICHMPV_TYPE +{ + ICHMPV_ADDOBJ, + ICHMPV_ADDSPAWN, + ICHMPV_DELOBJ, + ICHMPV_DELREDCANDLE, + ICHMPV_DELWHITECANDLE, + ICHMPV_INIT, + ICHMPV_MULTICREATE, + ICHMPV_START, + ICHMPV_STOP, + ICHMPV_QTY +}; + +enum CHAMPIONDEF_TYPE +{ + CHAMPIONDEF_CHAMPIONID, ///< Champion ID: _iChampion. + CHAMPIONDEF_DEFNAME, ///< Champion's DEFNAME. + CHAMPIONDEF_LEVELMAX, ///< Max Level for this champion. + CHAMPIONDEF_NAME, ///< Champion name: m_sName. + CHAMPIONDEF_NPCGROUP, ///< Monster level / group: _iSpawn[n][n]. + CHAMPIONDEF_SPAWNSMAX, ///< Total amount of monsters: _iSpawnsMax. + CHAMPIONDEF_QTY +}; + +enum CANDLEDELREASON_TYPE +{ + CANDLEDELREASON_TIMEOUT, + CANDLEDELREASON_COMMAND, + CANDLEDELREASON_CLEAR, + CANDLEDELREASON_QTY +}; + +class CObjBase; +class CItem; +class CChar; + /** * @brief This class manages a CItem making it to work as a Champion. */ @@ -56,7 +119,10 @@ class CCChampion : public CComponent idSpawn _spawnGroupsId; ///< Defining how many uchar (or levels) this Champion has and the group of monsters for each level. CResourceIDBase _idSpawn; ///< legacy more1=ID of the Object to Spawn. CREID_TYPE _idChampion; ///< Boss id - bool _fChampionSummoned; ///< True if the champion's boss has been summoned already (wether it was killed or not). + CUID m_ChampionSummoned; ///< True if the champion's boss has been summoned already (wether it was killed or not). + + std::vector _MonstersList; + std::vector _CandleList; // Ingame Spawn behaviour. bool _fActive; ///< Champion status @@ -88,11 +154,15 @@ class CCChampion : public CComponent ushort _iSpawnsNextRed; ushort _iSpawnsNextWhite; ///< Total monsters needed to the next White candle ( m_iSpawnsNextRed / 5 ). ushort _iDeathCount; ///< Keeping track of how many monsters died already. - uchar _iCandlesNextRed; ///< Required amount of White candles to get the next Red one. uchar _iCandlesNextLevel; ///< Required amount of Red candles to reach the next level. std::vector _pRedCandles; ///< Storing the Red Candles, reaching a certain amount of these increases the Champion's Level (refer to _iLevel). std::vector _pWhiteCandles; ///< Storing the White Candles (sublevel): 4 white candles = 1 red candle (Default max = 4). + /** + * @brief Calculates monsters and candles needed per level and saves them to _MonsterList and _CandleList to avoid unnecessary loops. + */ + void InitializeLists(); + public: //static const char *m_sClassName; ///< Class definition @@ -110,13 +180,17 @@ class CCChampion : public CComponent * Calls SetLevel(1), which automatically set the relevant data to work from now. * SetTimeoutS( 60 * 10 ) // 10 minutes. */ - void Start(); + void Start(CChar* pChar = nullptr); /** * @brief Stop the champion, cleaning everything. * * Clean killed monsters, level, spawned monsters and required monsters per both next White candle and Red candle. */ - void Stop(); + void Stop(CChar* pChar = nullptr); + /** + * @brief Just cleaning everything. + */ + void ClearData(); /** * @brief Everything is done, call Stop. * @@ -130,7 +204,7 @@ class CCChampion : public CComponent * if m_iSpawnsNextWhite < 1 calls AddWhiteCandle * otherwise sustracts one monsters from m_iSpawnsNextWhite */ - void OnKill(); + void OnKill(const CUID& uid = CUID()); /** * @brief Spawns a new character * @@ -158,11 +232,11 @@ class CCChampion : public CComponent /** * @brief Deleting last added White Candle. */ - void DelWhiteCandle(); + void DelWhiteCandle(CANDLEDELREASON_TYPE reason = CANDLEDELREASON_CLEAR); /** * @brief Deleting last added Red Candle.d. */ - void DelRedCandle(); + void DelRedCandle(CANDLEDELREASON_TYPE reason = CANDLEDELREASON_CLEAR); /** * @brief Clear all White Candles. */ @@ -194,7 +268,7 @@ class CCChampion : public CComponent * @param iMonsters total amount of monsters of the champion. * @return amount of killed monsters needed to reach the next level. */ - uint16 GetMonstersPerLevel(uint16 iMonsters) const; + uint16 GetMonstersCount(); /** * @brief Retrieves how much Red Candles are needed to reach next Champion's Level. @@ -205,7 +279,7 @@ class CCChampion : public CComponent * Value stored in morex (m_itNormal.m_morep.m_x). * @return how much red candles are needed to reach the next level */ - byte GetCandlesPerLevel(byte iLevel = 255) const; + uchar GetCandlesCount(); /** * @brief Set a new Level for this champion. * diff --git a/src/game/components/CCSpawn.cpp b/src/game/components/CCSpawn.cpp index 52a8ad6a7..b4e1f8ec3 100644 --- a/src/game/components/CCSpawn.cpp +++ b/src/game/components/CCSpawn.cpp @@ -585,6 +585,7 @@ void CCSpawn::AddObj(const CUID& uid) } bool fIsSpawnChar = (pSpawnItem->IsType(IT_SPAWN_CHAR) || pSpawnItem->IsType(IT_SPAWN_CHAMPION)); + bool fIsSpawnChampion = pSpawnItem->IsType(IT_SPAWN_CHAMPION); if (!g_Serv.IsLoading()) { @@ -628,7 +629,7 @@ void CCSpawn::AddObj(const CUID& uid) pChar->m_pNPC->m_Home_Dist_Wander = (word)_iMaxDist; } - if (GetCurrentSpawned() +1 >= GetAmount()) //Adding one because the item is not yet added at this moment + if (GetCurrentSpawned() +1 >= GetAmount() && !fIsSpawnChampion) //Adding one because the item is not yet added at this moment { pSpawnItem->_SetTimeoutS(-1); } @@ -1221,12 +1222,16 @@ bool CCSpawn::r_Verb(CScript & s, CTextConsole * pSrc) OnTickComponent(); return true; case ISPV_START: - pItem->SetTimeout(0); - return true; + { + pItem->SetTimeout(0); + return true; + } case ISPV_STOP: - KillChildren(); - pItem->SetTimeout(-1); - return true; + { + KillChildren(); + pItem->SetTimeout(-1); + return true; + } default: break; } diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index b054bd392..3aefb6a4a 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -44,21 +44,24 @@ lpctstr const CItem::sm_szTrigName[ITRIG_QTY+1] = // static { "@AAAUNUSED", - "@AddRedCandle", "@AddObj", // For t_spawn when obj is add to list - "@AddWhiteCandle", + "@AddRedCandle", + "@AddWhiteCandle", "@AfterClick", "@Buy", "@CarveCorpse", //I am a corpse and i am going to be carved. "@Click", "@ClientTooltip", // Sending tooltip to a client "@ClientTooltip_AfterDefault", + "@Complete", "@ContextMenuRequest", "@ContextMenuSelect", "@Create", "@DAMAGE", // I have been damaged in some way "@DCLICK", // I have been dclicked. "@DelObj", // For t_spawn when obj is remove from list + "@DelRedCandle", + "@DelWhiteCandle", "@Destroy", //+I am nearly destroyed "@DropOn_Char", // I have been dropped on this char "@DropOn_Ground", // I have been dropped on the ground here @@ -70,6 +73,7 @@ lpctstr const CItem::sm_szTrigName[ITRIG_QTY+1] = // static "@EQUIPTEST", "@GetHit", "@Hit", + "@Level", "@MemoryEquip", "@PICKUP_GROUND", // I was picked up off the ground. "@PICKUP_PACK", // picked up from inside some container. @@ -90,6 +94,7 @@ lpctstr const CItem::sm_szTrigName[ITRIG_QTY+1] = // static "@SpellEffect", // cast some spell on me. "@Start", "@STEP", // I have been walked on. + "@Stop", "@TARGON_CANCEL", "@TARGON_CHAR", "@TARGON_GROUND", diff --git a/src/tables/triggers.tbl b/src/tables/triggers.tbl index 080a9123e..63846284f 100644 --- a/src/tables/triggers.tbl +++ b/src/tables/triggers.tbl @@ -7,8 +7,8 @@ ADD(AAAUNUSED) ADD(ABORT) ADD(ADDMULTI) -ADD(ADDREDCANDLE) ADD(ADDOBJ) +ADD(ADDREDCANDLE) ADD(ADDWHITECANDLE) ADD(AFKMODE) ADD(AFTERCLICK) @@ -32,7 +32,8 @@ ADD(CLIPERIODIC) ADD(COMBATADD) ADD(COMBATDELETE) ADD(COMBATEND) -ADD(COMBATSTART) +ADD(COMBATSTART) +ADD(COMPLETE) ADD(CONTEXTMENUREQUEST) ADD(CONTEXTMENUSELECT) ADD(CREATE) @@ -42,8 +43,10 @@ ADD(DAMAGE) ADD(DCLICK) ADD(DEATH) ADD(DEATHCORPSE) -ADD(DELMULTI) -ADD(DELOBJ) +ADD(DELMULTI) +ADD(DELOBJ) +ADD(DELREDCANDLE) +ADD(DELWHITECANDLE) ADD(DESTROY) ADD(DISMOUNT) ADD(DRINK) @@ -120,7 +123,8 @@ ADD(ITEMUNEQUIP) ADD(JAILED) ADD(KARMACHANGE) ADD(KILL) -ADD(MEMORYEQUIP) +ADD(MEMORYEQUIP) +ADD(LEVEL) ADD(LOAD) ADD(LOGIN) ADD(LOGOUT) @@ -213,7 +217,8 @@ ADD(START) ADD(STATCHANGE) ADD(STEP) ADD(STEPSTEALTH) -ADD(STROKE) +ADD(STROKE) +ADD(STOP) ADD(SUCCESS) ADD(TARGETCANCEL) ADD(TARGON_CANCEL) From 5d92edc75268bfc70b6a5ff83f46c5fcf24be7b8 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sat, 20 Apr 2024 18:18:10 +0100 Subject: [PATCH 63/90] Fixed forgotten callstack names. --- src/game/components/CCChampion.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/components/CCChampion.cpp b/src/game/components/CCChampion.cpp index c123fc521..be098b3f4 100644 --- a/src/game/components/CCChampion.cpp +++ b/src/game/components/CCChampion.cpp @@ -618,7 +618,7 @@ void CCChampion::InitializeLists() // DONE uchar CCChampion::GetCandlesCount() { - ADDTOCALLSTACK("CCChampion::GetCandlesPerLevel"); + ADDTOCALLSTACK("CCChampion::GetCandlesCount"); if (_iLevel == UCHAR_MAX) return 16; @@ -641,7 +641,7 @@ uchar CCChampion::GetCandlesCount() // DONE ushort CCChampion::GetMonstersCount() { - ADDTOCALLSTACK("CCChampion::GetMonstersPerLevel"); + ADDTOCALLSTACK("CCChampion::GetMonstersCount"); if (_iLevel < 1) // Should never happen but put here to make sure avoid invalid index. _iLevel = 1; From 6cf816b261015e85065b8650f3e9d9c2e6a57ab7 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Sun, 21 Apr 2024 17:23:58 +0100 Subject: [PATCH 64/90] T_MULTI_ADDON Fix - Fixed: Script multis move 1 block north when their type set as t_multi_addon. (Issue: #1238) --- Changelog.txt | 5 ++++- src/game/items/CItemMulti.cpp | 5 ++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 39a575727..a1de20397 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3692,4 +3692,7 @@ Additionally, the problem of zig-zag issue following in the South direction has - I: Champion spawner uid. - SRC: The player that stopped spawner. Returns: - - 1: Cancel stopping action. \ No newline at end of file + - 1: Cancel stopping action. + +21-04-2024, xwerswoodx +- Fixed: Script multis move 1 block north when their type set as t_multi_addon. (Issue: #1238) \ No newline at end of file diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index 90b3da0b8..6c4dfd8a2 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -230,7 +230,7 @@ bool CItemMulti::MultiRealizeRegion() } else if (IsType(IT_MULTI) || IsType(IT_MULTI_CUSTOM)) { - if (Multi_GetSign()->IsType(IT_SIGN_GUMP)) + if (CItemBase::IsID_House(GetID())) dwFlags |= REGION_FLAG_HOUSE; } else @@ -3243,8 +3243,7 @@ CItem *CItemMulti::Multi_Create(CChar *pChar, const CItemBase * pItemDef, CPoint * let's remove that difference. * Note: this fix is added here, before GM check, because otherwise they will place houses on wrong position. */ - if (pMultiDef && (CItemBase::IsID_Multi(pItemDef->GetID()) || pItemDef->IsType(IT_MULTI_ADDON))) - // or is this happening only for houses? if (CItemBase::IsID_House(pItemDef->GetID())) + if (pMultiDef && CItemBase::IsID_Multi(pItemDef->GetID())) // It only happens for real multis that coming from mul/uop files. { pt.m_y -= (short)(pMultiDef->m_rect.m_bottom - 1); } From 665ded8e426a37d29a5f3ce40b05b46ec35e91e2 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Mon, 22 Apr 2024 01:29:10 +0100 Subject: [PATCH 65/90] ADDCOMPONENT - Fixed: ADDCOMPONENT command was added as ADDCOMP for houses. --- Changelog.txt | 3 ++- src/game/items/CItemMulti.cpp | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index a1de20397..40985a59d 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3695,4 +3695,5 @@ Additionally, the problem of zig-zag issue following in the South direction has - 1: Cancel stopping action. 21-04-2024, xwerswoodx -- Fixed: Script multis move 1 block north when their type set as t_multi_addon. (Issue: #1238) \ No newline at end of file +- Fixed: Script multis move 1 block north when their type set as t_multi_addon. (Issue: #1238) +- Fixed: ADDCOMPONENT command was added as ADDCOMP for houses. \ No newline at end of file diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index 6c4dfd8a2..83856c55f 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -2418,7 +2418,8 @@ enum SHL_TYPE SHL_ADDACCESS, SHL_ADDADDON, SHL_ADDBAN, - SHL_ADDCOMP, + SHL_ADDCOMP, //Kept for backward compatibility. + SHL_ADDCOMPONENT, //It was defined as ADDCOMPONENT in changelog. SHL_ADDCOOWNER, SHL_ADDFRIEND, SHL_ADDKEY, @@ -2469,6 +2470,7 @@ const lpctstr CItemMulti::sm_szLoadKeys[SHL_QTY + 1] = "ADDADDON", "ADDBAN", "ADDCOMP", + "ADDCOMPONENT", // Added because it's defined as ADDCOMPONENT in changelog, but added as ADDCOMP "ADDCOOWNER", "ADDFRIEND", "ADDKEY", @@ -3113,6 +3115,7 @@ bool CItemMulti::r_LoadVal(CScript & s) // House Storage case SHL_ADDCOMP: + case SHL_ADDCOMPONENT: { AddComponent(CUID(s.GetArgDWVal())); break; From 995161215a859dd26e83e8fe4f8893f6eb98dd87 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Mon, 22 Apr 2024 18:59:15 +0100 Subject: [PATCH 66/90] Some Review Changes --- Changelog.txt | 12 +++++++----- src/common/resource/CResourceHolder.cpp | 22 ++++++++++++++++++++++ src/common/resource/CResourceHolder.h | 1 + src/common/resource/sections/CSpellDef.cpp | 10 +++++----- src/common/resource/sections/CSpellDef.h | 10 +++++----- src/game/chars/CChar.cpp | 2 +- src/game/chars/CChar.h | 9 ++++++++- src/game/chars/CCharUse.cpp | 2 +- src/game/items/CItem.cpp | 6 +++--- 9 files changed, 53 insertions(+), 21 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 40985a59d..4a2cfdd33 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3464,8 +3464,8 @@ Additionally, the problem of zig-zag issue following in the South direction has - Added: New Layer LAYER_STORAGE (80) to let scripters create their own storage system. (Issue: #1209) Only t_container and t_container_locked can be equipped to this layer. - Changed: Decay time removed from spawned items, as Sphere gives tons of invalid link errors when items decayed. (Issue: #1218) -- Added: New spellflag SPELLFLAG_ASYNC (0100000000) to randomize field timers like old sphere versions. (Issue: #1169) - SPELLFLAG_ASYNC should be added to defs. +- Added: New spellflag SPELLFLAG_FIELD_RANDOMDECAY (0100000000) to randomize field timers like old sphere versions. (Issue: #1169) + SPELLFLAG_FIELD_RANDOMDECAY should be added to defs. - Added: New spellflag SPELLFLAG_TARG_ONLYSELF (0200000000) to make spell only be used on character himself. (Issue: #1171) SPELLFLAG_TARG_ONLYSELF should be added to defs. //magery_9 "You can only use this spell on yourself." could be added to defmessages. @@ -3542,6 +3542,8 @@ Additionally, the problem of zig-zag issue following in the South direction has 02-04-2024, xwerswoodx - Changed: dword CAN flags changed with uint64 to increase limits. + - CAN flag limit increased from 0xFFFF FFFF (dword/uint max) to 0xFFFF FFFF FFFF FFFF (uint64 max) + - But as sphere evaluation expressions (eval, hval etc.) supports int64 instead of uint64, avoid using any flag value more than 2 << 47 (0x1 0000 0000 0000). - Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/channels/354358315373035542/483721253773901824/1224030729906815077) 03-04-2024, xwerswoodx @@ -3623,7 +3625,6 @@ Additionally, the problem of zig-zag issue following in the South direction has - ARGN2: The type(s) of damage being applied. - ARGN3: Hits will be fixed to this amount after the hit if the value is greaten than it (default: 0) - LOCAL.ITEMDAMAGECHANCE: Sets the damage chance for the hitted part of the body. (Armor or shield, if any) (Default: 25%) - - LOCAL.DAMAGEPERCENTPHYSICAL: The amount in % of the physical damage received, only set if Elemental Engine is enabled. [Read Only] - LOCAL.DAMAGEPERCENTPHYSICAL: The amount in % of the physical damage received, only set if Elemental Engine is enabled. [Read Only] - LOCAL.DAMAGEPERCENTFIRE: The amount in % of the fire damage received, only set if Elemental Engine is enabled. [Read Only] - LOCAL.DAMAGEPERCENTCOLD: The amount in % of the cold damage received, only set if Elemental Engine is enabled. [Read Only] @@ -3641,10 +3642,11 @@ Additionally, the problem of zig-zag issue following in the South direction has For example, if you use .tag.test 100 returns 100 returns 064 -- Merged: raydienull's LAYER_STABLE build merged, but LAYER_AUCTION keep same while LAYER_STABLE added as a new layer. (PR: #1201) +- Merged: raydienull's LAYER_STABLE (81) build merged, but LAYER_AUCTION keep same while LAYER_STABLE added as a new layer. (PR: #1201) - Fixed: raydienull's LAYER_STABLE follower triggers isn't called while taking pet out of stable. - Fixed: raydienull's LAYER_STABLE doesn't work with the new follower system. - Removed: Unnecessary LINK == PLAYER checks as figurines will be stocked on the owned player. +- LAYER_STABLE layer number is 81. 18-04-2024, xwerswoodx - Fixed: Setting GMs dispid to c_man_gm in-game, prevents GMs to use in-game commands. @@ -3696,4 +3698,4 @@ Additionally, the problem of zig-zag issue following in the South direction has 21-04-2024, xwerswoodx - Fixed: Script multis move 1 block north when their type set as t_multi_addon. (Issue: #1238) -- Fixed: ADDCOMPONENT command was added as ADDCOMP for houses. \ No newline at end of file +- Fixed: ADDCOMPONENT command was added as ADDCOMP for houses. (Issue: #1239) \ No newline at end of file diff --git a/src/common/resource/CResourceHolder.cpp b/src/common/resource/CResourceHolder.cpp index 43072b1b1..ce4ccbf13 100644 --- a/src/common/resource/CResourceHolder.cpp +++ b/src/common/resource/CResourceHolder.cpp @@ -282,6 +282,28 @@ bool CResourceHolder::LoadResourceSection( CScript * pScript ) //********************************************************* // Resource Section Definitions +lpctstr CResourceHolder::ResourceGetName(const CResourceIDBase& rid, RES_TYPE iExpectedType) +{ + ADDTOCALLSTACK("CResourceHolder::ResourceGetNameFromMore"); + CResourceID ridValid = CResourceID(iExpectedType, 0); + if (!rid.IsValidResource()) + { + if (rid.GetResIndex() != 0) + { + g_Log.EventError("Expected a valid resource. Ignoring it/Converting it to an empty one.\n"); + } + } + else if (rid.GetResType() != iExpectedType) + { + g_Log.EventWarn("Expected resource with type %d, got %d. Ignoring it/Converting it to an empty one.\n", iExpectedType, rid.GetResType()); + } + else + { + ridValid = rid; + } + return g_Cfg.ResourceGetName(ridValid); // Even it's 0, we should return it's name, as it can be mr_nothing. +} + lpctstr CResourceHolder::ResourceGetName( const CResourceID& rid ) const { ADDTOCALLSTACK("CResourceHolder::ResourceGetName"); diff --git a/src/common/resource/CResourceHolder.h b/src/common/resource/CResourceHolder.h index c40d5dad8..73575da02 100644 --- a/src/common/resource/CResourceHolder.h +++ b/src/common/resource/CResourceHolder.h @@ -41,6 +41,7 @@ class CResourceHolder : public CScriptObj static lpctstr GetResourceBlockName( RES_TYPE restype ); lpctstr GetName() const; lpctstr ResourceGetName( const CResourceID& rid ) const; + static lpctstr ResourceGetName(const CResourceIDBase& rid, const RES_TYPE iExpectedType); CResourceScript * GetResourceFile( size_t i ); CResourceID ResourceGetID_Advance( RES_TYPE restype, lpctstr &pszName, word wPage = 0 ); // this moves forward (changes!) the ptcName pointer! CResourceID ResourceGetID( RES_TYPE restype, lpctstr ptcName, word wPage = 0 ); diff --git a/src/common/resource/sections/CSpellDef.cpp b/src/common/resource/sections/CSpellDef.cpp index 9087fc192..bb5243e22 100644 --- a/src/common/resource/sections/CSpellDef.cpp +++ b/src/common/resource/sections/CSpellDef.cpp @@ -72,7 +72,7 @@ lpctstr const CSpellDef::sm_szLoadKeys[SPC_QTY+1] = CSpellDef::CSpellDef( SPELL_TYPE id ) : CResourceLink( CResourceID( RES_SPELL, id )) { - m_dwFlags = SPELLFLAG_DISABLED; + m_uiFlags = SPELLFLAG_DISABLED; m_dwGroup = 0; m_sound = 0; m_idSpell = ITEMID_NOTHING; @@ -116,10 +116,10 @@ bool CSpellDef::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc sVal.FormatVal( m_idEffect ); break; case SPC_FLAGS: - sVal.FormatULLVal( m_dwFlags ); + sVal.FormatULLVal( m_uiFlags ); break; case SPC_GROUP: - sVal.FormatULLVal( m_dwGroup ); + sVal.FormatDWVal( m_dwGroup ); break; case SPC_INTERRUPT: sVal = m_Interrupt.Write(); @@ -228,10 +228,10 @@ bool CSpellDef::r_LoadVal( CScript &s ) m_idEffect = (ITEMID_TYPE)(g_Cfg.ResourceGetIndexType( RES_ITEMDEF, s.GetArgStr())); break; case SPC_FLAGS: - m_dwFlags = s.GetArgULLVal(); + m_uiFlags = s.GetArgULLVal(); break; case SPC_GROUP: - m_dwGroup = s.GetArgULLVal(); + m_dwGroup = s.GetArgDWVal(); break; case SPC_INTERRUPT: m_Interrupt.Load( s.GetArgRaw()); diff --git a/src/common/resource/sections/CSpellDef.h b/src/common/resource/sections/CSpellDef.h index e47c2e52a..c786623fc 100644 --- a/src/common/resource/sections/CSpellDef.h +++ b/src/common/resource/sections/CSpellDef.h @@ -42,8 +42,8 @@ enum SPTRIG_TYPE class CSpellDef : public CResourceLink { private: - uint64 m_dwFlags; // Spell Flags. - uint64 m_dwGroup; // Spell group. + uint64 m_uiFlags; // Spell Flags. + dword m_dwGroup; // Spell group. CSString m_sName; // Spell name @@ -71,7 +71,7 @@ class CSpellDef : public CResourceLink public: /** - * @fn bool CSpellDef::IsSpellType( uint64 wFlags ) const + * @fn bool CSpellDef::IsSpellType( uint64 uiFlags ) const * * @brief Check if this Spell has the given flags. * @@ -79,9 +79,9 @@ class CSpellDef : public CResourceLink * * @return true if match, false if not. */ - bool IsSpellType( uint64 wFlags ) const + bool IsSpellType( uint64 uiFlags ) const { - return (( m_dwFlags & wFlags ) ? true : false ); + return (( m_uiFlags & uiFlags ) ? true : false ); } public: diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index 06a0a91ee..b3f04db06 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -5079,7 +5079,7 @@ bool CChar::CanConsume(CItem* pItem, word iQty) return false; } -bool CChar::ConsumeAmount(CItem* pItem, word iQty) +bool CChar::ConsumeFromPack(CItem* pItem, word iQty) { ADDTOCALLSTACK("CChar::ConsumeFromPack"); diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index 0c410641e..b199a6f17 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -837,8 +837,15 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; void ChangeExperience(llong delta = 0, CChar *pCharDead = nullptr); uint GetSkillTotal(int what = 0, bool how = true); + /* + * @brief Check the pItem stack has amount more than iQty. If not, searches character's backpack to check if character has enough item to consume. + */ bool CanConsume(CItem* pItem, word iQty); - bool ConsumeAmount(CItem* pItem, word iQty); + + /* + * @brief Consumes iQty amount of the item from your stack. If the stack has less amount than iQty, searches character's backpack to consume from other stacks. + */ + bool ConsumeFromPack(CItem* pItem, word iQty); // skills and actions. ------------------------------------------- static bool IsSkillBase( SKILL_TYPE skill ) noexcept; diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 02f14577e..dab7eeaf3 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -1089,7 +1089,7 @@ void CChar::Use_Drink( CItem * pItem ) //Sound(sm_DrinkSounds[Calc_GetRandVal(ARRAY_COUNT(sm_DrinkSounds))]); UpdateAnimate(ANIM_EAT); if (wConsume > 0) //if ARGN2 > 0, consume. - ConsumeAmount(pItem, wConsume); + ConsumeFromPack(pItem, wConsume); // Create the empty bottle ? if (idbottle != ITEMID_NOTHING) diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 3aefb6a4a..c80bed250 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2278,14 +2278,14 @@ void CItem::r_WriteMore1(CSString & sVal) case IT_GRASS: case IT_ROCK: case IT_WATER: - sVal = g_Cfg.ResourceGetName(CResourceID(RES_REGIONRESOURCE, m_itResource.m_ridRes.GetResIndex())); //Changed to fix issue but it is not implemented. + sVal = g_Cfg.ResourceGetName(m_itResource.m_ridRes, RES_REGIONRESOURCE); //Changed to fix issue but it is not implemented. return; case IT_FRUIT: case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: - sVal = g_Cfg.ResourceGetName(CResourceID(RES_ITEMDEF, m_itFood.m_ridCook.GetResIndex())); + sVal = g_Cfg.ResourceGetName(m_itFood.m_ridCook, RES_ITEMDEF); return; case IT_TRAP: @@ -2338,7 +2338,7 @@ void CItem::r_WriteMore2( CSString & sVal ) case IT_CROPS: case IT_FOLIAGE: - sVal = g_Cfg.ResourceGetName(CResourceID(RES_ITEMDEF, m_itCrop.m_ridFruitOverride.GetResIndex())); + sVal = g_Cfg.ResourceGetName(m_itCrop.m_ridFruitOverride, RES_ITEMDEF); return; case IT_LEATHER: From 098b10e2c9d2fd3e1dccc65f34b17fd174835e69 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Mon, 22 Apr 2024 20:42:53 +0100 Subject: [PATCH 67/90] Reactivated Hardcoded Fishing Skill - Changed: Re-activated 56b style hardcoded fishing system, as I don't know why it's deactivated as softcoded system too bad and broken. - Fishing skill in default script pack should updated. - Delay should set to 2.5-3.0 - All softcoded system should removed. - If anyone want to code their own fishing system, they can use SKF_SCRIPTED. --- Changelog.txt | 9 +- src/game/chars/CChar.h | 2 +- src/game/chars/CCharSkill.cpp | 101 +++++++++++++---------- src/game/items/CItemBase.cpp | 2 +- src/game/uo_files/uofiles_enums_itemid.h | 48 ++++++++++- 5 files changed, 114 insertions(+), 48 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 4a2cfdd33..ecbba007b 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3698,4 +3698,11 @@ Additionally, the problem of zig-zag issue following in the South direction has 21-04-2024, xwerswoodx - Fixed: Script multis move 1 block north when their type set as t_multi_addon. (Issue: #1238) -- Fixed: ADDCOMPONENT command was added as ADDCOMP for houses. (Issue: #1239) \ No newline at end of file +- Fixed: ADDCOMPONENT command was added as ADDCOMP for houses. (Issue: #1239) + +22-04-2024, xwerswoodx +- Changed: Re-activated 56b style hardcoded fishing system, as I don't know why it's deactivated as softcoded system too bad and broken. + - Fishing skill in default script pack should updated. + - Delay should set to 2.5-3.0 + - All softcoded system should removed. + - If anyone want to code their own fishing system, they can use SKF_SCRIPTED. \ No newline at end of file diff --git a/src/game/chars/CChar.h b/src/game/chars/CChar.h index b199a6f17..36b96ea07 100644 --- a/src/game/chars/CChar.h +++ b/src/game/chars/CChar.h @@ -882,7 +882,7 @@ public: void StatFlag_Mod(uint64 uiStatFlag, bool fMod) noexcept; bool Skill_Wait( SKILL_TYPE skilltry ); bool Skill_Start( SKILL_TYPE skill, int iDifficultyIncrease = 0 ); // calc skill progress. void Skill_Fail( bool fCancel = false ); - int Skill_Stroke( bool fResource); // Strokes in crafting skills, calling for SkillStroke trig + int Skill_Stroke(); // Strokes in crafting skills, calling for SkillStroke trig ANIM_TYPE Skill_GetAnim( SKILL_TYPE skill); SOUND_TYPE Skill_GetSound( SKILL_TYPE skill); int Skill_Stage( SKTRIG_TYPE stage ); diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index cc89208c6..fc8c899c5 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -1345,7 +1345,7 @@ int CChar::Skill_Tracking( SKTRIG_TYPE stage ) if ( stage == SKTRIG_STROKE ) { - if ( Skill_Stroke(false) == -SKTRIG_ABORT ) + if ( Skill_Stroke() == -SKTRIG_ABORT ) return -SKTRIG_ABORT; //Use the maximum distance stored in m_AtTracking.m_dwDistMax(ACTARG2), calculated in Cmd_Skill_Tracking, when continuing to track the creature. @@ -1536,24 +1536,33 @@ int CChar::Skill_Fishing( SKTRIG_TYPE stage ) if ( stage == SKTRIG_START ) { - m_atResource.m_dwStrokeCount = 1; + CItem* pSplash = CItem::CreateBase(ITEMID_FX_SPLASH); + if (pSplash) + { + pSplash->SetType(IT_WATER_WASH); + pSplash->MoveToDecay(m_Act_p, 1 * MSECS_PER_SEC); + } + m_atResource.m_dwStrokeCount = Calc_GetRandVal(2) + 1; m_Act_UID = pResBit->GetUID(); return Skill_NaturalResource_Setup(pResBit); // How difficult? 1-1000 } - CItem *pItem = Skill_NaturalResource_Create(pResBit, SKILL_FISHING); - if ( !pItem ) - { - SysMessageDefault(DEFMSG_FISHING_2); - return -SKTRIG_FAIL; - } - - SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_FISHING_SUCCESS), pItem->GetName()); - if ( m_atResource.m_dwBounceItem ) - ItemBounce(pItem, false); - else - pItem->MoveToCheck(GetTopPoint(), this); // put at my feet. - return 0; + if (stage == SKTRIG_SUCCESS) + { + CItem* pItem = Skill_NaturalResource_Create(pResBit, SKILL_FISHING); + if (!pItem) + { + SysMessageDefault(DEFMSG_FISHING_2); + return -SKTRIG_FAIL; + } + SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_FISHING_SUCCESS), pItem->GetName()); + if (m_atResource.m_dwBounceItem) + ItemBounce(pItem, false); + else + pItem->MoveToCheck(GetTopPoint(), this); // put at my feet. + return 0; + } + return -SKTRIG_QTY; } int CChar::Skill_Lumberjack( SKTRIG_TYPE stage ) @@ -3423,8 +3432,8 @@ ANIM_TYPE CChar::Skill_GetAnim( SKILL_TYPE skill ) { switch ( skill ) { - /*case SKILL_FISHING: // softcoded - return ANIM_ATTACK_2H_BASH;*/ + case SKILL_FISHING: + return ANIM_ATTACK_2H_BASH; case SKILL_BLACKSMITHING: return ANIM_ATTACK_1H_SLASH; case SKILL_MINING: @@ -3440,8 +3449,8 @@ SOUND_TYPE CChar::Skill_GetSound( SKILL_TYPE skill ) { switch ( skill ) { - /*case SKILL_FISHING: // softcoded - return 0x364;*/ + case SKILL_FISHING: + return 0x364; case SKILL_ALCHEMY: return 0x242; case SKILL_TAILORING: @@ -3464,14 +3473,16 @@ SOUND_TYPE CChar::Skill_GetSound( SKILL_TYPE skill ) } } -int CChar::Skill_Stroke( bool fResource ) +int CChar::Skill_Stroke() { - // fResource means decreasing m_atResource.m_dwStrokeCount instead of m_atCreate.m_dwStrokeCount SKILL_TYPE skill = Skill_GetActive(); SOUND_TYPE sound = SOUND_NONE; int64 delay = Skill_GetTimeout(); ANIM_TYPE anim = ANIM_WALK_UNARM; - if ( m_atCreate.m_dwStrokeCount > 1 ) + // fResource means decreasing m_atResource.m_dwStrokeCount instead of m_atCreate.m_dwStrokeCount + bool fResource = g_Cfg.IsSkillFlag(skill, SKF_GATHER) ? true : false; + uint uiStroke = (fResource ? m_atResource.m_dwStrokeCount : m_atCreate.m_dwStrokeCount); + if (uiStroke >= 1) { if ( !g_Cfg.IsSkillFlag(skill, SKF_NOSFX) ) sound = Skill_GetSound(skill); @@ -3487,10 +3498,7 @@ int CChar::Skill_Stroke( bool fResource ) args.m_VarsLocal.SetNum("Delay", delay); args.m_VarsLocal.SetNum("Anim", anim); args.m_iN1 = 1; //UpdateDir() ? - if ( fResource ) - args.m_VarsLocal.SetNum("Strokes", m_atResource.m_dwStrokeCount); - else - args.m_VarsLocal.SetNum("Strokes", m_atCreate.m_dwStrokeCount); + args.m_VarsLocal.SetNum("Strokes", uiStroke); if ( OnTrigger(CTRIG_SkillStroke, this, &args) == TRIGRET_RET_TRUE ) return -SKTRIG_ABORT; @@ -3514,6 +3522,16 @@ int CChar::Skill_Stroke( bool fResource ) if ( anim ) UpdateAnimate(anim); // keep trying and updating the animation + if (skill == SKILL_FISHING) + { + CItem* pSplash = CItem::CreateBase(ITEMID_FX_SPLASH); + if (pSplash) + { + pSplash->SetType(IT_WATER_WASH); + pSplash->MoveToDecay(m_Act_p, 1 * MSECS_PER_SEC); + } + } + if ( fResource ) { if ( m_atResource.m_dwStrokeCount ) @@ -3540,24 +3558,19 @@ int CChar::Skill_Stroke( bool fResource ) int CChar::Skill_Stage( SKTRIG_TYPE stage ) { ADDTOCALLSTACK("CChar::Skill_Stage"); - if ( stage == SKTRIG_STROKE ) - { - if ( g_Cfg.IsSkillFlag(Skill_GetActive(), SKF_CRAFT) ) - return Skill_Stroke(false); - - if ( g_Cfg.IsSkillFlag(Skill_GetActive(), SKF_GATHER) ) - return Skill_Stroke(true); - } - - if ( g_Cfg.IsSkillFlag(Skill_GetActive(), SKF_SCRIPTED) ) - return Skill_Scripted(stage); - else if ( g_Cfg.IsSkillFlag(Skill_GetActive(), SKF_FIGHT) ) - return Skill_Fighting(stage); - else if ( g_Cfg.IsSkillFlag(Skill_GetActive(), SKF_MAGIC) ) - return Skill_Magery(stage); - /*else if ( g_Cfg.IsSkillFlag( Skill_GetActive(), SKF_CRAFT ) ) - return Skill_MakeItem(stage);*/ - else switch ( Skill_GetActive() ) + SKILL_TYPE skill = Skill_GetActive(); + if (skill == SKILL_NONE) + return 0; // If idling, return 0 before checks. + + if (g_Cfg.IsSkillFlag(skill, SKF_SCRIPTED)) + return Skill_Scripted(stage); + else if (g_Cfg.IsSkillFlag(skill, SKF_FIGHT)) + return Skill_Fighting(stage); + else if (g_Cfg.IsSkillFlag(skill, SKF_MAGIC)) + return Skill_Magery(stage); + else if (stage == SKTRIG_STROKE && (g_Cfg.IsSkillFlag(skill, SKF_CRAFT) || g_Cfg.IsSkillFlag(skill, SKF_GATHER))) + return Skill_Stroke(); + else switch (skill) { case SKILL_NONE: // idling. case SKILL_PARRYING: diff --git a/src/game/items/CItemBase.cpp b/src/game/items/CItemBase.cpp index 5d285aff9..700364b45 100644 --- a/src/game/items/CItemBase.cpp +++ b/src/game/items/CItemBase.cpp @@ -420,7 +420,7 @@ bool CItemBase::IsID_House(ITEMID_TYPE id) noexcept { // IT_MULTI // IT_MULTI_CUSTOM - return (((id >= ITEMID_HOUSE_SMALL_ST_PL) && (id <= ITEMID_HOUSE_SMALL_SHOP_MB)) || ((id >= ITEMID_HOUSEFOUNDATION_7x7) && (id <= ITEMID_HOUSEFOUNDATION_30x30))); + return (((id >= ITEMID_HOUSE_SMALL_ST_PL) && (id <= ITEMID_HOUSE_SMALL_SHOP_MB)) || ((id >= ITEMID_HOUSEFOUNDATION_7x7) && (id <= ITEMID_HOUSEFOUNDATION_32x32))); } int CItemBase::IsID_Door( ITEMID_TYPE id ) noexcept // static diff --git a/src/game/uo_files/uofiles_enums_itemid.h b/src/game/uo_files/uofiles_enums_itemid.h index 35307530a..be638b488 100644 --- a/src/game/uo_files/uofiles_enums_itemid.h +++ b/src/game/uo_files/uofiles_enums_itemid.h @@ -1182,7 +1182,53 @@ enum ITEMID_TYPE : uint32_t // InsideUO or UoFiddler are great for this stuff. ITEMID_HOUSEFOUNDATION_13x11, ITEMID_HOUSEFOUNDATION_13x12, ITEMID_HOUSEFOUNDATION_13x13, - ITEMID_HOUSEFOUNDATION_30x30 = ITEMID_MULTI + 0x147D, + ITEMID_HOUSEFOUNDATION_13x14, + ITEMID_HOUSEFOUNDATION_13x15, + ITEMID_HOUSEFOUNDATION_13x16, + ITEMID_HOUSEFOUNDATION_13x17, + ITEMID_HOUSEFOUNDATION_13x18, + ITEMID_HOUSEFOUNDATION_14x9 = ITEMID_MULTI + 0x1442, + ITEMID_HOUSEFOUNDATION_14x10, + ITEMID_HOUSEFOUNDATION_14x11, + ITEMID_HOUSEFOUNDATION_14x12, + ITEMID_HOUSEFOUNDATION_14x13, + ITEMID_HOUSEFOUNDATION_14x14, + ITEMID_HOUSEFOUNDATION_14x15, + ITEMID_HOUSEFOUNDATION_14x16, + ITEMID_HOUSEFOUNDATION_14x17, + ITEMID_HOUSEFOUNDATION_14x18, + ITEMID_HOUSEFOUNDATION_15x10 = ITEMID_MULTI + 0x144F, + ITEMID_HOUSEFOUNDATION_15x11, + ITEMID_HOUSEFOUNDATION_15x12, + ITEMID_HOUSEFOUNDATION_15x13, + ITEMID_HOUSEFOUNDATION_15x14, + ITEMID_HOUSEFOUNDATION_15x15, + ITEMID_HOUSEFOUNDATION_15x16, + ITEMID_HOUSEFOUNDATION_15x17, + ITEMID_HOUSEFOUNDATION_15x18, + ITEMID_HOUSEFOUNDATION_16x11 = ITEMID_MULTI + 0x145C, + ITEMID_HOUSEFOUNDATION_16x12, + ITEMID_HOUSEFOUNDATION_16x13, + ITEMID_HOUSEFOUNDATION_16x14, + ITEMID_HOUSEFOUNDATION_16x15, + ITEMID_HOUSEFOUNDATION_16x16, + ITEMID_HOUSEFOUNDATION_16x17, + ITEMID_HOUSEFOUNDATION_16x18, + ITEMID_HOUSEFOUNDATION_17x12 = ITEMID_MULTI + 0x1469, + ITEMID_HOUSEFOUNDATION_17x13, + ITEMID_HOUSEFOUNDATION_17x14, + ITEMID_HOUSEFOUNDATION_17x15, + ITEMID_HOUSEFOUNDATION_17x16, + ITEMID_HOUSEFOUNDATION_17x17, + ITEMID_HOUSEFOUNDATION_17x18, + ITEMID_HOUSEFOUNDATION_18x13 = ITEMID_MULTI + 0x1476, + ITEMID_HOUSEFOUNDATION_18x14, + ITEMID_HOUSEFOUNDATION_18x15, + ITEMID_HOUSEFOUNDATION_18x16, + ITEMID_HOUSEFOUNDATION_18x17, + ITEMID_HOUSEFOUNDATION_18x18, + ITEMID_HOUSEFOUNDATION_23x23, // ITEMID_MULTI + 0x147C + ITEMID_HOUSEFOUNDATION_32x32, // ITEMID_MULTI + 0x147D ITEMID_MULTISTAIRS_WOOD_SN = ITEMID_MULTI + 0x1db0, ITEMID_MULTISTAIRS_WOOD_WE, From 2d0446fd41115b7e1cc4643e6d4c238fdff2de5c Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 23 Apr 2024 00:09:11 +0100 Subject: [PATCH 68/90] Update CCharSkill.cpp --- src/game/chars/CCharSkill.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index fc8c899c5..1dd3fad8f 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -3559,9 +3559,6 @@ int CChar::Skill_Stage( SKTRIG_TYPE stage ) { ADDTOCALLSTACK("CChar::Skill_Stage"); SKILL_TYPE skill = Skill_GetActive(); - if (skill == SKILL_NONE) - return 0; // If idling, return 0 before checks. - if (g_Cfg.IsSkillFlag(skill, SKF_SCRIPTED)) return Skill_Scripted(stage); else if (g_Cfg.IsSkillFlag(skill, SKF_FIGHT)) From 3733da5922c4dac1c41d964e3a11178dcb83a20e Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 23 Apr 2024 04:41:24 +0100 Subject: [PATCH 69/90] EF_DAMAGETOOLS Update - Added: EF_DAMAGETOOLS flag implemented to the sphere. - Added LOCAL.ITEMDAMAGECHANCE to the @Success trigger for skills to decide damage chance for tools. (Default: 25) - Added LOCAL.ITEMDAMAGEAMOUNT to the @Success trigger for skills to decide damage amount. (Default: 1) - EF_DAMAGETOOLS only affects the skills with SKF_GATHER flag. --- Changelog.txt | 6 +++++- src/game/chars/CCharSkill.cpp | 24 ++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index ecbba007b..b462a6a70 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3705,4 +3705,8 @@ Additionally, the problem of zig-zag issue following in the South direction has - Fishing skill in default script pack should updated. - Delay should set to 2.5-3.0 - All softcoded system should removed. - - If anyone want to code their own fishing system, they can use SKF_SCRIPTED. \ No newline at end of file + - If anyone want to code their own fishing system, they can use SKF_SCRIPTED. +- Added: EF_DAMAGETOOLS flag implemented to the sphere. + - Added LOCAL.ITEMDAMAGECHANCE to the @Success trigger for skills to decide damage chance for tools. (Default: 25) + - Added LOCAL.ITEMDAMAGEAMOUNT to the @Success trigger for skills to decide damage amount. (Default: 1) + - EF_DAMAGETOOLS only affects the skills with SKF_GATHER flag. \ No newline at end of file diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index 1dd3fad8f..db00dd23c 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -3836,17 +3836,37 @@ int CChar::Skill_Done() if ( m_Act_Difficulty < 0 ) // was Bound to fail, but we had to wait for the timer anyhow. return -SKTRIG_FAIL; + CScriptTriggerArgs args; + args.m_VarsLocal.SetNumNew("ITEMDAMAGECHANCE", 25); + args.m_VarsLocal.SetNumNew("ITEMDAMAGEAMOUNT", 1); if ( IsTrigUsed(TRIGGER_SKILLSUCCESS) ) { - if ( Skill_OnCharTrigger(skill, CTRIG_SkillSuccess) == TRIGRET_RET_TRUE ) + if (Skill_OnCharTrigger(skill, CTRIG_SkillSuccess) == TRIGRET_RET_TRUE, &args) return -SKTRIG_ABORT; } if ( IsTrigUsed(TRIGGER_SUCCESS) ) { - if ( Skill_OnTrigger(skill, SKTRIG_SUCCESS) == TRIGRET_RET_TRUE ) + if (Skill_OnTrigger(skill, SKTRIG_SUCCESS) == TRIGRET_RET_TRUE, &args) return -SKTRIG_ABORT; } + int chance = minimum(maximum((int)args.m_VarsLocal.GetKeyNum("ITEMDAMAGECHANCE"), 0), 100); + if (IsSetEF(EF_DamageTools) && g_Cfg.IsSkillFlag(skill, SKF_GATHER) && chance > 0) + { + CItem* pTool = LayerFind(LAYER_HAND1); + if (!pTool || !pTool->IsTypeWeapon()) + pTool = LayerFind(LAYER_HAND2); + + if (pTool && pTool->IsTypeWeapon()) + { + if (Calc_GetRandVal(100) < chance) + { + int amount = maximum(minimum((int)args.m_VarsLocal.GetKeyNum("ITEMDAMAGEAMOUNT"), pTool->m_itWeapon.m_dwHitsCur), 0); + pTool->OnTakeDamage(amount, nullptr, DAMAGE_GOD); + } + } + } + // Success for the skill. iRet = Skill_Stage(SKTRIG_SUCCESS); if ( iRet < 0 ) From cc8ac5fc329a5c6730cc3d74048fe4f59a7f4f3f Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 23 Apr 2024 19:52:18 +0100 Subject: [PATCH 70/90] Review Changes --- src/common/resource/CResourceHolder.cpp | 2 +- src/game/CBase.h | 2 + src/game/items/CItem.cpp | 51 +++++++++++++++++++------ src/game/items/CItem.h | 3 ++ 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/common/resource/CResourceHolder.cpp b/src/common/resource/CResourceHolder.cpp index ce4ccbf13..1475a0128 100644 --- a/src/common/resource/CResourceHolder.cpp +++ b/src/common/resource/CResourceHolder.cpp @@ -284,7 +284,7 @@ bool CResourceHolder::LoadResourceSection( CScript * pScript ) lpctstr CResourceHolder::ResourceGetName(const CResourceIDBase& rid, RES_TYPE iExpectedType) { - ADDTOCALLSTACK("CResourceHolder::ResourceGetNameFromMore"); + ADDTOCALLSTACK("CResourceHolder::ResourceGetName"); CResourceID ridValid = CResourceID(iExpectedType, 0); if (!rid.IsValidResource()) { diff --git a/src/game/CBase.h b/src/game/CBase.h index a390f9dd4..c9d19647f 100644 --- a/src/game/CBase.h +++ b/src/game/CBase.h @@ -154,6 +154,8 @@ struct CBaseBaseDef : public CResourceLink, public CEntityProps #define CAN_I_DAMAGEABLE 0x2000000 // Display item health bar on HS clients >= 7.0.30.0 (MORE1L = cur hitpoints / MORE1H = max hitpoints) #define CAN_I_BLOCKLOS_HEIGHT 0x4000000 // blocks LOS without blocking walkchecks, but only if the item is too high for the viewer. #define CAN_I_EQUIPONCAST 0x8000000 // Allow items to stay equipped while EquippedCast disabled in sphere.ini. +// 0x10000000 // CAN_O_NOSLEEP +#define CAN_I_SCRIPTEDMORE 0x20000000 // This item doesn't use an hardcoded behavior, so its MORE value might be used for custom stuff. // (CItemBase) CanEquip specific defs. #define CAN_U_ALL 0x000 // Can be used by everyone. diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index c80bed250..ec874563f 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2278,14 +2278,14 @@ void CItem::r_WriteMore1(CSString & sVal) case IT_GRASS: case IT_ROCK: case IT_WATER: - sVal = g_Cfg.ResourceGetName(m_itResource.m_ridRes, RES_REGIONRESOURCE); //Changed to fix issue but it is not implemented. + sVal = ResourceGetName(m_itResource.m_ridRes, RES_REGIONRESOURCE, m_itNormal.m_more1); //Changed to fix issue but it is not implemented. return; case IT_FRUIT: case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: - sVal = g_Cfg.ResourceGetName(m_itFood.m_ridCook, RES_ITEMDEF); + sVal = ResourceGetName(m_itFood.m_ridCook, RES_ITEMDEF, m_itNormal.m_more1); return; case IT_TRAP: @@ -2297,21 +2297,21 @@ void CItem::r_WriteMore1(CSString & sVal) case IT_LOOM: case IT_ARCHERY_BUTTE: case IT_ITEM_STONE: - sVal = g_Cfg.ResourceGetName(CResourceID(RES_ITEMDEF, RES_GET_INDEX(m_itNormal.m_more1))); + sVal = ResourceGetName(CResourceID(RES_ITEMDEF, RES_GET_INDEX(m_itNormal.m_more1)), m_itNormal.m_more1); return; case IT_FIGURINE: case IT_EQ_HORSE: - sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, RES_GET_INDEX(m_itNormal.m_more1))); + sVal = ResourceGetName(CResourceID(RES_CHARDEF, RES_GET_INDEX(m_itNormal.m_more1)), m_itNormal.m_more1); return; case IT_POTION: - sVal = g_Cfg.ResourceGetName(CResourceID(RES_SPELL, RES_GET_INDEX(m_itPotion.m_Type))); + sVal = ResourceGetName(CResourceID(RES_SPELL, RES_GET_INDEX(m_itPotion.m_Type)), m_itNormal.m_more1); return; default: if (CResourceIDBase::IsValidResource(m_itNormal.m_more1)) - sVal = g_Cfg.ResourceGetName(CResourceID(m_itNormal.m_more1, 0)); + sVal = ResourceGetName(CResourceID(m_itNormal.m_more1, 0), m_itNormal.m_more1); else sVal.FormatHex(m_itNormal.m_more1); return; @@ -2333,12 +2333,12 @@ void CItem::r_WriteMore2( CSString & sVal ) case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: - sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, m_itFood.m_MeatType)); + sVal = ResourceGetName(CResourceID(RES_CHARDEF, m_itFood.m_MeatType), m_itNormal.m_more2); return; case IT_CROPS: case IT_FOLIAGE: - sVal = g_Cfg.ResourceGetName(m_itCrop.m_ridFruitOverride, RES_ITEMDEF); + sVal = ResourceGetName(m_itCrop.m_ridFruitOverride, RES_ITEMDEF, m_itNormal.m_more2); return; case IT_LEATHER: @@ -2348,16 +2348,16 @@ void CItem::r_WriteMore2( CSString & sVal ) case IT_WOOL: case IT_BLOOD: case IT_BONE: - sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, m_itNormal.m_more2)); + sVal = ResourceGetName(CResourceID(RES_CHARDEF, m_itNormal.m_more2), m_itNormal.m_more2); return; case IT_ANIM_ACTIVE: - sVal = g_Cfg.ResourceGetName(CResourceID(RES_CHARDEF, m_itAnim.m_PrevType)); + sVal = ResourceGetName(CResourceID(RES_CHARDEF, m_itAnim.m_PrevType), m_itNormal.m_more2); return; default: if (CResourceIDBase::IsValidResource(m_itNormal.m_more2)) - sVal = g_Cfg.ResourceGetName(CResourceID(m_itNormal.m_more2, 0)); + sVal = ResourceGetName(CResourceID(m_itNormal.m_more2, 0), m_itNormal.m_more2); else sVal.FormatHex(m_itNormal.m_more2); return; @@ -2991,6 +2991,35 @@ void CItem::r_LoadMore2(dword dwVal) } } +const lpctstr CItem::ResourceGetName(const CResourceID& rid, dword dwMore) +{ + if (Can(CAN_I_SCRIPTEDMORE)) + { + if (CResourceIDBase::IsValidResource(dwMore)) + return g_Cfg.ResourceGetName(CResourceID(dwMore, 0)); + + tchar* pszText = Str_GetTemp(); + sprintf(pszText, "%d", dwMore); + return pszText; + } + return g_Cfg.ResourceGetName(rid); +} + +const lpctstr CItem::ResourceGetName(const CResourceIDBase& rid, RES_TYPE iExpectedType, dword dwMore) +{ + if (Can(CAN_I_SCRIPTEDMORE)) + { + if (CResourceIDBase::IsValidResource(dwMore)) + return g_Cfg.ResourceGetName(CResourceID(dwMore, 0)); + + tchar* pszText = Str_GetTemp(); + sprintf(pszText, "%d", dwMore); + return pszText; + + } + return g_Cfg.ResourceGetName(rid, iExpectedType); +} + bool CItem::r_LoadVal( CScript & s ) // Load an item Script { ADDTOCALLSTACK("CItem::r_LoadVal"); diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index a5a81d1d2..b8ea19446 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -737,6 +737,9 @@ protected: virtual void _SetTimeout(int64 iMsecs) override final; void r_LoadMore1(dword dwVal); void r_LoadMore2(dword dwVal); + const lpctstr ResourceGetName(const CResourceID& rid, dword dwMore); + const lpctstr ResourceGetName(const CResourceIDBase& rid, RES_TYPE iExpectedType, dword dwMore); + virtual bool r_GetRef( lpctstr & ptcKey, CScriptObj * & pRef ) override; virtual void r_Write( CScript & s ) override; virtual bool r_WriteVal( lpctstr ptcKey, CSString & s, CTextConsole * pSrc = nullptr, bool fNoCallParent = false, bool fNoCallChildren = false ) override; From 8c4d9e68007043b220be143d255e35793b390a6e Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 23 Apr 2024 21:28:59 +0100 Subject: [PATCH 71/90] Review Changes --- Changelog.txt | 11 ++++++----- src/common/CScriptObj.cpp | 12 +----------- src/common/CVarDefMap.cpp | 2 +- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index b462a6a70..4cae953f2 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3521,6 +3521,7 @@ Additionally, the problem of zig-zag issue following in the South direction has This LOCALs changes default behaviour of poisoned weapons while removing poison. LOCAL.ItemPoisonReductionChance = Is the chance that weapon reduce poison morez. (Default 100%) LOCAL.ItemPoisonReductionAmount = Is the amount of poison that weapon reduce. (Default: CurrentPoisonAmount/ 2) + - Added: You can now use TDATA2 for setting default cooldown (delay) for drinks. (Default: 15secs for potions, 1500 secs for ales) - Changed: Reactive armor range increased from 1 to 2 in default. @@ -3543,7 +3544,8 @@ Additionally, the problem of zig-zag issue following in the South direction has 02-04-2024, xwerswoodx - Changed: dword CAN flags changed with uint64 to increase limits. - CAN flag limit increased from 0xFFFF FFFF (dword/uint max) to 0xFFFF FFFF FFFF FFFF (uint64 max) - - But as sphere evaluation expressions (eval, hval etc.) supports int64 instead of uint64, avoid using any flag value more than 2 << 47 (0x1 0000 0000 0000). + - The maximum allowed flag for UINT64 is 1 << 62 (0x4000 0000 0000 0000) as 1 << 63 is reserved for the sign. + - But as sphere evaluation expressions (eval, hval, qval etc.) supports int64 instead of uint64, avoid using any flag value more than 1 << 47 (0x1 0000 0000 0000). - Fixed: Possible fix for chat debugs. (Issue: #1212) (Issue: https://discord.com/channels/354358315373035542/483721253773901824/1224030729906815077) 03-04-2024, xwerswoodx @@ -3638,10 +3640,9 @@ Additionally, the problem of zig-zag issue following in the South direction has MapViewRadar=31 MapViewSize=18 MapViewSizeMax=24 -- Added: 'H' shortcut for variables to get the value as hexadecimal. - For example, if you use .tag.test 100 - returns 100 - returns 064 + - MapViewRadar affects the visibility range of the multis (castles, keeps, ships etc) and the range of spy glass. (Spyglass range is MapViewRadar - 5) + - MapViewSize affects the visibility range of the items. + - MapViewSizeMax is the maximum range of MapViewSize allowed for increasing VISUALRANGE on clients. - Merged: raydienull's LAYER_STABLE (81) build merged, but LAYER_AUCTION keep same while LAYER_STABLE added as a new layer. (PR: #1201) - Fixed: raydienull's LAYER_STABLE follower triggers isn't called while taking pet out of stable. - Fixed: raydienull's LAYER_STABLE doesn't work with the new follower system. diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index 5bc148a3d..02978f202 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -538,17 +538,7 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc return true; } - } - else if ((*ptcKey == 'h') || (*ptcKey == 'H')) // same as > to get hex from the val - { - lpctstr sArgs = ptcKey + 1; - if (r_WriteVal(sArgs, sVal, pSrc)) - { - if (*sVal != '-') - sVal.FormatLLHex(ahextoi64(sVal)); - return true; - } - } + } // , , are shortcuts to rand(), rand(15) and rand(3,15) else if (( *ptcKey == 'r' ) || ( *ptcKey == 'R' )) { diff --git a/src/common/CVarDefMap.cpp b/src/common/CVarDefMap.cpp index 688f04858..fee20a0a5 100644 --- a/src/common/CVarDefMap.cpp +++ b/src/common/CVarDefMap.cpp @@ -42,7 +42,7 @@ CVarDefContNum::CVarDefContNum( lpctstr ptcKey ) : m_sKey( ptcKey ), m_iVal( 0 ) lpctstr CVarDefContNum::GetValStr() const { - return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), 10); + return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), 16); } bool CVarDefContNum::r_LoadVal( CScript & s ) From f00c63845837cb449e4255e6a4e8535bd07e5180 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 23 Apr 2024 22:01:13 +0100 Subject: [PATCH 72/90] Review Changes Revert Back ELEMENTAL ENGINE Update, and Added SPELLFLAG for Ignoring SPELLFLAG --- Changelog.txt | 18 ++---- src/game/CServerConfig.h | 17 ------ src/game/chars/CCharFight.cpp | 2 +- src/game/chars/CCharSpell.cpp | 38 ++++-------- src/game/clients/CClientMsg.cpp | 7 ++- src/game/clients/CClientMsg_AOSTooltip.cpp | 2 +- src/game/game_macros.h | 67 +++++++++++----------- src/network/send.cpp | 2 +- src/sphere.ini | 14 ----- 9 files changed, 58 insertions(+), 109 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 4cae953f2..130ab1a5b 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3241,7 +3241,7 @@ Fixed: Multi type items weren't calling the @Destroy triggers when removed. (Iss - (Partially) Fixed: Localized messages throwing errors in console when the speaker is not visibile. Partially because i can't still display the speaker name in the journal if the hearer is dead and DeadCannotSeeLiving is set to 2. (Issue #1049) - Added: New locals (READ ONLY) in @GetHit trigger: local.damagePercentPhysical, local.damagePercentFire, local.damagePercentCold, local.damagePercentPoison, local.damagePercentEnergy These locals contains the amount in % of the elemental damage inflicted, and thus they are available only with Elemental Engine enabled. - + 22-03-2023, Drk84 - Fixed: Undefined item ID (it's actually Item ID 00) when adding ON=@Cancel trigger in SKILLMENU. (Issue #1056) @@ -3571,16 +3571,7 @@ Additionally, the problem of zig-zag issue following in the South direction has 08-04-2024, xwerswoodx - Fixed: Missing REGION reference for multis. (Issue: #1228) -- Added: ElementalEngineFlags variable added to sphere.ini to let servers to filter elemental engine. (Issue: #1230) - EE_CURSE = 0x1, // Adds Elemental buff/defuff to curse spell. - EE_MASS_CURSE = 0x2, // Adds Elemental buff/defuff to mass curse spell. - EE_REACTIVE_ARMOR = 0x4, // Adds Elemental buff/defuff to reactive armor spell. - EE_MAGIC_REFLECT = 0x8, // Adds Elemental buff/defuff to magic reflect spell. - EE_PROTECTION = 0x10, // Adds Elemental buff/defuff to protection spell. - EE_ARCH_PROTECTION = 0x20, // Adds Elemental buff/defuff to arch protection spell. - EE_STONESKIN = 0x40, // Adds Elemental buff/defuff to stone skin spell. - EE_STEELSKIN = 0x80, // Adds Elemental buff/defuff to steel skin spell. - EE_RESPHYSICAL = 0x100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. +- Added: SPELLFLAG_NO_ELEMENTALENGINE (0400000000) as spellflag, for ignoring Elemental Engine Damages in specific skills. 09-04-2024, xwerswoodx - Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) @@ -3710,4 +3701,7 @@ Additionally, the problem of zig-zag issue following in the South direction has - Added: EF_DAMAGETOOLS flag implemented to the sphere. - Added LOCAL.ITEMDAMAGECHANCE to the @Success trigger for skills to decide damage chance for tools. (Default: 25) - Added LOCAL.ITEMDAMAGEAMOUNT to the @Success trigger for skills to decide damage amount. (Default: 1) - - EF_DAMAGETOOLS only affects the skills with SKF_GATHER flag. \ No newline at end of file + - EF_DAMAGETOOLS only affects the skills with SKF_GATHER flag. +- Added: CAN_I_SCRIPTEDMORE (020000000) as item CAN. + - This can flag ignores MORE values that entered for hardcoded behaviour. + - It's new flag, need couple of updates for fully implemented. \ No newline at end of file diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 1b2cae326..6ee6779ae 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -129,23 +129,6 @@ enum COMBATFLAGS_TYPE COMBAT_PARALYZE_CANSWING = 0x80000 // Characters can continue attacking while paralyzed. (Old sphere behaviour) }; -/** -* @enum ELEMENTALENGINEFLAGS_TYPE -* @brief ElementalEngineFlags (sphere.ini) -*/ -enum ELEMENTALENGINEFLAGS_TYPE -{ - EE_CURSE = 0x1, // Adds Elemental buff/defuff to curse spell. - EE_MASS_CURSE = 0x2, // Adds Elemental buff/defuff to mass curse spell. - EE_REACTIVE_ARMOR = 0x4, // Adds Elemental buff/defuff to reactive armor spell. - EE_MAGIC_REFLECT = 0x8, // Adds Elemental buff/defuff to magic reflect spell. - EE_PROTECTION = 0x10, // Adds Elemental buff/defuff to protection spell. - EE_ARCH_PROTECTION = 0x20, // Adds Elemental buff/defuff to arch protection spell. - EE_STONESKIN = 0x40, // Adds Elemental buff/defuff to stone skin spell. - EE_STEELSKIN = 0x80, // Adds Elemental buff/defuff to steel skin spell. - EE_RESPHYSICAL = 0x100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. -}; - /** * @enum PARRYFLAGS_TYPE * @brief ParryEra (sphere.ini): Parrying behaviour diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index a0944db45..f66e54ca7 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -416,7 +416,7 @@ int CChar::CalcArmorDefense() const ADDTOCALLSTACK("CChar::CalcArmorDefense"); // If Combat Elemental Engine is enabled, we don't need to calculate the AC because RESPHYSICAL is used. - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_RESPHYSICAL)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) return 0; int iDefenseTotal = 0; diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 957d4750c..52eb940f9 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -808,7 +808,7 @@ void CChar::Spell_Effect_Remove(CItem * pSpell) case SPELL_Curse: case SPELL_Mass_Curse: { - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags((spell == SPELL_Mass_Curse ? EE_MASS_CURSE : EE_CURSE)) && m_pPlayer) + if (m_pPlayer && IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { CCPropsChar* pCCPChar = GetComponentProps(); CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); @@ -855,7 +855,7 @@ void CChar::Spell_Effect_Remove(CItem * pSpell) UpdateStatVal( STAT_INT, +uiStatEffect ); return; case SPELL_Reactive_Armor: - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_REACTIVE_ARMOR)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { CCPropsChar* pCCPChar = GetComponentProps(); CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); @@ -874,7 +874,7 @@ void CChar::Spell_Effect_Remove(CItem * pSpell) return; case SPELL_Magic_Reflect: StatFlag_Clear(STATF_REFLECTION); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_MAGIC_REFLECT)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { CCPropsChar* pCCPChar = GetComponentProps(); CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); @@ -892,15 +892,7 @@ void CChar::Spell_Effect_Remove(CItem * pSpell) case SPELL_Protection: case SPELL_Arch_Prot: { - ELEMENTALENGINEFLAGS_TYPE iType = EE_PROTECTION; - if (spell == SPELL_Steelskin) - iType = EE_STEELSKIN; - else if (spell == SPELL_Stoneskin) - iType = EE_STONESKIN; - else if (spell == SPELL_Arch_Prot) - iType = EE_ARCH_PROTECTION; - - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(iType)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { CCPropsChar* pCCPChar = GetComponentProps(); CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); @@ -1376,7 +1368,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) switch ( spell ) { case SPELL_Reactive_Armor: - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_REACTIVE_ARMOR)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { wStatEffectRef = 15 + (pCaster->Skill_GetBase(SKILL_INSCRIPTION) / 200); @@ -1399,7 +1391,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) if (pClient && IsSetOF(OF_Buffs)) { pClient->removeBuff(BI_REACTIVEARMOR); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_REACTIVE_ARMOR)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { Str_FromI(wStatEffectRef, NumBuff[0], sizeof(NumBuff[0]), 10); for ( int idx = 1; idx < 5; ++idx ) @@ -1485,7 +1477,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) { wStatEffectRef = 8 + (pCaster->Skill_GetBase(SKILL_EVALINT) / 100) - (Skill_GetBase(SKILL_MAGICRESISTANCE) / 100); } - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags((spell == SPELL_Mass_Curse ? EE_MASS_CURSE : EE_CURSE)) && m_pPlayer) // Curse also decrease max resistances on players + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE) && m_pPlayer) // Curse also decrease max resistances on players { CCPropsChar* pCCPChar = GetComponentProps(); CCPropsChar* pBaseCCPChar = Base_GetDef()->GetComponentProps(); @@ -1512,7 +1504,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) for ( int idx = STAT_STR; idx < STAT_BASE_QTY; ++idx ) Str_FromI(wStatEffectRef, NumBuff[idx], sizeof(NumBuff[0]), 10); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags((spell == SPELL_Mass_Curse ? EE_MASS_CURSE : EE_CURSE))) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { for ( int idx = 3; idx < 7; ++idx ) Str_FromI(10, NumBuff[idx], sizeof(NumBuff[0]), 10); @@ -1613,7 +1605,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) return; case SPELL_Magic_Reflect: StatFlag_Set( STATF_REFLECTION ); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_MAGIC_REFLECT)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { wStatEffectRef = 25 - (pCaster->Skill_GetBase(SKILL_INSCRIPTION) / 200); @@ -1628,7 +1620,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) if (pClient && IsSetOF(OF_Buffs)) { pClient->removeBuff(BI_MAGICREFLECTION); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_MAGIC_REFLECT)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { Str_FromI(-wStatEffectRef, NumBuff[0], sizeof(NumBuff[0]), 10); for ( int idx = 1; idx < 5; ++idx ) @@ -1649,15 +1641,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) { int iPhysicalResist = 0; int iMagicResist = 0; - ELEMENTALENGINEFLAGS_TYPE iType = EE_PROTECTION; - if (spell == SPELL_Steelskin) - iType = EE_STEELSKIN; - else if (spell == SPELL_Stoneskin) - iType = EE_STONESKIN; - else if (spell == SPELL_Arch_Prot) - iType = EE_ARCH_PROTECTION; - - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(iType)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { ushort uiCasterEvalInt = pCaster->Skill_GetBase(SKILL_EVALINT), uiCasterMeditation = pCaster->Skill_GetBase(SKILL_MEDITATION); ushort uiCasterInscription = pCaster->Skill_GetBase(SKILL_INSCRIPTION); diff --git a/src/game/clients/CClientMsg.cpp b/src/game/clients/CClientMsg.cpp index e0fee85db..1669c72b6 100644 --- a/src/game/clients/CClientMsg.cpp +++ b/src/game/clients/CClientMsg.cpp @@ -66,6 +66,7 @@ void CClient::resendBuffs() const int64 iTimerEffectSigned = pItem->GetTimerSAdjusted(); wTimerEffect = (word)(maximum(iTimerEffectSigned, 0)); SPELL_TYPE spell = (SPELL_TYPE)(RES_GET_INDEX(pItem->m_itSpell.m_spell)); + const CSpellDef* pSpellDef = g_Cfg.GetSpellDef(spell); switch (spell) { @@ -135,7 +136,7 @@ void CClient::resendBuffs() const case SPELL_Reactive_Armor: { removeBuff(BI_REACTIVEARMOR); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_REACTIVE_ARMOR)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { Str_FromI(wStatEffect, NumBuff[0], sizeof(NumBuff[0]), 10); for ( int idx = 1; idx < 5; ++idx ) @@ -161,7 +162,7 @@ void CClient::resendBuffs() const } removeBuff(BuffIcon); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags((spell == SPELL_Arch_Prot ? EE_ARCH_PROTECTION : EE_PROTECTION))) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { Str_FromI(-pItem->m_itSpell.m_PolyStr, NumBuff[0], sizeof(NumBuff[0]), 10); Str_FromI(-pItem->m_itSpell.m_PolyDex / 10, NumBuff[1], sizeof(NumBuff[0]), 10); @@ -188,7 +189,7 @@ void CClient::resendBuffs() const case SPELL_Magic_Reflect: { removeBuff(BI_MAGICREFLECTION); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(EE_MAGIC_REFLECT)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { Str_FromI(-wStatEffect, NumBuff[0], sizeof(NumBuff[0]), 10); for ( int idx = 1; idx < 5; ++idx ) diff --git a/src/game/clients/CClientMsg_AOSTooltip.cpp b/src/game/clients/CClientMsg_AOSTooltip.cpp index ff7307059..ec2009f0a 100644 --- a/src/game/clients/CClientMsg_AOSTooltip.cpp +++ b/src/game/clients/CClientMsg_AOSTooltip.cpp @@ -475,7 +475,7 @@ void CClient::AOSTooltip_addDefaultItemData(CItem * pItem) case IT_CLOTHING: case IT_SHIELD: { - if (!IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) || (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !IsSetEEFlags(EE_RESPHYSICAL))) + if (!IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE)) { int iArmorRating = pItem->Armor_GetDefense(); int iPercentArmorRating = 0; diff --git a/src/game/game_macros.h b/src/game/game_macros.h index c84ce2e70..f948c61d0 100644 --- a/src/game/game_macros.h +++ b/src/game/game_macros.h @@ -74,38 +74,39 @@ typedef dword DAMAGE_TYPE; // describe a type of damage. //--Spellflags -#define SPELLFLAG_DIR_ANIM 0x0000001 // Evoke type cast or directed. (animation) -#define SPELLFLAG_TARG_ITEM 0x0000002 // Need to target an object -#define SPELLFLAG_TARG_CHAR 0x0000004 // Needs to target a living thing -#define SPELLFLAG_TARG_OBJ (SPELLFLAG_TARG_ITEM|SPELLFLAG_TARG_CHAR) -#define SPELLFLAG_TARG_XYZ 0x0000008 // Can just target a location. -#define SPELLFLAG_HARM 0x0000010 // The spell is in some way harmfull. -#define SPELLFLAG_FX_BOLT 0x0000020 // Effect is a bolt to the target. -#define SPELLFLAG_FX_TARG 0x0000040 // Effect is at the target. -#define SPELLFLAG_FIELD 0x0000080 // create a field of stuff. (fire,poison,wall) -#define SPELLFLAG_SUMMON 0x0000100 // summon a creature. -#define SPELLFLAG_GOOD 0x0000200 // The spell is a good spell. u intend to help to receiver. -#define SPELLFLAG_RESIST 0x0000400 // Allowed to resist this. -#define SPELLFLAG_TARG_NOSELF 0x0000800 -#define SPELLFLAG_FREEZEONCAST 0x0001000 // freezes the char on cast for this spell. -#define SPELLFLAG_DISABLED 0x0008000 -#define SPELLFLAG_SCRIPTED 0x0010000 -#define SPELLFLAG_PLAYERONLY 0x0020000 // casted by players only -#define SPELLFLAG_NOUNPARALYZE 0x0040000 // casted by players only -#define SPELLFLAG_NO_CASTANIM 0x0080000 // play no anim while casting (also override SPELLFLAG_DIR_ANIM) -#define SPELLFLAG_TARG_NO_PLAYER 0x0100000 // if a char may be targetted, it may not be a player -#define SPELLFLAG_TARG_NO_NPC 0x0200000 // if a char may be targetted, it may not be an NPC -#define SPELLFLAG_NOPRECAST 0x0400000 // disable precasting for this spell -#define SPELLFLAG_NOFREEZEONCAST 0x0800000 // disable freeze on cast for this spell -#define SPELLFLAG_AREA 0x1000000 // area effect (uses local.arearadius) -#define SPELLFLAG_POLY 0x2000000 -#define SPELLFLAG_TARG_DEAD 0x4000000 // Allowed to targ dead chars -#define SPELLFLAG_DAMAGE 0x8000000 // Damage intended -#define SPELLFLAG_BLESS 0x10000000 // Benefitial spells like Bless,Agility,etc. -#define SPELLFLAG_CURSE 0x20000000 // Curses just like Weaken,Purge Magic,Curse,etc. -#define SPELLFLAG_HEAL 0x40000000 // Healing spell -#define SPELLFLAG_TICK 0x80000000 // A ticking spell like Poison. -#define SPELLFLAG_FIELD_RANDOMDECAY 0x100000000 // Make the field items have random timers. -#define SPELLFLAG_TARG_ONLYSELF 0x200000000 // You can only target yourself. +#define SPELLFLAG_DIR_ANIM 0x0000001 // Evoke type cast or directed. (animation) +#define SPELLFLAG_TARG_ITEM 0x0000002 // Need to target an object +#define SPELLFLAG_TARG_CHAR 0x0000004 // Needs to target a living thing +#define SPELLFLAG_TARG_OBJ (SPELLFLAG_TARG_ITEM|SPELLFLAG_TARG_CHAR) +#define SPELLFLAG_TARG_XYZ 0x0000008 // Can just target a location. +#define SPELLFLAG_HARM 0x0000010 // The spell is in some way harmfull. +#define SPELLFLAG_FX_BOLT 0x0000020 // Effect is a bolt to the target. +#define SPELLFLAG_FX_TARG 0x0000040 // Effect is at the target. +#define SPELLFLAG_FIELD 0x0000080 // create a field of stuff. (fire,poison,wall) +#define SPELLFLAG_SUMMON 0x0000100 // summon a creature. +#define SPELLFLAG_GOOD 0x0000200 // The spell is a good spell. u intend to help to receiver. +#define SPELLFLAG_RESIST 0x0000400 // Allowed to resist this. +#define SPELLFLAG_TARG_NOSELF 0x0000800 +#define SPELLFLAG_FREEZEONCAST 0x0001000 // freezes the char on cast for this spell. +#define SPELLFLAG_DISABLED 0x0008000 +#define SPELLFLAG_SCRIPTED 0x0010000 +#define SPELLFLAG_PLAYERONLY 0x0020000 // casted by players only +#define SPELLFLAG_NOUNPARALYZE 0x0040000 // casted by players only +#define SPELLFLAG_NO_CASTANIM 0x0080000 // play no anim while casting (also override SPELLFLAG_DIR_ANIM) +#define SPELLFLAG_TARG_NO_PLAYER 0x0100000 // if a char may be targetted, it may not be a player +#define SPELLFLAG_TARG_NO_NPC 0x0200000 // if a char may be targetted, it may not be an NPC +#define SPELLFLAG_NOPRECAST 0x0400000 // disable precasting for this spell +#define SPELLFLAG_NOFREEZEONCAST 0x0800000 // disable freeze on cast for this spell +#define SPELLFLAG_AREA 0x1000000 // area effect (uses local.arearadius) +#define SPELLFLAG_POLY 0x2000000 +#define SPELLFLAG_TARG_DEAD 0x4000000 // Allowed to targ dead chars +#define SPELLFLAG_DAMAGE 0x8000000 // Damage intended +#define SPELLFLAG_BLESS 0x10000000 // Benefitial spells like Bless,Agility,etc. +#define SPELLFLAG_CURSE 0x20000000 // Curses just like Weaken,Purge Magic,Curse,etc. +#define SPELLFLAG_HEAL 0x40000000 // Healing spell +#define SPELLFLAG_TICK 0x80000000 // A ticking spell like Poison. +#define SPELLFLAG_FIELD_RANDOMDECAY 0x100000000 // Make the field items have random timers. +#define SPELLFLAG_TARG_ONLYSELF 0x200000000 // You can only target yourself. +#define SPELLFLAG_NO_ELEMENTALENGINE 0x400000000 #endif // _INC_GAME_MACROS_H diff --git a/src/network/send.cpp b/src/network/send.cpp index 1a041f3ac..4b9c10d05 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -237,7 +237,7 @@ void PacketObjectStatus::WriteVersionSpecific(const CClient* target, CChar* othe writeInt32(other->ContentCount(CResourceID(RES_TYPEDEF, IT_GOLD))); } - if (fElemental && IsSetEEFlags(EE_RESPHYSICAL)) + if (fElemental) writeInt16((word)other->GetPropNum(pCCPChar, PROPCH_RESPHYSICAL, pBaseCCPChar)); else writeInt16(other->m_defense + otherDefinition->m_defense); diff --git a/src/sphere.ini b/src/sphere.ini index 741d28a7e..973a06868 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -406,20 +406,6 @@ SuppressCapitals=0 // COMBAT_PARALYZE_CANSWING 080000 // Characters can continue attacking while paralyzed. (Old sphere behaviour) //CombatFlags=0 -// Elemental Engine flags that can be used to filter COMBAT_ELEMENTAL_ENGINE -// EE_CURSE 0001 // Adds Elemental buff/defuff to curse spell. -// EE_MASS_CURSE 0002 // Adds Elemental buff/defuff to mass curse spell. -// EE_REACTIVE_ARMOR 0004 // Adds Elemental buff/defuff to reactive armor spell. -// EE_MAGIC_REFLECT 0008 // Adds Elemental buff/defuff to magic reflect spell. -// EE_PROTECTION 0010 // Adds Elemental buff/defuff to protection spell. -// EE_ARCH_PROTECTION 0020 // Adds Elemental buff/defuff to arch protection spell. -// EE_STONESKIN 0040 // Adds Elemental buff/defuff to stone skin spell. -// EE_STEELSKIN 0080 // Adds Elemental buff/defuff to steel skin spell. -// EE_RESPHYSICAL 0100 // Use RESPHYSICAL value instead of ARMOR for defense calculation. -// ALL 01FF // Includes all from 01 to 0100. -// MAX 0FFFFFFFF // Includes all flag values for UINT. -//ElementalEngineFlags=0FFFFFFFF - // If COMBAT_ARCHERYCANMOVE is not enabled, wait this much tenth of seconds (minimum=0) after the player // stopped moving before starting a new attack // (Values changed between expansions. SE:2~3 / AOS:5 / pre-AOS:10) From b4b055f0d2b73067962200a53b75e7001cd9be2b Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 23 Apr 2024 22:02:40 +0100 Subject: [PATCH 73/90] Update Changelog.txt --- Changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.txt b/Changelog.txt index 130ab1a5b..2258b203f 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3571,7 +3571,7 @@ Additionally, the problem of zig-zag issue following in the South direction has 08-04-2024, xwerswoodx - Fixed: Missing REGION reference for multis. (Issue: #1228) -- Added: SPELLFLAG_NO_ELEMENTALENGINE (0400000000) as spellflag, for ignoring Elemental Engine Damages in specific skills. +- Added: SPELLFLAG_NO_ELEMENTALENGINE (0400000000) as spellflag, for ignoring Elemental Engine Damages in specific spells. (Issue: #1230) 09-04-2024, xwerswoodx - Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) From 07a466d874817134ec7c012c446784cdb3face90 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Tue, 23 Apr 2024 22:23:45 +0100 Subject: [PATCH 74/90] Build Fix and Forgotten Ini Settings Removal --- src/game/CServerConfig.cpp | 6 ------ src/game/CServerConfig.h | 2 -- src/game/chars/CCharSpell.cpp | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 684e6dc7b..dfcbe2915 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -174,7 +174,6 @@ CServerConfig::CServerConfig() m_iHitsUpdateRate = MSECS_PER_SEC; m_iSpeedScaleFactor = 80000; m_iCombatFlags = 0; - m_iElementalEngineFlags = UINT32_MAX; //In default, all Elemental Engine flags are active, also I put UINT32_MAX to let sphere active new flags (if added) automatically. m_iCombatArcheryMovementDelay = 10; m_iCombatDamageEra = 0; m_iCombatHitChanceEra = 0; @@ -796,7 +795,6 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY+1] { "DUMPPACKETSFORACC", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sDumpAccPackets) }}, #endif { "DUNGEONLIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightDungeon) }}, - { "ELEMENTALENGINEFLAGS", { ELEM_MASK_INT, static_castOFFSETOF(CServerConfig, m_iElementalEngineFlags) }}, { "EMOTEFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iEmoteFlags) }}, { "EQUIPPEDCAST", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fEquippedCast) }}, { "ERALIMITGEAR", { ELEM_INT, static_castOFFSETOF(CServerConfig,_iEraLimitGear) }}, @@ -1396,10 +1394,6 @@ bool CServerConfig::r_LoadVal( CScript &s ) m_cCommandPrefix = *s.GetArgStr(); break; - case RC_ELEMENTALENGINEFLAGS: - m_iElementalEngineFlags = s.GetArgUVal(); - break; - case RC_EXPERIMENTAL: _uiExperimentalFlags = s.GetArgUVal(); //PrintEFOFFlags(true, false); diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 6ee6779ae..f9c7df8a9 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -375,7 +375,6 @@ extern class CServerConfig : public CResourceHolder // Flags for controlling pvp/pvm behaviour of players uint m_iCombatFlags; // combat flags uint m_iMagicFlags; // magic flags - uint m_iElementalEngineFlags; //Elemental engine flags uint m_iRacialFlags; // racial traits flags uint m_iRevealFlags; // reveal flags used for SPELL_REVEAL (mostly for backwards). uint m_iEmoteFlags; // emote flags @@ -1117,7 +1116,6 @@ typedef std::map KRGumpsMap; #define IsSetOF(of) ((g_Cfg._uiOptionFlags & of) != 0) #define IsSetCombatFlags(cf) ((g_Cfg.m_iCombatFlags & cf) != 0) #define IsSetMagicFlags(mf) ((g_Cfg.m_iMagicFlags & mf) != 0) -#define IsSetEEFlags(eef) ((g_Cfg.m_iElementalEngineFlags & eef) != 0) #define IsSetEmoteFlag(ef) ((g_Cfg.m_iEmoteFlags & ef) != 0) diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 52eb940f9..116ee3c0a 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -1682,7 +1682,7 @@ void CChar::Spell_Effect_Add( CItem * pSpell ) } pClient->removeBuff(BuffIcon); - if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && IsSetEEFlags(iType)) + if (IsSetCombatFlags(COMBAT_ELEMENTAL_ENGINE) && !pSpellDef->IsSpellType(SPELLFLAG_NO_ELEMENTALENGINE)) { Str_FromI(-iPhysicalResist, NumBuff[0], sizeof(NumBuff[0]), 10); Str_FromI(-iMagicResist/10, NumBuff[1], sizeof(NumBuff[0]), 10); From 0d28677cbd6f081db32173e5b945412ef3699e06 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 24 Apr 2024 14:08:20 +0100 Subject: [PATCH 75/90] Forgotten Sphere.ini entry that crashes sphere --- src/game/CServerConfig.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index dfcbe2915..35f926ba2 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -519,7 +519,6 @@ enum RC_TYPE RC_DUMPPACKETSFORACC, #endif RC_DUNGEONLIGHT, - RC_ELEMENTALENGINEFLAGS, RC_EMOTEFLAGS, // m_iEmoteFlags RC_EQUIPPEDCAST, // m_fEquippedCast RC_ERALIMITGEAR, // _iEraLimitGear From 9ccb383ac0287ac0e68158d25fbdad25061325db Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 24 Apr 2024 15:10:15 +0100 Subject: [PATCH 76/90] Fixed my stupid mistake. --- src/game/chars/CCharSkill.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index db00dd23c..d57eb931d 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -3841,12 +3841,12 @@ int CChar::Skill_Done() args.m_VarsLocal.SetNumNew("ITEMDAMAGEAMOUNT", 1); if ( IsTrigUsed(TRIGGER_SKILLSUCCESS) ) { - if (Skill_OnCharTrigger(skill, CTRIG_SkillSuccess) == TRIGRET_RET_TRUE, &args) + if (Skill_OnCharTrigger(skill, CTRIG_SkillSuccess, &args) == TRIGRET_RET_TRUE) return -SKTRIG_ABORT; } if ( IsTrigUsed(TRIGGER_SUCCESS) ) { - if (Skill_OnTrigger(skill, SKTRIG_SUCCESS) == TRIGRET_RET_TRUE, &args) + if (Skill_OnTrigger(skill, SKTRIG_SUCCESS, &args) == TRIGRET_RET_TRUE) return -SKTRIG_ABORT; } From 2e0a8f599574d45bad1c760d8b27a347cd5bde75 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 24 Apr 2024 15:19:24 +0100 Subject: [PATCH 77/90] Cancelled default more input for ResourceGetName --- src/game/items/CItem.cpp | 43 ++++++++++++++++++++-------------------- src/game/items/CItem.h | 4 ++-- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index ec874563f..a851ee5fd 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -2278,14 +2278,14 @@ void CItem::r_WriteMore1(CSString & sVal) case IT_GRASS: case IT_ROCK: case IT_WATER: - sVal = ResourceGetName(m_itResource.m_ridRes, RES_REGIONRESOURCE, m_itNormal.m_more1); //Changed to fix issue but it is not implemented. + sVal = ResourceGetName(m_itResource.m_ridRes, RES_REGIONRESOURCE); //Changed to fix issue but it is not implemented. return; case IT_FRUIT: case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: - sVal = ResourceGetName(m_itFood.m_ridCook, RES_ITEMDEF, m_itNormal.m_more1); + sVal = ResourceGetName(m_itFood.m_ridCook, RES_ITEMDEF); return; case IT_TRAP: @@ -2297,21 +2297,21 @@ void CItem::r_WriteMore1(CSString & sVal) case IT_LOOM: case IT_ARCHERY_BUTTE: case IT_ITEM_STONE: - sVal = ResourceGetName(CResourceID(RES_ITEMDEF, RES_GET_INDEX(m_itNormal.m_more1)), m_itNormal.m_more1); + sVal = ResourceGetName(CResourceID(RES_ITEMDEF, RES_GET_INDEX(m_itNormal.m_more1))); return; case IT_FIGURINE: case IT_EQ_HORSE: - sVal = ResourceGetName(CResourceID(RES_CHARDEF, RES_GET_INDEX(m_itNormal.m_more1)), m_itNormal.m_more1); + sVal = ResourceGetName(CResourceID(RES_CHARDEF, RES_GET_INDEX(m_itNormal.m_more1))); return; case IT_POTION: - sVal = ResourceGetName(CResourceID(RES_SPELL, RES_GET_INDEX(m_itPotion.m_Type)), m_itNormal.m_more1); + sVal = ResourceGetName(CResourceID(RES_SPELL, RES_GET_INDEX(m_itPotion.m_Type))); return; default: if (CResourceIDBase::IsValidResource(m_itNormal.m_more1)) - sVal = ResourceGetName(CResourceID(m_itNormal.m_more1, 0), m_itNormal.m_more1); + sVal = ResourceGetName(CResourceID(m_itNormal.m_more1, 0)); else sVal.FormatHex(m_itNormal.m_more1); return; @@ -2333,12 +2333,12 @@ void CItem::r_WriteMore2( CSString & sVal ) case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: - sVal = ResourceGetName(CResourceID(RES_CHARDEF, m_itFood.m_MeatType), m_itNormal.m_more2); + sVal = ResourceGetName(CResourceID(RES_CHARDEF, m_itFood.m_MeatType)); return; case IT_CROPS: case IT_FOLIAGE: - sVal = ResourceGetName(m_itCrop.m_ridFruitOverride, RES_ITEMDEF, m_itNormal.m_more2); + sVal = ResourceGetName(m_itCrop.m_ridFruitOverride, RES_ITEMDEF); return; case IT_LEATHER: @@ -2348,16 +2348,16 @@ void CItem::r_WriteMore2( CSString & sVal ) case IT_WOOL: case IT_BLOOD: case IT_BONE: - sVal = ResourceGetName(CResourceID(RES_CHARDEF, m_itNormal.m_more2), m_itNormal.m_more2); + sVal = ResourceGetName(CResourceID(RES_CHARDEF, m_itNormal.m_more2)); return; case IT_ANIM_ACTIVE: - sVal = ResourceGetName(CResourceID(RES_CHARDEF, m_itAnim.m_PrevType), m_itNormal.m_more2); + sVal = ResourceGetName(CResourceID(RES_CHARDEF, m_itAnim.m_PrevType)); return; default: if (CResourceIDBase::IsValidResource(m_itNormal.m_more2)) - sVal = ResourceGetName(CResourceID(m_itNormal.m_more2, 0), m_itNormal.m_more2); + sVal = ResourceGetName(CResourceID(m_itNormal.m_more2, 0)); else sVal.FormatHex(m_itNormal.m_more2); return; @@ -2991,31 +2991,30 @@ void CItem::r_LoadMore2(dword dwVal) } } -const lpctstr CItem::ResourceGetName(const CResourceID& rid, dword dwMore) +const lpctstr CItem::ResourceGetName(const CResourceID& rid) { if (Can(CAN_I_SCRIPTEDMORE)) { - if (CResourceIDBase::IsValidResource(dwMore)) - return g_Cfg.ResourceGetName(CResourceID(dwMore, 0)); - tchar* pszText = Str_GetTemp(); - sprintf(pszText, "%d", dwMore); + if (!rid.IsValidUID()) + sprintf(pszText, "%d", (int)rid.GetPrivateUID()); + else + sprintf(pszText, "0%" PRIx32, rid.GetResIndex()); return pszText; } return g_Cfg.ResourceGetName(rid); } -const lpctstr CItem::ResourceGetName(const CResourceIDBase& rid, RES_TYPE iExpectedType, dword dwMore) +const lpctstr CItem::ResourceGetName(const CResourceIDBase& rid, RES_TYPE iExpectedType) { if (Can(CAN_I_SCRIPTEDMORE)) { - if (CResourceIDBase::IsValidResource(dwMore)) - return g_Cfg.ResourceGetName(CResourceID(dwMore, 0)); - tchar* pszText = Str_GetTemp(); - sprintf(pszText, "%d", dwMore); + if (!rid.IsValidUID()) + sprintf(pszText, "%d", (int)rid.GetPrivateUID()); + else + sprintf(pszText, "0%" PRIx32, rid.GetResIndex()); return pszText; - } return g_Cfg.ResourceGetName(rid, iExpectedType); } diff --git a/src/game/items/CItem.h b/src/game/items/CItem.h index b8ea19446..81ded1be0 100644 --- a/src/game/items/CItem.h +++ b/src/game/items/CItem.h @@ -737,8 +737,8 @@ protected: virtual void _SetTimeout(int64 iMsecs) override final; void r_LoadMore1(dword dwVal); void r_LoadMore2(dword dwVal); - const lpctstr ResourceGetName(const CResourceID& rid, dword dwMore); - const lpctstr ResourceGetName(const CResourceIDBase& rid, RES_TYPE iExpectedType, dword dwMore); + const lpctstr ResourceGetName(const CResourceID& rid); + const lpctstr ResourceGetName(const CResourceIDBase& rid, RES_TYPE iExpectedType); virtual bool r_GetRef( lpctstr & ptcKey, CScriptObj * & pRef ) override; virtual void r_Write( CScript & s ) override; From 9ff16479b0715c92c075ae932e7f27ff6173374c Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 24 Apr 2024 16:06:33 +0100 Subject: [PATCH 78/90] m_ridFruitOverride CAN_I_SCRIPTEDMORE update --- src/game/items/CItemPlant.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/game/items/CItemPlant.cpp b/src/game/items/CItemPlant.cpp index 9923e04e7..db6da5bad 100644 --- a/src/game/items/CItemPlant.cpp +++ b/src/game/items/CItemPlant.cpp @@ -31,7 +31,9 @@ bool CItem::Plant_Use(CChar *pChar) ITEMID_TYPE iGrowID = (ITEMID_TYPE)pItemDef->m_ttCrops.m_ridGrow.GetResIndex(); ITEMID_TYPE iFruitID = (ITEMID_TYPE)pItemDef->m_ttCrops.m_ridFruit.GetResIndex(); - ITEMID_TYPE iFruitIDOverride = (ITEMID_TYPE)m_itCrop.m_ridFruitOverride.GetResIndex(); + ITEMID_TYPE iFruitIDOverride = ITEMID_NOTHING; + if (!Can(CAN_I_SCRIPTEDMORE)) + iFruitIDOverride = (ITEMID_TYPE)m_itCrop.m_ridFruitOverride.GetResIndex(); word iAmount = std::max(m_itCrop.m_ridAmount, (word)1); if (IsTrigUsed(TRIGGER_RESOURCETEST)) { @@ -121,7 +123,7 @@ bool CItem::Plant_OnTick() { // Some plants generate a fruit on the ground when ripe. ITEMID_TYPE iFruitID = ITEMID_NOTHING; - if ( m_itCrop.m_ridFruitOverride.IsValidUID()) + if ( m_itCrop.m_ridFruitOverride.IsValidUID() && !Can(CAN_I_SCRIPTEDMORE)) iFruitID = (ITEMID_TYPE)m_itCrop.m_ridFruitOverride.GetResIndex(); else iFruitID = (ITEMID_TYPE)pItemDef->m_ttCrops.m_ridFruit.GetResIndex(); From 688fd6815c8564ed0c9f65bd45103d7029d13bcc Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 24 Apr 2024 16:40:04 +0100 Subject: [PATCH 79/90] Update CItemPlant.cpp --- src/game/items/CItemPlant.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/items/CItemPlant.cpp b/src/game/items/CItemPlant.cpp index db6da5bad..e5182a59f 100644 --- a/src/game/items/CItemPlant.cpp +++ b/src/game/items/CItemPlant.cpp @@ -53,8 +53,8 @@ bool CItem::Plant_Use(CChar *pChar) return true; } - if ( iFruitIDOverride != ITEMID_NOTHING ) - iFruitID = iFruitIDOverride; + if (iFruitIDOverride != ITEMID_NOTHING) + iFruitID = iFruitIDOverride; if ( iFruitID == ITEMID_NOTHING ) pChar->SysMessageDefault(DEFMSG_CROPS_NO_FRUIT); From 2f1d08f42c6527685214239c199ee0f0f5321bf9 Mon Sep 17 00:00:00 2001 From: xwerswoodx Date: Wed, 24 Apr 2024 19:58:46 +0100 Subject: [PATCH 80/90] Update sphereCrypt.ini --- src/sphereCrypt.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sphereCrypt.ini b/src/sphereCrypt.ini index b24ad8556..da15882f3 100644 --- a/src/sphereCrypt.ini +++ b/src/sphereCrypt.ini @@ -24,6 +24,7 @@ ENC_LOGIN 4 // Rotation cipher used for the Login Server crypt by every client, [SPHERECRYPT] //Classic Clients +70010200 03992EB9D 0A81E227F ENC_TFISH //7.0.102 70010100 039C411AD 0A803DE7F ENC_TFISH //7.0.101 70010000 03A3D83BD 0A9F5127F ENC_TFISH //7.0.100 7009900 03A7731CD 0A9CE5E7F ENC_TFISH // 7.0.99 From 0720adf227dac32249a90349586f27f302ceffc5 Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Fri, 26 Apr 2024 19:57:46 +0100 Subject: [PATCH 81/90] ConsoleTextColor Location --- src/common/CLog.cpp | 14 +++++++------- src/common/CLog.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/common/CLog.cpp b/src/common/CLog.cpp index 8f74104e9..16e29e488 100644 --- a/src/common/CLog.cpp +++ b/src/common/CLog.cpp @@ -6,7 +6,7 @@ #include "CLog.h" -int CEventLog::VEvent(dword dwMask, lpctstr pszFormat, va_list args, ConsoleTextColor iColor) noexcept +int CEventLog::VEvent(dword dwMask, lpctstr pszFormat, ConsoleTextColor iColor, va_list args) noexcept { if (pszFormat == nullptr || pszFormat[0] == '\0') return 0; @@ -28,7 +28,7 @@ int CEventLog::Event(dword dwMask, lpctstr pszFormat, ...) noexcept { va_list vargs; va_start(vargs, pszFormat); - int iret = VEvent(dwMask, pszFormat, vargs); + int iret = VEvent(dwMask, pszFormat, CTCOL_DEFAULT, vargs); va_end(vargs); return iret; } @@ -37,7 +37,7 @@ int CEventLog::EventDebug(lpctstr pszFormat, ...) noexcept { va_list vargs; va_start(vargs, pszFormat); - int iret = VEvent(LOGM_DEBUG|LOGM_NOCONTEXT, pszFormat, vargs); + int iret = VEvent(LOGM_DEBUG|LOGM_NOCONTEXT, pszFormat, CTCOL_DEFAULT, vargs); va_end(vargs); return iret; } @@ -46,7 +46,7 @@ int CEventLog::EventError(lpctstr pszFormat, ...) noexcept { va_list vargs; va_start(vargs, pszFormat); - int iret = VEvent(LOGL_ERROR, pszFormat, vargs); + int iret = VEvent(LOGL_ERROR, pszFormat, CTCOL_DEFAULT, vargs); va_end(vargs); return iret; } @@ -55,7 +55,7 @@ int CEventLog::EventWarn(lpctstr pszFormat, ...) noexcept { va_list vargs; va_start(vargs, pszFormat); - int iret = VEvent(LOGL_WARN, pszFormat, vargs); + int iret = VEvent(LOGL_WARN, pszFormat, CTCOL_DEFAULT, vargs); va_end(vargs); return iret; } @@ -64,7 +64,7 @@ int CEventLog::EventCustom(ConsoleTextColor iColor, dword dwMask, lpctstr pszFor { va_list vargs; va_start(vargs, pszFormat); - int iret = VEvent(dwMask, pszFormat, vargs, iColor); + int iret = VEvent(dwMask, pszFormat, iColor, vargs); va_end(vargs); return iret; } @@ -74,7 +74,7 @@ int CEventLog::EventEvent(lpctstr pszFormat, ...) noexcept { va_list vargs; va_start(vargs, pszFormat); - int iret = VEvent(LOGL_EVENT, pszFormat, vargs); + int iret = VEvent(LOGL_EVENT, pszFormat, CTCOL_DEFAULT, vargs); va_end(vargs); return iret; } diff --git a/src/common/CLog.h b/src/common/CLog.h index 2fb9f13f2..afbe6a070 100644 --- a/src/common/CLog.h +++ b/src/common/CLog.h @@ -61,7 +61,7 @@ class CEventLog protected: virtual int EventStr(dword dwMask, lpctstr pszMsg, ConsoleTextColor iColor = CTCOL_DEFAULT) noexcept = 0; - int VEvent(dword dwMask, lpctstr pszFormat, va_list args, ConsoleTextColor iColor = CTCOL_DEFAULT) noexcept; + int VEvent(dword dwMask, lpctstr pszFormat, ConsoleTextColor iColor, va_list args) noexcept; public: int _cdecl Event( dword dwMask, lpctstr pszFormat, ... ) noexcept __printfargs(3,4); From 4e1a9c0b7ebfef98b7baea4852d852de11525af3 Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Fri, 26 Apr 2024 20:02:54 +0100 Subject: [PATCH 82/90] Update CItemMulti.cpp --- src/game/items/CItemMulti.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index 83856c55f..a785494c1 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -2693,16 +2693,11 @@ bool CItemMulti::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc if (m_pRegion != nullptr) { if (!IsStrEmpty(ptcKey)) - { - if (m_pRegion) - return m_pRegion->r_WriteVal(ptcKey, sVal, pSrc); - } - - if (m_pRegion) - sVal.FormatHex(m_pRegion->GetResourceID().GetObjUID()); - else - sVal.FormatHex(0); + return m_pRegion->r_WriteVal(ptcKey, sVal, pSrc); + sVal.FormatHex(m_pRegion->GetResourceID().GetObjUID()); } + else + sVal.FormatHex(0); break; } case SHL_OWNER: From 999f3afea1fd60e7d0dec91c4d3bfe05e9715647 Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Fri, 26 Apr 2024 20:11:23 +0100 Subject: [PATCH 83/90] ResourceGetName --- src/common/resource/CResourceHolder.cpp | 2 +- src/common/resource/CResourceHolder.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/resource/CResourceHolder.cpp b/src/common/resource/CResourceHolder.cpp index 1475a0128..78d2662da 100644 --- a/src/common/resource/CResourceHolder.cpp +++ b/src/common/resource/CResourceHolder.cpp @@ -301,7 +301,7 @@ lpctstr CResourceHolder::ResourceGetName(const CResourceIDBase& rid, RES_TYPE iE { ridValid = rid; } - return g_Cfg.ResourceGetName(ridValid); // Even it's 0, we should return it's name, as it can be mr_nothing. + return ResourceGetName(ridValid); // Even it's 0, we should return it's name, as it can be mr_nothing. } lpctstr CResourceHolder::ResourceGetName( const CResourceID& rid ) const diff --git a/src/common/resource/CResourceHolder.h b/src/common/resource/CResourceHolder.h index 73575da02..6174bb637 100644 --- a/src/common/resource/CResourceHolder.h +++ b/src/common/resource/CResourceHolder.h @@ -41,7 +41,7 @@ class CResourceHolder : public CScriptObj static lpctstr GetResourceBlockName( RES_TYPE restype ); lpctstr GetName() const; lpctstr ResourceGetName( const CResourceID& rid ) const; - static lpctstr ResourceGetName(const CResourceIDBase& rid, const RES_TYPE iExpectedType); + lpctstr ResourceGetName(const CResourceIDBase& rid, const RES_TYPE iExpectedType); CResourceScript * GetResourceFile( size_t i ); CResourceID ResourceGetID_Advance( RES_TYPE restype, lpctstr &pszName, word wPage = 0 ); // this moves forward (changes!) the ptcName pointer! CResourceID ResourceGetID( RES_TYPE restype, lpctstr ptcName, word wPage = 0 ); From 0f7fc6632cb028d2bb9fbabd0e7da173b2461330 Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Fri, 26 Apr 2024 20:11:39 +0100 Subject: [PATCH 84/90] std::max/min --- src/game/chars/CCharSkill.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index d57eb931d..2c86eead2 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -3850,7 +3850,7 @@ int CChar::Skill_Done() return -SKTRIG_ABORT; } - int chance = minimum(maximum((int)args.m_VarsLocal.GetKeyNum("ITEMDAMAGECHANCE"), 0), 100); + int chance = std::min(std::max((int)args.m_VarsLocal.GetKeyNum("ITEMDAMAGECHANCE"), (int)0), (int)100); if (IsSetEF(EF_DamageTools) && g_Cfg.IsSkillFlag(skill, SKF_GATHER) && chance > 0) { CItem* pTool = LayerFind(LAYER_HAND1); @@ -3861,7 +3861,7 @@ int CChar::Skill_Done() { if (Calc_GetRandVal(100) < chance) { - int amount = maximum(minimum((int)args.m_VarsLocal.GetKeyNum("ITEMDAMAGEAMOUNT"), pTool->m_itWeapon.m_dwHitsCur), 0); + int amount = std::max(std::min((int)args.m_VarsLocal.GetKeyNum("ITEMDAMAGEAMOUNT"), (int)pTool->m_itWeapon.m_dwHitsCur), 0); pTool->OnTakeDamage(amount, nullptr, DAMAGE_GOD); } } From de007c2bfd6cdfea7af4280497573deee1b56073 Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Fri, 26 Apr 2024 22:26:56 +0100 Subject: [PATCH 85/90] Revert spellflag_targ_onlyself update --- Changelog.txt | 5 +---- src/game/chars/CCharNPCAct_Magic.cpp | 27 ++++++++++++--------------- src/game/clients/CClientTarg.cpp | 6 ------ src/game/game_macros.h | 3 +-- src/tables/defmessages.tbl | 1 - 5 files changed, 14 insertions(+), 28 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index 2258b203f..a9867e636 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3466,9 +3466,6 @@ Additionally, the problem of zig-zag issue following in the South direction has - Changed: Decay time removed from spawned items, as Sphere gives tons of invalid link errors when items decayed. (Issue: #1218) - Added: New spellflag SPELLFLAG_FIELD_RANDOMDECAY (0100000000) to randomize field timers like old sphere versions. (Issue: #1169) SPELLFLAG_FIELD_RANDOMDECAY should be added to defs. -- Added: New spellflag SPELLFLAG_TARG_ONLYSELF (0200000000) to make spell only be used on character himself. (Issue: #1171) - SPELLFLAG_TARG_ONLYSELF should be added to defs. - //magery_9 "You can only use this spell on yourself." could be added to defmessages. - Changed: SERV.LOG command changed to support console colors. (Issue: [Feature Request] Colored Serv & Src Log System #1158) SERV.LOG works same as before. Usage of custom color system is: SERV.LOG @color,type,mask message @@ -3571,7 +3568,7 @@ Additionally, the problem of zig-zag issue following in the South direction has 08-04-2024, xwerswoodx - Fixed: Missing REGION reference for multis. (Issue: #1228) -- Added: SPELLFLAG_NO_ELEMENTALENGINE (0400000000) as spellflag, for ignoring Elemental Engine Damages in specific spells. (Issue: #1230) +- Added: SPELLFLAG_NO_ELEMENTALENGINE (0200000000) as spellflag, for ignoring Elemental Engine Damages in specific spells. (Issue: #1230) 09-04-2024, xwerswoodx - Fixed: An issue that causes T_MULTI_CUSTOM keep multi count saved. (Issue: #1232) diff --git a/src/game/chars/CCharNPCAct_Magic.cpp b/src/game/chars/CCharNPCAct_Magic.cpp index 7a45bd1cb..1029f2822 100644 --- a/src/game/chars/CCharNPCAct_Magic.cpp +++ b/src/game/chars/CCharNPCAct_Magic.cpp @@ -316,28 +316,25 @@ bool CChar::NPC_FightCast(CObjBase * &pTarg, CObjBase * pSrc, SPELL_TYPE &spell, if (NPC_GetAiFlags()&NPC_AI_COMBAT && !bIgnoreAITargetChoice) { - if (!pSpellDef->IsSpellType(SPELLFLAG_TARG_ONLYSELF)) { - // search for the neariest friend in combat if the spell has no SPELLFLAG_TARG_ONLYSELF flag. - CWorldSearch AreaChars(GetTopPoint(), UO_MAP_VIEW_SIGHT); - for (;;) + CWorldSearch AreaChars(GetTopPoint(), UO_MAP_VIEW_SIGHT); + for (;;) + { + pTarget = AreaChars.GetChar(); + if (!pTarget) + break; + + CItemMemory* pMemory = pTarget->Memory_FindObj(pTarg); + if (pMemory && pMemory->IsMemoryTypes(MEMORY_FIGHT | MEMORY_HARMEDBY | MEMORY_IRRITATEDBY)) { - pTarget = AreaChars.GetChar(); - if (!pTarget) + pFriend[iFriendIndex++] = pTarget; + if (iFriendIndex >= 4) break; - - CItemMemory* pMemory = pTarget->Memory_FindObj(pTarg); - if (pMemory && pMemory->IsMemoryTypes(MEMORY_FIGHT | MEMORY_HARMEDBY | MEMORY_IRRITATEDBY)) - { - pFriend[iFriendIndex++] = pTarget; - if (iFriendIndex >= 4) - break; - } } } } // i cannot cast this on self. ok, then friends only - if (pSpellDef->IsSpellType(SPELLFLAG_TARG_NOSELF) && !pSpellDef->IsSpellType(SPELLFLAG_TARG_ONLYSELF)) //Make sure the spell has no ONLYSELF flag to avoid issues. + if (pSpellDef->IsSpellType(SPELLFLAG_TARG_NOSELF)) { pFriend[0] = pFriend[1]; pFriend[1] = pFriend[2]; diff --git a/src/game/clients/CClientTarg.cpp b/src/game/clients/CClientTarg.cpp index 94656352f..c949b8642 100644 --- a/src/game/clients/CClientTarg.cpp +++ b/src/game/clients/CClientTarg.cpp @@ -1475,12 +1475,6 @@ bool CClient::OnTarg_Skill_Magery( CObjBase * pObj, const CPointMap & pt ) } } - if (pObj != m_pChar && pSpell->IsSpellType(SPELLFLAG_TARG_ONLYSELF) && !IsPriv(PRIV_GM)) - { - SysMessageDefault(DEFMSG_MAGERY_9); - return true; - } - if (pObj == m_pChar && pSpell->IsSpellType( SPELLFLAG_TARG_NOSELF ) && !IsPriv(PRIV_GM) ) { SysMessageDefault( DEFMSG_MAGERY_3 ); diff --git a/src/game/game_macros.h b/src/game/game_macros.h index f948c61d0..07646af56 100644 --- a/src/game/game_macros.h +++ b/src/game/game_macros.h @@ -106,7 +106,6 @@ typedef dword DAMAGE_TYPE; // describe a type of damage. #define SPELLFLAG_HEAL 0x40000000 // Healing spell #define SPELLFLAG_TICK 0x80000000 // A ticking spell like Poison. #define SPELLFLAG_FIELD_RANDOMDECAY 0x100000000 // Make the field items have random timers. -#define SPELLFLAG_TARG_ONLYSELF 0x200000000 // You can only target yourself. -#define SPELLFLAG_NO_ELEMENTALENGINE 0x400000000 +#define SPELLFLAG_NO_ELEMENTALENGINE 0x200000000 #endif // _INC_GAME_MACROS_H diff --git a/src/tables/defmessages.tbl b/src/tables/defmessages.tbl index d638763d4..781103de2 100644 --- a/src/tables/defmessages.tbl +++ b/src/tables/defmessages.tbl @@ -342,7 +342,6 @@ MSG(MAGERY_5, "You have not yet finished preparing the spell.") MSG(MAGERY_6, "An anti-magic field disturbs the spell.") MSG(MAGERY_7, "You cannot target a player with this spell.") MSG(MAGERY_8, "You cannot target an NPC with this spell.") -MSG(MAGERY_9, "You can only use this spell on yourself.") MSG(MAKESUCCESS_1, "Due to your poor skill, the item is of shoddy quality") MSG(MAKESUCCESS_2, "You were barely able to make this item. It is of poor quality") MSG(MAKESUCCESS_3, "You make the item, but it is of below average quality") From a7a494a6b7723ef799baee9d3fcfb24e7d7d7d50 Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Sat, 27 Apr 2024 15:49:58 +0100 Subject: [PATCH 86/90] H Keyword/Sphere Switch --- Changelog.txt | 16 +++++++++++++++- src/common/CScriptObj.cpp | 12 +++++++++++- src/common/CVarDefMap.cpp | 5 +++-- src/common/ListDefContMap.cpp | 7 +++++-- src/game/CServerConfig.cpp | 5 ++++- src/game/CServerConfig.h | 1 + src/sphere.ini | 5 +++++ 7 files changed, 44 insertions(+), 7 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index a9867e636..f4afd4b47 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3631,6 +3631,10 @@ Additionally, the problem of zig-zag issue following in the South direction has - MapViewRadar affects the visibility range of the multis (castles, keeps, ships etc) and the range of spy glass. (Spyglass range is MapViewRadar - 5) - MapViewSize affects the visibility range of the items. - MapViewSizeMax is the maximum range of MapViewSize allowed for increasing VISUALRANGE on clients. +Added: 'H' shortcut for variables to get the value as hexadecimal. + For example, if you use .tag.test 100 + returns 100 + returns 064 - Merged: raydienull's LAYER_STABLE (81) build merged, but LAYER_AUCTION keep same while LAYER_STABLE added as a new layer. (PR: #1201) - Fixed: raydienull's LAYER_STABLE follower triggers isn't called while taking pet out of stable. - Fixed: raydienull's LAYER_STABLE doesn't work with the new follower system. @@ -3701,4 +3705,14 @@ Additionally, the problem of zig-zag issue following in the South direction has - EF_DAMAGETOOLS only affects the skills with SKF_GATHER flag. - Added: CAN_I_SCRIPTEDMORE (020000000) as item CAN. - This can flag ignores MORE values that entered for hardcoded behaviour. - - It's new flag, need couple of updates for fully implemented. \ No newline at end of file + - It's new flag, need couple of updates for fully implemented. + +27-04-2024, xwerswoodx +- Fixed: Return of variables were return decimal value (10-base) instead of hexadecimal (16-base). +- Added: DecimalVariables (boolean) keyword for sphere.ini. (Default: 0) + 0: Makes Sphere return variables (TAGs, LOCALs, etc.) in hexadecimal (16-base) + 1: Makes Sphere return variables (TAGs, LOCALs, etc.) in decimal (10-base) + IMPORTANT: If you were using == DECIMAL for checking in your scripts and want to keep that behaviour, + you have to add DecimalVariables=1 to Sphere.ini. + SUGGESTION: Always use for hexadecimal returns, and for decimal returns to avoid any future issues, + when you switch this setting. \ No newline at end of file diff --git a/src/common/CScriptObj.cpp b/src/common/CScriptObj.cpp index 02978f202..5bc148a3d 100644 --- a/src/common/CScriptObj.cpp +++ b/src/common/CScriptObj.cpp @@ -538,7 +538,17 @@ bool CScriptObj::r_WriteVal( lpctstr ptcKey, CSString &sVal, CTextConsole * pSrc return true; } - } + } + else if ((*ptcKey == 'h') || (*ptcKey == 'H')) // same as > to get hex from the val + { + lpctstr sArgs = ptcKey + 1; + if (r_WriteVal(sArgs, sVal, pSrc)) + { + if (*sVal != '-') + sVal.FormatLLHex(ahextoi64(sVal)); + return true; + } + } // , , are shortcuts to rand(), rand(15) and rand(3,15) else if (( *ptcKey == 'r' ) || ( *ptcKey == 'R' )) { diff --git a/src/common/CVarDefMap.cpp b/src/common/CVarDefMap.cpp index fee20a0a5..f4d54a0d5 100644 --- a/src/common/CVarDefMap.cpp +++ b/src/common/CVarDefMap.cpp @@ -1,6 +1,7 @@ #include "../common/CLog.h" -#include "../game/CServer.h" +#include "../game/CServer.h" +#include "../game/CServerConfig.h" #include "CException.h" #include "CExpression.h" #include "CScript.h" @@ -42,7 +43,7 @@ CVarDefContNum::CVarDefContNum( lpctstr ptcKey ) : m_sKey( ptcKey ), m_iVal( 0 ) lpctstr CVarDefContNum::GetValStr() const { - return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), 16); + return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), (g_Cfg.m_bDecimalVariables ? 10 : 16)); } bool CVarDefContNum::r_LoadVal( CScript & s ) diff --git a/src/common/ListDefContMap.cpp b/src/common/ListDefContMap.cpp index d166db1d1..c6817bf20 100644 --- a/src/common/ListDefContMap.cpp +++ b/src/common/ListDefContMap.cpp @@ -1,7 +1,8 @@ #include "../common/sphere_library/sstringobjs.h" #include "../common/CLog.h" -#include "../sphere/threads.h" +#include "../sphere/threads.h" +#include "../game/CServerConfig.h" #include "CExpression.h" #include "CScript.h" #include "CTextConsole.h" @@ -25,7 +26,9 @@ CListDefContNum::CListDefContNum( lpctstr ptcKey ) : CListDefContElem( ptcKey ), } lpctstr CListDefContNum::GetValStr() const -{ +{ + // Left it commented because seems like CListDefContNum is not using anymore. + //return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), (g_Cfg.m_bDecimalVariables ? 10 : 16)); return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), 16); } diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 35f926ba2..bce4607e9 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -50,6 +50,7 @@ CServerConfig::CServerConfig() m_iFreezeRestartTime = 60; m_bAgree = false; m_fMd5Passwords = false; + m_bDecimalVariables = false; // In default, variables should return hexadecimal. //Magic m_fManaLossAbort = false; @@ -514,6 +515,7 @@ enum RC_TYPE RC_DISTANCETALK, RC_DISTANCEWHISPER, RC_DISTANCEYELL, + RC_DECIMALVARIABLES, RC_DRAGWEIGHTMAX, #ifdef _DUMPSUPPORT RC_DUMPPACKETSFORACC, @@ -711,7 +713,7 @@ enum RC_TYPE }; // NOTE: Need to be alphabetized order -const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY+1] +const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { { "ACCTFILES", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sAcctBaseDir) }}, { "ADVANCEDLOS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAdvancedLos) }}, @@ -783,6 +785,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY+1] { "DEADSOCKETTIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDeadSocketTime) }}, { "DEBUGFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iDebugFlags) }}, { "DECAYTIMER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDecay_Item) }}, + { "DECIMALVARIABLES", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bDecimalVariables) }}, { "DEFAULTCOMMANDLEVEL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDefaultCommandLevel) }}, { "DISPLAYARMORASPERCENT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fDisplayPercentAr) }}, { "DISPLAYELEMENTALRESISTANCE",{ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fDisplayElementalResistance)}}, diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index f9c7df8a9..db46e92a6 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -591,6 +591,7 @@ extern class CServerConfig : public CResourceHolder int m_iMaxPolyStats; // Max amount of each Stat gained through Polymorph spell. This affects separatelly to each stat. bool m_NPCShoveNPC; //NPC can walk through other NPC, by default this is disabled. + bool m_bDecimalVariables; //Variables like TAGs, LOCALs returns as decimal (10 base) instead of Hex. // End INI file options. CResourceScript m_scpIni; // Keep this around so we can link to it. diff --git a/src/sphere.ini b/src/sphere.ini index 973a06868..1e81871d6 100644 --- a/src/sphere.ini +++ b/src/sphere.ini @@ -268,6 +268,11 @@ EraLimitLoot = 9 // Don't allow to chars (players and NPCs) to have properties newer than the ones from the expansion in the given value (Clothes, weapons, hairs ...). EraLimitProps = 9 +// Define the default return base for variables like TAGs, LOCALs etc. +// 0: Hexadecimal return (base-16) +// 1: Decimal return (base-10) +//DecimalVariables=0 + // Maximum distance to hear char whispering // (-1 = never hear, 0 = hear if distance is <= listener's VisualRange) //DistanceWhisper=3 From cdc2e62d11caaaa7e0a0ef14230808f7a109a9fc Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Sat, 27 Apr 2024 19:06:17 +0100 Subject: [PATCH 87/90] Update CServerConfig.cpp --- src/game/CServerConfig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index bce4607e9..172141edd 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -50,7 +50,7 @@ CServerConfig::CServerConfig() m_iFreezeRestartTime = 60; m_bAgree = false; m_fMd5Passwords = false; - m_bDecimalVariables = false; // In default, variables should return hexadecimal. + m_fDecimalVariables = false; // In default, variables should return hexadecimal. //Magic m_fManaLossAbort = false; @@ -785,7 +785,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { "DEADSOCKETTIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDeadSocketTime) }}, { "DEBUGFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,m_iDebugFlags) }}, { "DECAYTIMER", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDecay_Item) }}, - { "DECIMALVARIABLES", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bDecimalVariables) }}, + { "DECIMALVARIABLES", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fDecimalVariables) }}, { "DEFAULTCOMMANDLEVEL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iDefaultCommandLevel) }}, { "DISPLAYARMORASPERCENT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fDisplayPercentAr) }}, { "DISPLAYELEMENTALRESISTANCE",{ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fDisplayElementalResistance)}}, From 3b24fea45a6c8d51e5a498266ca903094102e30f Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Sat, 27 Apr 2024 19:10:43 +0100 Subject: [PATCH 88/90] Build Fix --- src/common/CVarDefMap.cpp | 2 +- src/common/ListDefContMap.cpp | 2 +- src/game/CServerConfig.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/CVarDefMap.cpp b/src/common/CVarDefMap.cpp index f4d54a0d5..d63da200f 100644 --- a/src/common/CVarDefMap.cpp +++ b/src/common/CVarDefMap.cpp @@ -43,7 +43,7 @@ CVarDefContNum::CVarDefContNum( lpctstr ptcKey ) : m_sKey( ptcKey ), m_iVal( 0 ) lpctstr CVarDefContNum::GetValStr() const { - return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), (g_Cfg.m_bDecimalVariables ? 10 : 16)); + return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), (g_Cfg.m_fDecimalVariables ? 10 : 16)); } bool CVarDefContNum::r_LoadVal( CScript & s ) diff --git a/src/common/ListDefContMap.cpp b/src/common/ListDefContMap.cpp index c6817bf20..49693b997 100644 --- a/src/common/ListDefContMap.cpp +++ b/src/common/ListDefContMap.cpp @@ -28,7 +28,7 @@ CListDefContNum::CListDefContNum( lpctstr ptcKey ) : CListDefContElem( ptcKey ), lpctstr CListDefContNum::GetValStr() const { // Left it commented because seems like CListDefContNum is not using anymore. - //return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), (g_Cfg.m_bDecimalVariables ? 10 : 16)); + //return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), (g_Cfg.m_fDecimalVariables ? 10 : 16)); return Str_FromLL_Fast(m_iVal, Str_GetTemp(), Str_TempLength(), 16); } diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index db46e92a6..5c0611849 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -591,7 +591,7 @@ extern class CServerConfig : public CResourceHolder int m_iMaxPolyStats; // Max amount of each Stat gained through Polymorph spell. This affects separatelly to each stat. bool m_NPCShoveNPC; //NPC can walk through other NPC, by default this is disabled. - bool m_bDecimalVariables; //Variables like TAGs, LOCALs returns as decimal (10 base) instead of Hex. + bool m_fDecimalVariables; //Variables like TAGs, LOCALs returns as decimal (10 base) instead of Hex. // End INI file options. CResourceScript m_scpIni; // Keep this around so we can link to it. From 762b6c8bf7cec58975bb5a3095467e582d47c4a4 Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Sat, 27 Apr 2024 21:13:21 +0100 Subject: [PATCH 89/90] Some Prefix Changes --- src/common/CDataBase.cpp | 18 +++++------ src/common/CDataBase.h | 2 +- src/common/CServerMap.cpp | 6 ++-- src/common/CServerMap.h | 2 +- src/common/crashdump/crashdump.cpp | 14 ++++----- src/common/crashdump/crashdump.h | 2 +- src/game/CSector.cpp | 12 ++++---- src/game/CServer.cpp | 4 +-- src/game/CServerConfig.cpp | 48 +++++++++++++++--------------- src/game/CServerConfig.h | 16 +++++----- src/game/CServerDef.cpp | 8 ++--- src/game/chars/CChar.cpp | 10 +++---- src/game/chars/CCharNotoriety.cpp | 2 +- src/game/chars/CCharSkill.cpp | 2 +- src/game/chars/CCharStatus.cpp | 2 +- src/game/clients/CClient.cpp | 2 +- src/game/clients/CClient.h | 2 +- src/game/clients/CClientEvent.cpp | 30 +++++++++---------- src/game/clients/CClientMsg.cpp | 2 +- 19 files changed, 92 insertions(+), 92 deletions(-) diff --git a/src/common/CDataBase.cpp b/src/common/CDataBase.cpp index 022629b3a..ee4b011ce 100644 --- a/src/common/CDataBase.cpp +++ b/src/common/CDataBase.cpp @@ -13,7 +13,7 @@ extern CDataBaseAsyncHelper g_asyncHdb; CDataBase::CDataBase() { - m_bConnected = false; + m_fConnected = false; _myData = nullptr; } @@ -28,14 +28,14 @@ bool CDataBase::Connect(const char *user, const char *password, const char *base ADDTOCALLSTACK("CDataBase::Connect"); SimpleThreadLock lock(m_connectionMutex); - m_bConnected = false; + m_fConnected = false; // Starting with MariaDB 10.6.2+ the format for mysql_get_client_version* changed to report the version of the client library instead of the server version. unsigned long ver = mysql_get_client_version(); if ( ver < MIN_MARIADB_VERSION_ALLOW ) { g_Log.Event(LOGM_NOCONTEXT|LOGL_ERROR, "Your MariaDB client library is too old (version %lu). Minimal allowed version is %d. MySQL support disabled.\n", ver, MIN_MARIADB_VERSION_ALLOW); - g_Cfg.m_bMySql = false; + g_Cfg.m_fMySql = false; return false; } @@ -63,7 +63,7 @@ bool CDataBase::Connect(const char *user, const char *password, const char *base return false; } - return (m_bConnected = true); + return (m_fConnected = true); } bool CDataBase::Connect() @@ -75,7 +75,7 @@ bool CDataBase::Connect() bool CDataBase::isConnected() { ADDTOCALLSTACK("CDataBase::isConnected"); - return m_bConnected; + return m_fConnected; } void CDataBase::Close() @@ -84,7 +84,7 @@ void CDataBase::Close() SimpleThreadLock lock(m_connectionMutex); mysql_close(_myData); _myData = nullptr; - m_bConnected = false; + m_fConnected = false; } bool CDataBase::query(const char *query, CVarDefMap & mapQueryResult) @@ -258,7 +258,7 @@ bool CDataBase::_OnTick() static int tickcnt = 0; EXC_TRY("Tick"); - if ( !g_Cfg.m_bMySql ) // MariaDB is not supported + if ( !g_Cfg.m_fMySql ) // MariaDB is not supported return true; // do not ping sql server too heavily @@ -390,7 +390,7 @@ bool CDataBase::r_WriteVal(lpctstr ptcKey, CSString &sVal, CTextConsole *pSrc, b EXC_TRY("WriteVal"); // Just return 0 if MySQL/MariaDB is disabled - if (!g_Cfg.m_bMySql) + if (!g_Cfg.m_fMySql) { sVal.FormatVal( 0 ); return true; @@ -472,7 +472,7 @@ bool CDataBase::r_Verb(CScript & s, CTextConsole * pSrc) EXC_TRY("Verb"); // Just return true if MySQL/MariaDB is disabled - if (!g_Cfg.m_bMySql) + if (!g_Cfg.m_fMySql) return true; int index = FindTableSorted(s.GetKey(), sm_szVerbKeys, ARRAY_COUNT(sm_szVerbKeys)-1); diff --git a/src/common/CDataBase.h b/src/common/CDataBase.h index 37cb7fbfa..b956eb555 100644 --- a/src/common/CDataBase.h +++ b/src/common/CDataBase.h @@ -70,7 +70,7 @@ class CDataBase : public CScriptObj typedef std::queue QueueFunction_t; protected: - bool m_bConnected; // are we online? + bool m_fConnected; // are we online? MYSQL *_myData; // mySQL link QueueFunction_t m_QueryArgs; diff --git a/src/common/CServerMap.cpp b/src/common/CServerMap.cpp index 8cdda9552..a711ffb20 100644 --- a/src/common/CServerMap.cpp +++ b/src/common/CServerMap.cpp @@ -639,7 +639,7 @@ size_t CUOMulti::Load(MULTI_TYPE id) CServerMapDiffCollection::CServerMapDiffCollection() { - m_bLoaded = false; + m_fLoaded = false; } CServerMapDiffCollection::~CServerMapDiffCollection() @@ -658,7 +658,7 @@ void CServerMapDiffCollection::LoadMapDiffs() { // Load mapdif* and stadif* Files ADDTOCALLSTACK("CServerMapDiffCollection::LoadMapDiffs"); - if ( m_bLoaded ) // already loaded + if ( m_fLoaded ) // already loaded return; CServerMapDiffBlock * pMapDiffBlock = nullptr; @@ -787,7 +787,7 @@ void CServerMapDiffCollection::LoadMapDiffs() } // Stadif } - m_bLoaded = true; + m_fLoaded = true; } void CServerMapDiffCollection::Init() diff --git a/src/common/CServerMap.h b/src/common/CServerMap.h index ef33a88ea..3971d01ed 100644 --- a/src/common/CServerMap.h +++ b/src/common/CServerMap.h @@ -148,7 +148,7 @@ class CServerMapDiffCollection { // This class will be used to access mapdiff data private: - bool m_bLoaded; + bool m_fLoaded; CServerMapDiffBlockArray m_pMapDiffBlocks[MAP_SUPPORTED_QTY]; CServerMapDiffBlock * GetNewBlock( dword dwBlockId, int map ); diff --git a/src/common/crashdump/crashdump.cpp b/src/common/crashdump/crashdump.cpp index d023ec2da..9d26a3dc2 100644 --- a/src/common/crashdump/crashdump.cpp +++ b/src/common/crashdump/crashdump.cpp @@ -2,13 +2,13 @@ #include "crashdump.h" -bool CrashDump::m_bEnabled = false; +bool CrashDump::m_fEnabled = false; HMODULE CrashDump::m_hDll = nullptr; MINIDUMPWRITEDUMP CrashDump::m_tDumpFunction = nullptr; bool CrashDump::IsEnabled() { - return m_bEnabled; + return m_fEnabled; } void CrashDump::Enable() @@ -16,24 +16,24 @@ void CrashDump::Enable() m_hDll = LoadLibrary("dbghelp.dll"); if (!m_hDll) { - m_bEnabled = false; + m_fEnabled = false; return; } m_tDumpFunction = reinterpret_cast(GetProcAddress(m_hDll, "MiniDumpWriteDump")); if (!m_tDumpFunction) { - m_bEnabled = false; + m_fEnabled = false; FreeLibrary(m_hDll); return; } - m_bEnabled = true; + m_fEnabled = true; } void CrashDump::Disable() { - m_bEnabled = false; + m_fEnabled = false; if (m_tDumpFunction != nullptr) m_tDumpFunction = nullptr; @@ -75,4 +75,4 @@ void CrashDump::StartCrashDump( DWORD processID, DWORD threadID, struct _EXCEPTI return; } -#endif \ No newline at end of file +#endif diff --git a/src/common/crashdump/crashdump.h b/src/common/crashdump/crashdump.h index 1a84b9c40..8fdb81348 100644 --- a/src/common/crashdump/crashdump.h +++ b/src/common/crashdump/crashdump.h @@ -26,7 +26,7 @@ typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, class CrashDump { private: - static bool m_bEnabled; + static bool m_fEnabled; static HMODULE m_hDll; static MINIDUMPWRITEDUMP m_tDumpFunction; diff --git a/src/game/CSector.cpp b/src/game/CSector.cpp index ff7c954e0..21d6df1d3 100644 --- a/src/game/CSector.cpp +++ b/src/game/CSector.cpp @@ -286,7 +286,7 @@ bool CSector::r_LoadVal( CScript &s ) m_dwFlags = s.GetArgVal(); return true; case SC_LIGHT: - if ( g_Cfg.m_bAllowLightOverride ) + if ( g_Cfg.m_fAllowLightOverride ) SetLight( s.HasArgs() ? s.GetArgVal() : -1 ); else g_Log.EventWarn("AllowLightOverride flag is disabled in sphere.ini, so sector's LIGHT property wasn't set\n"); @@ -356,7 +356,7 @@ bool CSector::r_Verb( CScript & s, CTextConsole * pSrc ) SetWeather( WEATHER_DRY ); break; case SEV_LIGHT: - if ( g_Cfg.m_bAllowLightOverride ) + if ( g_Cfg.m_fAllowLightOverride ) SetLight( (s.HasArgs()) ? s.GetArgVal() : -1 ); else g_Log.EventWarn("AllowLightOverride flag is disabled in sphere.ini, so sector's LIGHT property wasn't set\n"); @@ -422,7 +422,7 @@ void CSector::r_Write() fHeaderCreated = true; } - if (g_Cfg.m_bAllowLightOverride && IsLightOverriden()) + if (g_Cfg.m_fAllowLightOverride && IsLightOverriden()) { if (fHeaderCreated == false ) { @@ -595,7 +595,7 @@ int CSector::GetLocalTime() const const CPointMap& pt(GetBasePoint()); int64 iLocalTime = CWorldGameTime::GetCurrentTimeInGameMinutes(); - if ( !g_Cfg.m_bAllowLightOverride ) + if ( !g_Cfg.m_fAllowLightOverride ) { iLocalTime += ( pt.m_x * 24*60 ) / g_MapList.GetMapSizeX(pt.m_map); } @@ -656,7 +656,7 @@ byte CSector::GetLightCalc( bool fQuickSet ) const ADDTOCALLSTACK("CSector::GetLightCalc"); // What is the light level default here in this sector. - if ( g_Cfg.m_bAllowLightOverride && IsLightOverriden() ) + if ( g_Cfg.m_fAllowLightOverride && IsLightOverriden() ) return m_Env.m_Light; if ( IsInDungeon() ) @@ -664,7 +664,7 @@ byte CSector::GetLightCalc( bool fQuickSet ) const int localtime = GetLocalTime(); - if ( !g_Cfg.m_bAllowLightOverride ) + if ( !g_Cfg.m_fAllowLightOverride ) { // Normalize time: // convert 0=midnight .. (23*60)+59=midnight diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index 0f97ae897..1b5384da1 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -2301,7 +2301,7 @@ nowinsock: g_Log.Event(LOGL_FATAL|LOGM_INIT, "Winsock 1.1 not found!\n"); #ifdef _NIGHTLYBUILD g_Log.Event(LOGL_WARN|LOGF_LOGFILE_ONLY, pszNightlyMsg); - if (!g_Cfg.m_bAgree) + if (!g_Cfg.m_fAgree) { g_Log.Event(LOGL_ERROR,"Please write AGREE=1 in Sphere.ini file to acknowledge that\nyou understand the risks of using nightly builds.\n"); return false; @@ -2313,7 +2313,7 @@ nowinsock: g_Log.Event(LOGL_FATAL|LOGM_INIT, "Winsock 1.1 not found!\n"); g_Log.Event(LOGM_INIT, wSockInfo); #endif - if (g_Cfg.m_bMySql && g_Cfg.m_bMySqlTicks) + if (g_Cfg.m_fMySql && g_Cfg.m_fMySqlTicks) { EXC_SET_BLOCK( "Connecting to MySQL server" ); if (_hDb.Connect()) diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 172141edd..b0be586eb 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -48,7 +48,7 @@ CServerConfig::CServerConfig() m_iDebugFlags = 0; //DEBUGF_NPC_EMOTE m_fSecure = true; m_iFreezeRestartTime = 60; - m_bAgree = false; + m_fAgree = false; m_fMd5Passwords = false; m_fDecimalVariables = false; // In default, variables should return hexadecimal. @@ -244,19 +244,19 @@ CServerConfig::CServerConfig() m_fUOGStatus = true; // Experience - m_bExperienceSystem = false; + m_fExperienceSystem = false; m_iExperienceMode = 0; m_iExperienceKoefPVP = 100; m_iExperienceKoefPVM = 100; - m_bLevelSystem = false; + m_fLevelSystem = false; m_iLevelMode = LEVEL_MODE_DOUBLE; m_iLevelNextAt = 0; // MySQL support - m_bMySql = false; - m_bMySqlTicks = false; + m_fMySql = false; + m_fMySqlTicks = false; - m_bAutoResDisp = true; + m_fAutoResDisp = true; m_iAutoPrivFlags = 0; _iEraLimitGear = RESDISPLAY_VERSION(RDS_QTY - 1); // Always latest by default @@ -275,8 +275,8 @@ CServerConfig::CServerConfig() _iTimerCall = 0; _iTimerCallUnit = 0; - m_bAllowLightOverride = true; - m_bAllowNewbTransfer = false; + m_fAllowLightOverride = true; + m_fAllowNewbTransfer = false; m_sZeroPoint = "1323,1624,0"; m_fAllowBuySellAgent = false; @@ -443,8 +443,8 @@ enum RC_TYPE RC_ADVANCEDLOS, // m_iAdvancedLos RC_AGREE, RC_ALLOWBUYSELLAGENT, // m_fAllowBuySellAgent - RC_ALLOWLIGHTOVERRIDE, // m_bAllowLightOverride - RC_ALLOWNEWBTRANSFER, // m_bAllowNewbTransfer + RC_ALLOWLIGHTOVERRIDE, // m_fAllowLightOverride + RC_ALLOWNEWBTRANSFER, // m_fAllowNewbTransfer RC_ARCHERYMAXDIST, // m_iArcheryMaxDist RC_ARCHERYMINDIST, // m_iArcheryMinDist RC_AREAFLAGS, // _uiAreaFlags @@ -455,7 +455,7 @@ enum RC_TYPE RC_AUTONEWBIEKEYS, // m_fAutoNewbieKeys RC_AUTOPRIVFLAGS, // m_iAutoPrivFlags RC_AUTOPROCESSPRIORITY, // m_iAutoProcessPriority - RC_AUTORESDISP, // m_bAutoResDisp + RC_AUTORESDISP, // m_fAutoResDisp RC_AUTOSHIPKEYS, // _fAutoShipKeys RC_BACKPACKOVERLOAD, // m_iBackpackOverload RC_BACKUPLEVELS, // m_iSaveBackupLevels @@ -533,7 +533,7 @@ enum RC_TYPE RC_EXPERIENCEKOEFPVM, // m_iExperienceKoefPVM RC_EXPERIENCEKOEFPVP, // m_iExperienceKoefPVP RC_EXPERIENCEMODE, // m_iExperienceMode - RC_EXPERIENCESYSTEM, // m_bExperienceSystem + RC_EXPERIENCESYSTEM, // m_fExperienceSystem RC_EXPERIMENTAL, // _uiExperimentalFlags RC_FEATURESAOS, RC_FEATURESEXTRA, @@ -563,7 +563,7 @@ enum RC_TYPE RC_ITEMSMAXAMOUNT, // m_iItemsMaxAmount RC_LEVELMODE, // m_iLevelMode RC_LEVELNEXTAT, // m_iLevelNextAt - RC_LEVELSYSTEM, // m_bLevelSystem + RC_LEVELSYSTEM, // m_fLevelSystem RC_LIGHTDAY, // m_iLightDay RC_LIGHTNIGHT, // m_iLightNight RC_LOCALIPADMIN, // m_fLocalIPAdmin @@ -614,11 +614,11 @@ enum RC_TYPE RC_MULFILES, RC_MURDERDECAYTIME, // m_iMurderDecayTime; RC_MURDERMINCOUNT, // m_iMurderMinCount - RC_MYSQL, // m_bMySql + RC_MYSQL, // m_fMySql RC_MYSQLDB, // m_sMySqlDatabase RC_MYSQLHOST, // m_sMySqlHost RC_MYSQLPASS, // m_sMySqlPassword - RC_MYSQLTICKS, // m_bMySqlTicks + RC_MYSQLTICKS, // m_fMySqlTicks RC_MYSQLUSER, // m_sMySqlUser RC_NETTTL, // m_iNetHistoryTTL RC_NETWORKTHREADPRIORITY, // _uiNetworkThreadPriority @@ -717,10 +717,10 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { { "ACCTFILES", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sAcctBaseDir) }}, { "ADVANCEDLOS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAdvancedLos) }}, - { "AGREE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAgree) }}, + { "AGREE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAgree) }}, { "ALLOWBUYSELLAGENT", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAllowBuySellAgent) }}, - { "ALLOWLIGHTOVERRIDE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAllowLightOverride) }}, - { "ALLOWNEWBTRANSFER", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAllowNewbTransfer) }}, + { "ALLOWLIGHTOVERRIDE", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAllowLightOverride) }}, + { "ALLOWNEWBTRANSFER", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAllowNewbTransfer) }}, { "ARCHERYMAXDIST", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iArcheryMaxDist) }}, { "ARCHERYMINDIST", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iArcheryMinDist) }}, { "AREAFLAGS", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiAreaFlags) }}, @@ -731,7 +731,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { "AUTONEWBIEKEYS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAutoNewbieKeys) }}, { "AUTOPRIVFLAGS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAutoPrivFlags) }}, { "AUTOPROCESSPRIORITY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iAutoProcessPriority) }}, - { "AUTORESDISP", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bAutoResDisp) }}, + { "AUTORESDISP", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fAutoResDisp) }}, { "AUTOSHIPKEYS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,_fAutoShipKeys) }}, { "BACKPACKOVERLOAD", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iBackpackOverload) }}, { "BACKUPLEVELS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iSaveBackupLevels) }}, @@ -809,7 +809,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { "EXPERIENCEKOEFPVM", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iExperienceKoefPVM) }}, { "EXPERIENCEKOEFPVP", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iExperienceKoefPVP) }}, { "EXPERIENCEMODE", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iExperienceMode) }}, - { "EXPERIENCESYSTEM", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bExperienceSystem) }}, + { "EXPERIENCESYSTEM", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fExperienceSystem) }}, { "EXPERIMENTAL", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiExperimentalFlags) }}, { "FEATUREAOS", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureAOS) }}, { "FEATUREEXTRA", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iFeatureExtra) }}, @@ -839,7 +839,7 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { "ITEMSMAXAMOUNT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iItemsMaxAmount), }}, { "LEVELMODE", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLevelMode), }}, { "LEVELNEXTAT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLevelNextAt), }}, - { "LEVELSYSTEM", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bLevelSystem), }}, + { "LEVELSYSTEM", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fLevelSystem), }}, { "LIGHTDAY", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightDay), }}, { "LIGHTNIGHT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iLightNight), }}, { "LOCALIPADMIN", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fLocalIPAdmin), }}, // The local ip is assumed to be the admin. @@ -890,11 +890,11 @@ const CAssocReg CServerConfig::sm_szLoadKeys[RC_QTY + 1] { "MULFILES", { ELEM_VOID, 0 }}, { "MURDERDECAYTIME", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iMurderDecayTime) }}, { "MURDERMINCOUNT", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iMurderMinCount) }}, // amount of murders before we get title. - { "MYSQL", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bMySql) }}, + { "MYSQL", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fMySql) }}, { "MYSQLDATABASE", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sMySqlDB) }}, { "MYSQLHOST", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sMySqlHost) }}, { "MYSQLPASSWORD", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sMySqlPass) }}, - { "MYSQLTICKS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_bMySqlTicks) }}, + { "MYSQLTICKS", { ELEM_BOOL, static_castOFFSETOF(CServerConfig,m_fMySqlTicks) }}, { "MYSQLUSER", { ELEM_CSTRING, static_castOFFSETOF(CServerConfig,m_sMySqlUser) }}, { "NETTTL", { ELEM_INT, static_castOFFSETOF(CServerConfig,m_iNetHistoryTTL) }}, { "NETWORKTHREADPRIORITY", { ELEM_MASK_INT,static_castOFFSETOF(CServerConfig,_uiNetworkThreadPriority)}}, @@ -1121,7 +1121,7 @@ bool CServerConfig::r_LoadVal( CScript &s ) switch (i) { case RC_AGREE: - m_bAgree = (s.GetArgVal() != 0); + m_fAgree = (s.GetArgVal() != 0); break; case RC_ACCTFILES: // Put acct files here. m_sAcctBaseDir = CSFile::GetMergedFileName( s.GetArgStr(), "" ); diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 5c0611849..0ef0844f0 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -496,7 +496,7 @@ extern class CServerConfig : public CResourceHolder uint m_iNpcAi; // NPCAI Flags. // Experience system - bool m_bExperienceSystem; // Enables the experience system. + bool m_fExperienceSystem; // Enables the experience system. #define EXP_MODE_RAISE_COMBAT 0x0001 // Gain experience in combat. #define EXP_MODE_RAISE_CRAFT 0x0002 // Gain experience in crafts. #define EXP_MODE_ALLOW_DOWN 0x0004 // Allow experience to go down. @@ -505,13 +505,13 @@ extern class CServerConfig : public CResourceHolder int m_iExperienceMode; // Experience system settings: int m_iExperienceKoefPVM; // If combat experience gain is allowed, use these percents for gaining exp in Player versus Monster. 0 Disables the gain. int m_iExperienceKoefPVP; // If combat experience gain is allowed, use these percents for gaining exp in Player versus Player. 0 Disables the gain. - bool m_bLevelSystem; // Enable levels system (as a part of experience system). + bool m_fLevelSystem; // Enable levels system (as a part of experience system). #define LEVEL_MODE_LINEAR 0 // (each NextLevelAt exp will give a level up). #define LEVEL_MODE_DOUBLE 1 // (you need (NextLevelAt * (level+1)) to get a level up). int m_iLevelMode; // Level system settings uint m_iLevelNextAt; // Amount of experience to raise to the next level. - bool m_bAutoResDisp; // Set account RESDISP automatically based on player client version. + bool m_fAutoResDisp; // Set account RESDISP automatically based on player client version. int m_iAutoPrivFlags; // Default setting for new accounts specifying default priv level. RESDISPLAY_VERSION _iEraLimitGear; // Don't allow to create gear newer than the given era (softcoded). @@ -550,8 +550,8 @@ extern class CServerConfig : public CResourceHolder int m_iChatFlags; // MySQL features - bool m_bMySql; // Enables MySQL. - bool m_bMySqlTicks; // Enables ticks from MySQL. + bool m_fMySql; // Enables MySQL. + bool m_fMySqlTicks; // Enables ticks from MySQL. CSString m_sMySqlHost; // MySQL Host. CSString m_sMySqlUser; // MySQL User. CSString m_sMySqlPass; // MySQL Password. @@ -579,15 +579,15 @@ extern class CServerConfig : public CResourceHolder int64 _iItemHitpointsUpdate; // Update period for CCItemDamageable (in seconds in the ini, then converted to msecs). int64 _iTimerCall; // Amount of time (converted to milliseconds internally) to call f_onserver_timer (0 disables this, default). bool _iTimerCallUnit; // TRUE mean TimerCall is in second and FALSE mean it's in minute - bool m_bAllowLightOverride; // Allow manual sector light override? + bool m_fAllowLightOverride; // Allow manual sector light override? CSString m_sZeroPoint; // Zero point for sextant coordinates counting. Comment this line out if you are not using ML-sized maps. bool m_fAllowBuySellAgent; // Allow rapid Buy/Sell through Buy/Sell agent. - bool m_bAllowNewbTransfer; // Set to 1 for items to keep their attr_newbie flag when item is transfered to an NPC. + bool m_fAllowNewbTransfer; // Set to 1 for items to keep their attr_newbie flag when item is transfered to an NPC. bool m_NPCNoFameTitle; // NPC will not be addressed as "Lord" or such if this is set. - bool m_bAgree; // AGREE=n for nightly builds. + bool m_fAgree; // AGREE=n for nightly builds. int m_iMaxPolyStats; // Max amount of each Stat gained through Polymorph spell. This affects separatelly to each stat. bool m_NPCShoveNPC; //NPC can walk through other NPC, by default this is disabled. diff --git a/src/game/CServerDef.cpp b/src/game/CServerDef.cpp index cc3ccc18d..1d2fe4eae 100644 --- a/src/game/CServerDef.cpp +++ b/src/game/CServerDef.cpp @@ -38,7 +38,7 @@ #else // (Unix) #include #endif - bool m_bPmemory = true; // process memory information is available? + bool m_fPmemory = true; // process memory information is available? ////////////////////////////////////////////////////////////////////// // -CServerDef @@ -67,7 +67,7 @@ size_t CServerDef::StatGet(SERV_STAT_TYPE i) const if ( i == SERV_STAT_MEM ) // memory information { d = 0; - if ( m_bPmemory ) + if ( m_fPmemory ) { #ifdef _WIN32 if ( !m_hmPsapiDll ) // try to load psapi.dll if not loaded yet @@ -76,7 +76,7 @@ size_t CServerDef::StatGet(SERV_STAT_TYPE i) const m_hmPsapiDll = LoadLibrary(TEXT("psapi.dll")); if (m_hmPsapiDll == nullptr) { - m_bPmemory = false; + m_fPmemory = false; g_Log.EventError(("Unable to load process information PSAPI.DLL library. Memory information will be not available.\n")); } else @@ -145,7 +145,7 @@ size_t CServerDef::StatGet(SERV_STAT_TYPE i) const if ( !d ) { g_Log.EventError(("Unable to load process information from getrusage() and procfs. Memory information will be not available.\n")); - m_bPmemory = false; + m_fPmemory = false; } #endif diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index b3f04db06..cbdb21155 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -1037,7 +1037,7 @@ void CChar::CreateNewCharCheck() if ( !m_pPlayer ) // need a starting brain tick. { // auto-set EXP/LEVEL level - if ( g_Cfg.m_bExperienceSystem && g_Cfg.m_iExperienceMode&EXP_MODE_AUTOSET_EXP ) + if ( g_Cfg.m_fExperienceSystem && g_Cfg.m_iExperienceMode&EXP_MODE_AUTOSET_EXP ) { if ( !m_exp ) { @@ -1066,7 +1066,7 @@ void CChar::CreateNewCharCheck() m_exp = (m_exp * mult) / 100; } - if ( !m_level && g_Cfg.m_bLevelSystem && ( m_exp > g_Cfg.m_iLevelNextAt )) + if ( !m_level && g_Cfg.m_fLevelSystem && ( m_exp > g_Cfg.m_iLevelNextAt )) ChangeExperience(); } @@ -4941,7 +4941,7 @@ void CChar::ChangeExperience(llong delta, CChar *pCharDead) if (!(g_Cfg.m_iExperienceMode&EXP_MODE_ALLOW_DOWN)) // do not allow changes to minus return; // limiting delta to current level? check if delta goes out of level - if (g_Cfg.m_bLevelSystem && g_Cfg.m_iExperienceMode&EXP_MODE_DOWN_NOLEVEL) + if (g_Cfg.m_fLevelSystem && g_Cfg.m_iExperienceMode&EXP_MODE_DOWN_NOLEVEL) { uint exp = Calc_ExpGet_Exp(m_level); if (delta + m_exp < exp) @@ -4977,7 +4977,7 @@ void CChar::ChangeExperience(llong delta, CChar *pCharDead) { int iWord = 0; llong absval = abs(delta); - llong maxval = (g_Cfg.m_bLevelSystem && g_Cfg.m_iLevelNextAt) ? maximum(g_Cfg.m_iLevelNextAt, 1000) : 1000; + llong maxval = (g_Cfg.m_fLevelSystem && g_Cfg.m_iLevelNextAt) ? maximum(g_Cfg.m_iLevelNextAt, 1000) : 1000; if (absval >= maxval) // 100% iWord = 7; @@ -5000,7 +5000,7 @@ void CChar::ChangeExperience(llong delta, CChar *pCharDead) } } - if (g_Cfg.m_bLevelSystem) + if (g_Cfg.m_fLevelSystem) { llong level = Calc_ExpGet_Level(m_exp); diff --git a/src/game/chars/CCharNotoriety.cpp b/src/game/chars/CCharNotoriety.cpp index 2f6629ace..3dbb70c29 100644 --- a/src/game/chars/CCharNotoriety.cpp +++ b/src/game/chars/CCharNotoriety.cpp @@ -612,7 +612,7 @@ void CChar::Noto_Kill(CChar * pKill, int iTotalKillers) Noto_Fame(g_Cfg.Calc_FameKill(pKill) / iTotalKillers, pKill); Noto_Karma(g_Cfg.Calc_KarmaKill(pKill, NotoThem) / iTotalKillers, INT32_MIN, false, pKill); - if (g_Cfg.m_bExperienceSystem && (g_Cfg.m_iExperienceMode & EXP_MODE_RAISE_COMBAT)) + if (g_Cfg.m_fExperienceSystem && (g_Cfg.m_iExperienceMode & EXP_MODE_RAISE_COMBAT)) { int change = (pKill->m_exp / 10) / iTotalKillers; if (change) diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index 2c86eead2..34e881bed 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -835,7 +835,7 @@ bool CChar::Skill_MakeItem_Success() } // Experience gain on craftings - if ( g_Cfg.m_bExperienceSystem && (g_Cfg.m_iExperienceMode & EXP_MODE_RAISE_CRAFT) ) + if ( g_Cfg.m_fExperienceSystem && (g_Cfg.m_iExperienceMode & EXP_MODE_RAISE_CRAFT) ) { int exp = 0; if ( pItemVend ) diff --git a/src/game/chars/CCharStatus.cpp b/src/game/chars/CCharStatus.cpp index 6102877a4..a4e3342cf 100644 --- a/src/game/chars/CCharStatus.cpp +++ b/src/game/chars/CCharStatus.cpp @@ -1687,7 +1687,7 @@ bool CChar::CanMove( const CItem *pItem, bool fMsg ) const } else if ( pObjTop->IsChar() && (pObjTop != this) ) { - if (( pItem->IsAttr(ATTR_NEWBIE) ) && g_Cfg.m_bAllowNewbTransfer ) + if (( pItem->IsAttr(ATTR_NEWBIE) ) && g_Cfg.m_fAllowNewbTransfer ) { const CChar *pPet = dynamic_cast( pItem->GetTopLevelObj() ); if (pPet && (pPet->GetOwner() == this) ) diff --git a/src/game/clients/CClient.cpp b/src/game/clients/CClient.cpp index 12dde8321..602d54747 100644 --- a/src/game/clients/CClient.cpp +++ b/src/game/clients/CClient.cpp @@ -56,7 +56,7 @@ CClient::CClient(CNetState* state) m_tmSetup.m_dwIP = 0; m_tmSetup.m_iConnect = 0; - m_tmSetup.m_bNewSeed = false; + m_tmSetup.m_fNewSeed = false; m_Env.SetInvalid(); diff --git a/src/game/clients/CClient.h b/src/game/clients/CClient.h index 9e15d714d..45a1908b7 100644 --- a/src/game/clients/CClient.h +++ b/src/game/clients/CClient.h @@ -149,7 +149,7 @@ class CClient : public CSObjListRec, public CScriptObj, public CChatChanMember, { dword m_dwIP; int m_iConnect; // used for debug only. - bool m_bNewSeed; + bool m_fNewSeed; } m_tmSetup; // CLIMODE_SETUP_CHARLIST diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index d14f14269..016d81b73 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -349,7 +349,7 @@ void CClient::Event_Item_Drop( CUID uidItem, CPointMap pt, CUID uidOn, uchar gri pItem->ClrAttr(ATTR_OWNED); // newbie items lose newbie status when transfered to NPC - if ( !g_Cfg.m_bAllowNewbTransfer ) + if ( !g_Cfg.m_fAllowNewbTransfer ) pItem->ClrAttr(ATTR_NEWBIE); } if ( pChar->GetBank()->IsItemInside( pContItem )) @@ -1054,22 +1054,22 @@ bool CClient::Event_Command(lpctstr pszCommand, TALKMODE_TYPE mode) return true; } - bool m_bAllowCommand = true; - bool m_bAllowSay = true; + bool m_fAllowCommand = true; + bool m_fAllowSay = true; pszCommand += 1; GETNONWHITESPACE(pszCommand); - m_bAllowCommand = g_Cfg.CanUsePrivVerb(this, pszCommand, this); + m_fAllowCommand = g_Cfg.CanUsePrivVerb(this, pszCommand, this); - if ( !m_bAllowCommand ) - m_bAllowSay = ( GetPrivLevel() <= PLEVEL_Player ); + if ( !m_fAllowCommand ) + m_fAllowSay = ( GetPrivLevel() <= PLEVEL_Player ); // filter on commands is active - so trigger it if ( !g_Cfg.m_sCommandTrigger.IsEmpty() ) { CScriptTriggerArgs Args(pszCommand); - Args.m_iN1 = m_bAllowCommand; - Args.m_iN2 = m_bAllowSay; + Args.m_iN1 = m_fAllowCommand; + Args.m_iN2 = m_fAllowSay; enum TRIGRET_TYPE tr; // Call the filtering function @@ -1077,16 +1077,16 @@ bool CClient::Event_Command(lpctstr pszCommand, TALKMODE_TYPE mode) if ( tr == TRIGRET_RET_TRUE ) return (Args.m_iN2 != 0); - m_bAllowCommand = ( Args.m_iN1 != 0 ); - m_bAllowSay = ( Args.m_iN2 != 0 ); + m_fAllowCommand = ( Args.m_iN1 != 0 ); + m_fAllowSay = ( Args.m_iN2 != 0 ); } - if ( !m_bAllowCommand && !m_bAllowSay ) + if ( !m_fAllowCommand && !m_fAllowSay ) SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_MSG_ACC_PRIV)); - if ( m_bAllowCommand ) + if ( m_fAllowCommand ) { - m_bAllowSay = false; + m_fAllowSay = false; // Assume you don't mean yourself ! if ( FindTableHeadSorted( pszCommand, sm_szCmd_Redirect, ARRAY_COUNT(sm_szCmd_Redirect)) >= 0 ) @@ -1103,9 +1103,9 @@ bool CClient::Event_Command(lpctstr pszCommand, TALKMODE_TYPE mode) } if ( GetPrivLevel() >= g_Cfg.m_iCommandLog ) - g_Log.Event(LOGM_GM_CMDS, "%x:'%s' commands '%s'=%d\n", GetSocketID(), GetName(), pszCommand, m_bAllowCommand); + g_Log.Event(LOGM_GM_CMDS, "%x:'%s' commands '%s'=%d\n", GetSocketID(), GetName(), pszCommand, m_fAllowCommand); - return !m_bAllowSay; + return !m_fAllowSay; } void CClient::Event_Attack( CUID uid ) diff --git a/src/game/clients/CClientMsg.cpp b/src/game/clients/CClientMsg.cpp index 1669c72b6..92a556153 100644 --- a/src/game/clients/CClientMsg.cpp +++ b/src/game/clients/CClientMsg.cpp @@ -1451,7 +1451,7 @@ void CClient::addPlayerStart( CChar * pChar ) if ( pItemChange != nullptr ) pItemChange->Delete(); - if ( g_Cfg.m_bAutoResDisp ) + if ( g_Cfg.m_fAutoResDisp ) m_pAccount->SetAutoResDisp(this); ClearTargMode(); // clear death menu mode. etc. ready to walk about. cancel any previous modes From 3e87445b6efa9c05f889c2413440690bcee32bab Mon Sep 17 00:00:00 2001 From: Hamit Devedjioglu Date: Sun, 28 Apr 2024 00:40:42 +0100 Subject: [PATCH 90/90] SPELLFLAG_NOUNPARALYZE - Fixed: SPELLFLAG_NOUNPARALYZE flag wasn't working as intended. --- Changelog.txt | 3 ++- src/game/chars/CCharFight.cpp | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Changelog.txt b/Changelog.txt index f4afd4b47..bd689fe53 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3715,4 +3715,5 @@ Added: 'H' shortcut for variables to get the value as hexadecimal. IMPORTANT: If you were using == DECIMAL for checking in your scripts and want to keep that behaviour, you have to add DecimalVariables=1 to Sphere.ini. SUGGESTION: Always use for hexadecimal returns, and for decimal returns to avoid any future issues, - when you switch this setting. \ No newline at end of file + when you switch this setting. +- Fixed: SPELLFLAG_NOUNPARALYZE flag wasn't working as intended. \ No newline at end of file diff --git a/src/game/chars/CCharFight.cpp b/src/game/chars/CCharFight.cpp index f66e54ca7..46f67255e 100644 --- a/src/game/chars/CCharFight.cpp +++ b/src/game/chars/CCharFight.cpp @@ -622,7 +622,6 @@ int CChar::CalcArmorDefense() const int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhysical, int iDmgFire, int iDmgCold, int iDmgPoison, int iDmgEnergy, SPELL_TYPE spell) { ADDTOCALLSTACK("CChar::OnTakeDamage"); - if ( pSrc == nullptr ) pSrc = this; @@ -777,12 +776,19 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys pItemHit->OnTakeDamage(iDmg, pSrc, uType); } + CSpellDef* pSpellDef = nullptr; // Remove stuck/paralyze effect - if ( !(uType & DAMAGE_NOUNPARALYZE) ) + if (!(uType & DAMAGE_NOUNPARALYZE)) { - CItem * pParalyze = LayerFind(LAYER_SPELL_Paralyze); - if ( pParalyze ) - pParalyze->Delete(); + if (spell) + pSpellDef = g_Cfg.GetSpellDef(spell); + + if (!pSpellDef || (pSpellDef && !pSpellDef->IsSpellType(SPELLFLAG_NOUNPARALYZE))) // Block spells with SPELLFLAG_NOUNPARALYZE flag, unparalyze the target. + { + CItem* pParalyze = LayerFind(LAYER_SPELL_Paralyze); + if (pParalyze) + pParalyze->Delete(); + } CItem * pStuck = LayerFind(LAYER_FLAG_Stuck); if ( pStuck ) @@ -870,7 +876,7 @@ int CChar::OnTakeDamage( int iDmg, CChar * pSrc, DAMAGE_TYPE uType, int iDmgPhys // Check if my spell can be interrupted int iDisturbChance = 0; int iSpellSkill = -1; - const CSpellDef *pSpellDef = g_Cfg.GetSpellDef(m_atMagery.m_iSpell); + pSpellDef = g_Cfg.GetSpellDef(m_atMagery.m_iSpell); if ( pSpellDef && pSpellDef->GetPrimarySkill(&iSpellSkill) ) iDisturbChance = pSpellDef->m_Interrupt.GetLinear(Skill_GetBase((SKILL_TYPE)iSpellSkill));