bool IronChain::targetsFeasible(const QList<const Player *> &targets, const Player *Self) const{ bool rec = (Sanguosha->currentRoomState()->getCurrentCardUseReason() == CardUseStruct::CARD_USE_REASON_PLAY); QList<int> sub; if (isVirtualCard()) sub = subcards; else sub << getEffectiveId(); foreach (int id, sub) { if (Self->getPile("wooden_ox").contains(id)) { rec = false; break; } } if (rec && Self->isCardLimited(this, Card::MethodUse)) return targets.length() == 0; if (Sanguosha->currentRoomState()->getCurrentCardUseReason() == CardUseStruct::CARD_USE_REASON_RESPONSE_USE) return targets.length() != 0; int total_num = 2 + Sanguosha->correctCardTarget(TargetModSkill::ExtraTarget, Self, this); if (!rec || getSkillName().contains("guhuo") || getSkillName() == "qice") //why dirty hack? return targets.length() > 0 && targets.length() <= total_num; else return targets.length() <= total_num; }
bool IronChain::targetsFeasible(const QList<const Player *> &targets, const Player *Self) const{ //saffah //铁索连环的目标是否合法? if(getSkillName() == "guhuo" or getSkillName() == "lianwang")//如果这张铁索是通过蛊惑或者联网转化的 return targets.length() == 1 || targets.length() == 2; //那么要选择1个或两个目标 else //如果不是 return targets.length() <= 2; //那么不超过两个目标都可以 } //不指定目标→重铸
bool IronChain::targetsFeasible(const QList<const Player *> &targets, const Player *Self) const{ if (Self->isCardLimited(this, Card::MethodUse)) return targets.length() == 0; if (getSkillName() == "guhuo" || getSkillName() == "qice") return targets.length() == 1 || targets.length() == 2; else return targets.length() <= 2; }
bool IronChain::targetsFeasible(const QList<const Player *> &targets, const Player *Self) const{ if (Self->isCardLimited(this, Card::MethodUse)) return targets.length() == 0; int total_num = 2 + Sanguosha->correctCardTarget(TargetModSkill::ExtraTarget, Self, this); if (getSkillName().contains("guhuo") || getSkillName() == "qice") return targets.length() > 0 && targets.length() <= total_num; else return targets.length() <= total_num; }
bool IronChain::targetsFeasible(const QList<const Player *> &targets, const Player *Self) const{ if (Self->isCardLimited(this, Card::MethodUse)) return targets.length() == 0; if (Sanguosha->currentRoomState()->getCurrentCardUseReason() == CardUseStruct::CARD_USE_REASON_RESPONSE_USE) return targets.length() != 0; int total_num = 2 + Sanguosha->correctCardTarget(TargetModSkill::ExtraTarget, Self, this); if (getSkillName().contains("guhuo") || getSkillName() == "qice") return targets.length() > 0 && targets.length() <= total_num; else return targets.length() <= total_num; }
void DelayedTrick::onEffect(const CardEffectStruct &effect) const { Room *room = effect.to->getRoom(); CardMoveReason reason(CardMoveReason::S_REASON_USE, effect.to->objectName(), getSkillName(), QString()); room->moveCardTo(this, NULL, Player::PlaceTable, reason, true); LogMessage log; log.from = effect.to; log.type = "#DelayedTrick"; log.arg = effect.card->objectName(); room->sendLog(log); JudgeStruct judge_struct = judge; judge_struct.who = effect.to; room->judge(judge_struct); if (judge_struct.negative == judge_struct.isBad()) { if (effect.to->isAlive()) takeEffect(effect.to); if (room->getCardOwner(getEffectiveId()) == NULL) { CardMoveReason reason(CardMoveReason::S_REASON_NATURAL_ENTER, QString()); room->throwCard(this, reason, NULL); } } else if (movable) { onNullified(effect.to); } else if (returnable && effect.to->isAlive()) { if (room->getCardOwner(getEffectiveId()) == NULL) { if (isVirtualCard()) { Card *delayTrick = Sanguosha->cloneCard(objectName()); WrappedCard *vs_card = Sanguosha->getWrappedCard(getEffectiveId()); vs_card->setSkillName(getSkillName()); vs_card->takeOver(delayTrick); room->broadcastUpdateCard(room->getAlivePlayers(), vs_card->getId(), vs_card); } CardsMoveStruct move; move.card_ids << getEffectiveId(); move.to = effect.to; move.to_place = Player::PlaceDelayedTrick; room->moveCardsAtomic(move, true); } } else { if (room->getCardOwner(getEffectiveId()) == NULL) { CardMoveReason reason(CardMoveReason::S_REASON_NATURAL_ENTER, QString()); room->throwCard(this, reason, NULL); } } }
void DelayedTrick::onUse(Room *room, const CardUseStruct &card_use) const { CardUseStruct use = card_use; WrappedCard *wrapped = Sanguosha->getWrappedCard(getEffectiveId()); use.card = wrapped; LogMessage log; log.from = use.from; log.to = use.to; log.type = "#UseCard"; log.card_str = toString(); room->sendLog(log); QVariant data = QVariant::fromValue(use); RoomThread *thread = room->getThread(); thread->trigger(PreCardUsed, room, data); //CardMoveReason reason(CardMoveReason::S_REASON_USE, use.from->objectName(), use.to.first()->objectName(), getSkillName(), QString()); //room->moveCardTo(this, use.from, use.to.first(), Player::PlaceDelayedTrick, reason, true); CardMoveReason reason(CardMoveReason::S_REASON_USE, use.from->objectName(), QString(), card_use.card->getSkillName(), QString()); CardsMoveStruct move(card_use.card->getEffectiveId(), NULL, Player::PlaceTable, reason); room->moveCardsAtomic(move, true); //show hidden after move Event to avoid filter card use.from->showHiddenSkill(getSkillName()); thread->trigger(CardUsed, room, data); thread->trigger(CardFinished, room, data); }
void DelayedTrick::onEffect(const CardEffectStruct &effect) const { Room *room = effect.to->getRoom(); CardMoveReason reason(CardMoveReason::S_REASON_USE, effect.to->objectName(), getSkillName(), QString()); room->moveCardTo(this, NULL, Player::PlaceTable, reason, true); LogMessage log; log.from = effect.to; log.type = "#DelayedTrick"; log.arg = effect.card->objectName(); room->sendLog(log); JudgeStruct judge_struct = judge; judge_struct.who = effect.to; room->judge(judge_struct); if (judge_struct.isBad()) { takeEffect(effect.to); if (room->getCardOwner(getEffectiveId()) == NULL) { CardMoveReason reason(CardMoveReason::S_REASON_NATURAL_ENTER, QString()); room->throwCard(this, reason, NULL); } } else if (movable) { onNullified(effect.to); } else { if (room->getCardOwner(getEffectiveId()) == NULL) { CardMoveReason reason(CardMoveReason::S_REASON_NATURAL_ENTER, QString()); room->throwCard(this, reason, NULL); } } }
void LijianCard::use(Room *room, ServerPlayer *, QList<ServerPlayer *> &targets) const{ ServerPlayer *to = targets.at(0); ServerPlayer *from = targets.at(1); Duel *duel = new Duel(Card::NoSuit, 0); duel->setCancelable(duel_cancelable); duel->setSkillName(QString("_%1").arg(getSkillName())); if (!from->isCardLimited(duel, Card::MethodUse) && !from->isProhibited(to, duel)) room->useCard(CardUseStruct(duel, from, to)); else delete duel; }
void Slash::onUse(Room *room, const CardUseStruct &card_use) const{ ServerPlayer *player = card_use.from; if(player->getPhase() == Player::Play && player->getMark("SlashCount") >= 1 && player->hasSkill("paoxiao") && getSkillName().isEmpty()) room->playSkillEffect("paoxiao", player->getGeneral2Name() == "zombie" ? 3 : qrand() % 2 + 1); else if(player->getPhase() == Player::Play && player->hasSkill("huxiao") && player->getMark("huxiao") > 0) { bool toSunquan = false; foreach(ServerPlayer *p, card_use.to) if(p->getGeneralName().contains("sunquan")) { toSunquan = true; break; } if(toSunquan) room->playSkillEffect("huxiao", 3); else room->playSkillEffect("huxiao", 2); }
bool Slash::targetFilter(const QList<const Player *> &targets, const Player *to_select, const Player *Self) const{ int slash_targets = 1; if(Self->hasWeapon("halberd") && Self->isLastHandCard(this)){ slash_targets = 3; } bool distance_limit = true; if(Self->hasFlag("tianyi_success")){ distance_limit = false; slash_targets ++; } if(Self->hasSkill("lihuo") && inherits("FireSlash")) slash_targets ++; if(Self->hasSkill("tieji_p") && Self->getWeapon() && Self->getWeapon()->getRange() >= 3){ slash_targets ++ ; } if(Self->hasSkill("shenji") && Self->getWeapon() == NULL) slash_targets = 3; if(targets.length() >= slash_targets) return false; if(inherits("WushenSlash")){ distance_limit = false; } if(getSkillName() == "wusheng" && Self->isSkillEnhance("wusheng", 1)){ int card_id = getSubcards().first() ; if(Sanguosha->getCard(card_id)->getSuit() == Card::Heart) distance_limit = false ; } return Self->canSlash(to_select, distance_limit); }
bool IronChain::targetsFeasible(const QList<const ClientPlayer *> &targets) const{ if(getSkillName() == "guhuo") return targets.length() == 1 || targets.length() == 2; else return targets.length() <= 2; }
void DelayedTrick::use(Room *room, ServerPlayer *source, QList<ServerPlayer *> &targets) const { QStringList nullified_list = room->getTag("CardUseNullifiedList").toStringList(); bool all_nullified = nullified_list.contains("_ALL_TARGETS"); if (all_nullified || targets.isEmpty() || targets.first()->isDead()) { if (movable) { onNullified(source); if (room->getCardOwner(getEffectiveId()) != source) return; } CardMoveReason reason(CardMoveReason::S_REASON_USE, source->objectName(), QString(), getSkillName(), QString()); //room->moveCardTo(this, room->getCardOwner(getEffectiveId()), NULL, Player::DiscardPile, reason, true); room->moveCardTo(this, source, NULL, Player::DiscardPile, reason, true); } else { CardMoveReason reason(CardMoveReason::S_REASON_USE, source->objectName(), targets.first()->objectName(), getSkillName(), QString()); room->moveCardTo(this, source, targets.first(), Player::PlaceDelayedTrick, reason, true); } }
bool IronChain::targetsFeasible(const QList<const Player *> &targets, const Player *Self) const{ if(getSkillName() == "guhuo" || getSkillName() == "qice") return targets.length() == 1 || targets.length() == 2; else return targets.length() <= 2; }
std::string Item::getDescription(const ItemType& it, int32_t lookDistance, const Item* item /*= NULL*/, int32_t subType /*= -1*/, bool addArticle /*= true*/) { std::ostringstream s; s << getNameDescription(it, item, subType, addArticle); if (item) { subType = item->getSubType(); } if (it.isRune()) { if (!it.runeSpellName.empty()) { s << " (\"" << it.runeSpellName << "\")"; } if (it.runeLevel > 0 || it.runeMagLevel > 0) { int32_t tmpSubType = subType; if (item) { tmpSubType = item->getSubType(); } s << ". " << (it.stackable && tmpSubType > 1 ? "They" : "It") << " can only be used with"; if (it.runeLevel > 0) { s << " level " << it.runeLevel; } if (it.runeMagLevel > 0) { if (it.runeLevel > 0) { s << " and"; } s << " magic level " << it.runeMagLevel; } s << " or higher"; } } else if (it.weaponType != WEAPON_NONE) { if (it.weaponType == WEAPON_DIST && it.ammoType != AMMO_NONE) { s << " (Range:" << it.shootRange; if (it.attack != 0) { s << ", Atk " << std::showpos << it.attack << std::noshowpos; } if (it.hitChance != 0) { s << ", Hit% " << std::showpos << it.hitChance << std::noshowpos; } s << ")"; } else if (it.weaponType != WEAPON_AMMO) { bool begin = true; if (it.attack != 0) { begin = false; s << " (Atk:" << it.attack; if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { s << " physical + " << it.abilities->elementDamage << " " << getCombatName(it.abilities->elementType); } } if (it.defense != 0 || it.extraDefense != 0) { if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "Def:" << it.defense; if (it.extraDefense != 0 || (item && item->getExtraDefense() != 0)) { s << " " << std::showpos << it.extraDefense << std::noshowpos; } } if (it.abilities) { for (uint16_t i = SKILL_FIRST; i <= SKILL_LAST; i++) { if (!it.abilities->skills[i]) { continue; } if (begin) { begin = false; s << " ("; } else { s << ", "; } s << getSkillName(i) << " " << std::showpos << it.abilities->skills[i] << std::noshowpos; } if (it.abilities->stats[STAT_MAGICPOINTS]) { if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "magic level " << std::showpos << it.abilities->stats[STAT_MAGICPOINTS] << std::noshowpos; } int32_t show = it.abilities->absorbPercent[COMBAT_FIRST]; for (uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_COUNT; ++i) { if (it.abilities->absorbPercent[i] == show) { continue; } show = 0; break; } if (!show) { bool tmp = true; for (uint32_t i = COMBAT_FIRST; i <= COMBAT_COUNT; i++) { if (!it.abilities->absorbPercent[i]) { continue; } if (tmp) { tmp = false; if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "protection "; } else { s << ", "; } s << getCombatName(indexToCombatType(i)) << " " << std::showpos << it.abilities->absorbPercent[i] << std::noshowpos << "%"; } } else { if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "protection all " << std::showpos << show << std::noshowpos << "%"; } if (it.abilities->speed) { if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos; } } if (!begin) { s << ")"; } } } else if (it.armor || (item && item->getArmor()) || it.showAttributes) { int32_t tmp = it.armor; if (item) { tmp = item->getArmor(); } bool begin = true; if (tmp != 0) { s << " (Arm:" << tmp; begin = false; } if (it.abilities) { for (uint16_t i = SKILL_FIRST; i <= SKILL_LAST; i++) { if (!it.abilities->skills[i]) { continue; } if (begin) { begin = false; s << " ("; } else { s << ", "; } s << getSkillName(i) << " " << std::showpos << it.abilities->skills[i] << std::noshowpos; } if (it.abilities->stats[STAT_MAGICPOINTS]) { if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "magic level " << std::showpos << it.abilities->stats[STAT_MAGICPOINTS] << std::noshowpos; } int32_t show = it.abilities->absorbPercent[COMBAT_FIRST]; for (uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_COUNT; ++i) { if (it.abilities->absorbPercent[i] == show) { continue; } show = 0; break; } if (!show) { bool protectionBegin = true; for (uint32_t i = COMBAT_FIRST; i <= COMBAT_COUNT; i++) { if (!it.abilities->absorbPercent[i]) { continue; } if (protectionBegin) { protectionBegin = false; if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "protection "; } else { s << ", "; } s << getCombatName(indexToCombatType(i)) << " " << std::showpos << it.abilities->absorbPercent[i] << std::noshowpos << "%"; } } else { if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "protection all " << std::showpos << show << std::noshowpos << "%"; } if (it.abilities->speed) { if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos; } } if (!begin) { s << ")"; } } else if (it.isContainer()) { s << " (Vol:" << (int32_t)it.maxItems << ")"; } else { bool found = true; if (it.abilities) { if (it.abilities->speed > 0) { s << " (speed " << std::showpos << (it.abilities->speed / 2) << std::noshowpos << ")"; } else if (it.abilities && hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions)) { s << " (hard drinking)"; } else if (it.abilities->invisible) { s << " (invisibility)"; } else if (it.abilities->regeneration) { s << " (faster regeneration)"; } else if (it.abilities->manaShield) { s << " (mana shield)"; } else { found = false; } } else { found = false; } if (!found) { if (it.isKey()) { s << " (Key:" << (item ? (int32_t)item->getActionId() : 0) << ")"; } else if (it.isFluidContainer()) { if (subType > 0) { const std::string& itemName = items[subType].name; s << " of " << (itemName.length() ? itemName : "unknown"); } else { s << ". It is empty"; } } else if (it.isSplash()) { s << " of "; if (subType > 0 && items[subType].name.length()) { s << items[subType].name; } else { s << "unknown"; } } else if (it.allowDistRead && it.id != 7369 && it.id != 7370 && it.id != 7371) { s << "." << std::endl; if (lookDistance <= 4) { if (item && !item->getText().empty()) { if (item->getWriter().length()) { s << item->getWriter() << " wrote"; time_t date = item->getDate(); if (date > 0) { s << " on " << formatDateShort(date); } s << ": "; } else { s << "You read: "; } std::string outtext; if (utf8ToLatin1(item->getText().c_str(), outtext)) { s << outtext; } else { s << item->getText(); } } else { s << "Nothing is written on it"; } } else { s << "You are too far away to read it"; } } else if (it.levelDoor && item && item->getActionId() >= (int32_t)it.levelDoor) { s << " for level " << item->getActionId() - it.levelDoor; } } } if (it.showCharges) { s << " that has " << subType << " charge" << (subType != 1 ? "s" : "") << " left"; } if (it.showDuration) { if (item && item->hasAttribute(ATTR_ITEM_DURATION)) { int32_t duration = item->getDuration() / 1000; s << " that will expire in "; if (duration >= 86400) { uint16_t days = duration / 86400; uint16_t hours = (duration % 86400) / 3600; s << days << " day" << (days != 1 ? "s" : ""); if (hours > 0) { s << " and " << hours << " hour" << (hours != 1 ? "s" : ""); } } else if (duration >= 3600) { uint16_t hours = duration / 3600; uint16_t minutes = (duration % 3600) / 60; s << hours << " hour" << (hours != 1 ? "s" : ""); if (minutes > 0) { s << " and " << minutes << " minute" << (minutes != 1 ? "s" : ""); } } else if (duration >= 60) { uint16_t minutes = duration / 60; s << minutes << " minute" << (minutes != 1 ? "s" : ""); uint16_t seconds = duration % 60; if (seconds > 0) { s << " and " << seconds << " second" << (seconds != 1 ? "s" : ""); } } else { s << duration << " second" << (duration != 1 ? "s" : ""); } } else { s << " that is brand-new"; } } if (!it.allowDistRead || item->getText().empty() || (it.id >= 7369 && it.id <= 7371)) { s << "."; } if (it.wieldInfo != 0) { s << std::endl << "It can only be wielded properly by "; if (it.wieldInfo & WIELDINFO_PREMIUM) { s << "premium "; } if (it.wieldInfo & WIELDINFO_VOCREQ) { s << it.vocationString; } else { s << "players"; } if (it.wieldInfo & WIELDINFO_LEVEL) { s << " of level " << (int32_t)it.minReqLevel << " or higher"; } if (it.wieldInfo & WIELDINFO_MAGLV) { if (it.wieldInfo & WIELDINFO_LEVEL) { s << " and"; } else { s << " of"; } s << " magic level " << (int32_t)it.minReqMagicLevel << " or higher"; } s << "."; } if (lookDistance <= 1) { double weight = (item == NULL ? it.weight : item->getWeight()); if (weight > 0 && it.pickupable) { int32_t count = weight / it.weight; s << std::endl << getWeightDescription(it, weight, count); } } if (item && !item->getSpecialDescription().empty()) { s << std::endl << item->getSpecialDescription(); } else if (it.description.length() && lookDistance <= 1) { s << std::endl << it.description; } if (it.allowDistRead && it.id >= 7369 && it.id <= 7371 && !item->getText().empty()) { s << std::endl << item->getText(); } return s.str(); }
std::string Item::getDescription(const ItemType& it, int32_t lookDistance, const Item* item/* = NULL*/, int32_t subType/* = -1*/, bool addArticle/* = true*/) { std::stringstream s; s << getNameDescription(it, item, subType, addArticle); if(item) subType = item->getSubType(); bool dot = true; if(it.isRune()) { if(!it.runeSpellName.empty()) s << "(\"" << it.runeSpellName << "\")"; if(it.runeLevel > 0 || it.runeMagLevel > 0 || (it.vocationString != "" && it.wieldInfo == 0)) { s << "." << std::endl << "It can only be used"; if(it.vocationString != "" && it.wieldInfo == 0) s << " by " << it.vocationString; bool begin = true; if(g_config.getBool(ConfigManager::USE_RUNE_REQUIREMENTS) && it.runeLevel > 0) { begin = false; s << " with level " << it.runeLevel; } if(g_config.getBool(ConfigManager::USE_RUNE_REQUIREMENTS) && it.runeMagLevel > 0) { begin = false; s << " " << (begin ? "with" : "and") << " magic level " << it.runeMagLevel; } if(g_config.getBool(ConfigManager::USE_RUNE_REQUIREMENTS) && !begin) s << " or higher"; } } else if(it.weaponType != WEAPON_NONE) { bool begin = true; if(it.weaponType == WEAPON_DIST && it.ammoType != AMMO_NONE) { begin = false; s << " (Range:" << int32_t(item ? item->getShootRange() : it.shootRange); if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack()))) { s << ", Atk " << std::showpos << int32_t(item ? item->getAttack() : it.attack); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; } if(it.hitChance != -1 || (item && item->getHitChance() != -1)) s << ", Hit% " << std::showpos << (item ? item->getHitChance() : it.hitChance) << std::noshowpos; if(it.attackSpeed || (item && item->getAttackSpeed())) s << ", AS: " << (item ? item->getAttackSpeed() : it.attackSpeed); } else if(it.weaponType != WEAPON_AMMO && it.weaponType != WEAPON_WAND) { if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack()))) { begin = false; s << " (Atk:"; if(it.hasAbilities() && it.abilities->elementType != COMBAT_NONE) { s << std::max((int32_t)0, int32_t((item ? item->getAttack() : it.attack) - it.abilities->elementDamage)); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; s << " physical + " << it.abilities->elementDamage << " " << getCombatName(it.abilities->elementType); } else { s << int32_t(item ? item->getAttack() : it.attack); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; } } if(it.defense || it.extraDefense || (item && (item->getDefense() || item->getExtraDefense()))) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Def:" << int32_t(item ? item->getDefense() : it.defense); if(it.extraDefense || (item && item->getExtraDefense())) s << " " << std::showpos << int32_t(item ? item->getExtraDefense() : it.extraDefense) << std::noshowpos; } } if(it.attackSpeed || (item && item->getAttackSpeed())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "AS: " << (item ? item->getAttackSpeed() : it.attackSpeed); } if(it.hasAbilities()) { for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { if(!it.abilities->skills[i]) continue; if(begin) { begin = false; s << " ("; } else s << ", "; s << getSkillName(i) << " " << std::showpos << (int32_t)it.abilities->skills[i] << std::noshowpos; } if(it.abilities->stats[STAT_MAGICLEVEL]) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "magic level " << std::showpos << (int32_t)it.abilities->stats[STAT_MAGICLEVEL] << std::noshowpos; } int32_t show = it.abilities->absorb[COMBAT_ALL]; if(!show) { bool tmp = true; for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1) { if(!it.abilities->absorb[i]) continue; if(tmp) { tmp = false; if(begin) { begin = false; s << " ("; } else s << ", "; s << "protection "; } else s << ", "; s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities->absorb[i] << std::noshowpos << "%"; } } else { if(begin) { begin = false; s << " ("; } else s << ", "; s << "protection all " << std::showpos << show << std::noshowpos << "%"; } show = it.abilities->fieldAbsorb[COMBAT_ALL]; if(!show) { bool tmp = true; for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1) { if(!it.abilities->fieldAbsorb[i]) continue; if(tmp) { tmp = false; if(begin) { begin = false; s << " ("; } else s << ", "; s << "protection "; } else s << ", "; s << getCombatName((CombatType_t)i) << " field " << std::showpos << it.abilities->absorb[i] << std::noshowpos << "%"; } } else { if(begin) { begin = false; s << " ("; } else s << ", "; s << "protection all fields " << std::showpos << show << std::noshowpos << "%"; } show = it.abilities->reflect[REFLECT_CHANCE][COMBAT_ALL]; if(!show) { bool tmp = true; for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1) { if(!it.abilities->reflect[REFLECT_CHANCE][i] || !it.abilities->reflect[REFLECT_PERCENT][i]) continue; if(tmp) { tmp = false; if(begin) { begin = false; s << " ("; } else s << ", "; s << "reflect: "; } else s << ", "; s << it.abilities->reflect[REFLECT_CHANCE][i] << "% for "; if(it.abilities->reflect[REFLECT_PERCENT][i] > 99) s << "whole"; else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 75) s << "huge"; else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 50) s << "medium"; else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 25) s << "small"; else s << "tiny"; s << getCombatName((CombatType_t)i); } if(!tmp) s << " damage"; } else { if(begin) { begin = false; s << " ("; } else s << ", "; int32_t tmp = it.abilities->reflect[REFLECT_PERCENT][COMBAT_ALL]; s << "reflect: " << show << "% for "; if(tmp) { if(tmp > 99) s << "whole"; else if(tmp >= 75) s << "huge"; else if(tmp >= 50) s << "medium"; else if(tmp >= 25) s << "small"; else s << "tiny"; } else s << "mixed"; s << " damage"; } if(it.abilities->speed) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos; } if(it.abilities->invisible) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "invisibility"; } if(it.abilities->regeneration) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "faster regeneration"; } if(it.abilities->manaShield) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "mana shield"; } if(hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions)) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "hard drinking"; } } if(it.dualWield || (item && item->isDualWield())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "dual wielding"; } if(!begin) s << ")"; } else if(it.armor || (item && item->getArmor()) || it.showAttributes) { int32_t tmp = it.armor; if(item) tmp = item->getArmor(); bool begin = true; if(tmp) { s << " (Arm:" << tmp; begin = false; } if(it.hasAbilities()) { for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { if(!it.abilities->skills[i]) continue; if(begin) { begin = false; s << " ("; } else s << ", "; s << getSkillName(i) << " " << std::showpos << (int32_t)it.abilities->skills[i] << std::noshowpos; } if(it.abilities->stats[STAT_MAGICLEVEL]) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "magic level " << std::showpos << (int32_t)it.abilities->stats[STAT_MAGICLEVEL] << std::noshowpos; } int32_t show = it.abilities->absorb[COMBAT_ALL]; if(!show) { bool tmp = true; for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1) { if(!it.abilities->absorb[i]) continue; if(tmp) { tmp = false; if(begin) { begin = false; s << " ("; } else s << ", "; s << "protection "; } else s << ", "; s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities->absorb[i] << std::noshowpos << "%"; } } else { if(begin) { begin = false; s << " ("; } else s << ", "; s << "protection all " << std::showpos << show << std::noshowpos << "%"; } show = it.abilities->reflect[REFLECT_CHANCE][COMBAT_ALL]; if(!show) { bool tmp = true; for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i <<= 1) { if(!it.abilities->reflect[REFLECT_CHANCE][i] || !it.abilities->reflect[REFLECT_PERCENT][i]) continue; if(tmp) { tmp = false; if(begin) { begin = false; s << " ("; } else s << ", "; s << "reflect: "; } else s << ", "; s << it.abilities->reflect[REFLECT_CHANCE][i] << "% for "; if(it.abilities->reflect[REFLECT_PERCENT][i] > 99) s << "whole"; else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 75) s << "huge"; else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 50) s << "medium"; else if(it.abilities->reflect[REFLECT_PERCENT][i] >= 25) s << "small"; else s << "tiny"; s << getCombatName((CombatType_t)i); } if(!tmp) s << " damage"; } else { if(begin) { begin = false; s << " ("; } else s << ", "; int32_t tmp = it.abilities->reflect[REFLECT_PERCENT][COMBAT_ALL]; s << "reflect: " << show << "% for "; if(tmp) { if(tmp > 99) s << "whole"; else if(tmp >= 75) s << "huge"; else if(tmp >= 50) s << "medium"; else if(tmp >= 25) s << "small"; else s << "tiny"; } else s << "mixed"; s << " damage"; } if(it.abilities->speed) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "speed " << std::showpos << (int32_t)(it.abilities->speed / 2) << std::noshowpos; } if(it.abilities->invisible) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "invisibility"; } if(it.abilities->regeneration) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "faster regeneration"; } if(it.abilities->manaShield) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "mana shield"; } if(hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions)) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "hard drinking"; } if(!begin) s << ")"; } } else if(it.isContainer()) s << " (Vol:" << (int32_t)it.maxItems << ")"; else if(it.isKey()) s << " (Key:" << (item ? (int32_t)item->getActionId() : 0) << ")"; else if(it.isFluidContainer()) { if(subType > 0) s << " of " << (items[subType].name.length() ? items[subType].name : "unknown"); else s << ". It is empty"; } else if(it.isSplash()) { s << " of "; if(subType > 0 && items[subType].name.length()) s << items[subType].name; else s << "unknown"; } else if(it.allowDistRead) { s << "." << std::endl; if(item && !item->getText().empty()) { if(lookDistance <= 4) { if(!item->getWriter().empty()) { s << item->getWriter() << " wrote"; time_t date = item->getDate(); if(date > 0) s << " on " << formatDate(date); s << ": "; } else s << "You read: "; std::string text = item->getText(); s << text; char end = *text.rbegin(); if(end == '?' || end == '!' || end == '.') dot = false; } else s << "You are too far away to read it"; } else s << "Nothing is written on it"; } else if(it.levelDoor && item && item->getActionId() >= (int32_t)it.levelDoor && item->getActionId() <= ((int32_t)it.levelDoor + g_config.getNumber(ConfigManager::MAXIMUM_DOOR_LEVEL))) s << " for level " << item->getActionId() - it.levelDoor; if(it.showCharges) s << " that has " << subType << " charge" << (subType != 1 ? "s" : "") << " left"; if(it.showDuration) { if(item && item->hasIntegerAttribute("duration")) { int32_t duration = item->getDuration() / 1000; s << " that will expire in "; if(duration >= 86400) { uint16_t days = duration / 86400; uint16_t hours = (duration % 86400) / 3600; s << days << " day" << (days > 1 ? "s" : ""); if(hours > 0) s << " and " << hours << " hour" << (hours > 1 ? "s" : ""); } else if(duration >= 3600) { uint16_t hours = duration / 3600; uint16_t minutes = (duration % 3600) / 60; s << hours << " hour" << (hours > 1 ? "s" : ""); if(hours > 0) s << " and " << minutes << " minute" << (minutes > 1 ? "s" : ""); } else if(duration >= 60) { uint16_t minutes = duration / 60; uint16_t seconds = duration % 60; s << minutes << " minute" << (minutes > 1 ? "s" : ""); if(seconds > 0) s << " and " << seconds << " second" << (seconds > 1 ? "s" : ""); } else s << duration << " second" << (duration > 1 ? "s" : ""); } else s << " that is brand-new"; } if(dot) s << "."; if(it.wieldInfo) { s << std::endl << "It can only be wielded properly by "; if(it.wieldInfo & WIELDINFO_PREMIUM) s << "premium "; if(it.wieldInfo & WIELDINFO_VOCREQ) s << it.vocationString; else s << "players"; if(it.wieldInfo & WIELDINFO_LEVEL) s << " of level " << (int32_t)it.minReqLevel << " or higher"; if(it.wieldInfo & WIELDINFO_MAGLV) { if(it.wieldInfo & WIELDINFO_LEVEL) s << " and"; else s << " of"; s << " magic level " << (int32_t)it.minReqMagicLevel << " or higher"; } s << "."; } if(lookDistance <= 1 && it.pickupable) { std::string tmp; if(!item) tmp = getWeightDescription(it.weight, it.stackable && it.showCount, subType); else tmp = item->getWeightDescription(); if(!tmp.empty()) s << std::endl << tmp; } if(item && !item->getSpecialDescription().empty()) s << std::endl << item->getSpecialDescription(); else if(!it.description.empty() && lookDistance <= 1) s << std::endl << it.description; std::string str = s.str(); if(str.find("|PLAYERNAME|") != std::string::npos) { std::string tmp = "You"; if(item) { if(const Player* player = item->getHoldingPlayer()) tmp = player->getName(); } replaceString(str, "|PLAYERNAME|", tmp); } if(str.find("|TIME|") != std::string::npos || str.find("|DATE|") != std::string::npos || str.find( "|DAY|") != std::string::npos || str.find("|MONTH|") != std::string::npos || str.find( "|YEAR|") != std::string::npos || str.find("|HOUR|") != std::string::npos || str.find( "|MINUTES|") != std::string::npos || str.find("|SECONDS|") != std::string::npos || str.find("|WEEKDAY|") != std::string::npos || str.find("|YEARDAY|") != std::string::npos) { time_t now = time(NULL); tm* ts = localtime(&now); std::stringstream ss; ss << ts->tm_sec; replaceString(str, "|SECONDS|", ss.str()); ss.str(""); ss << ts->tm_min; replaceString(str, "|MINUTES|", ss.str()); ss.str(""); ss << ts->tm_hour; replaceString(str, "|HOUR|", ss.str()); ss.str(""); ss << ts->tm_mday; replaceString(str, "|DAY|", ss.str()); ss.str(""); ss << (ts->tm_mon + 1); replaceString(str, "|MONTH|", ss.str()); ss.str(""); ss << (ts->tm_year + 1900); replaceString(str, "|YEAR|", ss.str()); ss.str(""); ss << ts->tm_wday; replaceString(str, "|WEEKDAY|", ss.str()); ss.str(""); ss << ts->tm_yday; replaceString(str, "|YEARDAY|", ss.str()); ss.str(""); ss << ts->tm_hour << ":" << ts->tm_min << ":" << ts->tm_sec; replaceString(str, "|TIME|", ss.str()); ss.str(""); replaceString(str, "|DATE|", formatDateEx(now)); } return str; }
void DelayedTrick::onNullified(ServerPlayer *target) const { Room *room = target->getRoom(); RoomThread *thread = room->getThread(); if (movable) { QList<ServerPlayer *> players = room->getOtherPlayers(target); players << target; ServerPlayer *next = NULL; //next meaning this next one bool next2next = false; //it's meaning another next(a second next) is necessary foreach (ServerPlayer *player, players) { if (player->containsTrick(objectName())) continue; const ProhibitSkill *skill = room->isProhibited(target, player, this); if (skill) { LogMessage log; log.type = "#SkillAvoid"; log.from = player; log.arg = skill->objectName(); log.arg2 = objectName(); room->sendLog(log); room->broadcastSkillInvoke(skill->objectName()); continue; } next = player; CardMoveReason reason(CardMoveReason::S_REASON_TRANSFER, target->objectName(), QString(), getSkillName(), QString()); room->moveCardTo(this, target, player, Player::PlaceDelayedTrick, reason, true); if (target == player) break; CardUseStruct use; use.from = NULL; use.to << player; use.card = this; QVariant data = QVariant::fromValue(use); thread->trigger(TargetConfirming, room, data); CardUseStruct new_use = data.value<CardUseStruct>(); if (new_use.to.isEmpty()) { next2next = true; break; } thread->trigger(TargetConfirmed, room, data); break; } //case:stop. if (!next) { CardMoveReason reason(CardMoveReason::S_REASON_TRANSFER, target->objectName(), QString(), getSkillName(), QString()); room->moveCardTo(this, target, target, Player::PlaceDelayedTrick, reason, true); } //case: next2next if (next && next2next) onNullified(next); } else {
void IronChain::use(Room *room, ServerPlayer *source, const QList<ServerPlayer *> &targets) const{ if(getSkillName() != "lianhuan") source->playCardEffect("@tiesuo"); TrickCard::use(room, source, targets); }
std::string Item::getDescription(const ItemType& it, int32_t lookDistance, const Item* item/* = NULL*/, int32_t subType/* = -1*/, bool addArticle/* = true*/) { std::stringstream s; s << getNameDescription(it, item, subType, addArticle); if(item) subType = item->getSubType(); bool dot = true; if(it.isRune()) { s << "("; if(!it.runeSpellName.empty()) s << "\"" << it.runeSpellName << "\", "; s << "Charges:" << subType << ")"; if(it.runeLevel > 0 || it.runeMagLevel > 0 || (it.vocationString != "" && it.wieldInfo == 0)) { s << "." << std::endl << "It can only be used"; if(it.vocationString != "" && it.wieldInfo == 0) s << " by " << it.vocationString; bool begin = true; if(it.runeLevel > 0) { begin = false; s << " with level " << it.runeLevel; } if(it.runeMagLevel > 0) { begin = false; s << " " << (begin ? "with" : "and") << " magic level " << it.runeMagLevel; } if(!begin) s << " or higher"; } } else if(it.weaponType != WEAPON_NONE) { bool begin = true; if(it.weaponType == WEAPON_DIST && it.ammoType != AMMO_NONE) { begin = false; s << " (Range:" << int32_t(item ? item->getShootRange() : it.shootRange); if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack()))) { s << ", Atk " << std::showpos << int32_t(item ? item->getAttack() : it.attack); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; } if(it.hitChance != -1 || (item && item->getHitChance() != -1)) s << ", Hit% " << std::showpos << (item ? item->getHitChance() : it.hitChance) << std::noshowpos; } else if(it.weaponType != WEAPON_AMMO && it.weaponType != WEAPON_WAND) { if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack()))) { begin = false; s << " (Atk:"; if(it.abilities.elementType != COMBAT_NONE && it.decayTo < 1) { s << std::max((int32_t)0, int32_t((item ? item->getAttack() : it.attack) - it.abilities.elementDamage)); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; s << " physical + " << it.abilities.elementDamage << " " << getCombatName(it.abilities.elementType); } else { s << int32_t(item ? item->getAttack() : it.attack); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; } } if(it.defense || it.extraDefense || (item && (item->getDefense() || item->getExtraDefense()))) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Def:" << int32_t(item ? item->getDefense() : it.defense); if(it.extraDefense || (item && item->getExtraDefense())) s << " " << std::showpos << int32_t(item ? item->getExtraDefense() : it.extraDefense) << std::noshowpos; } } for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; i++) { if(!it.abilities.skills[i]) continue; if(begin) { begin = false; s << " ("; } else s << ", "; s << getSkillName(i) << " " << std::showpos << (int32_t)it.abilities.skills[i] << std::noshowpos; } if(it.abilities.stats[STAT_MAGICLEVEL]) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "magic level " << std::showpos << (int32_t)it.abilities.stats[STAT_MAGICLEVEL] << std::noshowpos; } int32_t show = it.abilities.absorb[COMBAT_FIRST]; for(uint32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i++) { if(it.abilities.absorb[i] == show) continue; show = 0; break; } // TODO: update to the latest (from below) if(!show) { bool tmp = true; for(uint32_t i = COMBAT_FIRST; i <= COMBAT_LAST; i++) { if(!it.abilities.absorb[i]) continue; if(tmp) { if(begin) { begin = false; s << " ("; } else s << ", "; tmp = false; s << "protection "; } else s << ", "; s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities.absorb[i] << std::noshowpos << "%"; } } else { if(begin) { begin = false; s << " ("; } else s << ", "; s << "protection all " << std::showpos << show << std::noshowpos << "%"; } if(it.abilities.speed) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "speed " << std::showpos << (int32_t)(it.abilities.speed / 2) << std::noshowpos; } if(it.dualWield || (item && item->isDualWield())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "dual wielding"; } if(!begin) s << ")"; } else if(it.armor || (item && item->getArmor()) || it.showAttributes) { int32_t tmp = it.armor; if(item) tmp = item->getArmor(); bool begin = true; if(tmp) { s << " (Arm:" << tmp; begin = false; } for(uint16_t i = SKILL_FIRST; i <= SKILL_LAST; i++) { if(!it.abilities.skills[i]) continue; if(begin) { begin = false; s << " ("; } else s << ", "; s << getSkillName(i) << " " << std::showpos << (int32_t)it.abilities.skills[i] << std::noshowpos; } if(it.abilities.stats[STAT_MAGICLEVEL]) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "magic level " << std::showpos << (int32_t)it.abilities.stats[STAT_MAGICLEVEL] << std::noshowpos; } // TODO: we should find some better way of completing this int32_t show = it.abilities.absorb[COMBAT_FIRST]; for(int32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i++) { if(it.abilities.absorb[i] == show) continue; show = 0; break; } if(!show) { bool tmp = true; for(int32_t i = COMBAT_FIRST; i <= COMBAT_LAST; i++) { if(!it.abilities.absorb[i]) continue; if(tmp) { tmp = false; if(begin) { begin = false; s << " ("; } else s << ", "; s << "protection "; } else s << ", "; s << getCombatName((CombatType_t)i) << " " << std::showpos << it.abilities.absorb[i] << std::noshowpos << "%"; } } else { if(begin) { begin = false; s << " ("; } else s << ", "; s << "protection all " << std::showpos << show << std::noshowpos << "%"; } // TODO: same case as absorbs... show = it.abilities.reflect[REFLECT_CHANCE][COMBAT_FIRST]; for(int32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i++) { if(it.abilities.reflect[REFLECT_CHANCE][i] == show) continue; show = 0; break; } if(!show) { bool tmp = true; for(int32_t i = COMBAT_FIRST; i <= COMBAT_LAST; i++) { if(!it.abilities.reflect[REFLECT_CHANCE][i] || !it.abilities.reflect[REFLECT_PERCENT][i]) continue; if(tmp) { tmp = false; if(begin) { begin = false; s << " ("; } else s << ", "; s << "reflect: "; } else s << ", "; s << it.abilities.reflect[REFLECT_CHANCE][i] << "% for "; if(it.abilities.reflect[REFLECT_PERCENT][i] > 99) s << "whole"; else if(it.abilities.reflect[REFLECT_PERCENT][i] >= 75) s << "huge"; else if(it.abilities.reflect[REFLECT_PERCENT][i] >= 50) s << "medium"; else if(it.abilities.reflect[REFLECT_PERCENT][i] >= 25) s << "small"; else s << "tiny"; s << getCombatName((CombatType_t)i); } if(!tmp) s << " damage"; } else { if(begin) { begin = false; s << " ("; } else s << ", "; int32_t tmp = it.abilities.reflect[REFLECT_PERCENT][COMBAT_FIRST]; for(int32_t i = (COMBAT_FIRST + 1); i <= COMBAT_LAST; i++) { if(it.abilities.reflect[REFLECT_PERCENT][i] == tmp) continue; tmp = 0; break; } s << "reflect: " << show << "% for "; if(tmp) { if(tmp > 99) s << "whole"; else if(tmp >= 75) s << "huge"; else if(tmp >= 50) s << "medium"; else if(tmp >= 25) s << "small"; else s << "tiny"; } else s << "mixed"; s << " damage"; } if(it.abilities.speed) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "speed " << std::showpos << (int32_t)(it.abilities.speed / 2) << std::noshowpos; } if(!begin) s << ")"; } else if(it.isContainer()) s << " (Vol:" << (int32_t)it.maxItems << ")"; else if(it.isKey()) s << " (Key:" << (item ? (int32_t)item->getActionId() : 0) << ")"; else if(it.isFluidContainer()) { if(subType > 0) s << " of " << (items[subType].name.length() ? items[subType].name : "unknown"); else s << ". It is empty"; } else if(it.isSplash()) { s << " of "; if(subType > 0 && items[subType].name.length()) s << items[subType].name; else s << "unknown"; } else if(it.allowDistRead) { s << std::endl; if(item && !item->getText().empty()) { if(lookDistance <= 4) { if(!item->getWriter().empty()) { s << item->getWriter() << " wrote"; time_t date = item->getDate(); if(date > 0) s << " on " << formatDate(date); s << ": "; } else s << "You read: "; std::string text = item->getText(); s << text; if(!text.empty()) { char end = *text.rbegin(); if(end == '?' || end == '!' || end == '.') dot = false; } } else s << "You are too far away to read it"; } else s << "Nothing is written on it"; } else if(it.levelDoor && item && item->getActionId() >= (int32_t)it.levelDoor && item->getActionId() <= ((int32_t)it.levelDoor + g_config.getNumber(ConfigManager::MAXIMUM_DOOR_LEVEL))) s << " for level " << item->getActionId() - it.levelDoor; if(it.showCharges) s << " that has " << subType << " charge" << (subType != 1 ? "s" : "") << " left"; if(it.showDuration) { if(item && item->hasIntegerAttribute("duration")) { int32_t duration = item->getDuration() / 1000; s << " that has energy for "; if(duration >= 120) s << duration / 60 << " minutes left"; else if(duration > 60) s << "1 minute left"; else s << " less than a minute left"; } else s << " that is brand-new"; } if(dot) s << "."; if(it.wieldInfo) { s << std::endl << "It can only be wielded properly by "; if(it.wieldInfo & WIELDINFO_PREMIUM) s << "premium "; if(it.wieldInfo & WIELDINFO_VOCREQ) s << it.vocationString; else s << "players"; if(it.wieldInfo & WIELDINFO_LEVEL) s << " of level " << (int32_t)it.minReqLevel << " or higher"; if(it.wieldInfo & WIELDINFO_MAGLV) { if(it.wieldInfo & WIELDINFO_LEVEL) s << " and"; else s << " of"; s << " magic level " << (int32_t)it.minReqMagicLevel << " or higher"; } s << "."; } if(lookDistance <= 1 && it.pickupable) { std::string tmp; if(!item) tmp = getWeightDescription(it.weight, it.stackable, subType); else tmp = item->getWeightDescription(); if(!tmp.empty()) s << std::endl << tmp; } if(it.abilities.elementType != COMBAT_NONE && it.decayTo > 0) { s << std::endl << "It is temporarily enchanted with " << getCombatName(it.abilities.elementType) << " ("; s << std::max((int32_t)0, int32_t((item ? item->getAttack() : it.attack) - it.abilities.elementDamage)); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; s << " physical + " << it.abilities.elementDamage << " " << getCombatName(it.abilities.elementType) << " damage)."; } std::string str; if(item && !item->getSpecialDescription().empty()) str = item->getSpecialDescription(); else if(!it.description.empty() && lookDistance <= 1) str = it.description; if(str.empty()) return s.str(); if(str.find("|PLAYERNAME|") != std::string::npos) { std::string tmp = "You"; if(item) { if(const Player* player = item->getHoldingPlayer()) tmp = player->getName(); } replaceString(str, "|PLAYERNAME|", tmp); } if(str.find("|TIME|") != std::string::npos || str.find("|DATE|") != std::string::npos || str.find( "|DAY|") != std::string::npos || str.find("|MONTH|") != std::string::npos || str.find( "|YEAR|") != std::string::npos || str.find("|HOUR|") != std::string::npos || str.find( "|MINUTES|") != std::string::npos || str.find("|SECONDS|") != std::string::npos || str.find("|WEEKDAY|") != std::string::npos || str.find("|YEARDAY|") != std::string::npos) { time_t now = time(NULL); tm* ts = localtime(&now); std::stringstream ss; ss << ts->tm_sec; replaceString(str, "|SECONDS|", ss.str()); ss.str(""); ss << ts->tm_min; replaceString(str, "|MINUTES|", ss.str()); ss.str(""); ss << ts->tm_hour; replaceString(str, "|HOUR|", ss.str()); ss.str(""); ss << ts->tm_mday; replaceString(str, "|DAY|", ss.str()); ss.str(""); ss << (ts->tm_mon + 1); replaceString(str, "|MONTH|", ss.str()); ss.str(""); ss << (ts->tm_year + 1900); replaceString(str, "|YEAR|", ss.str()); ss.str(""); ss << ts->tm_wday; replaceString(str, "|WEEKDAY|", ss.str()); ss.str(""); ss << ts->tm_yday; replaceString(str, "|YEARDAY|", ss.str()); ss.str(""); ss << ts->tm_hour << ":" << ts->tm_min << ":" << ts->tm_sec; replaceString(str, "|TIME|", ss.str()); ss.str(""); replaceString(str, "|DATE|", formatDateEx(now)); } s << std::endl << str; return s.str(); }
void EquipCard::use(Room *room, ServerPlayer *source, QList<ServerPlayer *> &targets) const { if (targets.isEmpty()) { CardMoveReason reason(CardMoveReason::S_REASON_USE, source->objectName(), QString(), getSkillName(), QString()); room->moveCardTo(this, source, NULL, Player::DiscardPile, reason, true); return; } int equipped_id = Card::S_UNKNOWN_CARD_ID; ServerPlayer *target = targets.first(); if (target->getEquip(location())) equipped_id = target->getEquip(location())->getEffectiveId(); QList<CardsMoveStruct> exchangeMove; CardsMoveStruct move1(getEffectiveId(), target, Player::PlaceEquip, CardMoveReason(CardMoveReason::S_REASON_USE, target->objectName())); exchangeMove.push_back(move1); if (equipped_id != Card::S_UNKNOWN_CARD_ID) { CardsMoveStruct move2(equipped_id, NULL, Player::DiscardPile, CardMoveReason(CardMoveReason::S_REASON_CHANGE_EQUIP, target->objectName())); exchangeMove.push_back(move2); } LogMessage log; log.from = target; log.type = "$Install"; log.card_str = QString::number(getEffectiveId()); room->sendLog(log); room->moveCardsAtomic(exchangeMove, true); }