// Pick cotton/hay/etc... // use the // IT_CROPS = transforms into a "ripe" variety then is used up on reaping. // IT_FOLIAGE = is not consumed on reap (unless eaten then will regrow invis) // bool CItem::Plant_Use(CChar *pChar) { ADDTOCALLSTACK("CItem::Plant_Use"); if ( !pChar ) return false; if ( !pChar->CanSeeItem(this) ) // might be invis underground return false; const CItemBase *pItemDef = Item_GetDef(); ITEMID_TYPE iFruitID = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttCrops.m_idFruit)); // if it's reapable at this stage if ( iFruitID <= 0 ) { // not ripe. (but we could just eat it if we are herbivorous ?) pChar->SysMessageDefault(DEFMSG_CROPS_NOT_RIPE); return true; } if ( m_itCrop.m_ReapFruitID ) iFruitID = static_cast<ITEMID_TYPE>(RES_GET_INDEX(m_itCrop.m_ReapFruitID)); if ( iFruitID ) { CItem *pItemFruit = CItem::CreateScript(iFruitID, pChar); if ( pItemFruit ) pChar->ItemBounce(pItemFruit); } else pChar->SysMessageDefault(DEFMSG_CROPS_NO_FRUIT); Plant_CropReset(); pChar->UpdateAnimate(ANIM_BOW); pChar->Sound(0x13e); return true; }
bool CResourceDef::SetResourceName( LPCTSTR pszName ) { ADDTOCALLSTACK("CResourceDef::SetResourceName"); ASSERT(pszName); // This is the global def for this item. for ( size_t i = 0; pszName[i]; i++ ) { if ( i >= EXPRESSION_MAX_KEY_LEN ) { DEBUG_ERR(( "Too long DEFNAME=%s\n", pszName )); return( false ); } if ( ! _ISCSYM(pszName[i])) { DEBUG_ERR(( "Bad chars in DEFNAME=%s\n", pszName )); return( false ); } } int iVarNum; CVarDefCont * pVarKey = g_Exp.m_VarDefs.GetKey( pszName ); if ( pVarKey ) { if ( (DWORD)pVarKey->GetValNum() == GetResourceID().GetPrivateUID() ) { return( true ); } if ( RES_GET_INDEX(pVarKey->GetValNum()) == GetResourceID().GetResIndex()) { DEBUG_WARN(( "The DEFNAME=%s has a strange type mismatch? 0%llx!=0%lx\n", pszName, pVarKey->GetValNum(), GetResourceID().GetPrivateUID() )); } else { DEBUG_WARN(( "The DEFNAME=%s already exists! 0%llx!=0%x\n", pszName, RES_GET_INDEX(pVarKey->GetValNum()), GetResourceID().GetResIndex() )); } iVarNum = g_Exp.m_VarDefs.SetNum( pszName, GetResourceID().GetPrivateUID() ); } else { iVarNum = g_Exp.m_VarDefs.SetNumNew( pszName, GetResourceID().GetPrivateUID() ); } if ( iVarNum < 0 ) return( false ); SetResourceVar( dynamic_cast <const CVarDefContNum*>( g_Exp.m_VarDefs.GetAt( iVarNum ))); return( true ); }
bool CItem::Ship_Plank( bool fOpen ) { // IT_SHIP_PLANK to IT_SHIP_SIDE and IT_SHIP_SIDE_LOCKED // This item is the ships plank. CItemBase * pItemDef = Item_GetDef(); ITEMID_TYPE idState = (ITEMID_TYPE) RES_GET_INDEX( pItemDef->m_ttShipPlank.m_idState ); if ( ! idState ) { // Broken ? return( false ); } if ( IsType(IT_SHIP_PLANK)) { if ( fOpen ) return( true ); } else { DEBUG_CHECK( IsType(IT_SHIP_SIDE) || IsType(IT_SHIP_SIDE_LOCKED)); if ( ! fOpen ) return( true ); } SetID( idState ); Update(); return( true ); }
bool CItem::Plant_Use( CChar * pChar ) { ADDTOCALLSTACK("CItem::Plant_Use"); // Pick cotton/hay/etc... // use the // IT_CROPS = transforms into a "ripe" variety then is used up on reaping. // IT_FOLIAGE = is not consumed on reap (unless eaten then will regrow invis) // if ( !pChar ) return false; if ( ! pChar->CanSeeItem(this)) // might be invis underground. return( false ); const CItemBase * pItemDef = Item_GetDef(); ITEMID_TYPE iFruitID = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttCrops.m_idFruit)); // if it's reapable at this stage. if ( iFruitID <= 0 ) { // not ripe. (but we could just eat it if we are herbivorous ?) pChar->SysMessage( g_Cfg.GetDefaultMsg( DEFMSG_CROPS_NOT_RIPE ) ); return( true ); } if ( m_itCrop.m_ReapFruitID ) { iFruitID = static_cast<ITEMID_TYPE>(RES_GET_INDEX(m_itCrop.m_ReapFruitID)); } if ( iFruitID > 0 ) { CItem * pItemFruit = CItem::CreateScript( iFruitID , pChar ); if ( pItemFruit) { pChar->ItemBounce( pItemFruit ); } } else { pChar->SysMessage( g_Cfg.GetDefaultMsg( DEFMSG_CROPS_NO_FRUIT ) ); } Plant_CropReset(); pChar->UpdateAnimate( ANIM_BOW ); pChar->Sound( 0x13e ); return true; }
bool CItem::Plant_Use( CChar * pChar ) { // Pick cotton/hay/etc... // use the // IT_CROPS = transforms into a "ripe" variety then is used up on reaping. // IT_FOLIAGE = is not consumed on reap (unless eaten then will regrow invis) // DEBUG_CHECK( IsType(IT_CROPS) || IsType(IT_FOLIAGE)); ASSERT(pChar); if ( ! pChar->CanSeeItem(this)) // might be invis underground. return( false ); CItemBase * pItemDef = Item_GetDef(); ITEMID_TYPE iFruitID = (ITEMID_TYPE) RES_GET_INDEX( pItemDef->m_ttCrops.m_idFruit ); // if it's reapable at this stage. if ( iFruitID <= 0 ) { // not ripe. (but we could just eat it if we are herbivorous ?) pChar->SysMessage( "None of the crops are ripe enough." ); return( true ); } if ( m_itCrop.m_ReapFruitID ) { iFruitID = (ITEMID_TYPE) RES_GET_INDEX( m_itCrop.m_ReapFruitID ); } if ( iFruitID > 0 ) { CItem * pItemFruit = CItem::CreateScript( iFruitID , pChar ); if ( pItemFruit) { pChar->ItemBounce( pItemFruit ); } } else { pChar->SysMessage( "The plant yields nothing useful" ); } Plant_CropReset(); pChar->UpdateAnimate( ANIM_BOW ); pChar->Sound( 0x13e ); return true; }
LONG CItemVendable::GetVendorPrice( int iConvertFactor ) { ADDTOCALLSTACK("CItemVendable::GetVendorPrice"); // Player is buying/selling from a vendor. // ASSUME this item is on the vendor ! // Consider: (if not on a player vendor) // Quality of the item. // rareity of the item. // ARGS: // iConvertFactor will consider: // Vendors Karma. // Players Karma // -100 = reduce price by 100% (player selling to vendor?) // 0 = base price // +100 = increase price by 100% (vendor selling to player?) INT64 lPrice = m_price; if ( lPrice <= 0 ) // set on player vendor. { if ( lPrice == 0 ) // set a new randomized price for the item { CItemBase * pItemDef; if ( IsType( IT_DEED )) { // Deeds just represent the item they are deeding. pItemDef = CItemBase::FindItemBase(static_cast<ITEMID_TYPE>(RES_GET_INDEX(m_itDeed.m_Type))); if ( pItemDef == NULL ) return( 1 ); } else { pItemDef = Item_GetDef(); } lPrice = pItemDef->GetMakeValue(GetQuality()); m_price = static_cast<long>(-lPrice); } else { lPrice = -lPrice; } } lPrice += IMULDIV( lPrice, maximum(iConvertFactor, -100), 100 ); if (lPrice > LONG_MAX) return LONG_MAX; else if (lPrice <= 0) return 0; return static_cast<long>(lPrice); }
// Animals will eat crops before they are ripe, so we need a way to reset them prematurely void CItem::Plant_CropReset() { ADDTOCALLSTACK("CItem::Plant_CropReset"); if ( !IsType(IT_CROPS) && !IsType(IT_FOLIAGE) ) { // This isn't a crop, and since it just got eaten, we should delete it Delete(); return; } const CItemBase *pItemDef = Item_GetDef(); ITEMID_TYPE iResetID = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttCrops.m_idReset)); if ( iResetID != ITEMID_NOTHING ) SetID(iResetID); Plant_SetTimer(); RemoveFromView(); // remove from most screens. SetHue(HUE_RED_DARK); // Indicate to GM's that it is growing. SetAttr(ATTR_INVIS); // regrown invis. }
void CItem::Plant_CropReset() { // Animals will eat crops before they are ripe, so we need a way to reset them prematurely if ( ! IsType(IT_CROPS) && ! IsType(IT_FOLIAGE)) { // This isn't a crop, and since it just got eaten, we should delete it Delete(); return; } CItemBase * pItemDef = Item_GetDef(); ITEMID_TYPE iResetID = (ITEMID_TYPE) RES_GET_INDEX( pItemDef->m_ttCrops.m_idReset ); if ( iResetID != ITEMID_NOTHING ) { SetID(iResetID); } Plant_SetTimer(); RemoveFromView(); // remove from most screens. SetHue( HUE_RED_DARK ); // Indicate to GM's that it is growing. SetAttr(ATTR_INVIS); // regrown invis. }
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; }
// timer expired, should I grow? bool CItem::Plant_OnTick() { ADDTOCALLSTACK("CItem::Plant_OnTick"); ASSERT(IsType(IT_CROPS) || IsType(IT_FOLIAGE)); // If it is in a container, kill it. if ( !IsTopLevel() ) return false; // Make sure the darn thing isn't moveable SetAttr(ATTR_MOVE_NEVER); Plant_SetTimer(); // No tree stuff below here if ( IsAttr(ATTR_INVIS) ) // if it's invis, take care of it here and return { SetHue(HUE_DEFAULT); ClrAttr(ATTR_INVIS); Update(); return true; } const CItemBase *pItemDef = Item_GetDef(); ITEMID_TYPE iGrowID = pItemDef->m_ttCrops.m_idGrow; if ( iGrowID == -1 ) { // Some plants generate a fruit on the ground when ripe. ITEMID_TYPE iFruitID = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttCrops.m_idGrow)); if ( m_itCrop.m_ReapFruitID ) iFruitID = static_cast<ITEMID_TYPE>(RES_GET_INDEX(m_itCrop.m_ReapFruitID)); if ( !iFruitID ) return true; // Put a fruit on the ground if not already here. CWorldSearch AreaItems(GetTopPoint()); for (;;) { CItem *pItem = AreaItems.GetItem(); if ( !pItem ) { CItem *pItemFruit = CItem::CreateScript(iFruitID); ASSERT(pItemFruit); pItemFruit->MoveToDecay(GetTopPoint(), 10 * g_Cfg.m_iDecay_Item); break; } if ( pItem->IsType(IT_FRUIT) || pItem->IsType(IT_REAGENT_RAW) ) break; } // NOTE: ??? The plant should cycle here as well ! iGrowID = pItemDef->m_ttCrops.m_idReset; } if ( iGrowID ) { SetID(static_cast<ITEMID_TYPE>(RES_GET_INDEX(iGrowID))); Update(); return true; } // some plants go dormant again ? // m_itCrop.m_Fruit_ID = iTemp; return true; }
void CChar::Use_Drink( CItem * pItem ) { ADDTOCALLSTACK("CChar::Use_Drink"); // IT_POTION: // IT_DRINK: // IT_PITCHER: // IT_WATER_WASH: // IT_BOOZE: if ( !CanMove(pItem) ) { SysMessageDefault(DEFMSG_DRINK_CANTMOVE); return; } const CItemBase *pItemDef = pItem->Item_GetDef(); ITEMID_TYPE idbottle = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttDrink.m_idEmpty)); if ( pItem->IsType(IT_BOOZE) ) { // Beer wine and liquor. vary strength of effect. int iAlcohol = Calc_GetRandVal(4); CItem *pDrunkLayer = LayerFind(LAYER_FLAG_Drunk); if ( !pDrunkLayer ) pDrunkLayer = Spell_Effect_Create(SPELL_Liquor, LAYER_FLAG_Drunk, 0, 5 * TICK_PER_SEC, this); pDrunkLayer->m_itSpell.m_spellcharges += iAlcohol; if ( pDrunkLayer->m_itSpell.m_spellcharges > 60 ) pDrunkLayer->m_itSpell.m_spellcharges = 60; } if ( pItem->IsType(IT_POTION) ) { // Time limit on using potions. if ( LayerFind(LAYER_FLAG_PotionUsed) ) { SysMessageDefault(DEFMSG_DRINK_POTION_DELAY); return; } // Convey the effect of the potion. int iSkillQuality = pItem->m_itPotion.m_skillquality; if ( g_Cfg.m_iFeatureAOS & FEATURE_AOS_UPDATE_B ) { int iEnhance = static_cast<int>(GetDefNum("EnhancePotions", false)); if ( iEnhance ) iSkillQuality += IMULDIV(iSkillQuality, iEnhance, 100); } OnSpellEffect(static_cast<SPELL_TYPE>(RES_GET_INDEX(pItem->m_itPotion.m_Type)), this, iSkillQuality, pItem); // Give me the marker that i've used a potion. Spell_Effect_Create(SPELL_NONE, LAYER_FLAG_PotionUsed, iSkillQuality, 15 * TICK_PER_SEC, this); } if ( pItem->IsType(IT_DRINK) && IsSetOF(OF_DrinkIsFood) ) { short iRestore = 0; if ( pItem->m_itDrink.m_foodval ) iRestore = static_cast<short>(pItem->m_itDrink.m_foodval); else iRestore = static_cast<short>(pItem->Item_GetDef()->GetVolume()); if ( iRestore < 1 ) iRestore = 1; if ( Stat_GetVal(STAT_FOOD) >= Stat_GetMax(STAT_FOOD) ) { SysMessageDefault(DEFMSG_DRINK_FULL); return; } Stat_SetVal(STAT_FOOD, Stat_GetVal(STAT_FOOD) + iRestore); if ( pItem->m_itFood.m_poison_skill ) SetPoison(pItem->m_itFood.m_poison_skill * 10, 1 + (pItem->m_itFood.m_poison_skill / 50), this); } //Sound(sm_DrinkSounds[Calc_GetRandVal(COUNTOF(sm_DrinkSounds))]); UpdateAnimate(ANIM_EAT); pItem->ConsumeAmount(); // Create the empty bottle ? if ( idbottle != ITEMID_NOTHING ) ItemBounce(CItem::CreateScript(idbottle, this), false); }
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; }
llong CExpression::GetSingle( lpctstr & pszArgs ) { ADDTOCALLSTACK("CExpression::GetSingle"); // Parse just a single expression without any operators or ranges. ASSERT(pszArgs); GETNONWHITESPACE( pszArgs ); lpctstr orig = pszArgs; if (pszArgs[0]=='.') ++pszArgs; if ( pszArgs[0] == '0' ) // leading '0' = hex value. { // A hex value. if ( pszArgs[1] == '.' ) // leading 0. means it really is decimal. { pszArgs += 2; goto try_dec; } lpctstr pStart = pszArgs; ullong val = 0; while (true) { tchar ch = *pszArgs; if ( IsDigit(ch) ) ch -= '0'; else { ch = static_cast<tchar>(tolower(ch)); if ( ch > 'f' || ch < 'a' ) { if ( ch == '.' && pStart[0] != '0' ) // ok i'm confused. it must be decimal. { pszArgs = pStart; goto try_dec; } break; } ch -= 'a' - 10; } val *= 0x10; val += ch; ++pszArgs; } return (llong)val; } else if ( pszArgs[0] == '.' || IsDigit(pszArgs[0]) ) { // A decminal number try_dec: llong iVal = 0; for ( ; ; ++pszArgs ) { if ( *pszArgs == '.' ) continue; // just skip this. if ( ! IsDigit(*pszArgs) ) break; iVal *= 10; iVal += *pszArgs - '0'; } return iVal; } else if ( ! _ISCSYMF(pszArgs[0]) ) { #pragma region maths // some sort of math op ? switch ( pszArgs[0] ) { case '{': ++pszArgs; return GetRangeNumber( pszArgs ); case '[': case '(': // Parse out a sub expression. ++pszArgs; return GetVal( pszArgs ); case '+': ++pszArgs; break; case '-': ++pszArgs; return -GetSingle( pszArgs ); case '~': // Bitwise not. ++pszArgs; return ~GetSingle( pszArgs ); case '!': // boolean not. ++pszArgs; if ( pszArgs[0] == '=' ) // odd condition such as (!=x) which is always true of course. { ++pszArgs; // so just skip it. and compare it to 0 return GetSingle( pszArgs ); } return !GetSingle( pszArgs ); case ';': // seperate field. case ',': // seperate field. case '\0': return 0; } #pragma endregion maths } else #pragma region intrinsics { // Symbol or intrinsinc function ? INTRINSIC_TYPE iIntrinsic = (INTRINSIC_TYPE) FindTableHeadSorted( pszArgs, sm_IntrinsicFunctions, CountOf(sm_IntrinsicFunctions)-1 ); if ( iIntrinsic >= 0 ) { size_t iLen = strlen(sm_IntrinsicFunctions[iIntrinsic]); if ( pszArgs[iLen] == '(' ) { pszArgs += (iLen + 1); tchar * pszArgsNext; Str_Parse( const_cast<tchar*>(pszArgs), &(pszArgsNext), ")" ); tchar * ppCmd[5]; llong iResult; size_t iCount = 0; switch ( iIntrinsic ) { case INTRINSIC_ID: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = RES_GET_INDEX( GetVal(pszArgs) ); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_MAX: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 0; else { const int64 iVal1 = GetVal(ppCmd[0]), iVal2 = GetVal(ppCmd[1]); iResult = maximum(iVal1, iVal2); } } break; case INTRINSIC_MIN: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 0; else { const int64 iVal1 = GetVal(ppCmd[0]), iVal2 = GetVal(ppCmd[1]); iResult = minimum(iVal1, iVal2); } } break; case INTRINSIC_LOGARITHM: { iCount = 0; iResult = 0; if ( pszArgs && *pszArgs ) { llong iArgument = GetVal(pszArgs); if ( iArgument <= 0 ) { DEBUG_ERR(( "Exp_GetVal: (x)Log(%" PRId64 ") is %s\n", iArgument, (!iArgument) ? "infinite" : "undefined" )); } else { iCount = 1; if ( strchr(pszArgs, ',') ) { ++iCount; SKIP_ARGSEP(pszArgs); if ( !strcmpi(pszArgs, "e") ) { iResult = (llong)log( (double)iArgument ); } else if ( !strcmpi(pszArgs, "pi") ) { iResult = (llong)(log( (double)iArgument ) / log( M_PI ) ); } else { llong iBase = GetVal(pszArgs); if ( iBase <= 0 ) { DEBUG_ERR(( "Exp_GetVal: (%" PRId64 ")Log(%" PRId64 ") is %s\n", iBase, iArgument, (!iBase ? "infinite" : "undefined") )); iCount = 0; } else iResult = (llong)(log( (double)iArgument ) / log( (double)iBase )); } } else iResult = (llong)log10( (double)iArgument ); } } } break; case INTRINSIC_NAPIERPOW: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = (llong)exp( (double)GetVal( pszArgs ) ); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_SQRT: { iCount = 0; iResult = 0; if ( pszArgs && *pszArgs ) { llong iTosquare = GetVal(pszArgs); if (iTosquare >= 0) { ++iCount; iResult = (llong)sqrt( (double)iTosquare ); } else DEBUG_ERR(( "Exp_GetVal: Sqrt of negative number (%" PRId64 ") is impossible\n", iTosquare )); } } break; case INTRINSIC_SIN: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = (llong)sin( (double)GetVal( pszArgs ) ); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_ARCSIN: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = (llong)asin( (double)GetVal( pszArgs ) ); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_COS: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = (llong)cos( (double)GetVal( pszArgs ) ); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_ARCCOS: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = (llong)acos( (double)GetVal( pszArgs ) ); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_TAN: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = (llong)tan( (double)GetVal( pszArgs ) ); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_ARCTAN: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = (llong)atan( (double)GetVal( pszArgs ) ); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_StrIndexOf: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 3, "," ); if ( iCount < 2 ) iResult = -1; else iResult = Str_IndexOf( ppCmd[0] , ppCmd[1] , (iCount==3)?(int)GetVal(ppCmd[2]):0 ); } break; case INTRINSIC_STRMATCH: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 0; else iResult = (Str_Match( ppCmd[0], ppCmd[1] ) == MATCH_VALID ) ? 1 : 0; } break; case INTRINSIC_STRREGEX: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 0; else { tchar * tLastError = Str_GetTemp(); iResult = Str_RegExMatch( ppCmd[0], ppCmd[1], tLastError ); if ( iResult == -1 ) { DEBUG_ERR(( "STRREGEX bad function usage. Error: %s\n", tLastError )); } } } break; case INTRINSIC_RANDBELL: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 0; else iResult = Calc_GetBellCurve( (int)GetVal( ppCmd[0] ), (int)GetVal( ppCmd[1] ) ); } break; case INTRINSIC_STRASCII: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = pszArgs[0]; } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_RAND: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 2, "," ); if ( iCount <= 0 ) iResult = 0; else { int64 val1 = GetVal( ppCmd[0] ); if ( iCount == 2 ) { int64 val2 = GetVal( ppCmd[1] ); iResult = Calc_GetRandLLVal2( val1, val2 ); } else iResult = Calc_GetRandLLVal(val1); } } break; case INTRINSIC_STRCMP: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 1; else iResult = strcmp(ppCmd[0], ppCmd[1]); } break; case INTRINSIC_STRCMPI: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 1; else iResult = strcmpi(ppCmd[0], ppCmd[1]); } break; case INTRINSIC_STRLEN: { iCount = 1; iResult = strlen(pszArgs); } break; case INTRINSIC_ISOBSCENE: { iCount = 1; iResult = g_Cfg.IsObscene( pszArgs ); } break; case INTRINSIC_ISNUMBER: { iCount = 1; { GETNONWHITESPACE( pszArgs ); if (*pszArgs == '-') ++pszArgs; iResult = IsStrNumeric( pszArgs ); } } break; case INTRINSIC_QVAL: { iCount = Str_ParseCmds( const_cast<tchar*>(pszArgs), ppCmd, 5, "," ); if ( iCount < 3 ) iResult = 0; else { llong a1 = GetSingle(ppCmd[0]); llong a2 = GetSingle(ppCmd[1]); if ( a1 < a2 ) iResult = GetSingle(ppCmd[2]); else if ( a1 == a2 ) iResult = ( iCount < 4 ) ? 0 : GetSingle(ppCmd[3]); else iResult = ( iCount < 5 ) ? 0 : GetSingle(ppCmd[4]); } } break; case INTRINSIC_ABS: { iCount = 1; iResult = llabs(GetVal(pszArgs)); } break; default: iCount = 0; iResult = 0; break; } pszArgs = pszArgsNext; if ( !iCount ) { DEBUG_ERR(( "Bad intrinsic function usage: Missing arguments\n" )); return 0; } else return iResult; } } // Must be a symbol of some sort ? lpctstr ptcArgsOriginal = pszArgs; llong llVal; if ( m_VarGlobals.GetParseVal_Advance( pszArgs, &llVal ) ) // VAR. return llVal; if ( m_VarResDefs.GetParseVal( ptcArgsOriginal, &llVal ) ) // RESDEF. return llVal; if ( m_VarDefs.GetParseVal( ptcArgsOriginal, &llVal ) ) // DEF. return llVal; } #pragma endregion intrinsics // hard end ! Error of some sort. tchar szTag[ EXPRESSION_MAX_KEY_LEN ]; size_t i = GetIdentifierString( szTag, pszArgs ); pszArgs += i; // skip it. if ( strlen(orig) > 1) DEBUG_ERR(("Undefined symbol '%s' ['%s']\n", szTag, orig)); else DEBUG_ERR(("Undefined symbol '%s'\n", szTag)); return 0; }
bool CPointBase::r_WriteVal( LPCTSTR pszKey, CGString & sVal ) const { ADDTOCALLSTACK("CPointBase::r_WriteVal"); if ( !strnicmp( pszKey, "STATICS", 7 ) ) { pszKey += 7; const CGrayMapBlock * pBlock = g_World.GetMapBlock( *(this) ); if ( !pBlock ) return false; if ( *pszKey == '\0' ) { int iStaticQty = 0; for ( size_t i = 0; i < pBlock->m_Statics.GetStaticQty(); i++ ) { const CUOStaticItemRec * pStatic = pBlock->m_Statics.GetStatic( i ); CPointMap ptTest( pStatic->m_x+pBlock->m_x, pStatic->m_y+pBlock->m_y, pStatic->m_z, this->m_map ); if ( this->GetDist( ptTest ) > 0 ) continue; iStaticQty++; } sVal.FormatVal( iStaticQty ); return true; } SKIP_SEPARATORS( pszKey ); const CUOStaticItemRec * pStatic = NULL; int iStatic = 0; int type = 0; if ( !strnicmp( pszKey, "FINDID", 6 ) ) { pszKey += 6; SKIP_SEPARATORS( pszKey ); iStatic = Exp_GetVal( pszKey ); type = RES_GET_TYPE( iStatic ); if ( type == 0 ) type = RES_ITEMDEF; SKIP_SEPARATORS( pszKey ); } else { iStatic = Exp_GetVal( pszKey ); type = RES_GET_TYPE( iStatic ); } if ( type == RES_ITEMDEF ) { const CItemBase * pItemDef = CItemBase::FindItemBase(static_cast<ITEMID_TYPE>(RES_GET_INDEX(iStatic))); if ( !pItemDef ) { sVal.FormatVal( 0 ); return false; } for ( size_t i = 0; i < pBlock->m_Statics.GetStaticQty(); pStatic = NULL, i++ ) { pStatic = pBlock->m_Statics.GetStatic( i ); CPointMap ptTest( pStatic->m_x+pBlock->m_x, pStatic->m_y+pBlock->m_y, pStatic->m_z, this->m_map); if ( this->GetDist( ptTest ) > 0 ) continue; if ( pStatic->GetDispID() == pItemDef->GetDispID() ) break; } } else { for ( size_t i = 0; i < pBlock->m_Statics.GetStaticQty(); pStatic = NULL, i++ ) { pStatic = pBlock->m_Statics.GetStatic( i ); CPointMap ptTest( pStatic->m_x+pBlock->m_x, pStatic->m_y+pBlock->m_y, pStatic->m_z, this->m_map); if ( this->GetDist( ptTest ) > 0 ) continue; if ( iStatic == 0 ) break; iStatic--; } } if ( !pStatic ) { sVal.FormatHex(0); return true; } SKIP_SEPARATORS( pszKey ); if ( !*pszKey ) pszKey = "ID"; ITEMID_TYPE idTile = pStatic->GetDispID(); if ( !strnicmp( pszKey, "COLOR", 5 ) ) { sVal.FormatHex( pStatic->m_wHue ); return true; } else if ( !strnicmp( pszKey, "ID", 2 ) ) { sVal.FormatHex( idTile ); return true; } else if ( !strnicmp( pszKey, "Z", 1 ) ) { sVal.FormatVal( pStatic->m_z ); return true; } // Check the script def for the item. CItemBase * pItemDef = CItemBase::FindItemBase( idTile ); if ( pItemDef == NULL ) { DEBUG_ERR(("Must have ITEMDEF section for item ID 0%x\n", idTile )); return false; } return pItemDef->r_WriteVal( pszKey, sVal, &g_Serv ); } else if ( !strnicmp( pszKey, "COMPONENTS", 10) ) { pszKey += 10; CRegionLinks rlinks; const CRegionBase* pRegion = NULL; CItem* pItem = NULL; const CGrayMulti* pMulti = NULL; const CUOMultiItemRec2* pMultiItem = NULL; size_t iMultiQty = GetRegions(REGION_TYPE_MULTI, rlinks); if ( *pszKey == '\0' ) { int iComponentQty = 0; for (size_t i = 0; i < iMultiQty; i++) { pRegion = rlinks.GetAt(i); if (pRegion == NULL) continue; pItem = pRegion->GetResourceID().ItemFind(); if (pItem == NULL) continue; const CPointMap ptMulti = pItem->GetTopPoint(); pMulti = g_Cfg.GetMultiItemDefs(pItem); if (pMulti == NULL) continue; size_t iQty = pMulti->GetItemCount(); for (size_t ii = 0; ii < iQty; ii++) { pMultiItem = pMulti->GetItem(ii); if (pMultiItem == NULL) break; if (pMultiItem->m_visible == 0) continue; CPointMap ptTest(static_cast<WORD>(ptMulti.m_x + pMultiItem->m_dx), static_cast<WORD>(ptMulti.m_y + pMultiItem->m_dy), static_cast<signed char>(ptMulti.m_z + pMultiItem->m_dz), this->m_map); if (GetDist(ptTest) > 0) continue; iComponentQty++; } } sVal.FormatVal( iComponentQty ); return true; } SKIP_SEPARATORS( pszKey ); int iComponent = 0; int type = 0; if ( strnicmp( pszKey, "FINDID", 6 ) == 0 ) { pszKey += 6; SKIP_SEPARATORS( pszKey ); iComponent = Exp_GetVal( pszKey ); type = RES_GET_TYPE( iComponent ); if ( type == 0 ) type = RES_ITEMDEF; SKIP_SEPARATORS( pszKey ); } else { iComponent = Exp_GetVal( pszKey ); type = RES_GET_TYPE( iComponent ); } if ( type == RES_ITEMDEF ) { const CItemBase * pItemDef = CItemBase::FindItemBase(static_cast<ITEMID_TYPE>(RES_GET_INDEX(iComponent))); if ( pItemDef == NULL ) { sVal.FormatVal( 0 ); return false; } for (size_t i = 0; i < iMultiQty; i++) { pRegion = rlinks.GetAt(i); if (pRegion == NULL) continue; pItem = pRegion->GetResourceID().ItemFind(); if (pItem == NULL) continue; const CPointMap ptMulti = pItem->GetTopPoint(); pMulti = g_Cfg.GetMultiItemDefs(pItem); if (pMulti == NULL) continue; size_t iQty = pMulti->GetItemCount(); for (size_t ii = 0; ii < iQty; pMultiItem = NULL, ii++) { pMultiItem = pMulti->GetItem(ii); if (pMultiItem == NULL) break; if (pMultiItem->m_visible == 0) continue; CPointMap ptTest(static_cast<WORD>(ptMulti.m_x + pMultiItem->m_dx), static_cast<WORD>(ptMulti.m_y + pMultiItem->m_dy), static_cast<signed char>(ptMulti.m_z + pMultiItem->m_dz), this->m_map); if (GetDist(ptTest) > 0) continue; const CItemBase* pMultiItemDef = CItemBase::FindItemBase(pMultiItem->GetDispID()); if (pMultiItemDef != NULL && pMultiItemDef->GetDispID() == pItemDef->GetDispID()) break; } if (pMultiItem != NULL) break; } } else { for (size_t i = 0; i < iMultiQty; i++) { pRegion = rlinks.GetAt(i); if (pRegion == NULL) continue; pItem = pRegion->GetResourceID().ItemFind(); if (pItem == NULL) continue; const CPointMap ptMulti = pItem->GetTopPoint(); pMulti = g_Cfg.GetMultiItemDefs(pItem); if (pMulti == NULL) continue; size_t iQty = pMulti->GetItemCount(); for (size_t ii = 0; ii < iQty; pMultiItem = NULL, ii++) { pMultiItem = pMulti->GetItem(ii); if (pMultiItem == NULL) break; if (pMultiItem->m_visible == 0) continue; CPointMap ptTest(static_cast<WORD>(ptMulti.m_x + pMultiItem->m_dx), static_cast<WORD>(ptMulti.m_y + pMultiItem->m_dy), static_cast<signed char>(ptMulti.m_z + pMultiItem->m_dz), this->m_map); if (GetDist(ptTest) > 0) continue; if (iComponent == 0) break; iComponent--; } if (pMultiItem != NULL) break; } } if ( pMultiItem == NULL ) { sVal.FormatHex(0); return true; } SKIP_SEPARATORS( pszKey ); if ( !*pszKey ) pszKey = "ID"; ITEMID_TYPE idTile = pMultiItem->GetDispID(); if ( strnicmp( pszKey, "ID", 2 ) == 0 ) { sVal.FormatHex( idTile ); return true; } else if ( strnicmp( pszKey, "MULTI", 5 ) == 0 ) { pszKey += 5; if (*pszKey != '\0') { SKIP_SEPARATORS(pszKey); return pItem->r_WriteVal( pszKey, sVal, &g_Serv ); } sVal.FormatHex( pItem->GetUID() ); return true; } else if ( strnicmp( pszKey, "Z", 1 ) == 0 ) { sVal.FormatVal( pItem->GetTopZ() + pMultiItem->m_dz ); return true; } // Check the script def for the item. CItemBase * pItemDef = CItemBase::FindItemBase( idTile ); if ( pItemDef == NULL ) { DEBUG_ERR(("Must have ITEMDEF section for item ID 0%x\n", idTile )); return false; } return pItemDef->r_WriteVal( pszKey, sVal, &g_Serv ); } int index = FindTableHeadSorted( pszKey, sm_szLoadKeys, COUNTOF(sm_szLoadKeys)-1 ); if ( index < 0 ) return false; switch ( index ) { case PT_M: case PT_MAP: sVal.FormatVal(m_map); break; case PT_X: sVal.FormatVal(m_x); break; case PT_Y: sVal.FormatVal(m_y); break; case PT_Z: sVal.FormatVal(m_z); break; case PT_ISNEARTYPE: { pszKey += 10; SKIP_SEPARATORS( pszKey ); SKIP_ARGSEP( pszKey ); int iType = g_Cfg.ResourceGetIndexType( RES_TYPEDEF, pszKey ); int iDistance = 0; bool bCheckMulti = false; SKIP_IDENTIFIERSTRING( pszKey ); SKIP_SEPARATORS( pszKey ); SKIP_ARGSEP( pszKey ); if ( *pszKey ) iDistance = Exp_GetVal(pszKey); if ( *pszKey ) bCheckMulti = Exp_GetVal(pszKey) != 0; sVal.FormatVal( g_World.IsItemTypeNear(*this, static_cast<IT_TYPE>(iType), iDistance, bCheckMulti)); break; } case PT_REGION: { // Check that the syntax is correct. if ( pszKey[6] && pszKey[6] != '.' ) return false; CRegionWorld * pRegionTemp = dynamic_cast <CRegionWorld*>(this->GetRegion(REGION_TYPE_AREA | REGION_TYPE_MULTI)); if ( !pszKey[6] ) { // We're just checking if the reference is valid. sVal.FormatVal( pRegionTemp? 1:0 ); return true; } // We're trying to retrieve a property from the region. pszKey += 7; if ( pRegionTemp ) return pRegionTemp->r_WriteVal( pszKey, sVal, &g_Serv ); return false; } case PT_ROOM: { if ( pszKey[4] && pszKey[4] != '.' ) return false; CRegionBase * pRegionTemp = this->GetRegion( REGION_TYPE_ROOM ); if ( !pszKey[4] ) { sVal.FormatVal( pRegionTemp? 1:0 ); return true; } pszKey += 5; if ( pRegionTemp ) return pRegionTemp->r_WriteVal( pszKey, sVal, &g_Serv ); return false; } case PT_SECTOR: { if ( pszKey[6] == '.' ) { pszKey += 7; CSector * pSectorTemp = this->GetSector(); if (pSectorTemp) return pSectorTemp->r_WriteVal(pszKey, sVal, &g_Serv); } return false; } default: { const CUOMapMeter * pMeter = g_World.GetMapMeter(*this); if ( pMeter ) { switch( index ) { case PT_TYPE: { CItemTypeDef * pTypeDef = g_World.GetTerrainItemTypeDef( pMeter->m_wTerrainIndex ); if ( pTypeDef != NULL ) sVal = pTypeDef->GetResourceName(); else sVal = ""; } return true; case PT_TERRAIN: { pszKey += strlen(sm_szLoadKeys[index]); if ( *pszKey == '.' ) // do we have an argument? { SKIP_SEPARATORS( pszKey ); if ( !strnicmp( pszKey, "Z", 1 )) { sVal.FormatVal( pMeter->m_z ); return( true ); } return( false ); } else { sVal.FormatHex( pMeter->m_wTerrainIndex ); } } return true; } } return false; } } return true; }
INT64 CExpression::GetSingle( LPCTSTR & pszArgs ) { ADDTOCALLSTACK("CExpression::GetSingle"); // Parse just a single expression without any operators or ranges. ASSERT(pszArgs); GETNONWHITESPACE( pszArgs ); LPCTSTR orig = pszArgs; if (pszArgs[0]=='.') pszArgs++; if ( pszArgs[0] == '0' ) // leading '0' = hex value. { // A hex value. if ( pszArgs[1] == '.' ) // leading 0. means it really is decimal. { pszArgs += 2; goto try_dec; } LPCTSTR pStart = pszArgs; ULONGLONG val = 0; for (;;) { TCHAR ch = *pszArgs; if ( IsDigit( ch )) ch -= '0'; else { ch = static_cast<TCHAR>(tolower(ch)); if ( ch > 'f' || ch <'a' ) { if ( ch == '.' && pStart[0] != '0' ) // ok i'm confused. it must be decimal. { pszArgs = pStart; goto try_dec; } break; } ch -= 'a' - 10; } val *= 0x10; val += ch; pszArgs ++; } return( (INT64)val ); } else if ( pszArgs[0] == '.' || IsDigit(pszArgs[0])) { // A decminal number try_dec: INT64 iVal = 0; for ( ; ; pszArgs++ ) { if ( *pszArgs == '.' ) continue; // just skip this. if ( ! IsDigit( *pszArgs )) break; iVal *= 10; iVal += *pszArgs - '0'; } return( iVal ); } else if ( ! _ISCSYMF(pszArgs[0])) { #pragma region maths // some sort of math op ? switch ( pszArgs[0] ) { case '{': pszArgs ++; return( GetRange( pszArgs )); case '[': case '(': // Parse out a sub expression. pszArgs ++; return(GetVal( pszArgs )); case '+': pszArgs++; break; case '-': pszArgs++; return( -GetSingle( pszArgs )); case '~': // Bitwise not. pszArgs++; return( ~GetSingle( pszArgs )); case '!': // boolean not. pszArgs++; if ( pszArgs[0] == '=' ) // odd condition such as (!=x) which is always true of course. { pszArgs++; // so just skip it. and compare it to 0 return( GetSingle( pszArgs )); } return( !GetSingle( pszArgs )); case ';': // seperate field. case ',': // seperate field. case '\0': return( 0 ); } #pragma endregion maths } else #pragma region intrinsics { // Symbol or intrinsinc function ? INTRINSIC_TYPE iIntrinsic = (INTRINSIC_TYPE) FindTableHeadSorted( pszArgs, sm_IntrinsicFunctions, COUNTOF(sm_IntrinsicFunctions)-1 ); if ( iIntrinsic >= 0 ) { size_t iLen = strlen(sm_IntrinsicFunctions[iIntrinsic]); if ( pszArgs[iLen] == '(' ) { pszArgs += (iLen + 1); TCHAR * pszArgsNext; Str_Parse( const_cast<TCHAR*>(pszArgs), &(pszArgsNext), ")" ); TCHAR * ppCmd[5]; INT64 iResult; size_t iCount = 0; switch ( iIntrinsic ) { case INTRINSIC_ID: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = RES_GET_INDEX( GetVal( pszArgs )); // RES_GET_INDEX } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_LOGARITHM: { iCount = 0; iResult = 0; if ( pszArgs && *pszArgs ) { int iArgument = static_cast<long>(GetVal(pszArgs)); if ( iArgument <= 0 ) { DEBUG_ERR(( "Exp_GetVal: (x)Log(%d) is %s\n", iArgument, (!iArgument) ? "infinite" : "undefined" )); } else { iCount = 1; if ( strchr(pszArgs, ',') ) { iCount++; SKIP_ARGSEP(pszArgs); if ( !strcmpi(pszArgs, "e") ) { iResult = static_cast<INT64>(log(static_cast<double>(iArgument))); } else if ( !strcmpi(pszArgs, "pi") ) { iResult = static_cast<INT64>(log(static_cast<double>(iArgument)) / log(M_PI)); } else { INT64 iBase = GetVal(pszArgs); if ( iBase <= 0 ) { DEBUG_ERR(( "Exp_GetVal: (%lld)Log(%d) is %s\n", iBase, iArgument, (!iBase) ? "infinite" : "undefined" )); iCount = 0; } else { iResult = static_cast<INT64>(log(static_cast<double>(iArgument)) / log(static_cast<double>(iBase))); } } } else { iResult = static_cast<INT64>(log10(static_cast<double>(iArgument))); } } } } break; case INTRINSIC_NAPIERPOW: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = static_cast<INT64>(exp(static_cast<double>(GetVal(pszArgs)))); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_SQRT: { iCount = 0; iResult = 0; if ( pszArgs && *pszArgs ) { int iTosquare = static_cast<long>(GetVal(pszArgs)); if (iTosquare >= 0) { iCount++; iResult = static_cast<INT64>(sqrt(static_cast<double>(iTosquare))); } else { DEBUG_ERR(( "Exp_GetVal: Sqrt of negative number (%d) is impossible\n", iTosquare )); } } } break; case INTRINSIC_SIN: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = static_cast<INT64>(sin(static_cast<double>(GetVal(pszArgs)))); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_ARCSIN: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = static_cast<INT64>(asin(static_cast<double>(GetVal(pszArgs)))); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_COS: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = static_cast<INT64>(cos(static_cast<double>(GetVal(pszArgs)))); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_ARCCOS: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = static_cast<INT64>(acos(static_cast<double>(GetVal(pszArgs)))); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_TAN: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = static_cast<INT64>(tan(static_cast<double>(GetVal(pszArgs)))); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_ARCTAN: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = static_cast<INT64>(atan(static_cast<double>(GetVal(pszArgs)))); } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_StrIndexOf: { iCount = Str_ParseCmds( const_cast<TCHAR*>(pszArgs), ppCmd, 3, "," ); if ( iCount < 2 ) iResult = -1; else iResult = Str_IndexOf(ppCmd[0],ppCmd[1],(iCount==3)?static_cast<long>(GetVal(ppCmd[2])):0); } break; case INTRINSIC_STRMATCH: { iCount = Str_ParseCmds( const_cast<TCHAR*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 0; else iResult = (Str_Match( ppCmd[0], ppCmd[1] ) == MATCH_VALID ) ? 1 : 0; } break; case INTRINSIC_STRREGEX: { iCount = Str_ParseCmds( const_cast<TCHAR*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 0; else { TCHAR * tLastError = Str_GetTemp(); iResult = Str_RegExMatch( ppCmd[0], ppCmd[1], tLastError ); if ( iResult == -1 ) { DEBUG_ERR(( "STRREGEX bad function usage. Error: %s\n", tLastError )); } } } break; case INTRINSIC_RANDBELL: { iCount = Str_ParseCmds( const_cast<TCHAR*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 0; else iResult = Calc_GetBellCurve( static_cast<long>(GetVal( ppCmd[0] )), static_cast<long>(GetVal( ppCmd[1] ))); } break; case INTRINSIC_STRASCII: { if ( pszArgs && *pszArgs ) { iCount = 1; iResult = pszArgs[0]; } else { iCount = 0; iResult = 0; } } break; case INTRINSIC_RAND: { iCount = Str_ParseCmds( const_cast<TCHAR*>(pszArgs), ppCmd, 2, "," ); if ( iCount <= 0 ) iResult = 0; else { INT64 val1 = GetVal( ppCmd[0] ); if ( iCount == 2 ) { INT64 val2 = GetVal( ppCmd[1] ); iResult = Calc_GetRandLLVal2( val1, val2 ); } else iResult = Calc_GetRandLLVal(val1); } } break; case INTRINSIC_STRCMP: { iCount = Str_ParseCmds( const_cast<TCHAR*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 1; else iResult = strcmp(ppCmd[0], ppCmd[1]); } break; case INTRINSIC_STRCMPI: { iCount = Str_ParseCmds( const_cast<TCHAR*>(pszArgs), ppCmd, 2, "," ); if ( iCount < 2 ) iResult = 1; else iResult = strcmpi(ppCmd[0], ppCmd[1]); } break; case INTRINSIC_STRLEN: { iCount = 1; iResult = strlen(pszArgs); } break; case INTRINSIC_ISOBSCENE: { iCount = 1; iResult = g_Cfg.IsObscene( pszArgs ); } break; case INTRINSIC_ISNUMBER: { iCount = 1; { char z[64]; LTOA(atol(pszArgs), z, 10); iResult = strcmp(pszArgs, z) ? 0 : 1; } } break; case INTRINSIC_QVAL: { iCount = Str_ParseCmds( const_cast<TCHAR*>(pszArgs), ppCmd, 5, "," ); if ( iCount < 3 ) iResult = 0; else { INT64 a1 = GetSingle(ppCmd[0]); INT64 a2 = GetSingle(ppCmd[1]); if ( a1 < a2 ) iResult = GetSingle(ppCmd[2]); else if ( a1 == a2 ) iResult = ( iCount < 4 ) ? 0 : GetSingle(ppCmd[3]); else iResult = ( iCount < 5 ) ? 0 : GetSingle(ppCmd[4]); } } break; case INTRINSIC_ABS: { iCount = 1; iResult = llabs(GetVal(pszArgs)); } break; default: iCount = 0; iResult = 0; break; } pszArgs = pszArgsNext; if ( ! iCount ) { DEBUG_ERR(( "Bad intrinsic function usage: Missing arguments\n" )); return 0; } else { return iResult; } } } // Must be a symbol of some sort ? long long lVal; if ( m_VarGlobals.GetParseVal( pszArgs, &lVal ) ) return(lVal); if ( m_VarDefs.GetParseVal( pszArgs, &lVal ) ) return(lVal); } #pragma endregion intrinsics // hard end ! Error of some sort. TCHAR szTag[ EXPRESSION_MAX_KEY_LEN ]; size_t i = GetIdentifierString( szTag, pszArgs ); pszArgs += i; // skip it. if (strlen(orig)> 1) DEBUG_ERR(("Undefined symbol '%s' ['%s']\n", szTag, orig)); else DEBUG_ERR(("Undefined symbol '%s'\n", szTag)); return( 0 ); }