mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
Increased world load speed by almost 20% by reducing how often loading progress is written to the console Increased world save speed by almost 50% through the use of binary mode and buffer tweaks for ofstream combined with a cached newline char and std::to_string instead of static_cast Fixed a server crash involving killing NPCs of a specific spawn region using the 'spawnkill # command Fixed a server crash involving moving items from decaying corpses to the ground Fixed a server crash involving carving up human corpses Fixed a server crash related to AreaCharacterFunction JS function, which could trigger for any script that potentially kills any NPC this function iterates over (like explosion potions) Fixed a server crash related to GMs attempting to add items from add-menu while having no backpack Fixed a client crash issue caused by attempting to sell house deeds back to architect NPCs Fixed an issue where players would get incorrect amounts of gold for selling house deeds back to architect NPCs Fixed an issue with characters dying onboard boats which prevented players from packing up the boats later Added new item property in code (via bools bitset) that can be used to enable/disable maker's mark on crafted items. This property can be set to true for items crafted at exceptional quality by GM craftsmen Exposed the new item property to JS engine: .isMarkedByMaker // If true, maker's mark will be displayed Updated default item tooltip to display " of exceptional quality" for items crafted with exceptional quality Updated default item tooltip to display "[Crafted] by [Crafter's Name]" for exceptional quality items crafted by GM craftsmen. The [Crafted] text comes from the MADEWORD defined in dfndata/skills/skills.dfn for the primary skill used to craft the item Updated old-school single-click names for items (when AoS bit is disabled in client/server features) to display exceptional status and/or maker's mark for appropriate items Fixed an issue with the display of titles for NPCs that used dictionary lookups for their title Added new UOX.INI settings under the [settings] section: DISPLAYMAKERSMARK=1/0 // Controls if maker's marks on crafted items are shown on a global level SHOWNPCTITLESOVERHEAD=1/0 // Controls whether NPC titles are shown over their heads SHOWINVULNERABLETAGOVERHEAD=0/1 // Controls whether invulnerable tags are shown overhead GLOBALRESTOCKMULTIPLIER=1.0 // Global multiplier applied to RESTOCK property of items when loaded from DFNs Added new UOX.INI settings under the [combat] section: PETCOMBATTRAINING=1/0 // Controls whether pets can gain skills/stats from combat HIRELINGCOMBATTRAINING=1/0 // Controls whether hirelings can gain skills/stats from combat NPCCOMBATTRAINING=0/1 // Controls whether NPCs in general can gain skills/stats from combat Fixed an issue where a player meeting the exact minimum requirements for crafting an item would always fail Fixed a bug with teleporting off boats to valid nearby locations when double-clicking boat planks while standing on it Updated behaviour of planks on boats: Boat key can unlock plank, but won't automatically open it Boat key used on an open, unlocked plank will lock and automatically close the plank Boat key used on an open, locked plank will unlock the plank and leave it open Player using an unlocked plank now opens it Player using an open plank will disembark (if onboard) or embark (if not) the boat Player can always open a locked plank if they're on the boat, even with no key, to allow disembarking the boat. Planks that are open, but locked cannot be accessed from outside the boat, and will close automatically after five of seconds Updated behaviour of Magic Lock/Unlock spells: Magic Lock cannot be used on objects inside a multi Magic Lock applies difficulty to lock based on caster's Magery skill Magic Lock effect will last between 7 to 50 seconds (depending on caster's Magery skill) Any object that can be locked via Magic Lock spell can also be unlocked via Magic Unlock spell, if caster has high enough Magery skill Fixed a bug where certain JS Functions, Methods and Properties would occasionally pass incorrect values to scripts that called upon them. Scripts that rely on the GetCurrentClock() Function, the .GetTimer() Method, .decayTime, .logTime, .oreTime and .fishTime Properties might need to be updated to account for the fix, which causes larger values to be passed in than before. Fixed a bug related to GetCurrentClock() that caused decay and respawning of dungeon chests from working properly Fixed a bug related to GetCurrentClock() and .logTime/.fishTime that prevented consumption and regeneration of log/fish resources from working properly Added a new JS Function: GetStartTime() // Returns a timestamp for when server started up Fixed a bug related to GetCurrentClock() where server uptime stats in help menu was showing up incorrectly Fixed a bug related to GetCurrentClock() and purging of registrations of visitors in public houses so their visits can be counted again later Fixed a bug related to GetCurrentClock() that caused monster speech to not work properly Fixed a Z-related issue that sometimes prevented players from fishing when standing on the shoreline next to the sea Fixed an issue with Animal Lore skill that would always return a pet's loyalty level as "Wild" Increased max range pets can be from their owner in order to still be included in moongate/teleporter travel from 12 to 24 tiles Fixed an issue where the alchemy bonus damage for explosion potions was off by an order of magnitude Fixed an issue where food IDs from foodlists referenced by other foodlists was not detected as valid food for tamed pets or NPCs Fixed an issue where Alchemy crafting skill did not properly check for the existence of the crafting tool before proceeding with the crafting process Fixed an issue that prevented the Teleport spell from working as intended Fixed an issue where players would still get 1 gold even if STARTGOLD in uox.ini was set to 0 Fixed an issue with mount restrictions script that prevented players from mounting Unicorns, Ki-rins and Cu Sidhes Fixed an issue where aggressive creatures wouldn't stop attacking player after being tamed (js/skill/taming.js) Added a system message to inform the player when they've dropped out of stealth due to taking too many steps Fixed an issue where hunger level of NPCs instantly dropped upon spawning because hunger timer was not active yet Fixed a bug where character corpses would appear with a [unidentified] tag attached Fixed an issue where the [unidentified] tag did not show up for unidentified magic items Added ANIMAL tag to a small bunch of creature definitions (dfndata/creatures/creatures.dfn) Fixed an issue with Bowcraft skill where player could not gain enough skill from crafting bows to reach min requirement for crossbows, and similiarly could not reach min requirement for heavy crossbows from crossbows Updated default value of MURDERDECAYTIMER INI setting from 60 seconds to 28800 seconds (8 hours), to match the amount of time it would take for one (short term) murder count to decay on LBR-era OSI shards.
3383 lines
122 KiB
C++
3383 lines
122 KiB
C++
//o-----------------------------------------------------------------------------------------------o
|
|
//| File - cItem.cpp
|
|
//| Date - 2nd April, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - New class written based upon old UOX item_st. Number of old members removed
|
|
//| and a number of members types modified as well
|
|
//|
|
|
//| Version History -
|
|
//|
|
|
//| 1.0 2nd April, 2000
|
|
//| Initial implementation
|
|
//| Bools reduced down to a single short with get/set mechanisms for setting/clearings bits
|
|
//| No documentation currently done, all functions obvious so far
|
|
//| Note: individual byte setting within longs/shorts need speeding up
|
|
//| consider memcpy into correct word, note that this will be endian specific!
|
|
//|
|
|
//| 1.1 23rd July, 2000
|
|
//| Addition of SaveItem routine for text mode only
|
|
//|
|
|
//| 1.2 25th July, 2000
|
|
//| All Accessor funcs plus a few others are now flagged as const functions, meaning that
|
|
//| those functions GUARENTEE never to alter data, at compile time
|
|
//| Thoughts about CBaseObject and prelim plans made
|
|
//|
|
|
//| 1.3 28th July, 2000
|
|
//| CBaseObject initial implementation plus rework of CItem to deal with only what it needs to
|
|
//| Proper constructor written
|
|
//| Plans for CItem derived classes thought upon
|
|
//|
|
|
//| 1.4 17th July, 2004
|
|
//| Added CSpawnItem to begin breaking CItem into smaller subclasses
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
#include "uox3.h"
|
|
#include "weight.h"
|
|
#include "CPacketSend.h"
|
|
#include "classes.h"
|
|
#include "regions.h"
|
|
#include "ObjectFactory.h"
|
|
#include "speech.h"
|
|
#include "townregion.h"
|
|
#include "cRaces.h"
|
|
#include "cSpawnRegion.h"
|
|
#include "CJSEngine.h"
|
|
#include "CJSMapping.h"
|
|
#include "Dictionary.h"
|
|
#include "regions.h"
|
|
#include "msgboard.h"
|
|
#include "books.h"
|
|
#include "power.h"
|
|
#include "cServerDefinitions.h"
|
|
#include "ssection.h"
|
|
#include "StringUtility.hpp"
|
|
#include "osunique.hpp"
|
|
#include <charconv>
|
|
|
|
const UI32 BIT_MAKERSMARK = 0;
|
|
const UI32 BIT_DOOROPEN = 1;
|
|
const UI32 BIT_PILEABLE = 2;
|
|
const UI32 BIT_DYEABLE = 3;
|
|
const UI32 BIT_CORPSE = 4;
|
|
const UI32 BIT_HELDONCURSOR = 5;
|
|
const UI32 BIT_GUARDED = 6;
|
|
const UI32 BIT_SPAWNERLIST = 7;
|
|
|
|
const SI32 DEFITEM_RANDVALUE = 0;
|
|
const SI16 DEFITEM_GOOD = -1;
|
|
const SI08 DEFITEM_RANK = 0;
|
|
const UI16 DEFITEM_RESTOCK = 0;
|
|
const SI08 DEFITEM_MOVEABLE = 0;
|
|
const TIMERVAL DEFITEM_DECAYTIME = 0;
|
|
const ItemLayers DEFITEM_LAYER = IL_NONE;
|
|
const ItemTypes DEFITEM_TYPE = IT_NOTYPE;
|
|
const UI16 DEFITEM_ENTRYMADEFROM = 0;
|
|
const UI16 DEFITEM_AMOUNT = 1;
|
|
const UI08 DEFITEM_GLOWEFFECT = 0;
|
|
const SERIAL DEFITEM_GLOW = INVALIDSERIAL;
|
|
const COLOUR DEFITEM_GLOWCOLOUR = INVALIDCOLOUR;
|
|
const SI08 DEFITEM_MADEWITH = 0;
|
|
const ARMORCLASS DEFITEM_ARMORCLASS = 0;
|
|
const TIMERVAL DEFITEM_TEMPTIMER = 0;
|
|
const UI08 DEFITEM_SPEED = 0;
|
|
const UI16 DEFITEM_MAXHP = 0;
|
|
const SI08 DEFITEM_OFFSPELL = 0;
|
|
const SI08 DEFITEM_GRIDLOC = 0;
|
|
const SERIAL DEFITEM_CREATOR = INVALIDSERIAL;
|
|
const SI32 DEFITEM_WEIGHTMAX = 0;
|
|
const SI32 DEFITEM_BASEWEIGHT = 0;
|
|
const UI16 DEFITEM_MAXITEMS = 0;
|
|
const UI08 DEFITEM_MAXRANGE = 0;
|
|
const UI08 DEFITEM_BASERANGE = 0;
|
|
const UI16 DEFITEM_USESLEFT = 0;
|
|
const UI16 DEFITEM_MAXUSES = 0;
|
|
const UI16 DEFITEM_REGIONNUM = 255;
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CItem()
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Constructor
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CItem::CItem() : CBaseObject(),
|
|
contObj( nullptr ), glow_effect( DEFITEM_GLOWEFFECT ), glow( DEFITEM_GLOW ), glowColour( DEFITEM_GLOWCOLOUR ),
|
|
madewith( DEFITEM_MADEWITH ), rndvaluerate( DEFITEM_RANDVALUE ), good( DEFITEM_GOOD ), rank( DEFITEM_RANK ), armorClass( DEFITEM_ARMORCLASS ),
|
|
restock( DEFITEM_RESTOCK ), movable( DEFITEM_MOVEABLE ), tempTimer( DEFITEM_TEMPTIMER ), decaytime( DEFITEM_DECAYTIME ),
|
|
spd( DEFITEM_SPEED ), maxhp( DEFITEM_MAXHP ), amount( DEFITEM_AMOUNT ),
|
|
layer( DEFITEM_LAYER ), type( DEFITEM_TYPE ), offspell( DEFITEM_OFFSPELL ), entryMadeFrom( DEFITEM_ENTRYMADEFROM ),
|
|
creator( DEFITEM_CREATOR ), gridLoc( DEFITEM_GRIDLOC ), weightMax( DEFITEM_WEIGHTMAX ), baseWeight( DEFITEM_BASEWEIGHT ), maxItems( DEFITEM_MAXITEMS ),
|
|
maxRange( DEFITEM_MAXRANGE ), baseRange( DEFITEM_BASERANGE ), maxUses( DEFITEM_MAXUSES ), usesLeft( DEFITEM_USESLEFT ), regionNum( DEFITEM_REGIONNUM )
|
|
{
|
|
spells[0] = spells[1] = spells[2] = 0;
|
|
value[0] = value[1] = 0;
|
|
ammo[0] = ammo[1] = 0;
|
|
ammoFX[0] = ammoFX[1] = ammoFX[2] = 0;
|
|
objType = OT_ITEM;
|
|
name2 = "#";
|
|
name = "#";
|
|
race = 65535;
|
|
memset( tempVars, 0, sizeof( tempVars[0] ) * CITV_COUNT );
|
|
desc.reserve( MAX_NAME );
|
|
eventName.reserve( MAX_NAME );
|
|
id = 0x0000;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - ~CItem()
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Destructor to clean things up when deleted
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CItem::~CItem()
|
|
{
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CBaseObject * GetCont( void ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the container object
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CBaseObject * CItem::GetCont( void ) const
|
|
{
|
|
return contObj;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SERIAL GetContSerial( void ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the container's serial
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SERIAL CItem::GetContSerial( void ) const
|
|
{
|
|
if( contObj != nullptr )
|
|
return contObj->GetSerial();
|
|
return INVALIDSERIAL;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI08 GetGridLocation( void ) const
|
|
//| void SetGridLocation( SI08 newLoc )
|
|
//| Date - 7-23-2007
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets "Grid Location" - for UOKR
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI08 CItem::GetGridLocation( void ) const
|
|
{
|
|
return gridLoc;
|
|
}
|
|
void CItem::SetGridLocation( SI08 newLoc )
|
|
{
|
|
gridLoc = newLoc;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI32 GetTempVar( CITempVars whichVar ) const
|
|
//| void SetTempVar( CITempVars whichVar, UI32 newVal )
|
|
//| Date - 7/6/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets the temp value of the object
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI32 CItem::GetTempVar( CITempVars whichVar ) const
|
|
{
|
|
if( whichVar == CITV_COUNT )
|
|
return 0;
|
|
|
|
return tempVars[whichVar];
|
|
}
|
|
void CItem::SetTempVar( CITempVars whichVar, UI32 newVal )
|
|
{
|
|
if( whichVar == CITV_COUNT )
|
|
return;
|
|
|
|
tempVars[whichVar] = newVal;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI08 GetTempVar( CITempVars whichVar, UI08 part ) const
|
|
//| void SetTempVar( CITempVars whichVar, UI08 part, UI08 newVal )
|
|
//| Date - 7/6/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets one of the words of the temp value
|
|
//| Notes - Valid values for part are 1->4. If outside that, behaves as if it were 1
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI08 CItem::GetTempVar( CITempVars whichVar, UI08 part ) const
|
|
{
|
|
UI08 rVal = 0;
|
|
|
|
if( whichVar != CITV_COUNT )
|
|
{
|
|
|
|
switch( part )
|
|
{
|
|
default:
|
|
case 1: rVal = static_cast<UI08>(tempVars[whichVar]>>24); break;
|
|
case 2: rVal = static_cast<UI08>(tempVars[whichVar]>>16); break;
|
|
case 3: rVal = static_cast<UI08>(tempVars[whichVar]>>8); break;
|
|
case 4: rVal = static_cast<UI08>(tempVars[whichVar]%256); break;
|
|
}
|
|
}
|
|
return rVal;
|
|
}
|
|
void CItem::SetTempVar( CITempVars whichVar, UI08 part, UI08 newVal )
|
|
{
|
|
if( whichVar == CITV_COUNT )
|
|
return;
|
|
|
|
UI08 part1 = static_cast<UI08>(tempVars[whichVar]>>24);
|
|
UI08 part2 = static_cast<UI08>(tempVars[whichVar]>>16);
|
|
UI08 part3 = static_cast<UI08>(tempVars[whichVar]>>8);
|
|
UI08 part4 = static_cast<UI08>(tempVars[whichVar]%256);
|
|
|
|
switch( part )
|
|
{
|
|
default:
|
|
case 1: part1 = newVal; break;
|
|
case 2: part2 = newVal; break;
|
|
case 3: part3 = newVal; break;
|
|
case 4: part4 = newVal; break;
|
|
}
|
|
tempVars[whichVar] = (part1<<24) + (part2<<16) + (part3<<8) + part4;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool SetCont( CBaseObject *newCont )
|
|
//| bool SetContSerial( SERIAL newSerial )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Set's the item's container value to newValue
|
|
//| Takes it out of the old container, and puts in the new
|
|
//| Copes with being on paperdolls, ground and in containers
|
|
//| Also copes with removing and adding to a map region
|
|
//| Returns false if item needs deleting, true if fine
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::SetContSerial( SERIAL newSerial )
|
|
{
|
|
if( newSerial != INVALIDSERIAL )
|
|
{
|
|
if( newSerial >= BASEITEMSERIAL )
|
|
return SetCont( calcItemObjFromSer( newSerial ) );
|
|
else
|
|
return SetCont( calcCharObjFromSer( newSerial ) );
|
|
}
|
|
return SetCont( nullptr );
|
|
}
|
|
bool CItem::SetCont( CBaseObject *newCont, bool removeFromView )
|
|
{
|
|
if( isPostLoaded() )
|
|
{
|
|
Dirty( UT_UPDATE );
|
|
RemoveSelfFromCont();
|
|
}
|
|
|
|
bool contIsGround = true;
|
|
if( ValidateObject( newCont ) )
|
|
{
|
|
contObj = newCont;
|
|
if( newCont->GetObjType() == OT_CHAR )
|
|
{
|
|
CChar *charWearing = static_cast<CChar *>(newCont);
|
|
if( ValidateObject( charWearing ))
|
|
{
|
|
if( charWearing->IsDead() && ( this->GetLayer() == IL_HAIR || this->GetLayer() == IL_FACIALHAIR ))
|
|
{
|
|
// if charWaring is dead, it means we're setting the cont on a duped item soon-to-be-moved to his corpse,
|
|
// so we don't want him to attempt to wear it.
|
|
contIsGround = false;
|
|
if( isPostLoaded() )
|
|
{
|
|
Weight->addItemWeight( charWearing, this );
|
|
}
|
|
}
|
|
else if( charWearing->WearItem( this ) )
|
|
{
|
|
contIsGround = false;
|
|
if( isPostLoaded() )
|
|
Weight->addItemWeight( charWearing, this );
|
|
if( this->GetLayer() == IL_MOUNT && charWearing->IsNpc() )
|
|
charWearing->SetOnHorse( true );
|
|
|
|
// Set new save flag on item based on save flag of new owner
|
|
ShouldSave( charWearing->ShouldSave() );
|
|
}
|
|
}
|
|
|
|
// Update item's townregion based on parent character's location
|
|
CTownRegion *tRegion = calcRegionFromXY( charWearing->GetX(), charWearing->GetY(), charWearing->WorldNumber(), charWearing->GetInstanceID(), this );
|
|
SetRegion( (tRegion != nullptr ? tRegion->GetRegionNum() : 0xFF) );
|
|
}
|
|
else
|
|
{
|
|
CItem *itemHolder = static_cast<CItem *>(newCont);
|
|
if( itemHolder != nullptr )
|
|
{
|
|
contIsGround = false;
|
|
// ok heres what hair/beards should be handled like
|
|
if((( GetLayer() == IL_HAIR ) || ( GetLayer() == IL_FACIALHAIR ) ) && !itemHolder->isCorpse() )
|
|
{
|
|
CChar *itemPackOwner = FindItemOwner( itemHolder );
|
|
if( ValidateObject( itemPackOwner ))
|
|
{
|
|
CItem *oldItem = itemPackOwner->GetItemAtLayer( GetLayer() );
|
|
if( ValidateObject( oldItem ))
|
|
oldItem->Delete();
|
|
|
|
SetCont( itemPackOwner );
|
|
|
|
// Set new save flag on item based on save flag of new owner
|
|
ShouldSave( itemPackOwner->ShouldSave() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( removeFromView )
|
|
{
|
|
// Update old location of item
|
|
oldLocX = x;
|
|
oldLocY = y;
|
|
oldLocZ = z;
|
|
|
|
// Remove item from view of all nearby players
|
|
RemoveFromSight();
|
|
}
|
|
|
|
//itemHolder->GetContainsList()->Add( this );
|
|
itemHolder->GetContainsList()->AddInFront( this );
|
|
|
|
// Set new save flag on item based on save flag of new container
|
|
ShouldSave( itemHolder->ShouldSave() );
|
|
}
|
|
if( isPostLoaded() )
|
|
Weight->addItemWeight( itemHolder, this );
|
|
|
|
// Update item's townregion to match root container's location
|
|
CTownRegion *tRegion = calcRegionFromXY( itemHolder->GetX(), itemHolder->GetY(), itemHolder->WorldNumber(), itemHolder->GetInstanceID(), this );
|
|
SetRegion( (tRegion != nullptr ? tRegion->GetRegionNum() : 0xFF) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( contIsGround )
|
|
{
|
|
contObj = nullptr;
|
|
MapRegion->AddItem( this );
|
|
|
|
// If item has been moved to the ground, make sure we save it
|
|
ShouldSave( true );
|
|
}
|
|
else
|
|
{
|
|
// Remove item from any multi it might be in
|
|
if( ValidateObject( GetMultiObj() ))
|
|
{
|
|
RemoveFromMulti( false );
|
|
multis = nullptr;
|
|
}
|
|
}
|
|
|
|
if( GetGlow() != INVALIDSERIAL )
|
|
Items->GlowItem( this );
|
|
|
|
UpdateRegion();
|
|
|
|
return !contIsGround;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool inDungeon( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Determine if item is inside a dungeon
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::inDungeon( void )
|
|
{
|
|
bool rValue = false;
|
|
if( GetRegion() != nullptr )
|
|
rValue = GetRegion()->IsDungeon();
|
|
return rValue;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isDoorOpen( void ) const
|
|
//| void SetDoorOpen( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets door's open state
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isDoorOpen( void ) const
|
|
{
|
|
return bools.test( BIT_DOOROPEN );
|
|
}
|
|
void CItem::SetDoorOpen( bool newValue )
|
|
{
|
|
bools.set( BIT_DOOROPEN, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isPileable( void ) const
|
|
//| void SetPileable( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's pileable state
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isPileable( void ) const
|
|
{
|
|
return bools.test( BIT_PILEABLE );
|
|
}
|
|
void CItem::SetPileable( bool newValue )
|
|
{
|
|
bools.set( BIT_PILEABLE, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CItem::isMarkedByMaker()
|
|
//| CItem::SetMakersMark()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets maker's mark on item
|
|
//o------------------------------------------------------------------------------------------------o
|
|
bool CItem::isMarkedByMaker( void ) const
|
|
{
|
|
return bools.test( BIT_MAKERSMARK );
|
|
}
|
|
void CItem::SetMakersMark( bool newValue )
|
|
{
|
|
bools.set( BIT_MAKERSMARK, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CItem::isDyeable()
|
|
//| CItem::SetDye()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's dyeable state
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isDyeable( void ) const
|
|
{
|
|
return bools.test( BIT_DYEABLE );
|
|
}
|
|
void CItem::SetDye( bool newValue )
|
|
{
|
|
bools.set( BIT_DYEABLE, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isCorpse( void ) const
|
|
//| void SetCorpse( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's corpse state
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isCorpse( void ) const
|
|
{
|
|
return bools.test( BIT_CORPSE );
|
|
}
|
|
void CItem::SetCorpse( bool newValue )
|
|
{
|
|
bools.set( BIT_CORPSE, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isHeldOnCursor( void ) const
|
|
//| void SetHeldOnCursor( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets whether item is being held on cursor by a player
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isHeldOnCursor( void ) const
|
|
{
|
|
return bools.test( BIT_HELDONCURSOR );
|
|
}
|
|
void CItem::SetHeldOnCursor( bool newValue )
|
|
{
|
|
bools.set( BIT_HELDONCURSOR, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isGuarded( void ) const
|
|
//| void SetGuarded( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's guarded state
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isGuarded( void ) const
|
|
{
|
|
return bools.test( BIT_GUARDED );
|
|
}
|
|
void CItem::SetGuarded( bool newValue )
|
|
{
|
|
bools.set( BIT_GUARDED, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isSpawnerList( void ) const
|
|
//| void SetSpawnerList( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets whether spawner points to a a NPCLIST/ITEMLIST instead of an NPC/Item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isSpawnerList( void ) const
|
|
{
|
|
return bools.test( BIT_SPAWNERLIST );
|
|
}
|
|
void CItem::SetSpawnerList( bool newValue )
|
|
{
|
|
bools.set( BIT_SPAWNERLIST, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//=================================================================================================
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's name2 property - used for magical items
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
auto CItem::GetName2() const ->const std::string& {
|
|
return name2;
|
|
}
|
|
auto CItem::SetName2(const std::string &value) ->void {
|
|
name2 = value ;
|
|
if (name2.size() >=MAX_NAME){
|
|
name2 = name2.substr(0,MAX_NAME-1) ;
|
|
}
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SERIAL GetCreator( void ) const
|
|
//| void SetCreator( SERIAL newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets serial of item's creator - used for crafting and maker's marks
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SERIAL CItem::GetCreator( void ) const
|
|
{
|
|
return creator;
|
|
}
|
|
void CItem::SetCreator( SERIAL newValue )
|
|
{
|
|
creator = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - std::string GetDesc( void ) const
|
|
//| void SetDesc( std::string newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's description property - used for playervendors, among other things
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
std::string CItem::GetDesc( void ) const
|
|
{
|
|
return desc;
|
|
}
|
|
void CItem::SetDesc( std::string newValue )
|
|
{
|
|
desc = newValue.substr( 0, MAX_NAME - 1 );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - std::string GetEvent( void ) const
|
|
//| void SetEvent( std::string newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's event property - used to attach items to specific events
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
std::string CItem::GetEvent( void ) const
|
|
{
|
|
return eventName;
|
|
}
|
|
void CItem::SetEvent( std::string newValue )
|
|
{
|
|
eventName = newValue.substr( 0, MAX_NAME - 1 );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void IncZ( SI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Increases item's Z height by specified value
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::IncZ( SI16 newValue )
|
|
{
|
|
SetZ( z + newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void IncLocation( SI16 xInc, SI16 yInc )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Increases item's X and Y coordinates by specified values
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::IncLocation( SI16 xInc, SI16 yInc )
|
|
{
|
|
SetLocation( (GetX() + xInc), (GetY() + yInc), GetZ(), GetGridLocation(), WorldNumber(), GetInstanceID() );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SetOldLocation( SI16 newX, SI16 newY, SI08 newZ )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Updates item's old location
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::SetOldLocation( SI16 newX, SI16 newY, SI08 newZ )
|
|
{
|
|
oldLocX = newX;
|
|
oldLocY = newY;
|
|
oldLocZ = newZ;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SetLocation( const CBaseObject *toSet )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Sets item's new location to match specified object's location
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::SetLocation( const CBaseObject *toSet )
|
|
{
|
|
if( toSet == nullptr )
|
|
return;
|
|
SetLocation( toSet->GetX(), toSet->GetY(), toSet->GetZ(), toSet->WorldNumber(), toSet->GetInstanceID() );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SetLocation( SI16 newX, SI16 newY, SI08 newZ )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Sets item's new location to match specified coordinates
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::SetLocation( SI16 newX, SI16 newY, SI08 newZ )
|
|
{
|
|
SetLocation( newX, newY, newZ, GetGridLocation(), WorldNumber(), GetInstanceID() );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SetLocation( SI16 newX, SI16 newY, SI08 newZ, SI08 newLoc, UI08 world, UI16 instance_id )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Sets item's new location to match specified coordinates, grid location, world and instance
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::SetLocation( SI16 newX, SI16 newY, SI08 newZ, SI08 newLoc, UI08 world, UI16 instance_id )
|
|
{
|
|
if( GetCont() == nullptr )
|
|
MapRegion->ChangeRegion( this, newX, newY, world );
|
|
oldLocX = x;
|
|
oldLocY = y;
|
|
oldLocZ = z;
|
|
x = newX;
|
|
y = newY;
|
|
z = newZ;
|
|
gridLoc = newLoc;
|
|
worldNumber = world;
|
|
instanceID = instance_id;
|
|
if( GetCont() == nullptr )
|
|
{
|
|
// Calculate which townregion item exists in, based on its own location
|
|
CTownRegion *tRegion = calcRegionFromXY( x, y, worldNumber, instanceID, this );
|
|
SetRegion( (tRegion != nullptr ? tRegion->GetRegionNum() : 0xFF) );
|
|
|
|
if( !CanBeObjType( OT_MULTI ) )
|
|
{
|
|
// If it's a sign with a more value, assume that the more value contains the serial of the multi the sign belongs to
|
|
if((( id >= 0x0b95 && id <= 0x0c0e ) || id == 0x1f28 || id == 0x1f29 ) && GetTempVar( CITV_MORE ) != 0 )
|
|
{
|
|
CMultiObj *mMulti = calcMultiFromSer( GetTempVar( CITV_MORE ) );
|
|
if( ValidateObject( mMulti ) )
|
|
SetMulti( mMulti );
|
|
}
|
|
else
|
|
{
|
|
CMultiObj *mMulti = findMulti( newX, newY, newZ, world, instance_id );
|
|
if( GetMultiObj() != mMulti )
|
|
SetMulti( mMulti );
|
|
}
|
|
}
|
|
}
|
|
UpdateRegion();
|
|
Dirty( UT_LOCATION );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SetLocation( SI16 newX, SI16 newY, SI08 newZ, UI08 world, UI16 instanceID )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Sets item's new location to match specified coordinates, world and instance
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::SetLocation( SI16 newX, SI16 newY, SI08 newZ, UI08 world, UI16 instanceID )
|
|
{
|
|
SetLocation( newX, newY, newZ, GetGridLocation(), world, instanceID );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CTownRegion *GetRegion( void ) const
|
|
//| void SetRegion( UI16 newValue )
|
|
//| UI16 GetRegionNum( void ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets the town region the item is in
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CTownRegion *CItem::GetRegion( void ) const
|
|
{
|
|
if( cwmWorldState->townRegions.find( regionNum ) == cwmWorldState->townRegions.end() )
|
|
return cwmWorldState->townRegions[0xFF];
|
|
return cwmWorldState->townRegions[regionNum];
|
|
}
|
|
void CItem::SetRegion( UI16 newValue )
|
|
{
|
|
regionNum = newValue;
|
|
UpdateRegion();
|
|
}
|
|
UI16 CItem::GetRegionNum( void ) const
|
|
{
|
|
return regionNum;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - ItemLayers GetLayer( void ) const
|
|
//| void SetLayer( ItemLayers newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's layer property
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
ItemLayers CItem::GetLayer( void ) const
|
|
{
|
|
return layer;
|
|
}
|
|
void CItem::SetLayer( ItemLayers newValue )
|
|
{
|
|
CBaseObject *getCont = GetCont();
|
|
if( ValidateObject( getCont ) && getCont->GetObjType() == OT_CHAR ) // if we're on a char
|
|
{
|
|
CChar *charAffected = static_cast<CChar *>(getCont);
|
|
if( ValidateObject( charAffected ) )
|
|
{
|
|
if( layer != IL_NONE )
|
|
charAffected->TakeOffItem( layer );
|
|
layer = newValue;
|
|
charAffected->WearItem( this );
|
|
charAffected->UpdateRegion();
|
|
return;
|
|
}
|
|
}
|
|
layer = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - ItemTypes GetType( void ) const
|
|
//| void SetType( ItemTypes newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's type property
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
ItemTypes CItem::GetType( void ) const
|
|
{
|
|
return type;
|
|
}
|
|
void CItem::SetType( ItemTypes newValue )
|
|
{
|
|
type = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI08 GetOffSpell( void ) const
|
|
//| void SetOffSpell( SI08 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's offspell property - Unused?
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI08 CItem::GetOffSpell( void ) const
|
|
{
|
|
return offspell;
|
|
}
|
|
void CItem::SetOffSpell( SI08 newValue )
|
|
{
|
|
offspell = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetAmount( void ) const
|
|
//| void SetAmount( UI32 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's amount property, adjusts weight according to new value
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetAmount( void ) const
|
|
{
|
|
return amount;
|
|
}
|
|
void CItem::SetAmount( UI32 newValue )
|
|
{
|
|
CBaseObject *getCont = GetCont();
|
|
if( ValidateObject( getCont ) )
|
|
Weight->subtractItemWeight( getCont, this );
|
|
|
|
if( newValue > MAX_STACK )
|
|
amount = MAX_STACK;
|
|
else
|
|
amount = static_cast<UI16>(newValue);
|
|
|
|
if( ValidateObject( getCont ) )
|
|
Weight->addItemWeight( getCont, this );
|
|
Dirty( UT_UPDATE );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool :IncAmount( SI32 incValue, bool noDelete )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Increases item's amount property by specified amount,
|
|
//| adjusts weight according to new value
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::IncAmount( SI32 incValue, bool noDelete )
|
|
{
|
|
bool iDeleted = false;
|
|
SI32 newAmt = (amount + incValue);
|
|
if( newAmt >= 0 )
|
|
{
|
|
if( newAmt > MAX_STACK )
|
|
SetAmount( MAX_STACK );
|
|
else
|
|
SetAmount( static_cast< UI16 >( newAmt ) );
|
|
}
|
|
if( !noDelete && newAmt <= 0)
|
|
{
|
|
Delete();
|
|
iDeleted = true;
|
|
}
|
|
return iDeleted;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetMaxHP( void ) const
|
|
//| void SetMaxHP( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's max hp property
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetMaxHP( void ) const
|
|
{
|
|
return maxhp;
|
|
}
|
|
void CItem::SetMaxHP( UI16 newValue )
|
|
{
|
|
maxhp = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetMaxUses( void ) const
|
|
//| void SetMaxUses( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's max uses property
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetMaxUses( void ) const
|
|
{
|
|
return maxUses;
|
|
}
|
|
void CItem::SetMaxUses( UI16 newValue )
|
|
{
|
|
maxUses = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetUsesLeft( void ) const
|
|
//| void SetUsesLeft( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's property for remaining uses
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetUsesLeft( void ) const
|
|
{
|
|
return usesLeft;
|
|
}
|
|
void CItem::SetUsesLeft( UI16 newValue )
|
|
{
|
|
usesLeft = newValue;
|
|
Dirty( UT_UPDATE );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI08 GetSpeed( void ) const
|
|
//| void SetSpeed( UI08 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's speed property - used to determine weapon attack speed
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI08 CItem::GetSpeed( void ) const
|
|
{
|
|
return spd;
|
|
}
|
|
void CItem::SetSpeed( UI08 newValue )
|
|
{
|
|
spd = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI08 GetMaxRange( void ) const
|
|
//| void SetMaxRange( UI08 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's maximum range - primarily used by throwing/archery weapons
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI08 CItem::GetMaxRange( void ) const
|
|
{
|
|
return maxRange;
|
|
}
|
|
void CItem::SetMaxRange( UI08 newValue )
|
|
{
|
|
maxRange = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI08 GetBaseRange( void ) const
|
|
//| void SetBaseRange( UI08 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's base range - primarily used by throwing weapons
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI08 CItem::GetBaseRange( void ) const
|
|
{
|
|
return baseRange;
|
|
}
|
|
void CItem::SetBaseRange( UI08 newValue )
|
|
{
|
|
baseRange = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI08 GetMovable( void ) const
|
|
//| void SetMovable( SI08 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's movable property
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI08 CItem::GetMovable( void ) const
|
|
{
|
|
return movable;
|
|
}
|
|
void CItem::SetMovable( SI08 newValue )
|
|
{
|
|
movable = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - TIMERVAL GetTempTimer( void ) const
|
|
//| void SetTempTimer( TIMERVAL newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's temptimer
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
TIMERVAL CItem::GetTempTimer( void ) const
|
|
{
|
|
return tempTimer;
|
|
}
|
|
void CItem::SetTempTimer( TIMERVAL newValue )
|
|
{
|
|
tempTimer = newValue;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - TIMERVAL GetDecayTime( void ) const
|
|
//| void SetDecayTime( TIMERVAL newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's decay timer
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
TIMERVAL CItem::GetDecayTime( void ) const
|
|
{
|
|
return decaytime;
|
|
}
|
|
void CItem::SetDecayTime( TIMERVAL newValue )
|
|
{
|
|
decaytime = newValue;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI08 GetPriv( void ) const
|
|
//| void SetPriv( UI08 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets priv settings on item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI08 CItem::GetPriv( void ) const
|
|
{
|
|
return static_cast< UI08 >(priv.to_ulong());
|
|
}
|
|
void CItem::SetPriv( UI08 newValue )
|
|
{
|
|
priv = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI32 GetSellValue( void ) const
|
|
//| void SetSellValue( UI32 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets the item's sell value - determines how much player can sell it for
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI32 CItem::GetSellValue( void ) const
|
|
{
|
|
return value[1];
|
|
}
|
|
void CItem::SetSellValue( UI32 newValue )
|
|
{
|
|
value[1] = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI32 GetBuyValue( void ) const
|
|
//| void SetBuyValue( UI32 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's buy value - determines how much player must pay for it
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI32 CItem::GetBuyValue( void ) const
|
|
{
|
|
return value[0];
|
|
}
|
|
void CItem::SetBuyValue( UI32 newValue )
|
|
{
|
|
value[0] = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetRestock( void ) const
|
|
//| void SetRestock( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's restock value in vendor sellpack
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetRestock( void ) const
|
|
{
|
|
return restock;
|
|
}
|
|
void CItem::SetRestock( UI16 newValue )
|
|
{
|
|
restock = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - ARMORCLASS GetArmourClass( void ) const
|
|
//| void SetArmourClass( ARMORCLASS newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's armour class
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
ARMORCLASS CItem::GetArmourClass( void ) const
|
|
{
|
|
return armorClass;
|
|
}
|
|
void CItem::SetArmourClass( ARMORCLASS newValue )
|
|
{
|
|
armorClass = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI08 GetRank( void ) const
|
|
//| void SetRank( SI08 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's rank value - used in crafting
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI08 CItem::GetRank( void ) const
|
|
{
|
|
return rank;
|
|
}
|
|
void CItem::SetRank( SI08 newValue )
|
|
{
|
|
rank = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI16 GetGood( void ) const
|
|
//| void SetGood( SI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's good value - used by advanced trade system
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI16 CItem::GetGood( void ) const
|
|
{
|
|
return good;
|
|
}
|
|
void CItem::SetGood( SI16 newValue )
|
|
{
|
|
good = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI32 GetRndValueRate( void ) const
|
|
//| void SetRndValueRate( SI32 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets item's random value rate - used by advanced trade system
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI32 CItem::GetRndValueRate( void ) const
|
|
{
|
|
return rndvaluerate;
|
|
}
|
|
void CItem::SetRndValueRate( SI32 newValue )
|
|
{
|
|
rndvaluerate = newValue;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI08 GetMadeWith( void ) const
|
|
//| void SetMadeWith( SI08 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets ID of skill used to create item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI08 CItem::GetMadeWith( void ) const
|
|
{
|
|
return madewith;
|
|
}
|
|
void CItem::SetMadeWith( SI08 newValue )
|
|
{
|
|
madewith = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SERIAL GetGlow( void ) const
|
|
//| void SetGlow( SERIAL newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets serial of glow item attached to item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SERIAL CItem::GetGlow( void ) const
|
|
{
|
|
return glow;
|
|
}
|
|
void CItem::SetGlow( SERIAL newValue )
|
|
{
|
|
glow = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - COLOUR GetGlowColour( void ) const
|
|
//| void SetGlowColour( COLOUR newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets colour of glow item attached to item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
COLOUR CItem::GetGlowColour( void ) const
|
|
{
|
|
return glowColour;
|
|
}
|
|
void CItem::SetGlowColour( COLOUR newValue )
|
|
{
|
|
glowColour = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI08 GetGlowEffect( void ) const
|
|
//| void SetGlowEffect( UI08 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets colour of glow item attached to item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI08 CItem::GetGlowEffect( void ) const
|
|
{
|
|
return glow_effect;
|
|
}
|
|
void CItem::SetGlowEffect( UI08 newValue )
|
|
{
|
|
glow_effect = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetAmmoID( void ) const
|
|
//| void SetAmmoID( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets ammo ID for ammo used by ranged weapon
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetAmmoID( void ) const
|
|
{
|
|
return ammo[0];
|
|
}
|
|
void CItem::SetAmmoID( UI16 newValue )
|
|
{
|
|
ammo[0] = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetAmmoHue( void ) const
|
|
//| void SetAmmoHue( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets hue of ammo used by ranged weapon
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetAmmoHue( void ) const
|
|
{
|
|
return ammo[1];
|
|
}
|
|
void CItem::SetAmmoHue( UI16 newValue )
|
|
{
|
|
ammo[1] = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetAmmoFX( void ) const
|
|
//| void SetAmmoFX( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets projectile FX shown when firing ranged weapon
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetAmmoFX( void ) const
|
|
{
|
|
return ammoFX[0];
|
|
}
|
|
void CItem::SetAmmoFX( UI16 newValue )
|
|
{
|
|
ammoFX[0] = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SetAmmoFXHue( UI16 newValue )
|
|
//| void SetAmmoFXHue( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets colour of projectiles fired by ranged weapons
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetAmmoFXHue( void ) const
|
|
{
|
|
return ammoFX[1];
|
|
}
|
|
void CItem::SetAmmoFXHue( UI16 newValue )
|
|
{
|
|
ammoFX[1] = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetAmmoFXRender( void ) const
|
|
//| void SetAmmoFXRender( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets the render mode of projectile FX played when firing ranged weapons
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetAmmoFXRender( void ) const
|
|
{
|
|
return ammoFX[2];
|
|
}
|
|
void CItem::SetAmmoFXRender( UI16 newValue )
|
|
{
|
|
ammoFX[2] = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI32 GetWeightMax( void ) const
|
|
//| void SetWeightMax( SI32 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets maximum weight (in stones) a container can hold
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI32 CItem::GetWeightMax( void ) const
|
|
{
|
|
return weightMax;
|
|
}
|
|
void CItem::SetWeightMax( SI32 newValue )
|
|
{
|
|
weightMax = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI32 GetBaseWeight( void ) const
|
|
//| void SetBaseWeight( SI32 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets base item weight - primarily used to store original container weight
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI32 CItem::GetBaseWeight( void ) const
|
|
{
|
|
return baseWeight;
|
|
}
|
|
void CItem::SetBaseWeight( SI32 newValue )
|
|
{
|
|
baseWeight = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 GetMaxItems( void ) const
|
|
//| void SetMaxItems( UI16 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets maximum amount of items a container can hold
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::GetMaxItems( void ) const
|
|
{
|
|
return maxItems;
|
|
}
|
|
void CItem::SetMaxItems( UI16 newValue )
|
|
{
|
|
maxItems = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI08 IsFieldSpell( void ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns whether item belongs to a field spell - and if so - which one
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI08 CItem::IsFieldSpell( void ) const
|
|
{
|
|
switch( id )
|
|
{
|
|
case 0x3996:
|
|
case 0x398C: return 1;// fire
|
|
case 0x3915:
|
|
case 0x3920: return 2;// poison
|
|
case 0x3979:
|
|
case 0x3967: return 3;// paralyze
|
|
case 0x3956:
|
|
case 0x3946: return 4;// energy
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool CanBeLockedDown( void ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Checks whether item can be locked down
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::CanBeLockedDown( void ) const
|
|
{
|
|
if( type == IT_DOOR || type == IT_LOCKEDDOOR ) // can't lock down a door
|
|
return false;
|
|
if( IsFieldSpell() ) // can't lock down a field spell
|
|
return false;
|
|
if( id == 0x0BD2 || type == IT_HOUSESIGN ) // house sign
|
|
return false;
|
|
if( IsLockedDown() ) // can't lock down if already locked down
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool IsLockedDown( void ) const
|
|
//| void LockDown( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets whether item is locked down and immovable
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::IsLockedDown( void ) const
|
|
{
|
|
return ( movable == 3 );
|
|
}
|
|
void CItem::LockDown( void )
|
|
{
|
|
movable = 3;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool IsShieldType( void ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Checks whether item is a shield
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::IsShieldType( void ) const
|
|
{
|
|
if( id >= 0x1B72 && id <= 0x1B7B )
|
|
return true;
|
|
if( id >= 0x1BC3 && id <= 0x1BC7 )
|
|
return true;
|
|
if( id >= 0x4200 && id <= 0x420B )
|
|
return true;
|
|
if( id >= 0x4228 && id <= 0x422C )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool Save( std::ofstream &outStream )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Save item details to worldfile
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::Save( std::ofstream &outStream )
|
|
{
|
|
if( isFree() )
|
|
return false;
|
|
auto [width,height] = Map->sizeOfMap(worldNumber);
|
|
if( GetCont() || ( GetX() > 0 && GetX() < width && GetY() < height ) )
|
|
{
|
|
DumpHeader( outStream );
|
|
DumpBody( outStream );
|
|
DumpFooter( outStream );
|
|
|
|
for( CItem *toSave = Contains.First(); !Contains.Finished(); toSave = Contains.Next() )
|
|
{
|
|
if( ValidateObject( toSave ) && toSave->ShouldSave() )
|
|
toSave->Save( outStream );
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void RemoveSelfFromOwner( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Remove item (self) from owner it belongs to
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::RemoveSelfFromOwner( void )
|
|
{
|
|
CChar *oldOwner = GetOwnerObj();
|
|
if( oldOwner != nullptr )
|
|
{
|
|
oldOwner->RemoveOwnedItem( this );
|
|
oldOwner->UpdateRegion();
|
|
}
|
|
|
|
if( oldOwner == nullptr || oldOwner->ShouldSave() || ( !oldOwner->ShouldSave() && !isDeleted() ))
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void AddSelfToOwner( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Add item (self) to owner
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::AddSelfToOwner( void )
|
|
{
|
|
CChar *newOwner = GetOwnerObj();
|
|
if( !ValidateObject( newOwner ) )
|
|
return;
|
|
if( newOwner->GetSerial() != GetSerial() )
|
|
{
|
|
newOwner->AddOwnedItem( this );
|
|
newOwner->UpdateRegion();
|
|
}
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void RemoveSelfFromCont( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Remove item (self) from container it's in
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::RemoveSelfFromCont( void )
|
|
{
|
|
if( contObj != nullptr )
|
|
{
|
|
if( contObj->GetObjType() == OT_CHAR ) // it's a char!
|
|
{
|
|
CChar *targChar = dynamic_cast<CChar *>(contObj);
|
|
if( ValidateObject( targChar ) )
|
|
{
|
|
Weight->subtractItemWeight( targChar, this );
|
|
targChar->TakeOffItem( GetLayer() );
|
|
if( ShouldSave() && targChar->ShouldSave() )
|
|
{
|
|
UpdateRegion();
|
|
targChar->UpdateRegion();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CItem *targItem = dynamic_cast<CItem *>(contObj);
|
|
if( ValidateObject( targItem ) )
|
|
{
|
|
Weight->subtractItemWeight( targItem, this );
|
|
targItem->GetContainsList()->Remove( this );
|
|
UpdateRegion();
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
MapRegion->RemoveItem( this );
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CItem * Dupe( ObjectType itemType )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Make a copy of item and copy all properties from old item to new
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CItem * CItem::Dupe( ObjectType itemType )
|
|
{
|
|
CItem *target = static_cast< CItem * >(ObjectFactory::getSingleton().CreateObject( itemType ));
|
|
if( target == nullptr )
|
|
return nullptr;
|
|
|
|
CopyData( target );
|
|
|
|
return target;
|
|
}
|
|
|
|
void CItem::CopyData( CItem *target )
|
|
{
|
|
CBaseObject::CopyData( target );
|
|
|
|
target->SetGridLocation( GetGridLocation() );
|
|
target->SetPostLoaded( isPostLoaded() );
|
|
target->SetAmount( GetAmount() );
|
|
target->SetArmourClass( GetArmourClass() );
|
|
target->SetCarve( GetCarve() );
|
|
target->SetColour( GetColour() );
|
|
target->SetLayer( GetLayer() );
|
|
target->SetCont( GetCont() );
|
|
target->SetCreator( GetCreator() );
|
|
target->SetCorpse( isCorpse() );
|
|
target->SetDecayTime( GetDecayTime() );
|
|
target->SetDesc( GetDesc() );
|
|
target->SetEvent( GetEvent() );
|
|
target->SetDexterity( GetDexterity() );
|
|
target->SetDexterity2( GetDexterity2() );
|
|
target->SetResist( GetResist( PHYSICAL ), PHYSICAL );
|
|
target->SetDir( GetDir() );
|
|
target->SetDisabled( isDisabled() );
|
|
target->SetDoorOpen( isDoorOpen() );
|
|
target->SetDye( isDyeable() );
|
|
target->SetFree( isFree() );
|
|
target->SetTempTimer( GetTempTimer() );
|
|
target->SetGlow( GetGlow() );
|
|
target->SetGlowColour( GetGlowColour() );
|
|
target->SetGlowEffect( GetGlowEffect() );
|
|
target->SetAmmoID( GetAmmoID() );
|
|
target->SetAmmoHue( GetAmmoHue() );
|
|
target->SetAmmoFX( GetAmmoFX() );
|
|
target->SetAmmoFXHue( GetAmmoFXHue() );
|
|
target->SetAmmoFXRender( GetAmmoFXRender() );
|
|
target->SetGood( GetGood() );
|
|
target->SetHiDamage( GetHiDamage() );
|
|
target->SetHP( GetHP() );
|
|
target->SetID( GetID() );
|
|
target->SetIntelligence( GetIntelligence() );
|
|
target->SetIntelligence2( GetIntelligence2() );
|
|
target->SetLocation( this );
|
|
target->SetLoDamage( GetLoDamage() );
|
|
target->SetMadeWith( GetMadeWith() );
|
|
target->SetMovable( GetMovable() );
|
|
target->SetMana( GetMana() );
|
|
target->SetMaxHP( GetMaxHP() );
|
|
target->SetTempVar( CITV_MORE, GetTempVar( CITV_MORE ) );
|
|
target->SetTempVar( CITV_MOREX, GetTempVar( CITV_MOREX ) );
|
|
target->SetTempVar( CITV_MOREY, GetTempVar( CITV_MOREY ) );
|
|
target->SetTempVar( CITV_MOREZ, GetTempVar( CITV_MOREZ ) );
|
|
target->SetMulti( GetMultiObj() );
|
|
target->SetName( GetName() );
|
|
target->SetName2( GetName2() );
|
|
target->SetOffSpell( GetOffSpell() );
|
|
target->SetOwner( GetOwnerObj() );
|
|
target->SetPileable( isPileable() );
|
|
target->SetMakersMark( isMarkedByMaker() );
|
|
target->SetPoisoned( GetPoisoned() );
|
|
target->SetRace( GetRace() );
|
|
target->SetRank( GetRank() );
|
|
target->SetRestock( GetRestock() );
|
|
target->SetRndValueRate( GetRndValueRate() );
|
|
target->SetSpawn( GetSpawn() );
|
|
target->SetSpeed( GetSpeed() );
|
|
target->SetSpell( 0, GetSpell( 0 ) );
|
|
target->SetSpell( 1, GetSpell( 1 ) );
|
|
target->SetSpell( 2, GetSpell( 2 ) );
|
|
target->SetStamina( GetStamina() );
|
|
target->SetStrength( GetStrength() );
|
|
target->SetStrength2( GetStrength2() );
|
|
target->SetTitle( GetTitle() );
|
|
target->SetType( GetType() );
|
|
target->SetBuyValue( GetBuyValue() );
|
|
target->SetSellValue( GetSellValue() );
|
|
target->SetVisible( GetVisible() );
|
|
target->SetWeight( GetWeight() );
|
|
target->SetWeightMax( GetWeightMax() );
|
|
target->SetBaseWeight( GetBaseWeight() );
|
|
target->SetMaxItems( GetMaxItems() );
|
|
//target->SetWipeable( isWipeable() );
|
|
target->SetPriv( GetPriv() );
|
|
target->SetBaseRange( GetBaseRange() );
|
|
target->SetMaxRange( GetMaxRange() );
|
|
target->SetMaxUses( GetMaxUses() );
|
|
target->SetUsesLeft( GetUsesLeft() );
|
|
|
|
// Set damage types on new item
|
|
for( SI32 i = 0; i < WEATHNUM; ++i )
|
|
{
|
|
target->SetWeatherDamage( (WeatherType)i, GetWeatherDamage( (WeatherType)i ) );
|
|
}
|
|
|
|
// Add any script triggers present on object to the new object
|
|
target->scriptTriggers = GetScriptTriggers();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool GetWeatherDamage( WeatherType effectNum ) const
|
|
//| void SetWeatherDamage( WeatherType effectNum, bool value )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets weather damage of item - primarily used by weapons
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::GetWeatherDamage( WeatherType effectNum ) const
|
|
{
|
|
return weatherBools.test( effectNum );
|
|
}
|
|
void CItem::SetWeatherDamage( WeatherType effectNum, bool value )
|
|
{
|
|
weatherBools.set( effectNum, value );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool DumpHeader( std::ofstream &outStream ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Dump item header to worldfile
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::DumpHeader( std::ofstream &outStream ) const
|
|
{
|
|
outStream << "[ITEM]" << '\n';
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool DumpBody( std::ofstream &outStream ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Dump item tags and values to worldfile
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::DumpBody( std::ofstream &outStream ) const
|
|
{
|
|
CBaseObject::DumpBody( outStream );
|
|
const char newLine = '\n';
|
|
|
|
// Hexadecimal Values
|
|
outStream << std::hex;
|
|
outStream << "GridLoc=0x" << static_cast<SI16>( GetGridLocation() ) << newLine;
|
|
outStream << "Layer=0x" << static_cast<SI16>( GetLayer() ) << newLine;
|
|
outStream << "Cont=0x" << GetContSerial() << newLine;
|
|
outStream << "More=0x" << GetTempVar( CITV_MORE ) << newLine;
|
|
outStream << "Creator=0x" << GetCreator() << newLine;
|
|
outStream << "MoreXYZ=0x" << GetTempVar( CITV_MOREX ) << ",0x" << GetTempVar( CITV_MOREY ) << ",0x" << GetTempVar( CITV_MOREZ ) << newLine;
|
|
outStream << "Glow=0x" << GetGlow() << newLine;
|
|
outStream << "GlowBC=0x" << GetGlowColour() << newLine;
|
|
outStream << "Ammo=0x" << GetAmmoID() << ",0x" << GetAmmoHue() << newLine;
|
|
outStream << "AmmoFX=0x" << GetAmmoFX() << ",0x" << GetAmmoFXHue() << ",0x" << GetAmmoFXRender() << newLine;
|
|
outStream << "Spells=0x" << GetSpell( 0 ) << ",0x" << GetSpell( 1 ) << ",0x" << GetSpell( 2 ) << newLine;
|
|
|
|
// Decimal / String Values
|
|
outStream << std::dec;
|
|
outStream << "Name2=" << GetName2() << newLine;
|
|
outStream << "Desc=" << GetDesc() << newLine;
|
|
outStream << "Event=" << GetEvent() << newLine;
|
|
outStream << "Type=" + std::to_string( GetType() ) + newLine;
|
|
outStream << "Offspell=" + std::to_string( GetOffSpell() ) + newLine;
|
|
outStream << "Amount=" + std::to_string( GetAmount() ) + newLine;
|
|
outStream << "WeightMax=" + std::to_string( GetWeightMax() ) + newLine;
|
|
outStream << "BaseWeight=" + std::to_string( GetBaseWeight() ) + newLine;
|
|
outStream << "MaxItems=" + std::to_string( GetMaxItems() ) + newLine;
|
|
outStream << "MaxHP=" + std::to_string( GetMaxHP() ) + newLine;
|
|
outStream << "Speed=" + std::to_string( GetSpeed() ) + newLine;
|
|
outStream << "Movable=" + std::to_string( GetMovable() ) + newLine;
|
|
outStream << "Priv=" + std::to_string( GetPriv() ) + newLine;
|
|
outStream << "Value=" + std::to_string( GetBuyValue() ) + "," + std::to_string( GetSellValue() ) + newLine;
|
|
outStream << "Restock=" + std::to_string( GetRestock() ) + newLine;
|
|
outStream << "AC=" + std::to_string( GetArmourClass() ) + newLine;
|
|
outStream << "Rank=" + std::to_string( GetRank() ) + newLine;
|
|
outStream << "Sk_Made=" + std::to_string( GetMadeWith() ) + newLine;
|
|
outStream << "Bools=" + std::to_string(( bools.to_ulong() )) + newLine;
|
|
outStream << "Good=" + std::to_string( GetGood() ) + newLine;
|
|
outStream << "GlowType=" + std::to_string( GetGlowEffect() ) + newLine;
|
|
outStream << "Range=" + std::to_string( GetBaseRange() ) + "," + std::to_string(GetMaxRange()) + newLine;
|
|
outStream << "MaxUses=" + std::to_string( GetMaxUses() ) + newLine;
|
|
outStream << "UsesLeft=" + std::to_string( GetUsesLeft() ) + newLine;
|
|
outStream << "RaceDamage=" + std::to_string(static_cast<SI16>( GetWeatherDamage( LIGHT ) ? 1 : 0 )) + "," + std::to_string(static_cast<SI16>( GetWeatherDamage( RAIN ) ? 1 : 0 )) + ","
|
|
+ std::to_string( static_cast<SI16>( GetWeatherDamage( HEAT ) ? 1 : 0 )) + "," + std::to_string( static_cast<SI16>( GetWeatherDamage( COLD ) ? 1 : 0 )) + ","
|
|
+ std::to_string( static_cast<SI16>( GetWeatherDamage( SNOW ) ? 1 : 0 )) + "," + std::to_string( static_cast<SI16>( GetWeatherDamage( LIGHTNING ) ? 1 : 0 )) + newLine;
|
|
outStream << "EntryMadeFrom=" + std::to_string( EntryMadeFrom() ) + newLine;
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool HandleLine( std::string &UTag, std::string &data )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Handles loading in tags and values from world files on startup
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::HandleLine( std::string &UTag, std::string &data )
|
|
{
|
|
bool rvalue = CBaseObject::HandleLine( UTag, data );
|
|
if( !rvalue )
|
|
{
|
|
auto csecs = oldstrutil::sections( data, "," );
|
|
switch( (UTag.data()[0]) )
|
|
{
|
|
case 'A':
|
|
if( UTag == "AMMO" )
|
|
{
|
|
if( csecs.size() == 2 )
|
|
{
|
|
SetAmmoID( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetAmmoHue( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
}
|
|
else
|
|
{
|
|
SetAmmoID( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
SetAmmoHue( ( 0 ) );
|
|
}
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "AMMOFX" )
|
|
{
|
|
if( csecs.size() == 2 )
|
|
{
|
|
SetAmmoFX( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetAmmoFXHue( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
SetAmmoFXRender( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
}
|
|
else
|
|
{
|
|
SetAmmoFX( static_cast<UI16>(std::stoul( oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0 )));
|
|
SetAmmoFXHue( ( 0 ) );
|
|
SetAmmoFXRender( ( 0 ) );
|
|
}
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "AMOUNT" )
|
|
{
|
|
amount = static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0));
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "AC" )
|
|
{
|
|
SetArmourClass( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'B':
|
|
if( UTag == "BOOLS" )
|
|
{
|
|
bools = static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0));
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'C':
|
|
if( UTag == "CONT" )
|
|
{
|
|
temp_container_serial = static_cast<SERIAL>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0));
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "CREATOR" || UTag == "CREATER" )
|
|
{
|
|
SetCreator( static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "CORPSE" )
|
|
{
|
|
SetCorpse( static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "COLD" )
|
|
{
|
|
SetWeatherDamage( COLD, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'D':
|
|
if( UTag == "DESC" )
|
|
{
|
|
SetDesc( data.c_str() );
|
|
rvalue = true;
|
|
}
|
|
if( UTag == "DIR" )
|
|
{
|
|
SetDir( static_cast<SI08>(std::stoi(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)));
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "DYEABLE" )
|
|
{
|
|
SetDye( static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'E':
|
|
if( UTag == "ENTRYMADEFROM" )
|
|
{
|
|
EntryMadeFrom( static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "EVENT" )
|
|
{
|
|
SetEvent( data.c_str() );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'G':
|
|
if( UTag == "GRIDLOC" )
|
|
{
|
|
SetGridLocation( static_cast<SI08>(std::stoi(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "GLOWTYPE" )
|
|
{
|
|
SetGlowEffect( static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "GLOWBC" )
|
|
{
|
|
SetGlowColour( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "GLOW" )
|
|
{
|
|
SetGlow( static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "GOOD" )
|
|
{
|
|
SetGood( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'H':
|
|
if( UTag == "HEAT" )
|
|
{
|
|
SetWeatherDamage( HEAT, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'L':
|
|
if( UTag == "LAYER" )
|
|
{
|
|
layer = static_cast<ItemLayers>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0));
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "LIGHT" )
|
|
{
|
|
SetWeatherDamage( LIGHT, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "LIGHTNING" )
|
|
{
|
|
SetWeatherDamage( LIGHTNING, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'M':
|
|
if( UTag == "MAXITEMS" )
|
|
{
|
|
SetMaxItems( static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "MORE" )
|
|
{
|
|
if( csecs.size() >= 4 )
|
|
{
|
|
SetTempVar( CITV_MORE, 1, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MORE, 2, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MORE, 3, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[2], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MORE, 4, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[3], "//" )), nullptr, 0)) );
|
|
}
|
|
else
|
|
{
|
|
SetTempVar( CITV_MORE, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
}
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "MORE2" ) // Depreciated
|
|
rvalue = true;
|
|
else if( UTag == "MURDERER" )
|
|
rvalue = true;
|
|
else if( UTag == "MOREXYZ" )
|
|
{
|
|
SetTempVar( CITV_MOREX, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREY, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREZ, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[2], "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "MOREX" )
|
|
{
|
|
if( csecs.size() >= 4 )
|
|
{
|
|
SetTempVar( CITV_MOREX, 1, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREX, 2, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREX, 3, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[2], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREX, 4, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[3], "//" )), nullptr, 0)) );
|
|
}
|
|
else
|
|
{
|
|
SetTempVar( CITV_MOREX, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
}
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "MOREY" )
|
|
{
|
|
if( csecs.size() >= 4 )
|
|
{
|
|
SetTempVar( CITV_MOREY, 1, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREY, 2, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREY, 3, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[2], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREY, 4, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[3], "//" )), nullptr, 0)) );
|
|
}
|
|
else
|
|
{
|
|
SetTempVar( CITV_MOREY, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
}
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "MOREZ" )
|
|
{
|
|
if( csecs.size() >= 4 )
|
|
{
|
|
SetTempVar( CITV_MOREZ, 1, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREZ, 2, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREZ, 3, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[2], "//" )), nullptr, 0)) );
|
|
SetTempVar( CITV_MOREZ, 4, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[3], "//" )), nullptr, 0)) );
|
|
}
|
|
else
|
|
{
|
|
SetTempVar( CITV_MOREZ, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
}
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "MOVABLE" )
|
|
{
|
|
SetMovable( static_cast<SI08>(std::stoi(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "MAXHP" )
|
|
{
|
|
SetMaxHP( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "MAXUSES" )
|
|
{
|
|
SetMaxUses( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'N':
|
|
if( UTag == "NAME2" )
|
|
{
|
|
SetName2(data);
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'O':
|
|
if( UTag == "OFFSPELL" )
|
|
{
|
|
SetOffSpell( static_cast<SI08>(std::stoi(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'P':
|
|
if( UTag == "PRIV" )
|
|
{
|
|
SetPriv( static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "PILEABLE" )
|
|
{
|
|
SetPileable( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'R':
|
|
if( UTag == "RESTOCK" )
|
|
{
|
|
SetRestock( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "RACEDAMAGE" )
|
|
{
|
|
SetWeatherDamage( LIGHT, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) == 1 );
|
|
SetWeatherDamage( RAIN, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) == 1 );
|
|
SetWeatherDamage( HEAT, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[2], "//" )), nullptr, 0)) == 1 );
|
|
SetWeatherDamage( COLD, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[3], "//" )), nullptr, 0)) == 1 );
|
|
SetWeatherDamage( SNOW, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[4], "//" )), nullptr, 0)) == 1 );
|
|
SetWeatherDamage( LIGHTNING, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[5], "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "RANK" )
|
|
{
|
|
SetRank( static_cast<SI08>(std::stoi(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "RAIN" )
|
|
{
|
|
SetWeatherDamage( RAIN, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "RANGE" )
|
|
{
|
|
if( csecs.size() > 1 )
|
|
{
|
|
SetBaseRange( static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetMaxRange( static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
}
|
|
else
|
|
{
|
|
auto val = static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0));
|
|
SetBaseRange( val );
|
|
SetMaxRange( val / 2 );
|
|
}
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "REPUTATION" )
|
|
rvalue = true;
|
|
break;
|
|
case 'S':
|
|
if( UTag == "SPEED" )
|
|
{
|
|
SetSpeed( static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "SK_MADE" )
|
|
{
|
|
SetMadeWith( static_cast<SI08>(std::stoi(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "SNOW" )
|
|
{
|
|
SetWeatherDamage( SNOW, static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1 );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "SPELLS" )
|
|
{
|
|
SetSpell( 0, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetSpell( 1, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
SetSpell( 2, static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[2], "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'T':
|
|
if( UTag == "TYPE" )
|
|
{
|
|
if( csecs.size() != 1 )
|
|
{
|
|
SetType( static_cast<ItemTypes>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
}
|
|
else
|
|
{
|
|
SetType( static_cast<ItemTypes>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
}
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "TYPE2" )
|
|
rvalue = true;
|
|
break;
|
|
case 'U':
|
|
if( UTag == "USESLEFT" )
|
|
{
|
|
SetUsesLeft( static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'V':
|
|
if( UTag == "VALUE" )
|
|
{
|
|
if( csecs.size() > 1 )
|
|
{
|
|
SetBuyValue( static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetSellValue( static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
}
|
|
else
|
|
{
|
|
auto val = static_cast<UI32>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0));
|
|
SetBuyValue( val );
|
|
SetSellValue( val / 2 );
|
|
}
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'W':
|
|
if( UTag == "WEIGHTMAX" )
|
|
{
|
|
SetWeightMax( static_cast<SI32>(std::stoi(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return rvalue;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool LoadRemnants( void )
|
|
//| Date - 21st January, 2002
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - After handling data specific load, other parts go here
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::LoadRemnants( void )
|
|
{
|
|
SetSerial( serial );
|
|
|
|
// Tauriel adding region pointers
|
|
if( !contObj|| (UI64)contObj == INVALIDSERIAL )
|
|
{
|
|
auto [width,height] = Map->sizeOfMap(worldNumber);
|
|
if( GetX() < 0 || GetY() < 0 || GetX() > width || GetY() > height )
|
|
return false;
|
|
|
|
// Calculate which townregion item exists in, based on its own location
|
|
CTownRegion *tRegion = calcRegionFromXY( GetX(), GetY(), worldNumber, instanceID, this );
|
|
SetRegion( (tRegion != nullptr ? tRegion->GetRegionNum() : 0xFF) );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool IsContType( void ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Checks if item has a container type
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::IsContType( void ) const
|
|
{
|
|
if( GetLayer() == IL_PACKITEM || GetLayer() == IL_BANKBOX )
|
|
return true;
|
|
switch( GetType() )
|
|
{
|
|
case IT_CONTAINER:
|
|
case IT_LOCKEDCONTAINER:
|
|
case IT_SPAWNCONT:
|
|
case IT_LOCKEDSPAWNCONT:
|
|
case IT_UNLOCKABLESPAWNCONT:
|
|
case IT_TRASHCONT:
|
|
return true;
|
|
default: return false;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void PostLoadProcessing( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Used to setup any pointers that may need adjustment following the loading of the world
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::PostLoadProcessing( void )
|
|
{
|
|
CBaseObject::PostLoadProcessing();
|
|
// Add item weight if item doesn't have it yet
|
|
if( GetWeight() < 0 || GetWeight() > MAX_WEIGHT )
|
|
SetWeight( Weight->calcWeight( this ) );
|
|
|
|
CBaseObject *tmpObj = nullptr;
|
|
contObj = nullptr;
|
|
|
|
if( temp_container_serial != INVALIDSERIAL )
|
|
{
|
|
if( temp_container_serial >= BASEITEMSERIAL )
|
|
{
|
|
tmpObj = calcItemObjFromSer( temp_container_serial);
|
|
}
|
|
else
|
|
{
|
|
tmpObj = calcCharObjFromSer( temp_container_serial );
|
|
}
|
|
}
|
|
SetCont( tmpObj );
|
|
|
|
Items->StoreItemRandomValue( this, nullptr );
|
|
CheckItemIntegrity();
|
|
SetPostLoaded( true );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void CheckItemIntegrity( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Run some integrity checks on item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::CheckItemIntegrity( void )
|
|
{
|
|
SERIAL getSerial = GetSerial();
|
|
if( getSerial == INVALIDSERIAL )
|
|
{
|
|
Console.warning(oldstrutil::format( "Item (%s) has an invalid serial number, Deleting", GetName().c_str()) );
|
|
Delete();
|
|
return;
|
|
}
|
|
|
|
if( getSerial == GetContSerial() )
|
|
{
|
|
Console.warning( oldstrutil::format("Item 0x%X (%s) has dangerous container value, Auto-Correcting", getSerial, GetName().c_str()) );
|
|
SetCont( nullptr );
|
|
}
|
|
if( getSerial == GetOwner() )
|
|
{
|
|
Console.warning( oldstrutil::format("Item 0x%X (%s) has dangerous owner value, Auto-Correcting", getSerial, GetName().c_str()) );
|
|
SetOwner( nullptr );
|
|
}
|
|
if( getSerial == GetSpawn() )
|
|
{
|
|
Console.warning( oldstrutil::format("Item 0x%X (%s) has dangerous spawner value, Auto-Correcting", getSerial, GetName().c_str() ));
|
|
SetSpawn( INVALIDSERIAL );
|
|
}
|
|
|
|
if( type == IT_CONTAINER && GetLayer() == IL_PACKITEM && (contObj != nullptr && contObj->CanBeObjType( OT_CHAR )))
|
|
{
|
|
UI16 maxItemsVal = GetMaxItems();
|
|
if( maxItemsVal == 0 )
|
|
{
|
|
SetMaxItems(cwmWorldState->ServerData()->MaxPlayerPackItems());
|
|
Console.warning(oldstrutil::format("Container (%s) with maxItems set to 0 detected on character (%s). Resetting maxItems for container to default value.", std::to_string(GetSerial()).c_str(), std::to_string(contObj->GetSerial()).c_str()));
|
|
}
|
|
}
|
|
}
|
|
|
|
const UI32 BIT_DECAYABLE = 0;
|
|
const UI32 BIT_NEWBIE = 1;
|
|
const UI32 BIT_DISPELLABLE = 2;
|
|
const UI32 BIT_DIVINELOCK = 3;
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isDecayable( void ) const
|
|
//| void SetDecayable( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets whether item can decay
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isDecayable( void ) const
|
|
{
|
|
return priv.test( BIT_DECAYABLE );
|
|
}
|
|
void CItem::SetDecayable( bool newValue )
|
|
{
|
|
if( newValue )
|
|
SetDecayTime( 0 );
|
|
|
|
priv.set( BIT_DECAYABLE, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isNewbie( void ) const
|
|
//| void SetNewbie( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets whether item is marked as a newbie item (doesn't drop on death)
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isNewbie( void ) const
|
|
{
|
|
return priv.test( BIT_NEWBIE );
|
|
}
|
|
void CItem::SetNewbie( bool newValue )
|
|
{
|
|
priv.set( BIT_NEWBIE, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isDispellable( void ) const
|
|
//| void SetDispellable( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets whether item is dispellable (part of a field spell, for instance)
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isDispellable( void ) const
|
|
{
|
|
return priv.test( BIT_DISPELLABLE );
|
|
}
|
|
void CItem::SetDispellable( bool newValue )
|
|
{
|
|
priv.set( BIT_DISPELLABLE, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool isDivineLocked( void ) const
|
|
//| void SetDivineLock( bool newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets whether container was locked by a GM
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::isDivineLocked( void ) const
|
|
{
|
|
return priv.test( BIT_DIVINELOCK );
|
|
}
|
|
void CItem::SetDivineLock( bool newValue )
|
|
{
|
|
priv.set( BIT_DIVINELOCK, newValue );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI16 EntryMadeFrom( void ) const
|
|
//| void EntryMadeFrom( UI16 newValue )
|
|
//| Date - 13 September, 2001
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets the Create-DFNs entry the item was made from
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI16 CItem::EntryMadeFrom( void ) const
|
|
{
|
|
return entryMadeFrom;
|
|
}
|
|
void CItem::EntryMadeFrom( UI16 newValue )
|
|
{
|
|
entryMadeFrom = newValue;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SetWeight( SI32 newVal, bool doWeightUpdate )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Sets the weight of the item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::SetWeight( SI32 newVal, bool doWeightUpdate )
|
|
{
|
|
CBaseObject *checkCont = nullptr;
|
|
if( isPostLoaded() && doWeightUpdate )
|
|
checkCont = GetCont();
|
|
|
|
if( ValidateObject( checkCont ) )
|
|
Weight->subtractItemWeight( checkCont, this );
|
|
|
|
weight = newVal;
|
|
|
|
if( ValidateObject( checkCont ) )
|
|
Weight->addItemWeight( checkCont, this );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool IsMetalType( void ) const
|
|
//| Date - 13 November, 2001
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns true if it's a metal object
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::IsMetalType( void ) const
|
|
{
|
|
if( id >= 0x1B72 && id <= 0x1B7B )
|
|
return true;
|
|
else if( id >= 0x1BC3 && id <= 0x1BC5 )
|
|
return true;
|
|
else if( id >= 0x13AF && id <= 0x13B0 )
|
|
return true;
|
|
else if( id >= 0x13B5 && id <= 0x13C4 )
|
|
return true;
|
|
else if( id >= 0x13E5 && id <= 0x13F2 )
|
|
return true;
|
|
else if( id >= 0x13FA && id <= 0x13FB )
|
|
return true;
|
|
else if( id >= 0x13FE && id <= 0x141A )
|
|
return true;
|
|
else if( id >= 0x1438 && id <= 0x1443 )
|
|
return true;
|
|
else if( id >= 0x0F43 && id <= 0x0F4E )
|
|
return true;
|
|
else if( id >= 0x0F51 && id <= 0x0F52 )
|
|
return true;
|
|
else if( id >= 0x0F5C && id <= 0x0F63 )
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool IsLeatherType( void ) const
|
|
//| Date - 13 November, 2001
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns true if it's a leather object
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::IsLeatherType( void ) const
|
|
{
|
|
if( id >= 0x13C6 && id <= 0x13E2 )
|
|
return true;
|
|
if( id >= 0x144E && id <= 0x1457 )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
inline bool operator==( const CItem& x, const CItem& y )
|
|
{
|
|
return ( x.GetSerial() == y.GetSerial() );
|
|
}
|
|
|
|
inline bool operator<(const CItem& x, const CItem& y )
|
|
{
|
|
return ( x.GetSerial() < y.GetSerial() );
|
|
}
|
|
|
|
inline bool operator>(const CItem& x, const CItem& y )
|
|
{
|
|
return ( x.GetSerial() > y.GetSerial() );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void TextMessage( CSocket *s, SI32 dictEntry, R32 secsFromNow, UI16 Colour )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Display "speech" over an item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::TextMessage( CSocket *s, SI32 dictEntry, R32 secsFromNow, UI16 Colour )
|
|
{
|
|
UnicodeTypes dictLang = ZERO;
|
|
SERIAL speakTo = INVALIDSERIAL;
|
|
SpeechTarget target = SPTRG_PCNPC;
|
|
CChar *mChar = nullptr;
|
|
if( s != nullptr )
|
|
{
|
|
dictLang = s->Language();
|
|
mChar = s->CurrcharObj();
|
|
speakTo = mChar->GetSerial();
|
|
target = SPTRG_INDIVIDUAL;
|
|
}
|
|
|
|
std::string txt = Dictionary->GetEntry( dictEntry, dictLang );
|
|
if( txt.empty() )
|
|
return;
|
|
|
|
if( s != nullptr && cwmWorldState->ServerData()->UseUnicodeMessages() )
|
|
{
|
|
bool sendAll = true;
|
|
if( target == SPTRG_INDIVIDUAL )
|
|
sendAll = false;
|
|
|
|
if( Colour == 0x0 || Colour == 0x1700)
|
|
Colour = 0x03B2;
|
|
|
|
CPUnicodeMessage unicodeMessage;
|
|
unicodeMessage.Message( txt );
|
|
unicodeMessage.Font( FNT_NORMAL );
|
|
unicodeMessage.Colour( 0x000B );
|
|
unicodeMessage.Type( SYSTEM );
|
|
unicodeMessage.Language( "ENG" );
|
|
unicodeMessage.Name( GetNameRequest( mChar ));
|
|
unicodeMessage.ID( GetID() );
|
|
unicodeMessage.Serial( GetSerial() );
|
|
|
|
s->Send( &unicodeMessage );
|
|
}
|
|
else
|
|
{
|
|
CSpeechEntry& toAdd = SpeechSys->Add();
|
|
toAdd.Speech( txt );
|
|
toAdd.Font( FNT_NORMAL );
|
|
toAdd.Speaker( GetSerial() );
|
|
toAdd.SpokenTo( speakTo );
|
|
toAdd.Type( OBJ );
|
|
toAdd.At( BuildTimeValue( secsFromNow ) );
|
|
toAdd.TargType( target );
|
|
if( Colour == 0x0 || Colour == 0x1700)
|
|
toAdd.Colour( 0x03B2 );
|
|
else
|
|
toAdd.Colour( Colour );
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void Update( CSocket *mSock )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Send this item to specified socket or all online people in range
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::Update( CSocket *mSock, bool drawGamePlayer, bool sendToSelf )
|
|
{
|
|
if( GetType() == IT_TRADEWINDOW )
|
|
return;
|
|
|
|
//RemoveFromSight( mSock );
|
|
#pragma note( "To monitor: Commented out RemoveFromSight() in CItem::Update() to potentially fix a lot of flickering issues with animated items, boats, etc." )
|
|
|
|
if( GetCont() == this )
|
|
{
|
|
Console.warning( oldstrutil::format("Item %s(0x%X) has a dangerous container value, auto-correcting", GetName().c_str(), GetSerial() ));
|
|
SetCont( nullptr );
|
|
}
|
|
|
|
CBaseObject *iCont = GetCont();
|
|
if( iCont == nullptr )
|
|
{
|
|
std::vector< CSocket * > nearbyChars;
|
|
if( GetID( 1 ) >= 0x40 )
|
|
nearbyChars = FindNearbyPlayers( this, DIST_BUILDRANGE );
|
|
else
|
|
nearbyChars = FindPlayersInVisrange( this );
|
|
std::for_each(nearbyChars.begin(),nearbyChars.end(),[this](CSocket *tSock){
|
|
SendToSocket(tSock);
|
|
});
|
|
return;
|
|
}
|
|
else if( iCont->GetObjType() == OT_CHAR )
|
|
{
|
|
CChar *charCont = static_cast<CChar *>(iCont);
|
|
if( charCont != nullptr )
|
|
{
|
|
CPWornItem toWear = (*this);
|
|
auto nearbyChar = FindNearbyPlayers( charCont );
|
|
for( auto &tSock : nearbyChar )
|
|
{
|
|
if( tSock->LoginComplete() )
|
|
{
|
|
tSock->Send( &toWear );
|
|
|
|
// Only send tooltip if server feature for tooltips is enabled
|
|
if( cwmWorldState->ServerData()->GetServerFeature( SF_BIT_AOS ) )
|
|
{
|
|
CPToolTip pSend( GetSerial(), tSock );
|
|
tSock->Send( &pSend );
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CItem *itemCont = static_cast<CItem *>(iCont);
|
|
if( itemCont != nullptr )
|
|
{
|
|
ObjectType oType = OT_CBO;
|
|
for( auto &tSock: FindNearbyPlayers( FindItemOwner( this, oType ), DIST_NEARBY )) {
|
|
if( tSock->LoginComplete() ) {
|
|
SendPackItemToSocket( tSock );
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
Console.error(oldstrutil::format( " CItem::Update(0x%X): cannot determine container type!", GetSerial() ));
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SendToSocket( CSocket *mSock, bool drawGamePlayer )
|
|
//| Date - July 27, 2003
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Updates an item on the ground to specified socket
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::SendToSocket( CSocket *mSock, bool drawGamePlayer )
|
|
{
|
|
if( !mSock->LoginComplete() )
|
|
return;
|
|
|
|
CChar *mChar = mSock->CurrcharObj();
|
|
if( mChar != nullptr )
|
|
{
|
|
if( !mChar->IsGM() )
|
|
{
|
|
if( GetVisible() != VT_VISIBLE || ( GetVisible() == VT_TEMPHIDDEN && mChar != GetOwnerObj() ) ) // Not a GM, and not the Owner
|
|
return;
|
|
}
|
|
if( mSock->ClientType() >= CV_SA2D )
|
|
{
|
|
CPNewObjectInfo toSend( (*this), (*mChar) );
|
|
mSock->Send( &toSend );
|
|
}
|
|
else
|
|
{
|
|
CPObjectInfo toSend( (*this), (*mChar) );
|
|
mSock->Send( &toSend );
|
|
}
|
|
if( isCorpse() )
|
|
{
|
|
CPCorpseClothing cpcc( this );
|
|
mSock->Send( &cpcc );
|
|
CPItemsInContainer itemsIn( mSock, this, 0x01 );
|
|
mSock->Send( &itemsIn );
|
|
}
|
|
if( !CanBeObjType( OT_MULTI ) )
|
|
{
|
|
// Only send tooltip if server feature for tooltips is enabled
|
|
if( cwmWorldState->ServerData()->GetServerFeature( SF_BIT_AOS ) )
|
|
{
|
|
CPToolTip pSend( GetSerial(), mSock );
|
|
mSock->Send( &pSend );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SendPackItemToSocket( CSocket *mSock )
|
|
//| Date - July 27, 2003
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Updates an item contained in a pack to specified socket
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::SendPackItemToSocket( CSocket *mSock )
|
|
{
|
|
CChar *mChar = mSock->CurrcharObj();
|
|
if( mChar != nullptr )
|
|
{
|
|
bool isGM = mChar->IsGM();
|
|
ItemLayers iLayer = GetLayer();
|
|
if( !isGM && ( iLayer == IL_SELLCONTAINER || iLayer == IL_BOUGHTCONTAINER || iLayer == IL_BUYCONTAINER ) )
|
|
return;
|
|
|
|
CPAddItemToCont itemSend;
|
|
if( mSock->ClientVerShort() >= CVS_6017 )
|
|
itemSend.UOKRFlag( true );
|
|
itemSend.Object( (*this) );
|
|
if( isGM && GetID() == 0x1647 )
|
|
{
|
|
itemSend.Model( 0x0A0F );
|
|
itemSend.Colour( 0x00C6 );
|
|
}
|
|
mSock->Send( &itemSend );
|
|
// Only send tooltip if server feature for tooltips is enabled
|
|
if( cwmWorldState->ServerData()->GetServerFeature( SF_BIT_AOS ) )
|
|
{
|
|
CPToolTip pSend( GetSerial(), mSock );
|
|
mSock->Send( &pSend );
|
|
}
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void RemoveFromSight( CSocket *mSock )
|
|
//| Date - September 7th, 2003
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Loops through all online chars and removes the item from their sight
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::RemoveFromSight( CSocket *mSock )
|
|
{
|
|
CPRemoveItem toRemove = (*this);
|
|
CBaseObject *iCont = GetCont();
|
|
|
|
ObjectType oType = OT_CBO;
|
|
CBaseObject *iOwner = nullptr;
|
|
if( this->GetOwner() != INVALIDSERIAL )
|
|
iOwner = FindItemOwner( this, oType );
|
|
|
|
if( iCont == nullptr || oType == OT_ITEM )
|
|
{
|
|
CItem *rItem = nullptr;
|
|
if( iCont == nullptr )
|
|
rItem = this;
|
|
else
|
|
rItem = static_cast<CItem *>(iOwner);
|
|
if( rItem != nullptr )
|
|
{
|
|
if( mSock != nullptr )
|
|
mSock->Send( &toRemove );
|
|
else
|
|
{
|
|
CChar *tChar = nullptr;
|
|
std::vector< CSocket * > nearbyChars;
|
|
if( rItem == this )
|
|
nearbyChars = FindPlayersInOldVisrange( rItem );
|
|
else
|
|
nearbyChars = FindPlayersInVisrange( rItem );
|
|
for (auto &tSock : nearbyChars) {
|
|
if( tSock->LoginComplete() ){
|
|
tChar = tSock->CurrcharObj();
|
|
if( ValidateObject( tChar ) )
|
|
{
|
|
tSock->Send( &toRemove );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( iCont->GetObjType() == OT_CHAR || oType == OT_CHAR )
|
|
{
|
|
CChar *rChar = nullptr;
|
|
if( iCont->GetObjType() == OT_CHAR )
|
|
rChar = static_cast<CChar *>(iCont);
|
|
else
|
|
rChar = static_cast<CChar *>(iOwner);
|
|
if( rChar != nullptr )
|
|
{
|
|
if( mSock != nullptr )
|
|
mSock->Send( &toRemove );
|
|
else
|
|
{
|
|
|
|
for( auto &tSock : FindNearbyPlayers( rChar )) {
|
|
if( tSock->LoginComplete() ) {
|
|
tSock->Send( &toRemove );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( mSock != nullptr )
|
|
mSock->Send( &toRemove );
|
|
else
|
|
{
|
|
for (auto &nSock : Network->connClients) {
|
|
if( nSock->LoginComplete() ){
|
|
nSock->Send( &toRemove );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void PlaceInPack( void )
|
|
//| Date - October 18th, 2003
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Puts an item at a random location inside a pack
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::PlaceInPack( void )
|
|
{
|
|
auto itemCont = this->GetCont();
|
|
if( !ValidateObject( itemCont ))
|
|
return;
|
|
|
|
PackTypes packType = Items->getPackType( static_cast<CItem *>(itemCont) );
|
|
switch( packType )
|
|
{
|
|
case PT_PACK:
|
|
SetX(( RandomNum( 44, 142 )));
|
|
SetY(( RandomNum( 65, 127 )));
|
|
break;
|
|
case PT_BAG:
|
|
SetX(( RandomNum( 29, 93 )));
|
|
SetY(( RandomNum( 34, 96 )));
|
|
break;
|
|
case PT_SQBASKET:
|
|
SetX(( RandomNum( 19, 138 )));
|
|
SetY(( RandomNum( 47, 91 )));
|
|
break;
|
|
case PT_RBASKET:
|
|
SetX(( RandomNum( 40, 95 )));
|
|
SetY(( RandomNum( 30, 91 )));
|
|
break;
|
|
case PT_SEBASKET:
|
|
SetX(( RandomNum( 10, 112 )));
|
|
SetY(( RandomNum( 10, 73 )));
|
|
break;
|
|
case PT_BOOKCASE:
|
|
SetX(( RandomNum( 13, 36 )));
|
|
SetY(( RandomNum( 76, 96 )));
|
|
break;
|
|
case PT_FARMOIRE:
|
|
case PT_WARMOIRE:
|
|
SetX(( RandomNum( 24, 56 )));
|
|
SetY(( RandomNum( 18, 120 )));
|
|
break;
|
|
case PT_DRAWER:
|
|
case PT_DRESSER:
|
|
SetX(( RandomNum( 16, 110 )));
|
|
SetY(( RandomNum( 10, 62 )));
|
|
break;
|
|
case PT_SECHEST1:
|
|
case PT_SECHEST2:
|
|
case PT_SECHEST3:
|
|
case PT_SECHEST4:
|
|
case PT_SECHEST5:
|
|
case PT_SEARMOIRE1:
|
|
case PT_SEARMOIRE2:
|
|
case PT_SEARMOIRE3:
|
|
SetX(( RandomNum( 10, 115 )));
|
|
SetY(( RandomNum( 10, 73 )));
|
|
break;
|
|
case PT_MBOX:
|
|
case PT_WBOX:
|
|
SetY(( RandomNum( 51, 92 )));
|
|
SetX(( RandomNum( 16, 140 )));
|
|
break;
|
|
case PT_BARREL:
|
|
SetY(( RandomNum( 36, 116 )));
|
|
SetX(( RandomNum( 33, 98 )));
|
|
break;
|
|
case PT_CRATE:
|
|
SetY(( RandomNum( 10, 68 )));
|
|
SetX(( RandomNum( 20, 126 )));
|
|
break;
|
|
case PT_WCHEST:
|
|
case PT_SCHEST:
|
|
case PT_GCHEST:
|
|
SetY(( RandomNum( 105, 139 )));
|
|
SetX(( RandomNum( 18, 118 )));
|
|
break;
|
|
case PT_COFFIN:
|
|
case PT_SHOPPACK:
|
|
case PT_PACK2:
|
|
case PT_BANK:
|
|
case PT_UNKNOWN:
|
|
default:
|
|
SetX( static_cast<SI16>(25 + RandomNum( 0, 79 )) );
|
|
SetY( static_cast<SI16>(25 + RandomNum( 0, 79 )) );
|
|
break;
|
|
}
|
|
SetZ( 9 );
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI32 GetSpell( UI08 part ) const
|
|
//| void SetSpell( UI08 part, UI32 newValue )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets spells in a spellbook item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI32 CItem::GetSpell( UI08 part ) const
|
|
{
|
|
UI32 rvalue = 0;
|
|
if( part < 3 )
|
|
rvalue = spells[part];
|
|
return rvalue;
|
|
}
|
|
void CItem::SetSpell( UI08 part, UI32 newValue )
|
|
{
|
|
if( part < 3 )
|
|
{
|
|
spells[part] = newValue;
|
|
UpdateRegion();
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void Cleanup( void )
|
|
//| Date - 11/6/2003
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Cleans up after item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::Cleanup( void )
|
|
{
|
|
if( !isFree() ) // We're not the default item in the handler
|
|
{
|
|
MapRegion->RemoveItem( this );
|
|
|
|
JSEngine->ReleaseObject( IUE_ITEM, this );
|
|
|
|
CBaseObject::Cleanup();
|
|
|
|
CBaseObject *iCont = GetCont();
|
|
RemoveFromSight();
|
|
RemoveSelfFromCont();
|
|
RemoveSelfFromOwner();
|
|
|
|
for( CItem *tItem = Contains.First(); !Contains.Finished(); tItem = Contains.Next() )
|
|
{
|
|
if( ValidateObject( tItem ) )
|
|
tItem->Delete();
|
|
}
|
|
// if we delete an item we should delete it from spawnregions
|
|
// this will fix several crashes
|
|
if( isSpawned() )
|
|
{
|
|
if( GetSpawn() < BASEITEMSERIAL )
|
|
{
|
|
UI16 spawnRegNum = static_cast<UI16>(GetSpawn());
|
|
if( cwmWorldState->spawnRegions.find( spawnRegNum ) != cwmWorldState->spawnRegions.end() )
|
|
{
|
|
CSpawnRegion *spawnReg = cwmWorldState->spawnRegions[spawnRegNum];
|
|
if( spawnReg != nullptr )
|
|
spawnReg->deleteSpawnedItem( this );
|
|
}
|
|
}
|
|
SetSpawn( INVALIDSERIAL );
|
|
}
|
|
if( GetSpawnObj() != nullptr )
|
|
SetSpawn( INVALIDSERIAL );
|
|
|
|
if( GetGlow() != INVALIDSERIAL )
|
|
{
|
|
CItem *j = calcItemObjFromSer( GetGlow() );
|
|
if( ValidateObject( j ) )
|
|
j->Delete(); // glow stuff, deletes the glower of a glowing stuff automatically
|
|
}
|
|
|
|
if( isGuarded() )
|
|
{
|
|
CChar *owner = nullptr;
|
|
CMultiObj *multi = findMulti( this );
|
|
if( ValidateObject( multi ) )
|
|
owner = multi->GetOwnerObj();
|
|
if( !ValidateObject( owner ) )
|
|
owner = FindItemOwner( this );
|
|
if( ValidateObject( owner ) )
|
|
{
|
|
CChar *petGuard = Npcs->getGuardingPet( owner, this );
|
|
if( ValidateObject( petGuard ) )
|
|
petGuard->SetGuarding( nullptr );
|
|
SetGuarded( false );
|
|
}
|
|
}
|
|
|
|
if( GetType() == IT_MESSAGEBOARD )
|
|
MsgBoardRemoveFile( GetSerial() );
|
|
|
|
if( GetType() == IT_BOOK && ( GetTempVar( CITV_MOREX ) == 666 || GetTempVar( CITV_MOREX ) == 999 ) )
|
|
Books->DeleteBook( this );
|
|
|
|
// Update container tooltip for nearby players
|
|
if( ValidateObject( iCont ) && iCont->GetObjType() == OT_ITEM )
|
|
{
|
|
CChar *rootOwner = FindItemOwner( static_cast<CItem *>(iCont) );
|
|
if( ValidateObject( rootOwner ) && rootOwner->GetObjType() == OT_CHAR )
|
|
{
|
|
CSocket *ownerSocket = rootOwner->GetSocket();
|
|
if( ownerSocket != nullptr )
|
|
{
|
|
// Only send tooltip if server feature for tooltips is enabled
|
|
if( cwmWorldState->ServerData()->GetServerFeature( SF_BIT_AOS ) )
|
|
{
|
|
// Refresh container tooltip
|
|
CPToolTip pSend( iCont->GetSerial(), ownerSocket );
|
|
ownerSocket->Send(&pSend);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (auto &tSock : FindNearbyPlayers( iCont, DIST_NEARBY )) {
|
|
if( tSock->LoginComplete() ) {
|
|
|
|
// Only send tooltip if server feature for tooltips is enabled
|
|
if( cwmWorldState->ServerData()->GetServerFeature( SF_BIT_AOS ) )
|
|
{
|
|
// Refresh container tooltip
|
|
CPToolTip pSend( iCont->GetSerial(), tSock );
|
|
tSock->Send(&pSend);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Ensure that object is removed from refreshQueue
|
|
RemoveFromRefreshQueue();
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool UpdateRegion( void ) const
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Marks region item exists in as updated since last save
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::UpdateRegion( void )
|
|
{
|
|
// Make sure to only mark region as changed if item is supposed to be saved
|
|
if( ShouldSave() )
|
|
{
|
|
CMapRegion *curCell = MapRegion->GetMapRegion( this );
|
|
curCell->HasRegionChanged( true );
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool CanBeObjType( ObjectType toCompare ) const
|
|
//| Date - 24 June, 2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Indicates whether an object can behave as a particular type
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CItem::CanBeObjType( ObjectType toCompare ) const
|
|
{
|
|
bool rvalue = CBaseObject::CanBeObjType( toCompare );
|
|
if( !rvalue )
|
|
{
|
|
if( toCompare == OT_ITEM )
|
|
rvalue = true;
|
|
}
|
|
return rvalue;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void Delete( void )
|
|
//| Date - 11/6/2003
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Adds item to deletion queue
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CItem::Delete( void )
|
|
{
|
|
if(cwmWorldState->deletionQueue.count(this)==0)
|
|
{
|
|
++(cwmWorldState->deletionQueue[this]);
|
|
Cleanup();
|
|
SetDeleted( true );
|
|
ShouldSave( false );
|
|
UpdateRegion();
|
|
}
|
|
}
|
|
|
|
GenericList< CItem * > * CItem::GetContainsList( void )
|
|
{
|
|
return &Contains;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Class - CSpawnItem() : CItem()
|
|
//| Date - 29th June, 2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Version History
|
|
//|
|
|
//| 1.0 29th June, 2004
|
|
//| Original implementation
|
|
//| First attempt to begin breaking CItem into multiple smaller
|
|
//| classes, reducing overall memory usage. Currently stores all
|
|
//| objects spawned by an item.
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CSpawnItem::CSpawnItem() : CItem(),
|
|
isSectionAList( false )
|
|
{
|
|
objType = OT_SPAWNER;
|
|
Interval[0] = Interval[1] = 0;
|
|
spawnSection.reserve( 100 );
|
|
spawnSection = "";
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - UI08 GetInterval( UI08 part ) const
|
|
//| void SetInterval( UI08 part, UI08 newVal )
|
|
//| Date - 6/29/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets Min and Max interval for spawner to respawn
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
UI08 CSpawnItem::GetInterval( UI08 part ) const
|
|
{
|
|
UI08 rvalue = 0;
|
|
if( part < 2 )
|
|
rvalue = Interval[part];
|
|
return rvalue;
|
|
}
|
|
void CSpawnItem::SetInterval( UI08 part, UI08 newVal )
|
|
{
|
|
if( part < 2 )
|
|
{
|
|
Interval[part] = newVal;
|
|
UpdateRegion();
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - std::string GetSpawnSection( void ) const
|
|
//| void SetSpawnSection( const std::string &newVal )
|
|
//| Date - 6/29/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets Script section to spawn from
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
std::string CSpawnItem::GetSpawnSection( void ) const
|
|
{
|
|
return spawnSection;
|
|
}
|
|
void CSpawnItem::SetSpawnSection( const std::string &newVal )
|
|
{
|
|
spawnSection = newVal;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool IsSectionAList( void ) const
|
|
//| void IsSectionAList( bool newVal )
|
|
//| Date - 7/05/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets script section as a spawner list
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CSpawnItem::IsSectionAList( void ) const
|
|
{
|
|
return isSectionAList;
|
|
}
|
|
void CSpawnItem::IsSectionAList( bool newVal )
|
|
{
|
|
isSectionAList = newVal;
|
|
UpdateRegion();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool DumpHeader( std::ofstream &outStream ) const
|
|
//| Date - 6/29/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Dumps Header to Worldfile
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CSpawnItem::DumpHeader( std::ofstream &outStream ) const
|
|
{
|
|
outStream << "[SPAWNITEM]" << '\n';
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool DumpBody( std::ofstream &outStream ) const
|
|
//| Date - 6/29/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Dumps Spawn Item to Worldfile
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CSpawnItem::DumpBody( std::ofstream &outStream ) const
|
|
{
|
|
CItem::DumpBody( outStream );
|
|
outStream << "Interval=" << (UI16)GetInterval( 0 ) << "," << (UI16)GetInterval( 1 ) << '\n';
|
|
outStream << "SpawnSection=" << GetSpawnSection() << '\n';
|
|
outStream << "IsSectionAList=" << (UI16)(IsSectionAList()?1:0) << '\n';
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool HandleLine( std::string &UTag, std::string &data )
|
|
//| Date - 6/29/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Reads data from Worldfile into the class
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CSpawnItem::HandleLine( std::string &UTag, std::string &data )
|
|
{
|
|
bool rvalue = CItem::HandleLine( UTag, data );
|
|
if( !rvalue )
|
|
{
|
|
auto csecs = oldstrutil::sections( data, "," );
|
|
switch( (UTag.data()[0]) )
|
|
{
|
|
case 'I':
|
|
if( UTag == "INTERVAL" )
|
|
{
|
|
SetInterval( 0, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[0], "//" )), nullptr, 0)) );
|
|
SetInterval( 1, static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( csecs[1], "//" )), nullptr, 0)) );
|
|
rvalue = true;
|
|
}
|
|
else if( UTag == "ISSECTIONALIST" )
|
|
{
|
|
IsSectionAList( (static_cast<UI08>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( data, "//" )), nullptr, 0)) == 1) );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
case 'S':
|
|
if( UTag == "SPAWNSECTION" )
|
|
{
|
|
SetSpawnSection( data );
|
|
rvalue = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return rvalue;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool DoRespawn( void )
|
|
//| Date - 6/29/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Will eventually take the place of RespawnItem()
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CSpawnItem::DoRespawn( void )
|
|
{
|
|
bool rValue = false;
|
|
switch( GetType() )
|
|
{
|
|
case IT_ITEMSPAWNER: rValue = HandleItemSpawner(); break;
|
|
case IT_NPCSPAWNER:
|
|
case IT_AREASPAWNER:
|
|
case IT_ESCORTNPCSPAWNER: rValue = HandleNPCSpawner(); break;
|
|
case IT_SPAWNCONT:
|
|
case IT_LOCKEDSPAWNCONT:
|
|
case IT_UNLOCKABLESPAWNCONT: rValue = HandleSpawnContainer(); break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return rValue;
|
|
}
|
|
bool CSpawnItem::HandleItemSpawner( void )
|
|
{
|
|
bool shouldSpawn = true;
|
|
for( CBaseObject *mObj = spawnedList.First(); !spawnedList.Finished(); mObj = spawnedList.Next() )
|
|
{
|
|
if( ValidateObject( mObj ) && !mObj->isFree() )
|
|
{
|
|
if( mObj->GetSpawnObj() == this )
|
|
{
|
|
if( mObj != this && mObj->GetX() == GetX() && mObj->GetY() == GetY() && mObj->GetZ() == GetZ() )
|
|
{
|
|
shouldSpawn = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( shouldSpawn )
|
|
{
|
|
std::string listObj = GetSpawnSection();
|
|
if( !listObj.empty() )
|
|
Items->AddRespawnItem( this, listObj, false, IsSectionAList(), 1 );
|
|
else if( GetTempVar( CITV_MOREX ) != 0 )
|
|
Items->AddRespawnItem( this, oldstrutil::number( GetTempVar( CITV_MOREX ) ), false, 1 );
|
|
else
|
|
{
|
|
Console.warning( "Bad Item Spawner Found, Deleting" );
|
|
Delete();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CSpawnItem::HandleNPCSpawner( void )
|
|
{
|
|
if( spawnedList.Num() < GetAmount() )
|
|
{
|
|
std::string listObj = GetSpawnSection();
|
|
if( !listObj.empty() )
|
|
Npcs->CreateNPC( this, listObj );
|
|
else if( GetTempVar( CITV_MOREX ) != 0 )
|
|
Npcs->CreateNPC( this, oldstrutil::number( GetTempVar( CITV_MOREX ) ) );
|
|
else
|
|
{
|
|
Console.warning( "Bad Npc/Area Spawner found; SPAWNSECTION or MOREX values missing! Deleting Spawner." );
|
|
Delete();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
bool CSpawnItem::HandleSpawnContainer( void )
|
|
{
|
|
if( Contains.Num() < GetAmount() )
|
|
{
|
|
std::string listObj = GetSpawnSection();
|
|
if( GetType() == IT_SPAWNCONT )
|
|
{
|
|
SetType( IT_LOCKEDSPAWNCONT ); // Lock the container
|
|
|
|
if( GetTempVar( CITV_MOREZ, 2 ) > 0 )
|
|
{
|
|
// Part 2 of MOREZ being higher than 0 indicates container was previously trapped. Reapply trap!
|
|
SetTempVar( CITV_MOREZ, 1, 1 );
|
|
}
|
|
}
|
|
if( !listObj.empty() )
|
|
{
|
|
std::string sect = "ITEMLIST " + listObj;
|
|
sect = oldstrutil::trim( oldstrutil::removeTrailing( sect, "//" ));
|
|
|
|
// Look up the relevant ITEMLIST from DFNs
|
|
ScriptSection *itemList = FileLookup->FindEntry( sect, items_def );
|
|
if( itemList != nullptr )
|
|
{
|
|
// Count the number of entries in the list
|
|
const size_t itemListSize = itemList->NumEntries();
|
|
if( itemListSize > 0 )
|
|
{
|
|
// Spawn one instance of EACH entry in the list
|
|
std::string listEntry = "";
|
|
for( int i = 0; i < itemListSize; i++ )
|
|
{
|
|
// listObj will either contain an itemID and amount, or an itemlist/lootlist tag
|
|
auto listObj = oldstrutil::sections( oldstrutil::trim( oldstrutil::removeTrailing( itemList->MoveTo( i ), "//" )), "," );
|
|
if( !listObj.empty() )
|
|
{
|
|
UI16 amountToSpawn = 1;
|
|
std::vector< std::string > itemListData;
|
|
if( oldstrutil::upper( listObj[0] ) == "ITEMLIST" || oldstrutil::upper( listObj[0] ) == "LOOTLIST" )
|
|
{
|
|
bool useLootList = oldstrutil::upper( listObj[0] ) == "LOOTLIST";
|
|
|
|
// Itemlist/Lootlist
|
|
itemListData = oldstrutil::sections( oldstrutil::trim( oldstrutil::removeTrailing( itemList->GrabData(), "//" )), "," );
|
|
listEntry = itemListData[0];
|
|
|
|
if( itemListData.size() > 1 )
|
|
{
|
|
// Also grab amount
|
|
std::string amountData = oldstrutil::trim( oldstrutil::removeTrailing( itemListData[1], "//" ));
|
|
auto tsects = oldstrutil::sections( amountData, " " );
|
|
if( tsects.size() > 1 ) // check if the second part of the tag-data contains two sections separated by a space
|
|
{
|
|
auto first = static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( tsects[0], "//" )), nullptr, 0));
|
|
auto second = static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( tsects[1], "//" )), nullptr, 0));
|
|
|
|
// Tag contained a minimum and maximum value for amount! Let's randomize!
|
|
amountToSpawn = static_cast<UI16>(RandomNum( first, second ));
|
|
}
|
|
else
|
|
{
|
|
amountToSpawn = static_cast<UI16>(std::stoul(amountData, nullptr, 0));
|
|
}
|
|
}
|
|
|
|
// The chosen entry contained another ITEMLIST or LOOTLIST reference! Let's dive back into it...
|
|
for( int i = 0; i < amountToSpawn; i++ )
|
|
{
|
|
CItem *iCreated = Items->CreateRandomItem( this, listEntry, this->WorldNumber(), this->GetInstanceID(), false, useLootList );
|
|
if( ValidateObject( iCreated ))
|
|
{
|
|
// Place item in container and randomize location
|
|
iCreated->SetCont( this );
|
|
iCreated->PlaceInPack();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Direct item reference
|
|
listEntry = listObj[0];
|
|
|
|
if( listObj.size() > 1 )
|
|
{
|
|
// Grab amount
|
|
std::string amountData = oldstrutil::trim( oldstrutil::removeTrailing( listObj[1], "//" ));
|
|
auto tsects = oldstrutil::sections( amountData, " " );
|
|
if( tsects.size() > 1 ) // check if the second part of the tag-data contains two sections separated by a space
|
|
{
|
|
auto first = static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( tsects[0], "//" )), nullptr, 0));
|
|
auto second = static_cast<UI16>(std::stoul(oldstrutil::trim( oldstrutil::removeTrailing( tsects[1], "//" )), nullptr, 0));
|
|
|
|
// Tag contained a minimum and maximum value for amount! Let's randomize!
|
|
amountToSpawn = static_cast<UI16>(RandomNum( first, second ));
|
|
}
|
|
else
|
|
{
|
|
amountToSpawn = static_cast<UI16>(std::stoul(amountData, nullptr, 0));
|
|
}
|
|
}
|
|
|
|
// We have a direct item reference, it seems like. Spawn it!
|
|
CItem *iCreated = Items->CreateBaseScriptItem( this, listEntry, this->WorldNumber(), amountToSpawn, this->GetInstanceID(), OT_ITEM, 0xFFFF, false );
|
|
if( ValidateObject( iCreated ))
|
|
{
|
|
// Place item in container and randomize location
|
|
iCreated->SetCont( this );
|
|
iCreated->PlaceInPack();
|
|
}
|
|
|
|
if( amountToSpawn > 1 && !iCreated->isPileable() )
|
|
{
|
|
// Eee, item cannot pile, we need to spawn individual ones
|
|
for( int i = 1; i < amountToSpawn; i++ )
|
|
{
|
|
CItem *iCreated2 = Items->CreateBaseScriptItem( this, listEntry, this->WorldNumber(), 1, this->GetInstanceID(), OT_ITEM, 0xFFFF, false );
|
|
if( ValidateObject( iCreated2 ))
|
|
{
|
|
// Place item in container and randomize location
|
|
iCreated2->SetCont( this );
|
|
iCreated2->PlaceInPack();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( GetTempVar( CITV_MOREX ) != 0 )
|
|
Items->AddRespawnItem( this, oldstrutil::number( GetTempVar( CITV_MOREX ) ), true, 1 );
|
|
else
|
|
{
|
|
Console.warning( "Bad Spawn Container found; missing SPAWNSECTION or MOREX! Deleting Spawner." );
|
|
Delete();
|
|
return true;
|
|
}
|
|
RemoveFromSight();
|
|
Update();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void Cleanup( void )
|
|
//| Date - 6/29/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Cleans up after spawner item
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CSpawnItem::Cleanup( void )
|
|
{
|
|
CItem::Cleanup();
|
|
|
|
for( CBaseObject *mObj = spawnedList.First(); !spawnedList.Finished(); mObj = spawnedList.Next() )
|
|
{
|
|
if( mObj->GetSpawnObj() == this )
|
|
mObj->SetSpawn( INVALIDSERIAL );
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool CanBeObjType( ObjectType toCompare ) const
|
|
//| Date - 24 June, 2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Indicates whether an object can behave as a particular type
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CSpawnItem::CanBeObjType( ObjectType toCompare ) const
|
|
{
|
|
bool rvalue = CItem::CanBeObjType( toCompare );
|
|
if( !rvalue )
|
|
{
|
|
if( toCompare == OT_SPAWNER )
|
|
rvalue = true;
|
|
}
|
|
return rvalue;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CSpawnItem * Dupe( void )
|
|
//| Date - 7/11/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Creates a new CSpawnItem and copies all of this objects properties to the new one
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CSpawnItem * CSpawnItem::Dupe( void )
|
|
{
|
|
CSpawnItem *target = static_cast< CSpawnItem * >(ObjectFactory::getSingleton().CreateObject( OT_SPAWNER ));
|
|
if( target == nullptr )
|
|
return nullptr;
|
|
|
|
CopyData( target );
|
|
|
|
return target;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void CopyData( CSpawnItem *target )
|
|
//| Date - 7/11/2004
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Copies all of this objects properties to the new one
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CSpawnItem::CopyData( CSpawnItem *target )
|
|
{
|
|
CItem::CopyData( target );
|
|
|
|
target->SetSpawnSection( GetSpawnSection() );
|
|
target->IsSectionAList( IsSectionAList() );
|
|
target->SetInterval( 0, GetInterval( 0 ) );
|
|
target->SetInterval( 1, GetInterval( 1 ) );
|
|
}
|