TombsOfHarc/src/Pickable.cpp

189 lines
5.0 KiB
C++

#include "main.hpp"
TargetSelector::TargetSelector(SelectorType type, float range) : type(type), range(range) { }
void TargetSelector::selectTargets(Actor *wearer, TCODList<Actor *> & 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<Actor *> 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;
}