Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed: spiderwebs accumulating in sleeping sector (Issue #1249) #1382

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3989,7 +3989,7 @@ Added: 'H' shortcut for variables to get the value as hexadecimal.
08-01-2025, DavideRei
- Fixed: NPC FLEE action didn't work because it was using action target (empty) instead of fight target

28-02-2025 (dev), canerksk
28-02-2025, canerksk
- Added: Add OpenDoorMacro and World Search Distance as Local Variables to @UserExtCmd Trigger
LOCAL.DoorAutoDist <distance> (R/W). Default Distance = 2.
eg;
Expand All @@ -3999,3 +3999,7 @@ Added: 'H' shortcut for variables to get the value as hexadecimal.

28-02-2025, cbnolok
- Fixed: failing assertion if targeting a non-corpse object when casting Animate Dead spell.

05-03-2025, cbnolok
- Fixed: If Giant Spiders and Fire Elementals are denied going into sleeping state into a sleeping sector, their dropped items (ie. i_spider_web) went into sleeping state and didn't decay, leading to accumulation (Issue #1249).
Also, stamina wasn't consumed, thus NPCs had no limit in placing those items.
13 changes: 11 additions & 2 deletions src/game/chars/CCharAct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5822,21 +5822,30 @@ bool CChar::_OnTick()
EXC_TRY("Tick");

EXC_SET_BLOCK("Can Tick?");
if ((_IsSleeping() || IsDisconnected()) && (Skill_GetActive() != NPCACT_RIDDEN))

if ((_IsSleeping() || IsDisconnected()) && (Skill_GetActive() != NPCACT_RIDDEN))
{
// mounted horses can still get a tick.
return true;
}
if (!_CanTick())
if (!_CanTick())
{
// It can happen that i'm in the ticking list, but for various reasons right now i'm in a non-tickable state.
// Among the reasons why i can't tick, though, there cannot be being in a sleeping state: when a char goes into sleeping state
// it should also be removed from the list (it happens in _GoSleep()).
ASSERT(!_IsSleeping());

if (GetTopSector()->IsSleeping() && !g_Rand.Get16ValFast(15))
{
// Do not make the char sleep right when it enters a sleeping sector. Doing this
// will lead to an accumulation of npcs at the edge of the new sector.

_SetTimeout(1); //Make it tick after sector's awakening.
_GoSleep();
return true;
}
}
ASSERT(!_IsSleeping());

EXC_SET_BLOCK("Components Tick");
/*
Expand Down
44 changes: 37 additions & 7 deletions src/game/chars/CCharNPCAct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,38 +75,66 @@ void CChar::Action_StartSpecial( CREID_TYPE id )
if ( !g_Cfg.IsSkillFlag( Skill_GetActive(), SKF_NOANIM ) )
UpdateAnimate( ANIM_CAST_AREA );

CItem * pItem = nullptr;
short iMaxTimeoutS = 0;
switch ( id )
{
case CREID_FIRE_ELEM:
{
// Leave a fire path
CItem * pItem = CItem::CreateScript( g_Rand.Get16ValFast(2) ? ITEMID_FX_FIRE_F_EW : ITEMID_FX_FIRE_F_NS, this );
pItem = CItem::CreateScript( g_Rand.Get16ValFast(2) ? ITEMID_FX_FIRE_F_EW : ITEMID_FX_FIRE_F_NS, this );
ASSERT(pItem);
pItem->SetType(IT_FIRE);
pItem->m_itSpell.m_spell = (word)(SPELL_Fire_Field);
pItem->m_itSpell.m_spelllevel = (word)(100 + g_Rand.Get16ValFast(500));
pItem->m_itSpell.m_spellcharges = 1;
pItem->m_uidLink = GetUID();
pItem->MoveToDecay( GetTopPoint(), 10 + g_Rand.Get16ValFast(50)*MSECS_PER_SEC);
iMaxTimeoutS = 50;
}
break;

case CREID_GIANT_SPIDER:
{
// Leave a web path
CItem * pItem = CItem::CreateScript( (ITEMID_TYPE)(g_Rand.GetVal2Fast(ITEMID_WEB1_1, ITEMID_WEB1_4)), this );
pItem = CItem::CreateScript( (ITEMID_TYPE)(g_Rand.GetVal2Fast(ITEMID_WEB1_1, ITEMID_WEB1_4)), this );
ASSERT(pItem);
pItem->SetType(IT_WEB);
pItem->MoveToDecay( GetTopPoint(), 10 + g_Rand.Get16ValFast(170)*MSECS_PER_SEC);
iMaxTimeoutS = 170;
}
break;

default:
SysMessage( "You have no special abilities" );
ASSERT(false);
//SysMessage( "You have no special abilities" );
return;
}

UpdateStatVal( STAT_DEX, (ushort)(-(5 + g_Rand.Get16ValFast(5)) )); // the stamina cost
if (pItem)
{
if (Can(CAN_O_NOSLEEP))
{
pItem->m_CanMask |= CAN_O_NOSLEEP;
}
else
{
const CSector *pItemSector = pItem->GetTopSector();
ASSERT(pItemSector); // fPlaced is true, so the current sector should be valid
#ifdef _DEBUG
const CSector *pCharSector = GetTopSector();
ASSERT(pCharSector);
ASSERT(pCharSector == pItemSector);
#endif
if (pItemSector->IsSleeping() && !_IsSleeping())
{
// The char is temporarily walking in a sleeping sector.
// The items it creates need to be able to decay, even if in a sleeping sector.
pItem->m_CanMask |= CAN_O_NOSLEEP;
}
}
pItem->MoveToDecay( GetTopPoint(), 10 + g_Rand.Get16ValFast(iMaxTimeoutS)*MSECS_PER_SEC);
}

UpdateStatVal( STAT_DEX, -(5 + g_Rand.Get16ValFast(5)) ); // the stamina cost
}

bool CChar::NPC_OnVerb( CScript &s, CTextConsole * pSrc ) // Execute command from script
Expand Down Expand Up @@ -1951,7 +1979,9 @@ void CChar::NPC_Act_Idle()
Action_StartSpecial(CREID_GIANT_SPIDER);
return;
}
} else {
}
else
{
if ( GetDispID() == CREID_GIANT_SPIDER )
{
Action_StartSpecial(CREID_GIANT_SPIDER);
Expand Down