void StartFishing(CCharEntity* PChar) { if (PChar->animation != ANIMATION_NONE) { PChar->pushPacket(new CMessageSystemPacket(0,0,142)); PChar->pushPacket(new CReleasePacket(PChar,RELEASE_FISHING)); return; } uint16 MessageOffset = GetMessageOffset(PChar->getZone()); if (MessageOffset == 0) { ShowWarning(CL_YELLOW"Player wants to fish in %s\n" CL_RESET, PChar->loc.zone->GetName()); PChar->pushPacket(new CReleasePacket(PChar,RELEASE_FISHING)); return; } CItemWeapon* WeaponItem = nullptr; WeaponItem = (CItemWeapon*)PChar->getEquip(SLOT_RANGED); if ((WeaponItem == nullptr) || !(WeaponItem->isType(ITEM_WEAPON)) || (WeaponItem->getSkillType() != SKILL_FSH)) { // сообщение: "You can't fish without a rod in your hands" PChar->pushPacket(new CMessageTextPacket(PChar, MessageOffset + 0x01)); PChar->pushPacket(new CReleasePacket(PChar,RELEASE_FISHING)); return; } WeaponItem = (CItemWeapon*)PChar->getEquip(SLOT_AMMO); if ((WeaponItem == nullptr) || !(WeaponItem->isType(ITEM_WEAPON)) || (WeaponItem->getSkillType() != SKILL_FSH)) { // сообщение: "You can't fish without bait on the hook" PChar->pushPacket(new CMessageTextPacket(PChar, MessageOffset + 0x02)); PChar->pushPacket(new CReleasePacket(PChar,RELEASE_FISHING)); return; } PChar->animation = ANIMATION_FISHING_START; PChar->updatemask |= UPDATE_HP; PChar->pushPacket(new CCharUpdatePacket(PChar)); PChar->pushPacket(new CCharSyncPacket(PChar)); }
bool CLatentEffect::Deactivate() { if (IsActivated()) { //remove the modifier from weapon, not player if (GetModValue() == Mod::ADDITIONAL_EFFECT || GetModValue() == Mod::DMG) { CCharEntity* PChar = (CCharEntity*)m_POwner; CItemWeapon* weapon = (CItemWeapon*)PChar->getEquip((SLOTTYPE)GetSlot()); int16 modPower = GetModPower(); if (weapon != nullptr && (weapon->isType(ITEM_ARMOR) || weapon->isType(ITEM_WEAPON))) { if (GetModValue() == Mod::ADDITIONAL_EFFECT) { for (uint8 i = 0; i < weapon->modList.size(); ++i) { //ensure the additional effect is fully removed from the weapon if (weapon->modList.at(i).getModID() == Mod::ADDITIONAL_EFFECT) { weapon->modList.at(i).setModAmount(0); } } } else { weapon->addModifier(CModifier(GetModValue(), -modPower)); } } } else { m_POwner->delModifier(m_ModValue, m_ModPower); } m_Activated = false; //printf("LATENT DEACTIVATED: %d\n", m_ModValue); return true; } return false; }
void CMagicState::CharAfterFinish() { if(m_PEntity->objtype != TYPE_PC) { return; } CCharEntity* PChar = (CCharEntity*)m_PEntity; charutils::RemoveStratagems(PChar, m_PSpell); charutils::UpdateHealth(PChar); // only skill up if the effect landed if(m_PSpell->tookEffect()){ charutils::TrySkillUP(PChar, (SKILLTYPE)m_PSpell->getSkillType(), m_PTarget->GetMLevel()); if (m_PSpell->getSkillType() == SKILL_SNG) { CItemWeapon* PItem = (CItemWeapon*)PChar->getEquip(SLOT_RANGED); if (PItem && PItem->isType(ITEM_ARMOR)) { SKILLTYPE Skilltype = (SKILLTYPE)PItem->getSkillType(); if (Skilltype == SKILL_STR || Skilltype == SKILL_WND || Skilltype == SKILL_SNG) { charutils::TrySkillUP(PChar, Skilltype, m_PTarget->GetMLevel()); } } } } PChar->pushPacket(new CCharUpdatePacket(PChar)); // make wyvern use breath if(PChar->PPet!=NULL && ((CPetEntity*)PChar->PPet)->getPetType() == PETTYPE_WYVERN) { ((CAIPetDummy*)PChar->PPet->PBattleAI)->m_MasterCommand = MASTERCOMMAND_HEALING_BREATH; PChar->PPet->PBattleAI->SetCurrentAction(ACTION_MOBABILITY_START); } SetHiPCLvl(m_PTarget, PChar->GetMLevel()); }
bool LureLoss(CCharEntity* PChar, bool RemoveFly) { CItemWeapon* PLure = (CItemWeapon*)PChar->getEquip(SLOT_AMMO); DSP_DEBUG_BREAK_IF(PLure == nullptr); DSP_DEBUG_BREAK_IF(PLure->isType(ITEM_WEAPON) == false); DSP_DEBUG_BREAK_IF(PLure->getSkillType() != SKILL_FSH); if (!RemoveFly && ( PLure->getStackSize() == 1)) { return false; } if (PLure->getQuantity() == 1) { charutils::EquipItem(PChar, 0, PChar->equip[SLOT_AMMO], LOC_INVENTORY); } charutils::UpdateItem(PChar, PLure->getLocationID(), PLure->getSlotID(), -1); PChar->pushPacket(new CInventoryFinishPacket()); return true; }
bool CheckFisherLuck(CCharEntity* PChar) { if (PChar->UContainer->GetType() != UCONTAINER_EMPTY) { ShowDebug(CL_CYAN"Player cannot fish! UContainer is not empty\n" CL_RESET); return false; } CItemFish* PFish = nullptr; CItemWeapon* WeaponItem = nullptr; WeaponItem = (CItemWeapon*)PChar->getEquip(SLOT_RANGED); DSP_DEBUG_BREAK_IF(WeaponItem == nullptr); DSP_DEBUG_BREAK_IF(WeaponItem->isType(ITEM_WEAPON) == false); DSP_DEBUG_BREAK_IF(WeaponItem->getSkillType() != SKILL_FSH); uint16 RodID = WeaponItem->getID(); WeaponItem = (CItemWeapon*)PChar->getEquip(SLOT_AMMO); DSP_DEBUG_BREAK_IF(WeaponItem == nullptr); DSP_DEBUG_BREAK_IF(WeaponItem->isType(ITEM_WEAPON) == false); DSP_DEBUG_BREAK_IF(WeaponItem->getSkillType() != SKILL_FSH); uint16 LureID = WeaponItem->getID(); int32 FishingChance = WELL512::irand()%100; if (FishingChance <= 20) { const int8* Query = "SELECT " "fish.fishid," // 0 "fish.max," // 1 "fish.watertype," // 2 "fish.size," // 3 "fish.stamina," // 4 "fish.log," // 5 "fish.quest," // 6 "rod.flag " // 7 "FROM fishing_zone AS zone " "INNER JOIN fishing_rod AS rod USING (fishid) " "INNER JOIN fishing_lure AS lure USING (fishid) " "INNER JOIN fishing_fish AS fish USING (fishid) " "WHERE zone.zoneid = %u AND rod.rodid = %u AND lure.lureid = %u AND lure.luck = 0"; int32 ret = Sql_Query(SqlHandle, Query, PChar->getZone(), RodID, LureID); if( ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) { while(Sql_NextRow(SqlHandle) == SQL_SUCCESS) { // ловля предметов, необходимых для поисков uint8 logid = (uint8)Sql_GetIntData(SqlHandle,5); uint8 quest = (uint8)Sql_GetIntData(SqlHandle,6); if(logid < MAX_QUESTAREA && quest < MAX_QUESTID) { uint8 current = PChar->m_questLog[logid].current [quest/8] & (1 << (quest % 8)); uint8 complete = PChar->m_questLog[logid].complete[quest/8] & (1 << (quest % 8)); if (complete == 0 && current != 0) { PFish = new CItemFish(*itemutils::GetItemPointer(Sql_GetIntData(SqlHandle,0))); PChar->UContainer->SetType(UCONTAINER_FISHING); PChar->UContainer->SetItem(0, PFish); break; } } // TODO: ловля простых предметов } } } else { const int8* Query = "SELECT " "fish.fishid," // 0 "fish.min," // 1 "fish.max," // 2 "fish.size," // 3 "fish.stamina," // 4 "fish.watertype," // 5 "rod.flag, " // 6 "lure.luck " // 7 "FROM fishing_zone AS zone " "INNER JOIN fishing_rod AS rod USING (fishid) " "INNER JOIN fishing_lure AS lure USING (fishid) " "INNER JOIN fishing_fish AS fish USING (fishid) " "WHERE zone.zoneid = %u AND rod.rodid = %u AND lure.lureid = %u AND lure.luck != 0 " "ORDER BY luck"; int32 ret = Sql_Query(SqlHandle, Query, PChar->getZone(), RodID, LureID); if( ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) { int32 FisherLuck = 0; int32 FishingChance = WELL512::irand()%1000; while(Sql_NextRow(SqlHandle) == SQL_SUCCESS) { FisherLuck += Sql_GetIntData(SqlHandle,7); if (FishingChance <= FisherLuck) { PFish = new CItemFish(*itemutils::GetItemPointer(Sql_GetIntData(SqlHandle,0))); PChar->UContainer->SetType(UCONTAINER_FISHING); PChar->UContainer->SetItem(0, PFish); break; } } } } return (PFish != nullptr); }
bool CRangeState::CanUseRangedAttack(CBattleEntity* PTarget) { if (!PTarget) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, 0, 0, MSGBASIC_CANNOT_ATTACK_TARGET); return false; } CItemWeapon* PRanged = (CItemWeapon*)m_PEntity->getEquip(SLOT_RANGED); CItemWeapon* PAmmo = (CItemWeapon*)m_PEntity->getEquip(SLOT_AMMO); if (!(PRanged && PRanged->isType(ITEM_WEAPON) || PAmmo && PAmmo->isThrowing())) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, 0, 0, MSGBASIC_NO_RANGED_WEAPON); return false; } auto SkillType = PRanged ? PRanged->getSkillType() : PAmmo->getSkillType(); switch (SkillType) { case SKILL_THR: { // remove barrage, doesn't work here m_PEntity->StatusEffectContainer->DelStatusEffect(EFFECT_BARRAGE); break; } case SKILL_ARC: case SKILL_MRK: { PRanged = (CItemWeapon*)m_PEntity->getEquip(SLOT_AMMO); if (PRanged != nullptr && PRanged->isType(ITEM_WEAPON)) { break; } } default: { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, 0, 0, MSGBASIC_NO_RANGED_WEAPON); return false; } } if (!isFaceing(m_PEntity->loc.p, PTarget->loc.p, 40)) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, 0, 0, MSGBASIC_CANNOT_SEE); return false; } if (distance(m_PEntity->loc.p, PTarget->loc.p) > 25) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, 0, 0, MSGBASIC_TOO_FAR_AWAY); return false; } if (!m_PEntity->PAI->TargetFind->canSee(&PTarget->loc.p)) { m_errorMsg = std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, 0, 0, MSGBASIC_CANNOT_PERFORM_ACTION); return false; } return true; }
bool CheckFisherLuck(CCharEntity* PChar) { if (PChar->UContainer->GetType() != UCONTAINER_EMPTY) { ShowDebug(CL_CYAN"Player cannot fish! UContainer is not empty\n" CL_RESET); return false; } CItemFish* PFish = NULL; CItemWeapon* WeaponItem = NULL; WeaponItem = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_RANGED]); DSP_DEBUG_BREAK_IF(WeaponItem == NULL); DSP_DEBUG_BREAK_IF(WeaponItem->isType(ITEM_WEAPON) == false); DSP_DEBUG_BREAK_IF(WeaponItem->getSkillType() != SKILL_FSH); uint16 RodID = WeaponItem->getID(); WeaponItem = (CItemWeapon*)PChar->getStorage(LOC_INVENTORY)->GetItem(PChar->equip[SLOT_AMMO]); DSP_DEBUG_BREAK_IF(WeaponItem == NULL); DSP_DEBUG_BREAK_IF(WeaponItem->isType(ITEM_WEAPON) == false); DSP_DEBUG_BREAK_IF(WeaponItem->getSkillType() != SKILL_FSH); uint16 LureID = WeaponItem->getID(); int FishingChance = rand() % 100; int ListID = GridList(PChar); if (ListID == 0) { ShowDebug(CL_CYAN"Fish list not found for Zone: %u \n" CL_RESET, PChar->getZone()); } if (ListID > 0 && FishingChance <= 50) { const int8* Query = "SELECT ListID, EntityID \ FROM fishing_list \ WHERE ListID = %u \ ORDER BY ListID ASC"; int32 ret = Sql_Query(SqlHandle, Query, ListID); int RC = 0; // this will pick a random number from range 1 to max record count int RID = rand() % Sql_NumRows(SqlHandle) + 1; if (ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0) { while (Sql_NextRow(SqlHandle) == SQL_SUCCESS) { RC = RC + 1; uint32 EntityID = Sql_GetIntData(SqlHandle, 1); if (RC == RID) { // Gil if (EntityID == 0x0000FFFF) { // do not change this item number this is a place holder ID for gil PFish = new CItemFish(*itemutils::GetItemPointer(14117)); PChar->UContainer->SetType(UCONTAINER_FISHING); PChar->UContainer->SetItem(0, PFish); catchtype[0] = 2; break; } // Monster if (EntityID == 0x0001046A) { GetMobInfo(PChar); if (IsSpawned(mobid[0]) == false && mobid[0] > 0) { // do not change this item number this is a place holder ID for mobs PFish = new CItemFish(*itemutils::GetItemPointer(14117)); PChar->UContainer->SetType(UCONTAINER_FISHING); PChar->UContainer->SetItem(0, PFish); break; } } if (EntityID != 0x0000FFFF || EntityID != 0x0001046A) { // get fish or item for returned record if its not a monster or gil GetOtherInfo(EntityID); // Fish if (catchtype[0] == 0) { // will create a fish entity if the bait can be used to catch the fish if (BaitCheck(LureID, EntityID) == true) { PFish = new CItemFish(*itemutils::GetItemPointer(EntityID)); PChar->UContainer->SetType(UCONTAINER_FISHING); PChar->UContainer->SetItem(0, PFish); break; } } // Item if (catchtype[0] == 1) { PFish = new CItemFish(*itemutils::GetItemPointer(EntityID)); PChar->UContainer->SetType(UCONTAINER_FISHING); PChar->UContainer->SetItem(0, PFish); break; } } } if(RC == Sql_NumRows(SqlHandle)) { break; } } } } return (PFish != NULL); }
void CPlayerController::WeaponSkill(uint16 targid, uint16 wsid) { auto PChar = static_cast<CCharEntity*>(POwner); if (PChar->PAI->CanChangeState()) { //#TODO: put all this in weaponskill_state CWeaponSkill* PWeaponSkill = battleutils::GetWeaponSkill(wsid); if (PWeaponSkill && !charutils::hasWeaponSkill(PChar, PWeaponSkill->getID())) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 0, MSGBASIC_CANNOT_USE_WS)); return; } if (PChar->StatusEffectContainer->HasStatusEffect(EFFECT_AMNESIA)) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 0, MSGBASIC_CANNOT_USE_ANY_WS)); return; } if (PChar->health.tp < 1000) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 0, MSGBASIC_NOT_ENOUGH_TP)); return; } if (PWeaponSkill->getType() == SKILL_ARC || PWeaponSkill->getType() == SKILL_MRK) { CItemWeapon* PItem = (CItemWeapon*)PChar->getEquip(SLOT_AMMO); // before allowing ranged weapon skill... if (PItem == nullptr || !(PItem->isType(ITEM_WEAPON)) || !PChar->m_Weapons[SLOT_AMMO]->isRanged() || !PChar->m_Weapons[SLOT_RANGED]->isRanged() || PChar->equip[SLOT_AMMO] == 0) { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 0, MSGBASIC_NO_RANGED_WEAPON)); return; } } std::unique_ptr<CMessageBasicPacket> errMsg; auto PTarget = PChar->IsValidTarget(targid, battleutils::isValidSelfTargetWeaponskill(wsid) ? TARGET_SELF : TARGET_ENEMY, errMsg); if (PTarget) { if (!isFaceing(PChar->loc.p, PTarget->loc.p, 40)) { PChar->pushPacket(new CMessageBasicPacket(PChar, PTarget, 0, 0, MSGBASIC_CANNOT_SEE)); return; } CController::WeaponSkill(targid, wsid); } else if (errMsg) { PChar->pushPacket(std::move(errMsg)); } } else { PChar->pushPacket(new CMessageBasicPacket(PChar, PChar, 0, 0, MSGBASIC_UNABLE_TO_USE_WS)); } }