virtual MoveInfo getMove() { if (creature->getAttributes().getSkills().hasDiscrete(SkillId::HEALING)) { int healingRadius = 2; for (Position pos : creature->getPosition().getRectangle( Rectangle(-healingRadius, -healingRadius, healingRadius + 1, healingRadius + 1))) if (const Creature* other = pos.getCreature()) if (creature->isFriend(other)) if (auto action = creature->heal(creature->getPosition().getDir(other->getPosition()))) return MoveInfo(0.5, action); } if (!creature->getAttributes().isHumanoid()) return NoMove; if (creature->isAffected(LastingEffect::POISON)) { if (MoveInfo move = tryEffect(EffectType(EffectId::LASTING, LastingEffect::POISON_RESISTANT), 1)) return move; if (MoveInfo move = tryEffect(EffectType(EffectId::CURE_POISON), 1)) return move; } if (creature->getHealth() < 1) { if (MoveInfo move = tryEffect(EffectId::HEAL, 1)) return move.withValue(min(1.0, 1.5 - creature->getHealth())); if (MoveInfo move = tryEffect(EffectId::HEAL, 3)) return move.withValue(0.5 * min(1.0, 1.5 - creature->getHealth())); } for (Position pos : creature->getPosition().neighbors8()) if (Creature* c = pos.getCreature()) if (creature->isFriend(c) && c->getHealth() < 1) for (Item* item : creature->getEquipment().getItems(Item::effectPredicate(EffectId::HEAL))) if (auto action = creature->give(c, {item})) return MoveInfo(0.5, action); return NoMove; }
double getThrowValue(Item* it) { if (contains<EffectType>({ EffectType(EffectId::LASTING, LastingEffect::POISON), EffectType(EffectId::LASTING, LastingEffect::SLOWED), EffectType(EffectId::LASTING, LastingEffect::BLIND), EffectType(EffectId::LASTING, LastingEffect::SLEEP)}, it->getEffectType())) return 100; return it->getModifier(ModifierType::THROWN_DAMAGE); }
virtual double itemValue(const Item* item) override { if (contains<EffectType>({ EffectType(EffectId::LASTING, LastingEffect::INVISIBLE), EffectType(EffectId::LASTING, LastingEffect::SLOWED), EffectType(EffectId::LASTING, LastingEffect::BLIND), EffectType(EffectId::LASTING, LastingEffect::SLEEP), EffectType(EffectId::LASTING, LastingEffect::POISON), EffectType(EffectId::LASTING, LastingEffect::POISON_RESISTANT), EffectId::CURE_POISON, EffectId::TELEPORT, EffectType(EffectId::LASTING, LastingEffect::STR_BONUS), EffectType(EffectId::LASTING, LastingEffect::DEX_BONUS)}, item->getEffectType())) return 1; if (item->getClass() == ItemClass::AMMO && creature->getAttributes().getSkills().getValue(SkillId::ARCHERY) > 0) return 0.1; if (!creature->isEquipmentAppropriate(item)) return 0; if (item->getModifier(ModifierType::THROWN_DAMAGE) > 0) return (double)item->getModifier(ModifierType::THROWN_DAMAGE) / 50; int damage = item->getModifier(ModifierType::DAMAGE); Item* best = getBestWeapon(); if (best && best != item && best->getModifier(ModifierType::DAMAGE) >= damage) return 0; return (double)damage / 50; }
virtual double itemValue(const Item* item) { if (item->getEffectType() == EffectType(EffectId::HEAL)) { return 0.5; } else return 0; }
optional<MinionEquipment::EquipmentType> MinionEquipment::getEquipmentType(const Item* it) { if (it->canEquip()) return MinionEquipment::ARMOR; if (contains({ItemClass::RANGED_WEAPON, ItemClass::AMMO}, it->getClass())) return MinionEquipment::ARCHERY; if (it->getEffectType() == EffectType(EffectId::HEAL)) return MinionEquipment::HEALING; if (contains(combatConsumables, it->getEffectType())) return MinionEquipment::COMBAT_ITEM; return none; }
MoveInfo getAttackMove(Creature* other, bool chase) { int distance = 10000; CHECK(other); if (other->getAttributes().isInvincible()) return NoMove; Debug() << creature->getName().bare() << " enemy " << other->getName().bare(); Vec2 enemyDir = creature->getPosition().getDir(other->getPosition()); distance = enemyDir.length8(); if (creature->getAttributes().isHumanoid() && !creature->getWeapon()) { if (Item* weapon = getBestWeapon()) if (auto action = creature->equip(weapon)) return {3.0 / (2.0 + distance), action.prepend([=](Creature* creature) { creature->setInCombat(); other->setInCombat(); })}; } if (distance == 1) if (MoveInfo move = tryEffect(EffectId::AIR_BLAST, 1)) return move; if (distance <= 5) for (EffectType effect : { EffectType(EffectId::LASTING, LastingEffect::INVISIBLE), EffectType(EffectId::LASTING, LastingEffect::STR_BONUS), EffectType(EffectId::LASTING, LastingEffect::DEX_BONUS), EffectType(EffectId::LASTING, LastingEffect::SPEED), EffectType(EffectId::DECEPTION), EffectType(EffectId::SUMMON, CreatureId::SPIRIT)}) if (MoveInfo move = tryEffect(effect, 1)) return move; if (distance > 1) { if (distance < 10) { if (MoveInfo move = getFireMove(enemyDir)) return move; if (MoveInfo move = getThrowMove(enemyDir)) return move; } if (chase && !other->getAttributes().dontChase() && !isChaseFrozen(other)) { lastSeen = none; if (auto action = creature->moveTowards(other->getPosition())) return {max(0., 1.0 - double(distance) / 10), action.prepend([=](Creature* creature) { creature->setInCombat(); other->setInCombat(); lastSeen = {other->getPosition(), creature->getGlobalTime(), LastSeen::ATTACK, other->getUniqueId()}; if (!chaseFreeze.count(other) || other->getGlobalTime() > chaseFreeze.at(other).second) chaseFreeze[other] = make_pair(other->getGlobalTime() + 20, other->getGlobalTime() + 70); })}; } } if (distance == 1) if (auto action = creature->attack(other, getAttackParams(other))) return {1.0, action.prepend([=](Creature* creature) { creature->setInCombat(); other->setInCombat(); })}; return NoMove; }
KeeperRL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ . */ #include "stdafx.h" #include "minion_equipment.h" #include "item.h" #include "creature.h" #include "effect.h" static vector<EffectType> combatConsumables { EffectType(EffectId::LASTING, LastingEffect::SPEED), EffectType(EffectId::LASTING, LastingEffect::SLOWED), EffectType(EffectId::LASTING, LastingEffect::SLEEP), EffectType(EffectId::LASTING, LastingEffect::POISON), EffectType(EffectId::LASTING, LastingEffect::BLIND), EffectType(EffectId::LASTING, LastingEffect::INVISIBLE), EffectType(EffectId::LASTING, LastingEffect::STR_BONUS), EffectType(EffectId::LASTING, LastingEffect::DEX_BONUS), EffectType(EffectId::LASTING, LastingEffect::POISON_RESISTANT), }; template <class Archive> void MinionEquipment::serialize(Archive& ar, const unsigned int version) { ar & SVAR(owners); CHECK_SERIAL; }
void MeleeSystem::update(float dt) { CCArray * entities = this->entityManager->getAllEntitiesPosessingComponentOfClass("MeleeComponent"); CCObject* object = NULL; CCARRAY_FOREACH(entities, object) { Entity* entity = (Entity*) object; RenderComponent* render = entity->render(); MeleeComponent* melee = entity->melee(); TeamComponent* team = entity->team(); if (!render || !melee || !team) continue; bool aoeDamageCaused = false; CCArray * enemies = entity->getAllEntitiesOnTeam(OPPOSITE_TEAM(team->team),"RenderComponent"); CCObject* temp = NULL; CCARRAY_FOREACH(enemies, temp){ Entity* enemy = (Entity*) temp; RenderComponent * enemyRender = enemy->render(); HealthComponent * enemyHealth = enemy->health(); if (!enemyRender || !enemyHealth) continue; float distance = ccpDistance(render->node->getPosition(), enemyRender->node->getPosition()); MonsterComponent* monsterCom = entity->monster(); if (render->node->boundingBox().intersectsRect(enemyRender->node->boundingBox()) ||monsterCom && abs(distance) < monsterCom->monster->deck->fight.Range) { if (GetTickCount() - melee->_damage->lastDamageTime > melee->deck->fight.FireRate * 1000) { CCPoint edge = ccp((render->node->getPosition().x+enemyRender->node->getPosition().x)/2, (render->node->getPosition().y+enemyRender->node->getPosition().y)/2); //make slow enemy MoveComponent* move = (MoveComponent*) enemy->move(); if(move) move->velocity = ccpNormalize(move->velocity) ; #if SOUND CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(melee->deck->sound); #endif MonsterComponent* enemyMonster = enemy->monster(); if(enemyMonster) { CCPoint currrent = enemyRender->node->getPosition(); //float scale = enemyRender->node->getScale(); CCScaleTo* a = CCScaleBy::create(0.1f,1.5f); int ran = rand()%2; CCRotateTo* b = CCRotateTo::create(0.1f,ran?15:-15); //CCRotateTo* c = CCRotateTo::create(0.1f,-30); CCRotateTo* d = CCRotateTo::create(0.1f,0); CCScaleTo* e = CCScaleTo::create(0.1f,1.0f); CCSequence* sequence = CCSequence::create(a,b,d,e,NULL); enemyRender->node->runAction(sequence); } MonsterComponent* monster = entity->monster(); if(monster) { entityFactory->createEffect(EffectType((int)monster->monsterType +4),edge); } if (melee->deck->fight.aoe) { aoeDamageCaused = true; } else { melee->_damage->lastDamageTime = GetTickCount(); } enemyHealth->curHP -= melee->deck->fight.Damage; char temp[64]; sprintf(temp, "%d", (int)melee->deck->fight.Damage); CCLabelBMFont* hitLabel = CCLabelBMFont::create(temp,"Courier_red.fnt"); hitLabel->setPosition(edge); entityFactory->_batchNode->getParent()->addChild(hitLabel); CCScaleTo* scaleFrom = CCScaleTo::create(0.1f,1.5f); CCDelayTime* delay = CCDelayTime::create(0.1f); CCScaleTo* scaleTo = CCScaleTo::create(0.1f,1.0f); CCFiniteTimeAction* actionMoveDone = CCCallFuncN::create(this,callfuncN_selector(MeleeSystem::clean)); CCSequence* sequence = CCSequence::create(scaleFrom,delay,scaleTo,delay,actionMoveDone,NULL); hitLabel->runAction(sequence); if (enemyHealth->curHP < 0) { enemyHealth->curHP = 0; } if (melee->_damage->destroySelf) { render->node->removeFromParentAndCleanup(true); //CCLog("Removing entity:%d, I am a bullet.",entity->_eid); this->entityManager->removeEntity(entity); } } } }
vector<DirEffectType> getOffensiveEffects() { return makeVec<DirEffectType>( DirEffectId::BLAST, DirEffectType(DirEffectId::CREATURE_EFFECT, EffectType(EffectId::LASTING, LastingEffect::STUNNED)) ); }