global func TutorialMessage(string strMessage) { // Message with speech marker if (HasSpeech(strMessage)) // PlayerMessage will handle the speech output (and it won't show the message) PlayerMessage(0, strMessage); // Normal message display, in addition to speech output if (GetLength(strMessage)) strMessage = Format("@%s", strMessage); CustomMessage(strMessage, 0, GetPlayerByIndex(0), g_msgoffx, g_msgoffy, 0xffffff, DECO, "Portrait:SCLK::0000ff::1", g_msgpos | MSG_DropSpeech, g_msgwdt); }
void VillageControl::onPickupEvent(const Creature* who, const vector<Item*>& items) { if (getCollective()->getTerritory().contains(who->getPosition())) if (isEnemy(who) && villain) if (contains(villain->triggers, AttackTriggerId::STOLEN_ITEMS)) { bool wasTheft = false; for (const Item* it : items) if (myItems.contains(it)) { wasTheft = true; ++stolenItemCount; myItems.erase(it); } if (getCollective()->hasLeader() && wasTheft) { who->playerMessage(PlayerMessage("You are going to regret this", MessagePriority::HIGH)); } } }
protected func ActivateEntrance(object obj) { if (this->~IsBase() && this->~CanBlockEnemies()) { var for_plr = obj->GetOwner(); if (Hostile(GetOwner(), for_plr)) { Sound("Error", false, 100, for_plr); PlayerMessage(for_plr, "$TxtNoEntryEnemy$", GetPlayerName(GetOwner())); return false; } } if (ActIdle()) SetAction("OpenDoor"); return true; }
void VillageControl::considerWelcomeMessage() { if (!getCollective()->hasLeader()) return; if (villain) if (villain->welcomeMessage) switch (*villain->welcomeMessage) { case DRAGON_WELCOME: for (Position pos : getCollective()->getTerritory().getAll()) if (Creature* c = pos.getCreature()) if (c->isAffected(LastingEffect::INVISIBLE) && isEnemy(c) && c->isPlayer() && getCollective()->getLeader()->canSee(c->getPosition())) { c->playerMessage(PlayerMessage("\"Well thief! I smell you and I feel your air. " "I hear your breath. Come along!\"", MessagePriority::CRITICAL)); villain->welcomeMessage.reset(); } break; } }
bool LastingEffects::tick(Creature* c, LastingEffect effect) { PROFILE_BLOCK("LastingEffects::tick"); switch (effect) { case LastingEffect::BLEEDING: c->getBody().bleed(c, 0.03); c->secondPerson(PlayerMessage("You are bleeding.", MessagePriority::HIGH)); c->thirdPerson(PlayerMessage(c->getName().the() + " is bleeding.", MessagePriority::HIGH)); if (c->getBody().getHealth() <= 0) { c->you(MsgType::DIE_OF, "bleeding"); c->dieWithLastAttacker(); return true; } break; case LastingEffect::REGENERATION: c->getBody().heal(c, 0.03); break; case LastingEffect::ON_FIRE: c->getPosition().fireDamage(0.1); break; case LastingEffect::POISON: c->getBody().bleed(c, 0.03); c->secondPerson(PlayerMessage("You suffer from poisoning.", MessagePriority::HIGH)); c->thirdPerson(PlayerMessage(c->getName().the() + " suffers from poisoning.", MessagePriority::HIGH)); if (c->getBody().getHealth() <= 0) { c->you(MsgType::DIE_OF, "poisoning"); c->dieWithLastAttacker(); return true; } break; case LastingEffect::WARNING: { const int radius = 5; bool isDanger = false; bool isBigDanger = false; auto position = c->getPosition(); for (Position v : position.getRectangle(Rectangle(-radius, -radius, radius + 1, radius + 1))) { for (auto f : v.getFurniture()) if (f->emitsWarning(c)) { if (v.dist8(position).value_or(2) <= 1) isBigDanger = true; else isDanger = true; } if (Creature* enemy = v.getCreature()) { if (!c->canSee(enemy) && c->isEnemy(enemy)) { int diff = enemy->getAttr(AttrType::DAMAGE) - c->getAttr(AttrType::DEFENSE); if (diff > 5) isBigDanger = true; else if (diff > 0) isDanger = true; } } } if (isBigDanger) c->privateMessage(PlayerMessage("You sense big danger!", MessagePriority::HIGH)); else if (isDanger) c->privateMessage(PlayerMessage("You sense danger!", MessagePriority::HIGH)); break; } case LastingEffect::SUNLIGHT_VULNERABLE: if (c->getPosition().sunlightBurns()) { c->you(MsgType::ARE, "burnt by the sun"); if (Random.roll(10)) { c->you(MsgType::YOUR, "body crumbles to dust"); c->dieWithReason("killed by sunlight", Creature::DropType::ONLY_INVENTORY); return true; } } break; case LastingEffect::ENTERTAINER: if (!c->isAffected(LastingEffect::SLEEP) && Random.roll(50)) { auto others = c->getVisibleCreatures().filter([](const Creature* c) { return c->getBody().hasBrain() && c->getBody().isHumanoid(); }); if (others.empty()) break; string jokeText = "a joke"; optional<LastingEffect> hatedGroup; for (auto effect : getHateEffects()) if (c->isAffected(effect) || (c->getAttributes().getHatedByEffect() != effect && Random.roll(10 * getHateEffects().size()))) { hatedGroup = effect; break; } if (hatedGroup) jokeText.append(" about "_s + getHatedGroupName(*hatedGroup)); c->verb("crack", "cracks", jokeText); for (auto other : others) if (other != c && !other->isAffected(LastingEffect::SLEEP)) { if (hatedGroup && hatedGroup == other->getAttributes().getHatedByEffect()) { other->addMorale(-0.05); other->you(MsgType::ARE, "offended"); } else { other->verb("laugh", "laughs"); other->addMorale(0.01); } } } break; case LastingEffect::BAD_BREATH: for (auto pos : c->getPosition().getRectangle(Rectangle::centered(7))) if (auto other = pos.getCreature()) other->addMorale(-0.002); break; case LastingEffect::DISAPPEAR_DURING_DAY: if (c->getGame()->getSunlightInfo().getState() == SunlightState::DAY) c->dieNoReason(Creature::DropType::ONLY_INVENTORY); break; default: break; } return false; }