#include "main.hpp" TargetSelector::TargetSelector(SelectorType type, float range) : type(type), range(range) { } void TargetSelector::selectTargets(Actor *wearer, TCODList & list) { switch(type) { case CLOSEST_MONSTER: { Actor *closestMonster=engine.getClosestMonster(wearer->x, wearer->y, range); if(closestMonster) { list.push(closestMonster); } } break; case SELECTED_MONSTER: { int x, y; engine.gui->message(TCODColor::cyan, "Left-click to select a target,\nor right-click to cancel."); if(engine.pickATile(&x, &y, range)) { Actor *actor=engine.getActor(x, y); if(actor) { list.push(actor); } } } break; case WEARER_RANGE: for(Actor **iterator=engine.actors.begin(); iterator != engine.actors.end(); iterator++) { Actor *actor=*iterator; if(actor != wearer && actor->destructible && !actor->destructible->isDead() && actor->getDistance(wearer->x, wearer->y) <= range) { list.push(actor); } } break; case SELECTED_RANGE: int x, y; engine.gui->message(TCODColor::cyan, "Left-click to select a tile,\nor right-click to cancel."); if(engine.pickATile(&x, &y)) { for(Actor **iterator = engine.actors.begin(); iterator != engine.actors.end(); iterator++) { Actor *actor=*iterator; if(actor->destructible && !actor->destructible->isDead() && actor->getDistance(x, y) <= range) { list.push(actor); } } } break; } if(list.isEmpty()) { engine.gui->message(TCODColor::lightGrey, "No enemy is close enough"); } } void TargetSelector::save(TCODZip &zip) { int persistType = 0; switch(type) { case CLOSEST_MONSTER: persistType = 1; break; case SELECTED_MONSTER: persistType = 2; break; case WEARER_RANGE: persistType = 3; break; case SELECTED_RANGE: persistType = 4; break; } zip.putInt(persistType); zip.putFloat(range); } void TargetSelector::load(TCODZip &zip) { int persistType = zip.getInt(); switch(persistType) { case 1: type = CLOSEST_MONSTER; break; case 2: type = SELECTED_MONSTER; break; case 3: type = WEARER_RANGE; break; case 4: type = SELECTED_RANGE; break; } range = zip.getFloat(); } HealthEffect::HealthEffect(float amount, const char *message) : amount(amount), message(message) { } bool HealthEffect::applyTo(Actor *actor) { if(!actor->destructible) return false; if(amount > 0) { float pointsHealed=actor->destructible->heal(amount); if(pointsHealed > 0) { if(message) { engine.gui->message(TCODColor::lightGrey, message, actor->name, pointsHealed); } return true; } } else { if(message && -amount-actor->destructible->defense > 0) { engine.gui->message(TCODColor::lightGrey, message, actor->name, -amount-actor->destructible->defense); } if(actor->destructible->takeDamage(actor, -amount) > 0) { return true; } } return false; } AiChangeEffect::AiChangeEffect(TemporaryAi *newAi, const char *message) : newAi(newAi), message(message) { } bool AiChangeEffect::applyTo(Actor *actor) { newAi->applyTo(actor); if(message) { engine.gui->message(TCODColor::lightGrey, message, actor->name); } return true; } Pickable::Pickable(TargetSelector *selector, Effect *effect) : selector(selector), effect(effect) { } Pickable::~Pickable() { if(selector) delete selector; if(effect) delete effect; } bool Pickable::pick(Actor *owner, Actor *wearer) { if(wearer->container && wearer->container->add(owner)) { engine.actors.remove(owner); return true; } return false; } void Pickable::drop(Actor *owner, Actor *wearer) { if(wearer->container) { wearer->container->remove(owner); engine.actors.push(owner); owner->x = wearer->x; owner->y = wearer->y; engine.gui->message(TCODColor::lightGrey, "%s drops a %s.", wearer->name, owner->name); } } bool Pickable::use(Actor *owner, Actor *wearer) { TCODList list; if(selector) { selector->selectTargets(wearer, list); } else { list.push(wearer); } bool succeed=false; for(Actor **it=list.begin(); it!=list.end(); it++) { if(effect->applyTo(*it)) { succeed=true; } } if(succeed) { if(wearer->container) { wearer->container->remove(owner); delete owner; } } return succeed; } void Pickable::save(TCODZip &zip) { zip.putInt(selector != NULL); zip.putInt(effect != NULL); if(selector) selector->save(zip); //if(effect) effect->save(zip); } void Pickable::load(TCODZip &zip) { bool hasSelector = zip.getInt(); bool hasEffect = zip.getInt(); if(hasSelector) { selector = new TargetSelector(TargetSelector::CLOSEST_MONSTER, 0); selector->load(zip); } /* if(hasEffect) { effect = new Effect(); effect->load(zip); } */ } /* Pickable Factory */ Pickable *Pickable::create(TCODZip &zip) { Pickable *pickable=NULL; pickable->load(zip); return pickable; }