Exemple #1
0
bool CClient::CanHear( const CObjBaseTemplate * pSrc, TALKMODE_TYPE mode ) const
{
	ADDTOCALLSTACK("CClient::CanHear");
	// can we hear this text or sound.

	if ( !IsConnectTypePacket() )
		return false;
	if ( !pSrc || (mode == TALKMODE_BROADCAST) )
		return true;
	if ( !m_pChar )
		return false;

	if ( IsPriv(PRIV_HEARALL) && pSrc->IsChar() && ((mode == TALKMODE_SYSTEM) || (mode == TALKMODE_SAY) || (mode == TALKMODE_WHISPER) || (mode == TALKMODE_YELL)) )
	{
		const CChar *pCharSrc = dynamic_cast<const CChar *>(pSrc);
		ASSERT(pCharSrc);
		if ( pCharSrc && pCharSrc->m_pClient )
		{
			if ( pCharSrc->GetPrivLevel() <= GetPrivLevel() )
				return true;
		}
	}

	return m_pChar->CanHear(pSrc, mode);
}
Exemple #2
0
bool CClient::CanHear( const CObjBaseTemplate * pSrc, TALKMODE_TYPE mode ) const
{
	ADDTOCALLSTACK("CClient::CanHear");
	// can we hear this text or sound.

	if ( !IsConnectTypePacket() )
		return( false );
	if ( mode == TALKMODE_BROADCAST || pSrc == NULL )
		return( true );
	if ( m_pChar == NULL )
		return( false );

	if ( IsPriv( PRIV_HEARALL ) &&
		pSrc->IsChar()&&
		( mode == TALKMODE_SYSTEM || mode == TALKMODE_SAY || mode == TALKMODE_WHISPER || mode == TALKMODE_YELL ))
	{
		const CChar * pCharSrc = dynamic_cast <const CChar*> ( pSrc );
		ASSERT(pCharSrc);
		if ( pCharSrc && pCharSrc->IsClient())
		{
			if ( pCharSrc->GetPrivLevel() <= GetPrivLevel())
			{
				return( true );
			}
		}
	}

	return( m_pChar->CanHear( pSrc, mode ));
}
Exemple #3
0
bool CClient::CanInstantLogOut() const
{
	ADDTOCALLSTACK("CClient::CanInstantLogOut");
	if ( g_Serv.IsLoading())	// or exiting.
		return( true );
	if ( ! g_Cfg.m_iClientLingerTime )
		return true;
	if ( IsPriv( PRIV_GM ))
		return true;
	if ( m_pChar == NULL )
		return( true );
	if ( m_pChar->IsStatFlag(STATF_DEAD))
		return( true );

	const CRegionWorld * pArea = m_pChar->GetRegion();
	if ( pArea == NULL )
		return( true );
	if ( pArea->IsFlag( REGION_FLAG_INSTA_LOGOUT ))
		return( true );

	const CRegionBase * pRoom = m_pChar->GetRoom(); //Allows Room flag to work!
	if ( pRoom != NULL && pRoom->IsFlag( REGION_FLAG_INSTA_LOGOUT )) //sanity check for null rooms // Can C++ guarantee short-circuit evaluation for CRegionBase ?
		return( true );

	return( false );
}
Exemple #4
0
bool CChar::FollowersUpdate( CChar * pChar, short iFollowerSlots, bool bCheckOnly )
{
	ADDTOCALLSTACK("CChar::FollowersUpdate");
	// Attemp to update followers on this character based on pChar
	// bSustract = true for pet's release, shrink, etc ...
	// This is supossed to be called only when OF_PetSlots is enabled, so no need to check it here.

	if ( !bCheckOnly && IsTrigUsed(TRIGGER_FOLLOWERSUPDATE) )
	{
		CScriptTriggerArgs Args;
		Args.m_iN1 = (iFollowerSlots > 0) ? 0 : 1;
		Args.m_iN2 = abs(iFollowerSlots);
		if ( OnTrigger(CTRIG_FollowersUpdate, pChar, &Args) == TRIGRET_RET_TRUE )
			return false;

		iFollowerSlots = static_cast<short>(Args.m_iN2);
	}

	short iCurFollower = static_cast<short>(GetDefNum("CURFOLLOWER", true, true));
	short iMaxFollower = static_cast<short>(GetDefNum("MAXFOLLOWER", true, true));
	short iSetFollower = iCurFollower + iFollowerSlots;

	if ( (iSetFollower > iMaxFollower) && !IsPriv(PRIV_GM) )
		return false;

	if ( !bCheckOnly )
	{
		SetDefNum("CURFOLLOWER", maximum(iSetFollower, 0));
		UpdateStatsFlag();
	}
	return true;
}
Exemple #5
0
bool CClient::CanSee( const CObjBaseTemplate * pObj ) const
{
	ADDTOCALLSTACK("CClient::CanSee");
	// Can player see item b
	if ( m_pChar == NULL || pObj == NULL )
		return false;

	if (!IsPriv(PRIV_ALLSHOW) && pObj->IsChar())
	{
		const CChar *pChar = static_cast<const CChar*>(pObj);
		if (pChar->IsDisconnected())
			return false;
	}
	return( m_pChar->CanSee( pObj ));
}
Exemple #6
0
bool CClient::CanInstantLogOut() const
{
	ADDTOCALLSTACK("CClient::CanInstantLogOut");
	if ( g_Serv.IsLoading() )
		return true;
	if ( !g_Cfg.m_iClientLingerTime || IsPriv(PRIV_GM) )
		return true;
	if ( !m_pChar || m_pChar->IsStatFlag(STATF_DEAD) )
		return true;
	if ( !m_pChar->m_pArea || m_pChar->m_pArea->IsFlag(REGION_FLAG_INSTA_LOGOUT) )
		return true;
	if ( m_pChar->m_pRoom && m_pChar->m_pRoom->IsFlag(REGION_FLAG_INSTA_LOGOUT) )
		return true;

	return false;
}
Exemple #7
0
bool CClient::CanInstantLogOut() const
{
	ADDTOCALLSTACK("CClient::CanInstantLogOut");
	if ( g_Serv.IsLoading() )	// or exiting.
		return true;
	if ( !g_Cfg.m_iClientLingerTime || IsPriv(PRIV_GM) )
		return true;
	if ( !m_pChar || m_pChar->IsStatFlag(STATF_DEAD) )
		return true;

	const CRegionWorld *pArea = m_pChar->GetRegion();
	if ( !pArea || pArea->IsFlag(REGION_FLAG_INSTA_LOGOUT) )
		return true;

	const CRegionBase *pRoom = m_pChar->GetRoom();
	if ( pRoom && pRoom->IsFlag(REGION_FLAG_INSTA_LOGOUT) )
		return true;

	return false;
}
Exemple #8
0
bool CClient::CanHear(const CObjBaseTemplate *pSrc, TALKMODE_TYPE mode) const
{
	ADDTOCALLSTACK("CClient::CanHear");
	// can we hear this text or sound.

	if ( !IsConnectTypePacket() )
		return false;
	if ( !pSrc )
		return true;
	if ( !m_pChar )
		return false;

	if ( IsPriv(PRIV_HEARALL) && pSrc->IsChar() && ((mode == TALKMODE_SAY) || (mode == TALKMODE_WHISPER) || (mode == TALKMODE_YELL)) )
	{
		const CChar *pChar = static_cast<const CChar *>(pSrc);
		if ( GetPrivLevel() >= pChar->GetPrivLevel() )
			return true;
	}

	return m_pChar->CanHear(pSrc, mode);
}
Exemple #9
0
bool CClient::r_WriteVal( LPCTSTR pszKey, CGString & sVal, CTextConsole * pSrc )
{
	ADDTOCALLSTACK("CClient::r_WriteVal");
	EXC_TRY("WriteVal");
	int index;

	if ( !strnicmp("CTAG.", pszKey, 5) )		//	CTAG.xxx - client tag
	{
		if ( pszKey[4] != '.' )
			return( false );
		pszKey += 5;
		CVarDefCont *vardef = m_TagDefs.GetKey(pszKey);
		sVal = vardef ? vardef->GetValStr() : "";
		return true;
	}

	if ( !strnicmp("CTAG0.", pszKey, 6) )		//	CTAG0.xxx - client tag
	{
		if ( pszKey[5] != '.' )
			return( false );
		pszKey += 6;
		CVarDefCont *vardef = m_TagDefs.GetKey(pszKey);
		sVal = vardef ? vardef->GetValStr() : "0";
		return true;
	}

	if ( !strnicmp( "TARGP", pszKey, 5 ) && ( pszKey[5] == '\0' || pszKey[5] == '.' ) )
		index = CC_TARGP;
	else if ( !strnicmp( "SCREENSIZE", pszKey, 10 ) && ( pszKey[10] == '\0' || pszKey[10] == '.' ) )
		index = CC_SCREENSIZE;
	else if ( !strnicmp( "REPORTEDCLIVER", pszKey, 14 ) && ( pszKey[14] == '\0' || pszKey[14] == '.' ) )
		index = CC_REPORTEDCLIVER;
	else
		index	= FindTableSorted( pszKey, sm_szLoadKeys, COUNTOF(sm_szLoadKeys)-1 );

	switch (index)
	{
		case CC_ALLMOVE:
			sVal.FormatVal( IsPriv( PRIV_ALLMOVE ));
			break;
		case CC_ALLSHOW:
			sVal.FormatVal( IsPriv( PRIV_ALLSHOW ));
			break;
		case CC_CLIENTIS3D:
			sVal.FormatVal( GetNetState()->isClient3D() );
			break;
		case CC_CLIENTISKR:
			sVal.FormatVal( GetNetState()->isClientKR() );
			break;
		case CC_CLIENTISSA:
			sVal.FormatVal( GetNetState()->isClientSA() );
			break;
		case CC_CLIENTVERSION:
			{
				TCHAR szVersion[ 128 ];
				sVal = m_Crypt.WriteClientVer( szVersion );
			}
			break;
		case CC_DEBUG:
			sVal.FormatVal( IsPriv( PRIV_DEBUG ));
			break;
		case CC_DETAIL:
			sVal.FormatVal( IsPriv( PRIV_DETAIL ));
			break;
		case CC_GM:	// toggle your GM status on/off
			sVal.FormatVal( IsPriv( PRIV_GM ));
			break;
		case CC_HEARALL:
			sVal.FormatVal( IsPriv( PRIV_HEARALL ));
			break;
		case CC_LASTEVENT:
			sVal.FormatLLVal( m_timeLastEvent.GetTimeRaw() );
			break;
		case CC_PRIVSHOW:
			// Show my priv title.
			sVal.FormatVal( ! IsPriv( PRIV_PRIV_NOSHOW ));
			break;
		case CC_REPORTEDCLIVER:
			{
				pszKey += strlen(sm_szLoadKeys[index]);
				GETNONWHITESPACE( pszKey );

				int iCliVer = (GetNetState()->getReportedVersion() & 0xFFFFFF0);
				if ( pszKey[0] != '\0' )
					iCliVer = GetNetState()->getReportedVersion();

				TCHAR szVersion[128];
				sVal = CCrypt::WriteClientVerString( iCliVer, szVersion );
			}
			break;
		case CC_SCREENSIZE:
			{
				if ( pszKey[10] == '.' )
				{
					pszKey += strlen(sm_szLoadKeys[index]);
					SKIP_SEPARATORS(pszKey);

					if ( !strnicmp("X", pszKey, 1) )
						sVal.Format( "%lu", m_ScreenSize.x );
					else if ( !strnicmp("Y", pszKey, 1) )
						sVal.Format( "%lu", m_ScreenSize.y );
					else
						return( false );
				}
				else
					sVal.Format( "%lu,%lu", m_ScreenSize.x, m_ScreenSize.y );
			} break;
		case CC_TARG:
			sVal.FormatHex(m_Targ_UID);
			break;
		case CC_TARGP:
			if ( pszKey[5] == '.' )
			{
				return m_Targ_p.r_WriteVal( pszKey+6, sVal );
			}
			sVal = m_Targ_p.WriteUsed();
			break;
		case CC_TARGPROP:
			sVal.FormatHex(m_Prop_UID);
			break;
		case CC_TARGPRV:
			sVal.FormatHex(m_Targ_PrvUID);
			break;
		case CC_TARGTXT:
			sVal = m_Targ_Text;
			break;
		default:
			return( CScriptObj::r_WriteVal( pszKey, sVal, pSrc ));
	}
	return true;
	EXC_CATCH;

	EXC_DEBUG_START;
	EXC_ADD_KEYRET(pSrc);
	EXC_DEBUG_END;
	return false;
}
Exemple #10
0
bool CChar::Use_Item_Web( CItem * pItemWeb )
{
	ADDTOCALLSTACK("CChar::Use_Item_Web");
	// IT_WEB
	// IT_EQ_STUCK
	// Try to break out of the web.
	// Or just try to damage it.
	//
	// RETURN: true = held in place.
	//  false = walk thru it.

	if ( GetDispID() == CREID_GIANT_SPIDER || !pItemWeb || !pItemWeb->IsTopLevel() || IsStatFlag(STATF_DEAD|STATF_Insubstantial) || IsPriv(PRIV_GM) )
		return false;	// just walk through it

	// Try to break it.
	int iStr = pItemWeb->m_itWeb.m_Hits_Cur;
	if ( iStr == 0 )
		iStr = pItemWeb->m_itWeb.m_Hits_Cur = 60 + Calc_GetRandVal(250);

	// Since broken webs become spider silk, we should get out of here now if we aren't in a web.
	CItem *pFlag = LayerFind(LAYER_FLAG_Stuck);
	if ( CanMove(pItemWeb, false) )
	{
		if ( pFlag )
			pFlag->Delete();
		return false;
	}

	if ( pFlag )
	{
		if ( pFlag->IsTimerSet() )	// don't allow me to try to damage it too often
			return true;
	}

	int iDmg = pItemWeb->OnTakeDamage(Stat_GetAdjusted(STAT_STR), this);
	switch ( iDmg )
	{
		case 0:			// damage blocked
		case 1:			// web survived
		default:		// unknown
			if ( GetTopPoint() == pItemWeb->GetTopPoint() )		// is character still stuck on the web?
				break;

		case 2:			// web turned into silk
		case INT_MAX:	// web destroyed
			if ( pFlag )
				pFlag->Delete();
			return false;
	}

	// Stuck in it still.
	if ( !pFlag )
	{
		if ( iDmg < 0 )
			return false;

		// First time message.
		pFlag = CItem::CreateBase(ITEMID_WEB1_1);
		ASSERT(pFlag);
		pFlag->SetAttr(ATTR_DECAY);
		pFlag->SetType(IT_EQ_STUCK);
		pFlag->m_uidLink = pItemWeb->GetUID();
		pFlag->SetTimeout(pItemWeb->GetTimerDAdjusted());
		LayerAdd(pFlag, LAYER_FLAG_Stuck);
	}
	else
	{
		if ( iDmg < 0 )
		{
			pFlag->Delete();
			return false;
		}
		SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SWEB_STUCK), pItemWeb->GetName());
	}

	return true;
}
Exemple #11
0
int CChar::Do_Use_Item(CItem *pItem, bool fLink)
{
	ADDTOCALLSTACK("CChar::Do_Use_Item");
	if (!pItem)
		return false;

	if (m_pNPC && (IsTrigUsed(TRIGGER_DCLICK) ||
	               IsTrigUsed(TRIGGER_ITEMDCLICK)))        // for players, DClick was called before this function
	{
		if (pItem->OnTrigger(ITRIG_DCLICK, this) == TRIGRET_RET_TRUE)
			return false;
	}

	CItemSpawn *pSpawn = static_cast<CItemSpawn *>(pItem->m_uidSpawnItem.ItemFind());
	if (pSpawn)
		pSpawn->DelObj(pItem->GetUID());    // remove this item from it's spawn when DClicks it

	int fAction = true;
	switch(pItem->GetType()) {
		case IT_ITEM_STONE: {
			// Give them this item
			if (pItem->m_itItemStone.m_wAmount == USHRT_MAX) {
				SysMessageDefault(DEFMSG_MSG_IT_IS_DEAD);
				return true;
			}
			if (pItem->m_itItemStone.m_wRegenTime) {
				if (pItem->IsTimerSet()) {
					SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_MSG_STONEREG_TIME), pItem->GetTimerDiff() / TICK_PER_SEC);
					return true;
				}
				pItem->SetTimeout(pItem->m_itItemStone.m_wRegenTime * TICK_PER_SEC);
			}
			ItemBounce(CItem::CreateTemplate(pItem->m_itItemStone.m_ItemID, GetPackSafe(), this));
			if (pItem->m_itItemStone.m_wAmount != 0) {
				pItem->m_itItemStone.m_wAmount--;
				if (pItem->m_itItemStone.m_wAmount == 0)
					pItem->m_itItemStone.m_wAmount = USHRT_MAX;
			}
			return true;
		}

		case IT_SEED:
			return Use_Seed(pItem, NULL);

		case IT_BEDROLL:
			return Use_BedRoll(pItem);

		case IT_KINDLING:
			return Use_Kindling(pItem);

		case IT_SPINWHEEL: {
			if (fLink)
				return false;

			// Just make them spin
			pItem->SetAnim(static_cast<ITEMID_TYPE>(pItem->GetID() + 1), 2 * TICK_PER_SEC);
			SysMessageDefault(DEFMSG_ITEMUSE_SPINWHEEL);
			return true;
		}

		case IT_TRAIN_DUMMY: {
			if (fLink)
				return false;

			Use_Train_Dummy(pItem, true);
			return true;
		}

		case IT_TRAIN_PICKPOCKET: {
			if (fLink)
				return false;

			Use_Train_PickPocketDip(pItem, true);
			return true;
		}

		case IT_ARCHERY_BUTTE: {
			if (fLink)
				return false;

			Use_Train_ArcheryButte(pItem, true);
			return true;
		}

		case IT_LOOM: {
			if (fLink)
				return false;

			SysMessageDefault(DEFMSG_ITEMUSE_LOOM);
			return true;
		}

		case IT_BEE_HIVE: {
			if (fLink)
				return false;

			// Get honey from it
			ITEMID_TYPE id = ITEMID_NOTHING;
			if (!pItem->m_itBeeHive.m_honeycount)
				SysMessageDefault(DEFMSG_ITEMUSE_BEEHIVE);
			else {
				switch(Calc_GetRandVal(3)) {
					case 1:
						id = ITEMID_JAR_HONEY;
						break;
					case 2:
						id = ITEMID_BEE_WAX;
						break;
				}
			}
			if (id) {
				ItemBounce(CItem::CreateScript(id, this));
				pItem->m_itBeeHive.m_honeycount--;
			}
			else {
				SysMessageDefault(DEFMSG_ITEMUSE_BEEHIVE_STING);
				OnTakeDamage(Calc_GetRandVal(5), this, DAMAGE_POISON | DAMAGE_GENERAL);
			}
			pItem->SetTimeout(15 * 60 * TICK_PER_SEC);
			return true;
		}

		case IT_MUSICAL: {
			if (!Skill_Wait(SKILL_MUSICIANSHIP)) {
				m_Act_Targ = pItem->GetUID();
				Skill_Start(SKILL_MUSICIANSHIP);
			}
			break;
		}

		case IT_CROPS:
		case IT_FOLIAGE: {
			// Pick cotton/hay/etc
			fAction = pItem->Plant_Use(this);
			break;
		}

		case IT_FIGURINE: {
			// Create the creature here
			if (Use_Figurine(pItem) != NULL)
				pItem->Delete();
			return true;
		}

		case IT_TRAP:
		case IT_TRAP_ACTIVE: {
			// Activate the trap (plus any linked traps)
			int iDmg = pItem->Use_Trap();
			if (CanTouch(pItem->GetTopLevelObj()->GetTopPoint()))
				OnTakeDamage(iDmg, NULL, DAMAGE_HIT_BLUNT | DAMAGE_GENERAL);
			break;
		}

		case IT_SWITCH: {
			// Switches can be linked to gates and doors and such.
			// Flip the switch graphic.
			pItem->SetSwitchState();
			break;
		}

		case IT_PORT_LOCKED:
			if (!fLink && !IsPriv(PRIV_GM)) {
				SysMessageDefault(DEFMSG_ITEMUSE_PORT_LOCKED);
				return true;
			}
		case IT_PORTCULIS:
			// Open a metal gate vertically
			pItem->Use_Portculis();
			break;

		case IT_DOOR_LOCKED:
			if (!ContentFindKeyFor(pItem)) {
				SysMessageDefault(DEFMSG_MSG_KEY_DOORLOCKED);
				if (!pItem->IsTopLevel())
					return false;
				if (pItem->IsAttr(ATTR_MAGIC))    // show it's magic face
				{
					ITEMID_TYPE id = (GetDispID() & DOOR_NORTHSOUTH) ? ITEMID_DOOR_MAGIC_SI_NS
					                                                 : ITEMID_DOOR_MAGIC_SI_EW;
					CItem *pFace = CItem::CreateBase(id);
					ASSERT(pFace);
					pFace->MoveToDecay(pItem->GetTopPoint(), 4 * TICK_PER_SEC);
				}
				if (!IsPriv(PRIV_GM))
					return true;
			}
		case IT_DOOR_OPEN:
		case IT_DOOR: {
			bool fOpen = pItem->Use_DoorNew(fLink);
			if (fLink || !fOpen)    // don't link if we are just closing the door
				return true;
		}
			break;

		case IT_SHIP_PLANK: {
			// Close the plank if I'm inside the ship
			if (m_pArea->IsFlag(REGION_FLAG_SHIP) && m_pArea->GetResourceID() == pItem->m_uidLink) {
				if (pItem->m_itShipPlank.m_itSideType == IT_SHIP_SIDE_LOCKED && !ContentFindKeyFor(pItem)) {
					SysMessageDefault(DEFMSG_ITEMUSE_SHIPSIDE);
					return true;
				}
				return pItem->Ship_Plank(false);
			}
			else if (pItem->IsTopLevel()) {
				// Teleport to plank if I'm outside the ship
				CPointMap pntTarg = pItem->GetTopPoint();
				pntTarg.m_z++;
				Spell_Teleport(pntTarg, true, false, false);
			}
			return true;
		}

		case IT_SHIP_SIDE_LOCKED:
			if (!ContentFindKeyFor(pItem)) {
				SysMessageDefault(DEFMSG_ITEMUSE_SHIPSIDE);
				return true;
			}
		case IT_SHIP_SIDE:
			// Open the plank
			pItem->Ship_Plank(true);
			return true;

		case IT_GRAIN:
		case IT_GRASS:
		case IT_GARBAGE:
		case IT_FRUIT:
		case IT_FOOD:
		case IT_FOOD_RAW:
		case IT_MEAT_RAW: {
			if (fLink)
				return false;

			Use_Eat(pItem);
			return true;
		}

		case IT_POTION:
		case IT_DRINK:
		case IT_PITCHER:
		case IT_WATER_WASH:
		case IT_BOOZE: {
			if (fLink)
				return false;

			Use_Drink(pItem);
			return true;
		}

		case IT_LIGHT_OUT:        // can the light be lit?
		case IT_LIGHT_LIT:        // can the light be doused?
			fAction = pItem->Use_Light();
			break;

		case IT_CLOTHING:
		case IT_ARMOR:
		case IT_ARMOR_LEATHER:
		case IT_SHIELD:
		case IT_WEAPON_MACE_CROOK:
		case IT_WEAPON_MACE_PICK:
		case IT_WEAPON_MACE_SMITH:
		case IT_WEAPON_MACE_SHARP:
		case IT_WEAPON_SWORD:
		case IT_WEAPON_FENCE:
		case IT_WEAPON_BOW:
		case IT_WEAPON_AXE:
		case IT_WEAPON_XBOW:
		case IT_WEAPON_MACE_STAFF:
		case IT_JEWELRY:
		case IT_WEAPON_THROWING: {
			if (fLink)
				return false;

			return ItemEquip(pItem);
		}

		case IT_WEB: {
			if (fLink)
				return false;

			Use_Item_Web(pItem);
			return true;
		}

		case IT_SPY_GLASS: {
			if (fLink)
				return false;

			// Spyglass will tell you the moon phases
			static LPCTSTR const sm_sPhases[8] =
					{
							g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M1),
							g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M2),
							g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M3),
							g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M4),
							g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M5),
							g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M6),
							g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M7),
							g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M8)
					};
			SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_TR), sm_sPhases[g_World.GetMoonPhase(false)]);
			SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_FE), sm_sPhases[g_World.GetMoonPhase(true)]);

			if (m_pArea && m_pArea->IsFlag(REGION_FLAG_SHIP))
				ObjMessage(pItem->Use_SpyGlass(this), this);
			return true;
		}

		case IT_SEXTANT: {
			if (fLink)
				return false;

			if ((GetTopPoint().m_map <= 1) && (GetTopPoint().m_x > UO_SIZE_X_REAL))    // dungeons and T2A lands
				ObjMessage(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SEXTANT_T2A), this);
			else {
				TCHAR *pszMsg = Str_GetTemp();
				sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SEXTANT), m_pArea->GetName(),
				        pItem->Use_Sextant(GetTopPoint()));
				ObjMessage(pszMsg, this);
			}
			return true;
		}

		default:
			fAction = false;
	}
	return fAction | MASK_RETURN_FOLLOW_LINKS;
}
Exemple #12
0
CChar * CChar::Use_Figurine( CItem * pItem, bool bCheckFollowerSlots )
{
	ADDTOCALLSTACK("CChar::Use_Figurine");
	// NOTE: The figurine is NOT destroyed.
	bool bCreatedNewNpc = false;
	if ( !pItem )
		return NULL;

	if ( pItem->m_uidLink.IsValidUID() && pItem->m_uidLink.IsChar() && pItem->m_uidLink != GetUID() && !IsPriv(PRIV_GM) )
	{
		SysMessageDefault(DEFMSG_MSG_FIGURINE_NOTYOURS);
		return NULL;
	}

	// Create a new NPC if there's no one linked to this figurine 
	CChar *pPet = pItem->m_itFigurine.m_UID.CharFind();
	if ( !pPet )
	{
		CREID_TYPE id = pItem->m_itFigurine.m_ID;
		if ( !id )
		{
			id = CItemBase::FindCharTrack(pItem->GetID());
			if ( !id )
			{
				DEBUG_ERR(("FIGURINE id 0%x, no creature\n", pItem->GetDispID()));
				return NULL;
			}
		}
		bCreatedNewNpc = true;
		pPet = CreateNPC(id);
		ASSERT(pPet);
		pPet->SetName(pItem->GetName());
		if ( pItem->GetHue() )
		{
			pPet->m_prev_Hue = pItem->GetHue();
			pPet->SetHue(pItem->GetHue());
		}
	}

	if ( bCheckFollowerSlots && IsSetOF(OF_PetSlots) )
	{
		if ( !FollowersUpdate(pPet, static_cast<short>(maximum(1, pPet->GetDefNum("FOLLOWERSLOTS", true, true))), true) )
		{
			SysMessageDefault(DEFMSG_PETSLOTS_TRY_CONTROL);
			if ( bCreatedNewNpc )
				pPet->Delete();
			return NULL;
		}
	}

	if ( pPet->IsDisconnected() )
		pPet->StatFlag_Clear(STATF_Ridden);		// pull the creature out of IDLE space

	pItem->m_itFigurine.m_UID.InitUID();
	pPet->m_dirFace = m_dirFace;
	pPet->NPC_PetSetOwner(this);
	pPet->MoveToChar(pItem->GetTopLevelObj()->GetTopPoint());
	pPet->Update();
	pPet->Skill_Start(SKILL_NONE);	// was NPCACT_RIDDEN
	pPet->SoundChar(CRESND_RAND1);
	return pPet;
}
Exemple #13
0
bool CChar::CanSeeLOS( const CPointMap &ptDst, CPointMap *pptBlock, int iMaxDist, word wFlags, bool bCombatCheck ) const
{
	ADDTOCALLSTACK("CChar::CanSeeLOS");
	// WARNING: CanSeeLOS is an expensive function (lot of calculations but	most importantly it has to read the UO files, and file I/O is slow).

	if ( (m_pPlayer && (g_Cfg.m_iAdvancedLos & ADVANCEDLOS_PLAYER)) || (m_pNPC && (g_Cfg.m_iAdvancedLos & ADVANCEDLOS_NPC)) )
		return CanSeeLOS_New(ptDst, pptBlock, iMaxDist, wFlags);

	// Max distance of iMaxDist
	// Line of sight check
	// NOTE: if not blocked. pptBlock is undefined.
	// 3D LOS later - real LOS, i.e. we can't shoot through the floor, but can shoot through the hole in it

	if ( !bCombatCheck && IsPriv(PRIV_GM) )	// If i'm checking the LOS during a combat, i don't want to shoot through the walls even if i'm a GM
		return true;

	CPointMap ptSrc = GetTopPoint();
	int iDist = ptSrc.GetDist(ptDst);
	if ( iDist > iMaxDist )
	{
	blocked:
		if ( pptBlock )
			*pptBlock = ptSrc;
		return false;	// blocked
	}

	// Walk towards the object. If any spot is too far above our heads then we can not see what's behind it.
	int iDistTry = 0;
	while ( --iDist >= 0 )
	{
		DIR_TYPE dir = ptSrc.GetDir(ptDst);
		dword dwBlockFlags;
		if ( dir % 2 && !IsSetEF(EF_NoDiagonalCheckLOS) )	// test only diagonal dirs
		{
			CPointMap ptTest = ptSrc;
			DIR_TYPE dirTest1 = (DIR_TYPE)(dir - 1);	// get 1st ortogonal
			DIR_TYPE dirTest2 = (DIR_TYPE)(dir + 1);	// get 2nd ortogonal
			if ( dirTest2 == DIR_QTY )		// roll over
				dirTest2 = DIR_N;

			ptTest.Move(dirTest1);
			dwBlockFlags = CAN_C_SWIM|CAN_C_WALK|CAN_C_FLY;
			char z = g_World.GetHeightPoint2(ptTest, dwBlockFlags, true);
			short zDiff = (short)(abs(z - ptTest.m_z));

			if ( (zDiff > PLAYER_HEIGHT) || (dwBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR)) )		// blocked
			{
				ptTest = ptSrc;
				ptTest.Move(dirTest2);
				{
					dwBlockFlags = CAN_C_SWIM|CAN_C_WALK|CAN_C_FLY;
					z = g_World.GetHeightPoint2(ptTest, dwBlockFlags, true);
					zDiff = (short)(abs(z - ptTest.m_z));
					if ( zDiff > PLAYER_HEIGHT )
						goto blocked;

					if ( dwBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR) )
					{
						ptSrc = ptTest;
						goto blocked;
					}
				}
			}
			ptTest.m_z = z;
		}

		if ( iDist )
		{
			ptSrc.Move(dir);	// NOTE: The dir is very coarse and can change slightly.
			dwBlockFlags = CAN_C_SWIM|CAN_C_WALK|CAN_C_FLY;
			char z = g_World.GetHeightPoint2(ptSrc, dwBlockFlags, true);
            short zDiff = (short)(abs(z - ptSrc.m_z));

			if ( (zDiff > PLAYER_HEIGHT) || (dwBlockFlags & (CAN_I_BLOCK|CAN_I_DOOR)) || (iDistTry > iMaxDist) )
				goto blocked;

			ptSrc.m_z = z;
			++iDistTry;
		}
	}

	if ( abs(ptSrc.m_z - ptDst.m_z) >= 20 )
		return false;
	return true;	// made it all the way to the object with no obstructions.
}
Exemple #14
0
bool CChar::CanSeeLOS_New( const CPointMap &ptDst, CPointMap *pptBlock, int iMaxDist, word flags, bool bCombatCheck ) const
{
	ADDTOCALLSTACK("CChar::CanSeeLOS_New");
	// WARNING: CanSeeLOS is an expensive function (lot of calculations but	most importantly it has to read the UO files, and file I/O is slow).

	if ( !bCombatCheck && IsPriv(PRIV_GM) )	// If i'm checking the LOS during a combat, i don't want to shoot through the walls even if i'm a GM
	{
		WARNLOS(("GM Pass\n"));
		return true;
	}

	CPointMap ptSrc = GetTopPoint();
	CPointMap ptNow(ptSrc);

	if ( ptSrc.m_map != ptDst.m_map )	// Different map
		return this->CanSeeLOS_New_Failed(pptBlock, ptNow);

	if ( ptSrc == ptDst )	// Same point ^^
		return true;

	short iTotalZ = ptSrc.m_z + GetHeightMount(true);
	ptSrc.m_z = (char)minimum(iTotalZ, UO_SIZE_Z);	//true - substract one from the height because of eyes height
	WARNLOS(("Total Z: %d\n", ptSrc.m_z));

	int dx, dy, dz;
	dx = ptDst.m_x - ptSrc.m_x;
	dy = ptDst.m_y - ptSrc.m_y;
	dz = ptDst.m_z - ptSrc.m_z;

    float dist2d, dist3d;
	dist2d = sqrt((float)(dx*dx + dy*dy));
	if ( dz )
		dist3d = sqrt((float)(dist2d*dist2d + dz*dz));
	else
		dist3d = dist2d;

	if ( APPROX(dist2d) > (float)iMaxDist )
	{
		WARNLOS(("( APPROX(dist2d)(%f) > ((double)iMaxDist)(%f) ) --> NOLOS\n", APPROX(dist2d), (float)iMaxDist));
		return CanSeeLOS_New_Failed(pptBlock, ptNow);
	}

	float dFactorX, dFactorY, dFactorZ;
	dFactorX = dx / dist3d;
	dFactorY = dy / dist3d;
	dFactorZ = dz / dist3d;

    float nPx, nPy, nPz;
	nPx = ptSrc.m_x;
	nPy = ptSrc.m_y;
	nPz = ptSrc.m_z;

	std::vector<CPointMap> path;
	for (;;)
	{
		if ( BETWEENPOINT(nPx, ptDst.m_x, ptSrc.m_x) && BETWEENPOINT(nPy, ptDst.m_y, ptSrc.m_y) && BETWEENPOINT(nPz, ptDst.m_z, ptSrc.m_z) )
		{
			dx = (int)APPROX(nPx);
			dy = (int)APPROX(nPy);
			dz = (int)APPROX(nPz);

			// Add point to vector
			if ( !path.empty() )
			{
				CPointMap ptEnd = path[path.size() - 1];
				if ( ptEnd.m_x != dx || ptEnd.m_y != dy || ptEnd.m_z != dz )
					path.emplace_back((word)dx, (word)dy, (char)dz, ptSrc.m_map);
			}
			else
			{
				path.emplace_back((word)dx, (word)dy, (char)dz, ptSrc.m_map);
			}
			WARNLOS(("PATH X:%d Y:%d Z:%d\n", dx, dy, dz));

			nPx += dFactorX;
			nPy += dFactorY;
			nPz += dFactorZ;
		}
		else
			break;
	}

	if ( !path.empty() )
	{
		if ( path[path.size() - 1] != ptDst )
			path.emplace_back(ptDst.m_x, ptDst.m_y, ptDst.m_z, ptDst.m_map);
	}
	else
	{
		path.clear();
		return CanSeeLOS_New_Failed(pptBlock, ptNow);
	}

	WARNLOS(("Path calculated %" PRIuSIZE_T "\n", path.size()));
	// Ok now we should loop through all the points and checking for maptile, staticx, items, multis.
	// If something is in the way and it has the wrong flags LOS return false

	const CServerMapBlock *pBlock			= nullptr;		// Block of the map (for statics)
	const CUOStaticItemRec *pStatic			= nullptr;		// Statics iterator (based on SphereMapBlock)
	const CSphereMulti *pMulti 				= nullptr;		// Multi Def (multi check)
	const CUOMultiItemRec_HS *pMultiItem	= nullptr;		// Multi item iterator
	CRegion *pRegion					= nullptr;		// Nulti regions
	CRegionLinks rlinks;								// Links to multi regions
	CItem *pItem						= nullptr;
	CItemBase *pItemDef 				= nullptr;
	CItemBaseDupe *pDupeDef				= nullptr;

	dword wTFlags = 0;
	height_t Height = 0;
	word terrainid = 0;
	bool bPath = true;
	bool bNullTerrain = false;

	CRegion *pSrcRegion = ptSrc.GetRegion(REGION_TYPE_AREA|REGION_TYPE_ROOM|REGION_TYPE_MULTI);
	CRegion *pNowRegion = nullptr;

	int lp_x = 0, lp_y = 0;
	short min_z = 0, max_z = 0;

	for (uint i = 0, pathSize = uint(path.size()); i < pathSize; lp_x = ptNow.m_x, lp_y = ptNow.m_y, pItemDef = nullptr, pStatic = nullptr, pMulti = nullptr, pMultiItem = nullptr, min_z = 0, max_z = 0, ++i )
	{
		ptNow = path[i];
		WARNLOS(("---------------------------------------------\n"));
		WARNLOS(("Point %d,%d,%d \n", ptNow.m_x, ptNow.m_y, ptNow.m_z));

		pNowRegion = ptNow.GetRegion(REGION_TYPE_AREA|REGION_TYPE_ROOM|REGION_TYPE_MULTI);

		if ( (flags & LOS_NO_OTHER_REGION) && (pSrcRegion != pNowRegion) )
		{
			WARNLOS(("flags & 0200 and path is leaving my region - BLOCK\n"));
			bPath = false;
			break;
		}

		if ( (flags & LOS_NC_MULTI) && ptNow.GetRegion(REGION_TYPE_MULTI) && (ptNow.GetRegion(REGION_TYPE_MULTI) != ptSrc.GetRegion(REGION_TYPE_MULTI)) )
		{
			WARNLOS(("flags & 0400 and path is crossing another multi - BLOCK\n"));
			bPath = false;
			break;
		}

		if ( (lp_x != ptNow.m_x) || (lp_y != ptNow.m_y) )
		{
			WARNLOS(("\tLoading new map block.\n"));
			pBlock = g_World.GetMapBlock(ptNow);
		}

		if ( !pBlock ) // something is wrong
		{
			WARNLOS(("GetMapBlock Failed\n"));
			bPath = false;
			break;
		}

		if ( !(flags & LOS_NB_TERRAIN) )
		{
			if ( !((flags & LOS_NB_LOCAL_TERRAIN) && (pSrcRegion == pNowRegion)) )
			{
				// ------ MapX.mul Check ----------
				terrainid = pBlock->GetTerrain(UO_BLOCK_OFFSET(ptNow.m_x), UO_BLOCK_OFFSET(ptNow.m_y))->m_wTerrainIndex;
				WARNLOS(("Terrain %d\n", terrainid));

				if ( (flags & LOS_FISHING) && (ptSrc.GetDist(ptNow) >= 2) && (g_World.GetTerrainItemType(terrainid) != IT_WATER) && (g_World.GetTerrainItemType(terrainid) != IT_NORMAL) )
				{
					WARNLOS(("Terrain %d blocked - flags & LOS_FISHING, distance >= 2 and type of pItemDef is not IT_WATER\n", terrainid));
					WARNLOS(("ptSrc: %d,%d,%d; ptNow: %d,%d,%d; terrainid: %d; terrainid type: %d\n", ptSrc.m_x, ptSrc.m_y, ptSrc.m_z, ptNow.m_x, ptNow.m_y, ptNow.m_z, terrainid, g_World.GetTerrainItemType(terrainid)));
					bPath = false;
					break;
				}

				//#define MAPTILEMIN minimum(minimum(minimum(pBlock->GetTerrain(0,0)->m_z, pBlock->GetTerrain(0,1)->m_z), pBlock->GetTerrain(1,0)->m_z), pBlock->GetTerrain(1,1)->m_z)
				//#define MAPTILEMAX maximum(maximum(maximum(pBlock->GetTerrain(0,0)->m_z, pBlock->GetTerrain(0,1)->m_z), pBlock->GetTerrain(1,0)->m_z), pBlock->GetTerrain(1,1)->m_z);
				//#define MAPTILEZ pBlock->GetTerrain(UO_BLOCK_OFFSET(ptNow.m_x), UO_BLOCK_OFFSET(ptNow.m_y))->m_z;

				if ( (terrainid != TERRAIN_HOLE) && (terrainid != 475) )
				{
					if ( terrainid < 430 || terrainid > 437 )
					{
						/*this stuff should do some checking for surrounding items:
						aaa
						aXa
						aaa
						min_z is determined as a minimum of all a/X terrain, where X is ptNow
						*/
						byte pos_x = UO_BLOCK_OFFSET(ptNow.m_x) > 1 ? UO_BLOCK_OFFSET(ptNow.m_x - 1) : 0;
						byte pos_y = UO_BLOCK_OFFSET(ptNow.m_y) > 1 ? UO_BLOCK_OFFSET(ptNow.m_y - 1) : 0;
						const byte defx = UO_BLOCK_OFFSET(ptNow.m_x);
						const byte defy = UO_BLOCK_OFFSET(ptNow.m_y);
						min_z = pBlock->GetTerrain(pos_x, pos_y)->m_z;
						max_z = pBlock->GetTerrain(defx, defy)->m_z;
						for ( byte posy = pos_y; (abs(defx - UO_BLOCK_OFFSET(pos_x)) <= 1 && pos_x <= 7); ++pos_x )
						{
							for ( pos_y = posy; (abs(defy - UO_BLOCK_OFFSET(pos_y)) <= 1 && pos_y <= 7); ++pos_y )
							{
								char terrain_z = pBlock->GetTerrain(pos_x, pos_y)->m_z;
								min_z = minimum(min_z, terrain_z);
							}
						}
						//min_z = MAPTILEZ;
						//max_z = MAPTILEZ;
						WARNLOS(("Terrain %d - m:%d M:%d\n", terrainid, min_z, max_z));
						if ( CUOMapMeter::IsTerrainNull(terrainid) )
							bNullTerrain = true; //what if there are some items on that hole?
						if ( (min_z <= ptNow.m_z && max_z >= ptNow.m_z) && (ptNow.m_x != ptDst.m_x || ptNow.m_y != ptDst.m_y || min_z > ptDst.m_z || max_z < ptDst.m_z) )
						{
							WARNLOS(("Terrain %d - m:%d M:%d - block\n", terrainid, min_z, max_z));
							bPath = false;
							break;
						}
						CUOTerrainInfo land(terrainid);
						if ( (land.m_flags & UFLAG1_WATER) && (flags & LOS_NC_WATER) )
							bNullTerrain = true;
					}
				}
				//#undef MAPTILEMIN
				//#undef MAPTILEMAX
				//#undef MAPTILEZ
			}
		}

		// ------ StaticsX.mul Check --------
		if ( !(flags & LOS_NB_STATIC) )
		{
			if ( !((flags & LOS_NB_LOCAL_STATIC) && (pSrcRegion == pNowRegion)) )
			{
                uint uiStaticMaxQty = pBlock->m_Statics.GetStaticQty();
				for ( uint s = 0; s < uiStaticMaxQty; pStatic = nullptr, pItemDef = nullptr, ++s )
				{
					pStatic = pBlock->m_Statics.GetStatic(s);
					if ( (pStatic->m_x + pBlock->m_x != ptNow.m_x) || (pStatic->m_y + pBlock->m_y != ptNow.m_y) )
						continue;

					//Fix for Stacked items blocking view
					if ( (pStatic->m_x == ptDst.m_x) && (pStatic->m_y == ptDst.m_y) && (pStatic->m_z >= GetTopZ()) && (pStatic->m_z <= ptSrc.m_z) )
						continue;

					pItemDef = CItemBase::FindItemBase(pStatic->GetDispID());
					wTFlags = 0;
					Height = 0;
					bNullTerrain = false;

					if ( !pItemDef )
					{
						WARNLOS(("STATIC - Cannot get pItemDef for item (0%x)\n", pStatic->GetDispID()));
					}
					else
					{
                        if (pItemDef->Can(CAN_I_BLOCKLOS))
                        {
                            WARNLOS(("pStatic blocked by CAN_I_BLOCKLOS"));
                            bPath = false;
                            break;
                        }

						if ( (flags & LOS_FISHING) && (ptSrc.GetDist(ptNow) >= 2) && (pItemDef->GetType() != IT_WATER) &&
							( pItemDef->Can(CAN_I_DOOR | CAN_I_PLATFORM | CAN_I_BLOCK | CAN_I_CLIMB | CAN_I_FIRE | CAN_I_ROOF | CAN_I_BLOCKLOS | CAN_I_BLOCKLOS_HEIGHT)) )
						{
							WARNLOS(("pStatic blocked - flags & 0800, distance >= 2 and type of pItemDef is not IT_WATER\n"));
							bPath = false;
							break;
						}

						wTFlags = pItemDef->GetTFlags();
						Height = pItemDef->GetHeight();

						if ( pItemDef->GetID() != pStatic->GetDispID() ) //not a parent item
						{
							WARNLOS(("Not a parent item (STATIC)\n"));
							pDupeDef = CItemBaseDupe::GetDupeRef((ITEMID_TYPE)(pStatic->GetDispID()));
							if ( !pDupeDef )
							{
								g_Log.EventDebug("AdvancedLoS: Failed to get non-parent reference (static) (DispID 0%x) (X: %d Y: %d Z: %hhd M: %hhu)\n", pStatic->GetDispID(), ptNow.m_x, ptNow.m_y, pStatic->m_z, ptNow.m_map);
							}
							else
							{
								wTFlags = pDupeDef->GetTFlags();
								Height = pDupeDef->GetHeight();
							}
						}
						else
						{
							WARNLOS(("Parent item (STATIC)\n"));
						}

						Height = (wTFlags & UFLAG2_CLIMBABLE) ? Height / 2 : Height;

						if ( ((wTFlags & (UFLAG1_WALL|UFLAG1_BLOCK|UFLAG2_PLATFORM)) || (pItemDef->Can(CAN_I_BLOCKLOS_HEIGHT))) && !((wTFlags & UFLAG2_WINDOW) && (flags & LOS_NB_WINDOWS)) )
						{
							WARNLOS(("pStatic %0x %d,%d,%d - %d\n", pStatic->GetDispID(), pStatic->m_x, pStatic->m_y, pStatic->m_z, Height));
							min_z = pStatic->m_z;
							max_z = minimum(Height + min_z, UO_SIZE_Z);
							WARNLOS(("wTFlags(0%x)\n", wTFlags));

							WARNLOS(("pStatic %0x Z check: %d,%d (Now: %d) (Dest: %d).\n", pStatic->GetDispID(), min_z, max_z, ptNow.m_z, ptDst.m_z));
							if ( (min_z <= ptNow.m_z) && (max_z >= ptNow.m_z) )
							{
								if ( ptNow.m_x != ptDst.m_x || ptNow.m_y != ptDst.m_y || min_z > ptDst.m_z || max_z < ptDst.m_z )
								{
									WARNLOS(("pStatic blocked - m:%d M:%d\n", min_z, max_z));
									bPath = false;
									break;
								}
							}
						}
					}
				}
			}
		}

		if ( !bPath )
			break;

		// --------- In game items ----------
		if ( !(flags & LOS_NB_DYNAMIC) )
		{
			if ( !((flags & LOS_NB_LOCAL_DYNAMIC) && (pSrcRegion == pNowRegion)) )
			{
				CWorldSearch AreaItems(ptNow, 0);
				for (;;)
				{
					pItem = AreaItems.GetItem();
					if ( !pItem )
						break;
					if ( pItem->GetUnkPoint().m_x != ptNow.m_x || pItem->GetUnkPoint().m_y != ptNow.m_y )
						continue;
					if ( !CanSeeItem(pItem) )
						continue;

					//Fix for Stacked items blocking view
					if ( (pItem->GetUnkPoint().m_x == ptDst.m_x) && (pItem->GetUnkPoint().m_y == ptDst.m_y) && (pItem->GetUnkPoint().m_z >= GetTopZ()) && (pItem->GetUnkPoint().m_z <= ptSrc.m_z) )
						continue;

					pItemDef = static_cast<CItemBase*>(pItem->Base_GetDef());
					wTFlags = 0;
					Height = 0;
					bNullTerrain = false;

					if ( !pItemDef )
					{
						WARNLOS(("DYNAMIC - Cannot get pItemDef for item (0%x)\n", pItem->GetDispID()));
					}
					else
					{
                        if (pItem->Can(CAN_I_BLOCKLOS))
                        {
                            WARNLOS(("pItem blocked by CAN_I_BLOCKLOS"));
                            bPath = false;
                            break;
                        }

						if ( (flags & LOS_FISHING) && (ptSrc.GetDist(ptNow) >= 2) && (pItem->GetType() != IT_WATER) &&
							( pItem->Can(CAN_I_DOOR | CAN_I_PLATFORM | CAN_I_BLOCK | CAN_I_CLIMB | CAN_I_FIRE | CAN_I_ROOF | CAN_I_BLOCKLOS | CAN_I_BLOCKLOS_HEIGHT) ) )
						{
							WARNLOS(("pItem blocked - flags & 0800, distance >= 2 and type of pItemDef is not IT_WATER\n"));
							bPath = false;
							break;
							//return CanSeeLOS_New_Failed(pptBlock, ptNow);
						}

						wTFlags = pItemDef->GetTFlags();
						Height = pItemDef->GetHeight();

						if ( pItemDef->GetID() != pItem->GetDispID() )	//not a parent item
						{
							WARNLOS(("Not a parent item (DYNAMIC)\n"));
							pDupeDef = CItemBaseDupe::GetDupeRef((ITEMID_TYPE)(pItem->GetDispID()));
							if ( !pDupeDef )
							{
                                // Not an error: i have changed the DISPID of the item.
                                CItemBase* pParentDef = CItemBase::FindItemBase(pItem->GetDispID());
                                if (pParentDef)
                                {
                                    wTFlags = pParentDef->GetTFlags();
                                    Height = pParentDef->GetHeight();
                                }
                                else
                                    g_Log.EventDebug("AdvancedLoS: Failed to get reference (dynamic): non-dupe, baseless dispid (DispID 0%x) (X: %d Y: %d Z: %hhd M: %hhu)\n", pItem->GetDispID(), ptNow.m_x, ptNow.m_y, pItem->GetUnkZ(), ptNow.m_map);
							}
							else
							{
                                // It's a dupe item
								wTFlags = pDupeDef->GetTFlags();
								Height = pDupeDef->GetHeight();
							}
						}
						else
						{
							WARNLOS(("Parent item (DYNAMIC)\n"));
						}

						Height = (wTFlags & UFLAG2_CLIMBABLE) ? Height / 2 : Height;

						if ( ((wTFlags & (UFLAG1_WALL|UFLAG1_BLOCK|UFLAG2_PLATFORM)) || pItem->Can(CAN_I_BLOCKLOS_HEIGHT)) && !((wTFlags & UFLAG2_WINDOW) && (flags & LOS_NB_WINDOWS)) )
						{
							WARNLOS(("pItem %0x(%0x) %d,%d,%d - %d\n", (dword)pItem->GetUID(), pItem->GetDispID(), pItem->GetUnkPoint().m_x, pItem->GetUnkPoint().m_y, pItem->GetUnkPoint().m_z, Height));
							min_z = pItem->GetUnkPoint().m_z;
							max_z = minimum(Height + min_z, UO_SIZE_Z);
							WARNLOS(("wTFlags(0%x)\n", wTFlags));

							WARNLOS(("pItem %0x(%0x) Z check: %d,%d (Now: %d) (Dest: %d).\n", (dword)pItem->GetUID(), pItem->GetDispID(), min_z, max_z, ptNow.m_z, ptDst.m_z));
							if ( min_z <= ptNow.m_z && max_z >= ptNow.m_z )
							{
								if ( ptNow.m_x != ptDst.m_x || ptNow.m_y != ptDst.m_y || min_z > ptDst.m_z || max_z < ptDst.m_z )
								{
									WARNLOS(("pItem blocked - m:%d M:%d\n", min_z, max_z));
									bPath = false;
									break;
								}
							}
						}
					}
				}
			}
		}

		if ( !bPath )
			break;

		// ----------- Multis ---------------

		if ( !(flags & LOS_NB_MULTI) )
		{
			if ( !((flags & LOS_NB_LOCAL_MULTI) && (pSrcRegion == pNowRegion)) )
			{
				size_t iQtyr = ptNow.GetRegions(REGION_TYPE_MULTI, &rlinks);
				if ( iQtyr > 0 )
				{
					for ( size_t ii = 0; ii < iQtyr; pMulti = nullptr, ++ii, pItem = nullptr, pRegion = nullptr )
					{
						pRegion = rlinks[ii];
						if ( pRegion )
							pItem = pRegion->GetResourceID().ItemFindFromResource();

						if ( !pItem )
							continue;

						pMulti = g_Cfg.GetMultiItemDefs(pItem);
						if ( !pMulti )
							continue;

						uint iQty = pMulti->GetItemCount();
						for ( uint iii = 0; iii < iQty; pItemDef = nullptr, pMultiItem = nullptr, ++iii )
						{
							pMultiItem = pMulti->GetItem(iii);
							if ( !pMultiItem )
								break;
							if ( !pMultiItem->m_visible )
								continue;
							if ( (pMultiItem->m_dx + pItem->GetTopPoint().m_x != ptNow.m_x) || (pMultiItem->m_dy + pItem->GetTopPoint().m_y != ptNow.m_y) )
								continue;

							pItemDef = CItemBase::FindItemBase(pMultiItem->GetDispID());
							wTFlags = 0;
							Height = 0;
							bNullTerrain = false;

							if ( !pItemDef )
							{
								WARNLOS(("MULTI - Cannot get pItemDef for item (0%x)\n", pMultiItem->GetDispID()));
							}
							else
							{
                                if (pItemDef->Can(CAN_I_BLOCKLOS))
                                {
                                    WARNLOS(("pMultiItem blocked by CAN_I_BLOCKLOS"));
                                    bPath = false;
                                    break;
                                }

								if ( (flags & LOS_FISHING) && (ptSrc.GetDist(ptNow) >= 2) && (pItemDef->GetType() != IT_WATER) &&
									( pItemDef->Can(CAN_I_DOOR | CAN_I_PLATFORM | CAN_I_BLOCK | CAN_I_CLIMB | CAN_I_FIRE | CAN_I_ROOF | CAN_I_BLOCKLOS | CAN_I_BLOCKLOS_HEIGHT) ) )
								{
									WARNLOS(("pMultiItem blocked - flags & 0800, distance >= 2 and type of pItemDef is not IT_WATER\n"));
									bPath = false;
									break;
									//return CanSeeLOS_New_Failed(pptBlock, ptNow);
								}

								wTFlags = pItemDef->GetTFlags();
								Height = pItemDef->GetHeight();

								if ( pItemDef->GetID() != pMultiItem->GetDispID() ) //not a parent item
								{
									WARNLOS(("Not a parent item (MULTI)\n"));
									pDupeDef = CItemBaseDupe::GetDupeRef((ITEMID_TYPE)(pMultiItem->GetDispID()));
									if ( !pDupeDef )
									{
										g_Log.EventDebug("AdvancedLoS: Failed to get non-parent reference (multi) (DispID 0%x) (X: %d Y: %d Z: %hhd M: %hhu)\n", pMultiItem->GetDispID(), ptNow.m_x, ptNow.m_y, pMultiItem->m_dz + pItem->GetTopPoint().m_z, ptNow.m_map);
									}
									else
									{
										wTFlags = pDupeDef->GetTFlags();
										Height = pDupeDef->GetHeight();
									}
								}
								else
								{
									WARNLOS(("Parent item (MULTI)\n"));
								}

								Height = (wTFlags & UFLAG2_CLIMBABLE) ? Height / 2 : Height;

								if ( ((wTFlags & (UFLAG1_WALL|UFLAG1_BLOCK|UFLAG2_PLATFORM) || pItemDef->Can(CAN_I_BLOCKLOS_HEIGHT))) && !((wTFlags & UFLAG2_WINDOW) && (flags & LOS_NB_WINDOWS)) )
								{
									WARNLOS(("pMultiItem %0x %d,%d,%d - %d\n", pMultiItem->GetDispID(), pMultiItem->m_dx, pMultiItem->m_dy, pMultiItem->m_dz, Height));
									min_z = (char)(pMultiItem->m_dz) + pItem->GetTopPoint().m_z;
									max_z = minimum(Height + min_z, UO_SIZE_Z);
									WARNLOS(("wTFlags(0%x)\n", wTFlags));

									if ( min_z <= ptNow.m_z && max_z >= ptNow.m_z )
									{
										if ( ptNow.m_x != ptDst.m_x || ptNow.m_y != ptDst.m_y || min_z > ptDst.m_z || max_z < ptDst.m_z )
										{
											WARNLOS(("pMultiItem blocked - m:%d M:%d\n", min_z, max_z));
											bPath = false;
											break;
										}
									}
								}
							}
						}

						if ( !bPath )
							break;
					}
				}
			}
		}

		if ( bNullTerrain )
			bPath = false;

		if ( !bPath )
			break;
	}

	path.clear();

	if ( !bPath )
		return CanSeeLOS_New_Failed(pptBlock, ptNow);

	return true;
}
Exemple #15
0
bool CClient::r_WriteVal(LPCTSTR pszKey, CGString &sVal, CTextConsole *pSrc)
{
	ADDTOCALLSTACK("CClient::r_WriteVal");
	EXC_TRY("WriteVal");

	if ( !strnicmp("CTAG.", pszKey, 5) )
	{
		if ( pszKey[4] != '.' )
			return false;
		pszKey += 5;
		CVarDefCont *pVar = m_TagDefs.GetKey(pszKey);
		sVal = pVar ? pVar->GetValStr() : "";
		return true;
	}

	if ( !strnicmp("CTAG0.", pszKey, 6) )
	{
		if ( pszKey[5] != '.' )
			return false;
		pszKey += 6;
		CVarDefCont *pVar = m_TagDefs.GetKey(pszKey);
		sVal = pVar ? pVar->GetValStr() : "0";
		return true;
	}

	int index;
	if ( !strnicmp("TARGP", pszKey, 5) && ((pszKey[5] == '\0') || (pszKey[5] == '.')) )
		index = CC_TARGP;
	else if ( !strnicmp("SCREENSIZE", pszKey, 10) && ((pszKey[10] == '\0') || (pszKey[10] == '.')) )
		index = CC_SCREENSIZE;
	else if ( !strnicmp("REPORTEDCLIVER", pszKey, 14) && ((pszKey[14] == '\0') || (pszKey[14] == '.')) )
		index = CC_REPORTEDCLIVER;
	else
		index = FindTableSorted(pszKey, sm_szLoadKeys, COUNTOF(sm_szLoadKeys) - 1);

	switch ( index )
	{
		case CC_ALLMOVE:
			sVal.FormatVal(IsPriv(PRIV_ALLMOVE));
			break;
		case CC_ALLSHOW:
			sVal.FormatVal(IsPriv(PRIV_ALLSHOW));
			break;
		case CC_CLIENTIS3D:
			sVal.FormatVal(m_NetState->isClient3D());
			break;
		case CC_CLIENTISKR:
			sVal.FormatVal(m_NetState->isClientKR());
			break;
		case CC_CLIENTISSA:
			sVal.FormatVal(m_NetState->isClientEnhanced());
			break;
		case CC_CLIENTVERSION:
		{
			TCHAR szVersion[128];
			sVal = m_Crypt.WriteClientVerString(m_Crypt.GetClientVer(), szVersion);
			break;
		}
		case CC_DEBUG:
			sVal.FormatVal(IsPriv(PRIV_DEBUG));
			break;
		case CC_DETAIL:
			sVal.FormatVal(IsPriv(PRIV_DETAIL));
			break;
		case CC_GM:
			sVal.FormatVal(IsPriv(PRIV_GM));
			break;
		case CC_HEARALL:
			sVal.FormatVal(IsPriv(PRIV_HEARALL));
			break;
		case CC_LASTEVENT:
			sVal.FormatLLVal(m_timeLastEvent.GetTimeRaw());
			break;
		case CC_PRIVSHOW:
			sVal.FormatVal(!IsPriv(PRIV_PRIV_NOSHOW));
			break;
		case CC_REPORTEDCLIVER:
		{
			pszKey += 14;
			GETNONWHITESPACE(pszKey);

			DWORD dwCliVer = m_NetState->getReportedVersion();
			if ( pszKey[0] == '\0' )
			{
				// Return full version string (eg: 5.0.2d)
				TCHAR szVersion[128];
				sVal = CCrypt::WriteClientVerString(dwCliVer, szVersion);
			}
			else
			{
				// Return raw version number (eg: 5.0.2d = 5000204)
				sVal.FormatUVal(dwCliVer);
			}
			break;
		}
		case CC_SCREENSIZE:
		{
			if ( pszKey[10] == '.' )
			{
				pszKey += 10;
				SKIP_SEPARATORS(pszKey);

				if ( !strnicmp("X", pszKey, 1) )
					sVal.Format("%hu", m_ScreenSize.x);
				else if ( !strnicmp("Y", pszKey, 1) )
					sVal.Format("%hu", m_ScreenSize.y);
				else
					return false;
			}
			else
				sVal.Format("%hu,%hu", m_ScreenSize.x, m_ScreenSize.y);
			break;
		}
		case CC_TARG:
			sVal.FormatHex(m_Targ_UID);
			break;
		case CC_TARGP:
		{
			if ( pszKey[5] == '.' )
				return m_Targ_p.r_WriteVal(pszKey + 6, sVal);
			sVal = m_Targ_p.WriteUsed();
			break;
		}
		case CC_TARGPROP:
			sVal.FormatHex(m_Prop_UID);
			break;
		case CC_TARGPRV:
			sVal.FormatHex(m_Targ_PrvUID);
			break;
		case CC_TARGTXT:
			sVal = m_Targ_Text;
			break;
		default:
			return CScriptObj::r_WriteVal(pszKey, sVal, pSrc);
	}
	return true;
	EXC_CATCH;

	EXC_DEBUG_START;
	EXC_ADD_KEYRET(pSrc);
	EXC_DEBUG_END;
	return false;
}
Exemple #16
0
bool CClient::r_LoadVal( CScript & s )
{
	ADDTOCALLSTACK("CClient::r_LoadVal");
	EXC_TRY("LoadVal");
	if ( GetAccount() == NULL )
		return( false );

	LPCTSTR pszKey = s.GetKey();

	if ( s.IsKeyHead( "CTAG.", 5 ) || s.IsKeyHead( "CTAG0.", 6 ) )
	{
		bool fZero = s.IsKeyHead( "CTAG0.", 6 );
		bool fQuoted = false;

		pszKey = pszKey + (fZero ? 6 : 5);
		m_TagDefs.SetStr( pszKey, fQuoted, s.GetArgStr( &fQuoted ), fZero );
		return( true );
	}

	switch ( FindTableSorted( pszKey, sm_szLoadKeys, COUNTOF(sm_szLoadKeys)-1 ))
	{
		case CC_ALLMOVE:
			addRemoveAll(true, false);
			GetAccount()->TogPrivFlags( PRIV_ALLMOVE, s.GetArgStr() );
			if ( IsSetOF( OF_Command_Sysmsgs ) )
				m_pChar->SysMessage( IsPriv(PRIV_ALLMOVE)? "Allmove ON" : "Allmove OFF" );
			addPlayerView(NULL);
			break;
		case CC_ALLSHOW:
			addRemoveAll(false, true);
			GetAccount()->TogPrivFlags( PRIV_ALLSHOW, s.GetArgStr() );
			if ( IsSetOF( OF_Command_Sysmsgs ) )
				m_pChar->SysMessage( IsPriv(PRIV_ALLSHOW)? "Allshow ON" : "Allshow OFF" );
			addPlayerView(NULL);
			break;
		case CC_DEBUG:
			addRemoveAll(true, false);
			GetAccount()->TogPrivFlags( PRIV_DEBUG, s.GetArgStr() );
			if ( IsSetOF( OF_Command_Sysmsgs ) )
					m_pChar->SysMessage( IsPriv(PRIV_DEBUG)? "Debug ON" : "Debug OFF" );
			addPlayerView(NULL);
			break;
		case CC_DETAIL:
			GetAccount()->TogPrivFlags( PRIV_DETAIL, s.GetArgStr() );
			if ( IsSetOF( OF_Command_Sysmsgs ) )
					m_pChar->SysMessage( IsPriv(PRIV_DETAIL)? "Detail ON" : "Detail OFF" );
			break;
		case CC_GM: // toggle your GM status on/off
			if ( GetPrivLevel() >= PLEVEL_GM )
			{
				GetAccount()->TogPrivFlags( PRIV_GM, s.GetArgStr() );
				m_pChar->ResendTooltip();
				if ( IsSetOF( OF_Command_Sysmsgs ) )
					m_pChar->SysMessage( IsPriv(PRIV_GM)? "GM ON" : "GM OFF" );
			}
			break;
		case CC_HEARALL:
			GetAccount()->TogPrivFlags( PRIV_HEARALL, s.GetArgStr() );
			if ( IsSetOF( OF_Command_Sysmsgs ) )
					m_pChar->SysMessage( IsPriv(PRIV_HEARALL)? "Hearall ON" : "Hearall OFF" );
			break;
		case CC_PRIVSHOW:
			// Hide my priv title.
			if ( GetPrivLevel() >= PLEVEL_Counsel )
			{
				if ( ! s.HasArgs())
				{
					GetAccount()->TogPrivFlags( PRIV_PRIV_NOSHOW, NULL );
				}
				else if ( s.GetArgVal() )
				{
					GetAccount()->ClearPrivFlags( PRIV_PRIV_NOSHOW );
				}
				else
				{
					GetAccount()->SetPrivFlags( PRIV_PRIV_NOSHOW );
				}
				m_pChar->ResendTooltip();
				if ( IsSetOF( OF_Command_Sysmsgs ) )
					m_pChar->SysMessage( IsPriv(PRIV_PRIV_NOSHOW)? "Privshow OFF" : "Privshow ON" );
			}
			break;

		case CC_TARG:
			m_Targ_UID = s.GetArgVal();
			break;
		case CC_TARGP:
			m_Targ_p.Read( s.GetArgRaw());
			if ( !m_Targ_p.IsValidPoint() )
			{
				m_Targ_p.ValidatePoint();
				SysMessagef( "Invalid point: %s", s.GetArgStr() );
			}
			break;
		case CC_TARGPROP:
			m_Prop_UID = s.GetArgVal();
			break;
		case CC_TARGPRV:
			m_Targ_PrvUID = s.GetArgVal();
			break;
		default:
			return( false );
	}
	return true;
	EXC_CATCH;

	EXC_DEBUG_START;
	EXC_ADD_SCRIPT;
	EXC_DEBUG_END;
	return false;
}
Exemple #17
0
bool CClient::Cmd_Use_Item( CItem *pItem, bool fTestTouch, bool fScript )
{
	ADDTOCALLSTACK("CClient::Cmd_Use_Item");
	// Assume we can see the target.
	// called from Event_DoubleClick

	if ( !pItem )
		return false;

	if ( pItem->m_Can & CAN_I_FORCEDC )
		fTestTouch = false;

	if ( fTestTouch )
	{
		if ( !fScript )
		{
			CItemContainer *pContainer = dynamic_cast<CItemContainer *>(pItem->GetParent());
			if ( pContainer )
			{
				// protect from ,snoop - disallow picking from not opened containers
				bool isInOpenedContainer = false;
				if ( pContainer->GetType() == IT_EQ_TRADE_WINDOW )
					isInOpenedContainer = true;
				else
				{
					CClient::OpenedContainerMap_t::iterator itContainerFound = m_openedContainers.find(pContainer->GetUID().GetPrivateUID());
					if ( itContainerFound != m_openedContainers.end() )
					{
						DWORD dwTopContainerUID = (((*itContainerFound).second).first).first;
						DWORD dwTopMostContainerUID = (((*itContainerFound).second).first).second;
						CPointMap ptOpenedContainerPosition = ((*itContainerFound).second).second;
						const CObjBaseTemplate *pObjTop = pItem->GetTopLevelObj();
						const CObjBase *pObjParent = pContainer->GetParentObj();

						DWORD dwTopContainerUID_ToCheck = 0;
						if ( pObjParent )
							dwTopContainerUID_ToCheck = pObjParent->GetUID().GetPrivateUID();
						else
							dwTopContainerUID_ToCheck = pObjTop->GetUID().GetPrivateUID();

						if ( (dwTopMostContainerUID == pObjTop->GetUID().GetPrivateUID()) && (dwTopContainerUID == dwTopContainerUID_ToCheck) )
						{
							if ( pObjTop->IsChar() )
							{
								// probably a pickup check from pack if pCharTop != this?
								isInOpenedContainer = true;
							}
							else
							{
								const CItem *pItemTop = static_cast<const CItem *>(pObjTop);
								if ( pItemTop && (pItemTop->IsType(IT_SHIP_HOLD) || pItemTop->IsType(IT_SHIP_HOLD_LOCK)) && (pItemTop->GetTopPoint().GetRegion(REGION_TYPE_MULTI) == m_pChar->GetTopPoint().GetRegion(REGION_TYPE_MULTI)) )
									isInOpenedContainer = true;
								else if ( ptOpenedContainerPosition.GetDist(pObjTop->GetTopPoint()) <= 3 )
									isInOpenedContainer = true;
							}
						}
					}
				}

				if ( !isInOpenedContainer )
				{
					SysMessageDefault(DEFMSG_REACH_UNABLE);
					return false;
				}
			}
		}

		// CanTouch handles priv level compares for chars
		if ( !m_pChar->CanUse(pItem, false) )
		{
			if ( !m_pChar->CanTouch(pItem) )
				SysMessage((m_pChar->IsStatFlag(STATF_DEAD)) ? g_Cfg.GetDefaultMsg(DEFMSG_REACH_GHOST) : g_Cfg.GetDefaultMsg(DEFMSG_REACH_FAIL));
			else
				SysMessageDefault(DEFMSG_REACH_UNABLE);

			return false;
		}
	}

	if ( IsTrigUsed(TRIGGER_DCLICK) || IsTrigUsed(TRIGGER_ITEMDCLICK) )
	{
		if ( pItem->OnTrigger(ITRIG_DCLICK, m_pChar) == TRIGRET_RET_TRUE )
			return true;
	}

	CItemBase *pItemDef = pItem->Item_GetDef();
	bool bIsEquipped = pItem->IsItemEquipped();
	if ( pItemDef->IsTypeEquippable() && !bIsEquipped && pItemDef->GetEquipLayer() )
	{
		bool bMustEquip = true;
		if ( pItem->IsTypeSpellbook() )
			bMustEquip = false;
		else if ( (pItem->IsType(IT_LIGHT_OUT) || pItem->IsType(IT_LIGHT_LIT)) && !pItem->IsItemInContainer() )
			bMustEquip = false;

		if ( bMustEquip )
		{
			if ( !m_pChar->CanMove(pItem) )
				return false;

			if ( !m_pChar->CanCarry(pItem) )
			{
				SysMessageDefault(DEFMSG_MSG_HEAVY);
				return false;
			}

			if ( !m_pChar->ItemEquip(pItem, NULL, true) )
				return false;
		}
	}

	CItemSpawn *pSpawn = static_cast<CItemSpawn *>(pItem->m_uidSpawnItem.ItemFind());	// remove this item from its spawn when players DClick it from ground, no other way to take it out.
	if ( pSpawn )
		pSpawn->DelObj(pItem->GetUID());

	SetTargMode();
	m_Targ_PrvUID = m_Targ_UID;
	m_Targ_UID = pItem->GetUID();
	m_tmUseItem.m_pParent = pItem->GetParent();		// store item location to check later if it was not moved

	// Use types of items (specific to client)
	switch ( pItem->GetType() )
	{
		case IT_TRACKER:
		{
			if ( !m_pChar->Skill_Tracking(pItem->m_uidLink) )
			{
				if ( pItem->m_uidLink.IsValidUID() )
					SysMessageDefault(DEFMSG_TRACKING_UNABLE);
				addTarget(CLIMODE_TARG_LINK, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_TRACKER_ATTUNE));
			}
			return true;
		}

		case IT_SHAFT:
		case IT_FEATHER:
		{
			if ( IsTrigUsed(TRIGGER_SKILLMENU) )
			{
				CScriptTriggerArgs args("sm_bolts");
				if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE )
					return true;
			}
			return Cmd_Skill_Menu(g_Cfg.ResourceGetIDType(RES_SKILLMENU, "sm_bolts"));
		}

		case IT_FISH_POLE:	// Just be near water ?
			addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_FISHING_PROMT), true);
			return true;

		case IT_DEED:
			addTargetDeed(pItem);
			return true;

		case IT_EQ_BANK_BOX:
		case IT_EQ_VENDOR_BOX:
			if ( !fScript )
				g_Log.Event(LOGL_WARN|LOGM_CHEAT, "%lx:Cheater '%s' is using 3rd party tools to open bank box\n", GetSocketID(), m_pAccount->GetName());
			return false;

		case IT_CONTAINER_LOCKED:
		case IT_SHIP_HOLD_LOCK:
			if ( !m_pChar->GetContainerCreate(LAYER_PACK)->ContentFindKeyFor(pItem) )
			{
				SysMessageDefault(DEFMSG_ITEMUSE_LOCKED);
				if ( !IsPriv(PRIV_GM) )
					return false;
			}

		case IT_CORPSE:
		case IT_SHIP_HOLD:
		case IT_CONTAINER:
		case IT_TRASH_CAN:
		{
			CItemContainer *pPack = static_cast<CItemContainer *>(pItem);
			if ( !pPack )
				return false;

			if ( !m_pChar->Skill_Snoop_Check(pPack) )
			{
				if ( !addContainerSetup(pPack) )
					return false;
			}

			const CItemCorpse *pCorpseItem = static_cast<const CItemCorpse *>(pPack);
			if ( m_pChar->CheckCorpseCrime(pCorpseItem, true, true) )
				SysMessageDefault(DEFMSG_LOOT_CRIMINAL_ACT);
			return true;
		}

		case IT_GAME_BOARD:
		{
			if ( !pItem->IsTopLevel() )
			{
				SysMessageDefault(DEFMSG_ITEMUSE_GAMEBOARD_FAIL);
				return false;
			}
			CItemContainer *pBoard = static_cast<CItemContainer *>(pItem);
			ASSERT(pBoard);
			pBoard->Game_Create();
			addContainerSetup(pBoard);
			return true;
		}

		case IT_BBOARD:
			addBulletinBoard(static_cast<CItemContainer *>(pItem));
			return true;

		case IT_SIGN_GUMP:
		{
			GUMP_TYPE gumpid = pItemDef->m_ttContainer.m_gumpid;
			if ( !gumpid )
				return false;
			addGumpTextDisp(pItem, gumpid, pItem->GetName(), pItem->IsIndividualName() ? pItem->GetName() : NULL);
			return true;
		}

		case IT_BOOK:
		case IT_MESSAGE:
		{
			if ( !addBookOpen(pItem) )
				SysMessageDefault(DEFMSG_ITEMUSE_BOOK_FAIL);
			return true;
		}

		case IT_STONE_GUILD:
		case IT_STONE_TOWN:
			return true;

		case IT_POTION:
		{
			if ( !m_pChar->CanMove(pItem) )
			{
				SysMessageDefault(DEFMSG_ITEMUSE_POTION_FAIL);
				return false;
			}
			if ( RES_GET_INDEX(pItem->m_itPotion.m_Type) == SPELL_Poison )
			{
				// If we click directly on poison potion, we will drink poison and get ill.
				// To use it on Poisoning skill, the skill will request to target the potion.
				m_pChar->OnSpellEffect(SPELL_Poison, m_pChar, pItem->m_itSpell.m_spelllevel, NULL);
				return true;
			}
			if ( RES_GET_INDEX(pItem->m_itPotion.m_Type) == SPELL_Explosion )
			{
				// Throw explosion potion
				if ( !m_pChar->ItemPickup(pItem, 1) )	// put the potion in our hand
					return false;

				pItem->m_itPotion.m_tick = 4;		// countdown to explode
				pItem->m_itPotion.m_ignited = 1;	// ignite it
				pItem->m_uidLink = m_pChar->GetUID();
				pItem->SetTimeout(TICK_PER_SEC);
				m_tmUseItem.m_pParent = pItem->GetParent();
				addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_POTION_TARGET), true, true, pItem->m_itPotion.m_tick * TICK_PER_SEC);
				return true;
			}
			m_pChar->Use_Drink(pItem);
			return true;
		}

		case IT_ANIM_ACTIVE:
			SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_ITEM_IN_USE));
			return false;

		case IT_CLOCK:
			addObjMessage(m_pChar->GetTopSector()->GetLocalGameTime(), pItem);
			return true;

		case IT_SPAWN_ITEM:
		case IT_SPAWN_CHAR:
		{
			pSpawn = static_cast<CItemSpawn *>(pItem);
			if ( !pSpawn )
				return false;

			if ( pSpawn->m_currentSpawned )
			{
				SysMessageDefault(DEFMSG_ITEMUSE_SPAWN_NEG);
				pSpawn->KillChildren();		// Removing existing objects spawned from it ( RESET ).
			}
			else
			{
				SysMessageDefault(DEFMSG_ITEMUSE_SPAWN_RESET);
				pSpawn->OnTick(true);		// Forcing the spawn to work and create some objects ( START ).
			}
			return true;
		}

		case IT_SHRINE:
		{
			if ( m_pChar->OnSpellEffect(SPELL_Resurrection, m_pChar, 1000, pItem) )
				return true;
			SysMessageDefault(DEFMSG_ITEMUSE_SHRINE);
			return true;
		}

		case IT_SHIP_TILLER:
			pItem->Speak(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_TILLERMAN), HUE_TEXT_DEF, TALKMODE_SAY, FONT_NORMAL);
			return true;

		case IT_WAND:
		case IT_SCROLL:
		{
			SPELL_TYPE spell = static_cast<SPELL_TYPE>(RES_GET_INDEX(pItem->m_itWeapon.m_spell));
			CSpellDef *pSpellDef = g_Cfg.GetSpellDef(spell);
			if ( !pSpellDef )
				return false;

			if ( IsSetMagicFlags(MAGICF_PRECAST) && !pSpellDef->IsSpellType(SPELLFLAG_NOPRECAST) )
			{
				int skill;
				if ( !pSpellDef->GetPrimarySkill(&skill, NULL) )
					return false;

				m_tmSkillMagery.m_Spell = spell;	// m_atMagery.m_Spell
				m_pChar->m_atMagery.m_Spell = spell;
				m_pChar->Skill_Start(static_cast<SKILL_TYPE>(skill));
				return true;
			}
			return Cmd_Skill_Magery(spell, pItem);
		}

		case IT_RUNE:
		{
			if ( !m_pChar->CanMove(pItem, true) )
				return false;
			addPromptConsole(CLIMODE_PROMPT_NAME_RUNE, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_RUNE_NAME), pItem->GetUID());
			return true;
		}

		case IT_CARPENTRY:
		{
			if ( IsTrigUsed(TRIGGER_SKILLMENU) )
			{
				CScriptTriggerArgs args("sm_carpentry");
				if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE )
					return true;
			}
			return Cmd_Skill_Menu(g_Cfg.ResourceGetIDType(RES_SKILLMENU, "sm_carpentry"));
		}

		case IT_FORGE:
			// Solve for the combination of this item with another.
			addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_FORGE));
			return true;

		case IT_ORE:
			return m_pChar->Skill_Mining_Smelt(pItem, NULL);

		case IT_INGOT:
			return Cmd_Skill_Smith(pItem);

		case IT_KEY:
		case IT_KEYRING:
		{
			if ( pItem->GetTopLevelObj() != m_pChar && !m_pChar->IsPriv(PRIV_GM) )
			{
				SysMessageDefault(DEFMSG_ITEMUSE_KEY_FAIL);
				return false;
			}
			addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_KEY_PROMT), false, true);
			return true;
		}

		case IT_BANDAGE:		// SKILL_HEALING, or SKILL_VETERINARY
			addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_BANDAGE_PROMT), false, false);
			return true;

		case IT_BANDAGE_BLOOD:	// Clean the bandages.
		case IT_COTTON:			// use on a spinning wheel.
		case IT_WOOL:			// use on a spinning wheel.
		case IT_YARN:			// Use this on a loom.
		case IT_THREAD: 		// Use this on a loom.
		case IT_COMM_CRYSTAL:
			addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_TARGET_PROMT), false, false);
			return true;

		case IT_CARPENTRY_CHOP:
		case IT_LOCKPICK:		// Use on a locked thing.
		case IT_SCISSORS:
			addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_TARGET_PROMT), false, true);
			return true;

		case IT_WEAPON_MACE_PICK:
			if ( bIsEquipped || !IsSetOF(OF_NoDClickTarget) )
			{
				// Mine at the location
				TCHAR *pszTemp = Str_GetTemp();
				sprintf(pszTemp, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_MACEPICK_TARG), pItem->GetName());
				addTarget(CLIMODE_TARG_USE_ITEM, pszTemp, true, true);
				return true;
			}

		case IT_WEAPON_SWORD:
		case IT_WEAPON_FENCE:
		case IT_WEAPON_AXE:
		case IT_WEAPON_MACE_SHARP:
		case IT_WEAPON_MACE_STAFF:
		case IT_WEAPON_MACE_SMITH:
		{
			if ( bIsEquipped || !IsSetOF(OF_NoDClickTarget) )
				addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_WEAPON_PROMT), false, true);
			return true;
		}

		case IT_WEAPON_MACE_CROOK:
			if ( bIsEquipped || !IsSetOF(OF_NoDClickTarget) )
				addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_CROOK_PROMT), false, true);
			return true;

		case IT_FISH:
			SysMessageDefault(DEFMSG_ITEMUSE_FISH_FAIL);
			return true;

		case IT_TELESCOPE:
			SysMessageDefault(DEFMSG_ITEMUSE_TELESCOPE);
			return true;

		case IT_MAP:
			addDrawMap(static_cast<CItemMap *>(pItem));
			return true;

		case IT_CANNON_BALL:
		{
			TCHAR *pszTemp = Str_GetTemp();
			sprintf(pszTemp, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_CBALL_PROMT), pItem->GetName());
			addTarget(CLIMODE_TARG_USE_ITEM, pszTemp);
			return true;
		}

		case IT_CANNON_MUZZLE:
		{
			if ( !m_pChar->CanUse(pItem, false) )
				return false;

			// Make sure the cannon is loaded.
			if ( !(pItem->m_itCannon.m_Load & 1) )
			{
				addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_CANNON_POWDER));
				return true;
			}
			if ( !(pItem->m_itCannon.m_Load & 2) )
			{
				addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_CANNON_SHOT));
				return true;
			}
			addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_CANNON_TARG), false, true);
			return true;
		}

		case IT_CRYSTAL_BALL:
			// Gaze into the crystal ball.
			return true;

		case IT_SEED:
		case IT_PITCHER_EMPTY:
		{
			TCHAR *pszTemp = Str_GetTemp();
			sprintf(pszTemp, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_PITCHER_TARG), pItem->GetName());
			addTarget(CLIMODE_TARG_USE_ITEM, pszTemp, true);
			return true;
		}

		case IT_SPELLBOOK:
			addSpellbookOpen(pItem);
			return true;

		case IT_SPELLBOOK_NECRO:
			addSpellbookOpen(pItem, 101);
			return true;

		case IT_SPELLBOOK_PALA:
			addSpellbookOpen(pItem, 201);
			return true;

		case IT_SPELLBOOK_BUSHIDO:
			addSpellbookOpen(pItem, 401);
			return true;

		case IT_SPELLBOOK_NINJITSU:
			addSpellbookOpen(pItem, 501);
			return true;

		case IT_SPELLBOOK_ARCANIST:
			addSpellbookOpen(pItem, 601);
			return true;

		case IT_SPELLBOOK_MYSTIC:
			addSpellbookOpen(pItem, 678);
			return true;

		case IT_SPELLBOOK_BARD:
			addSpellbookOpen(pItem, 701);
			return true;

		case IT_HAIR_DYE:
		{
			if ( !m_pChar->LayerFind(LAYER_BEARD) && !m_pChar->LayerFind(LAYER_HAIR) )
			{
				SysMessageDefault(DEFMSG_ITEMUSE_DYE_NOHAIR);
				return true;
			}
			Dialog_Setup(CLIMODE_DIALOG, g_Cfg.ResourceGetIDType(RES_DIALOG, "d_hair_dye"), 0, pItem);
			return true;
		}

		case IT_DYE:
			addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_DYE_VAT));
			return true;

		case IT_DYE_VAT:
			addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_DYE_TARG), false, true);
			return true;

		case IT_MORTAR:
		{
			if ( IsTrigUsed(TRIGGER_SKILLMENU) )
			{
				CScriptTriggerArgs args("sm_alchemy");
				if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE )
					return true;
			}
			return Cmd_Skill_Menu(g_Cfg.ResourceGetIDType(RES_SKILLMENU, "sm_alchemy"));
		}

		case IT_CARTOGRAPHY:
		{
			if ( IsTrigUsed(TRIGGER_SKILLMENU) )
			{
				CScriptTriggerArgs args("sm_cartography");
				if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE )
					return true;
			}
			return Cmd_Skill_Menu(g_Cfg.ResourceGetIDType(RES_SKILLMENU, "sm_cartography"));
		}

		case IT_COOKING:
		{
			if ( IsTrigUsed(TRIGGER_SKILLMENU) )
			{
				CScriptTriggerArgs args("sm_cooking");
				if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE )
					return true;
			}
			return Cmd_Skill_Menu(g_Cfg.ResourceGetIDType(RES_SKILLMENU, "sm_cooking"));
		}

		case IT_TINKER_TOOLS:
		{
			if ( IsTrigUsed(TRIGGER_SKILLMENU) )
			{
				CScriptTriggerArgs args("sm_tinker");
				if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE )
					return true;
			}
			return Cmd_Skill_Menu(g_Cfg.ResourceGetIDType(RES_SKILLMENU, "sm_tinker"));
		}

		case IT_SEWING_KIT:
		{
			TCHAR *pszTemp = Str_GetTemp();
			sprintf(pszTemp, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SEWKIT_PROMT), pItem->GetName());
			addTarget(CLIMODE_TARG_USE_ITEM, pszTemp);
			return true;
		}

		case IT_SCROLL_BLANK:
			Cmd_Skill_Inscription();
			return true;

		default:
		{
			// An NPC could use it this way.
			if ( m_pChar->Use_Item(pItem) )
				return true;
			break;
		}
	}

	SysMessageDefault(DEFMSG_ITEMUSE_CANTTHINK);
	return false;
}
Exemple #18
0
bool CChar::Use_Seed( CItem * pSeed, CPointMap * pPoint )
{
	ADDTOCALLSTACK("CChar::Use_Seed");
	// Use the seed at the current point on the ground or some new point that i can touch.
	// IT_SEED from IT_FRUIT

	ASSERT(pSeed);
	CPointMap pt;
	if ( pPoint )
		pt = *pPoint;
	else if ( pSeed->IsTopLevel() )
		pt = pSeed->GetTopPoint();
	else
		pt = GetTopPoint();

	if ( !CanTouch(pt) )
	{
		SysMessageDefault(DEFMSG_MSG_SEED_REACH);
		return false;
	}

	// is there soil here ? IT_DIRT
	if ( !IsPriv(PRIV_GM) && !g_World.IsItemTypeNear(pt, IT_DIRT, 0, false) )
	{
		SysMessageDefault(DEFMSG_MSG_SEED_TARGSOIL);
		return(false);
	}

	const CItemBase *pItemDef = pSeed->Item_GetDef();
	ITEMID_TYPE idReset = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttFruit.m_idReset));
	if ( idReset == 0 )
	{
		SysMessageDefault(DEFMSG_MSG_SEED_NOGOOD);
		return false;
	}

	// Already a plant here ?
	CWorldSearch AreaItems(pt);
	for (;;)
	{
		CItem *pItem = AreaItems.GetItem();
		if ( !pItem )
			break;
		if ( pItem->IsType(IT_TREE) || pItem->IsType(IT_FOLIAGE) )		// there's already a tree here
		{
			SysMessageDefault(DEFMSG_MSG_SEED_ATREE);
			return false;
		}
		if ( pItem->IsType(IT_CROPS) )		// there's already a plant here
			pItem->Delete();
	}

	// plant it and consume the seed.

	CItem *pPlant = CItem::CreateScript(idReset, this);
	ASSERT(pPlant);

	pPlant->MoveToUpdate(pt);
	if ( pPlant->IsType(IT_CROPS) || pPlant->IsType(IT_FOLIAGE) )
	{
		pPlant->m_itCrop.m_ReapFruitID = pSeed->GetID();
		pPlant->Plant_CropReset();
	}
	else
	{
		pPlant->SetDecayTime(10 * g_Cfg.m_iDecay_Item);
	}

	pSeed->ConsumeAmount();
	return true;
}