Monster::Monster(MonsterClass *specy): Being(OBJECT_MONSTER), mSpecy(specy), mTargetListener(&monsterTargetEventDispatch), mOwner(NULL), mCurrentAttack(NULL) { LOG_DEBUG("Monster spawned! (id: " << mSpecy->getId() << ")."); setWalkMask(Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER); /* * Initialise the attribute structures. */ const AttributeManager::AttributeScope &mobAttr = attributeManager->getAttributeScope(MonsterScope); for (AttributeManager::AttributeScope::const_iterator it = mobAttr.begin(), it_end = mobAttr.end(); it != it_end; ++it) { mAttributes.insert(std::pair< unsigned int, Attribute > (it->first, Attribute(*it->second))); } /* * Set the attributes to the values defined by the associated monster * class with or without mutations as needed. */ int mutation = specy->getMutation(); for (AttributeMap::iterator it2 = mAttributes.begin(), it2_end = mAttributes.end(); it2 != it2_end; ++it2) { double attr = 0.0f; if (specy->hasAttribute(it2->first)) { attr = specy->getAttribute(it2->first); setAttribute(it2->first, mutation ? attr * (100 + (rand()%(mutation << 1)) - mutation) / 100.0 : attr); } } setSize(specy->getSize()); setGender(specy->getGender()); // Set positions relative to target from which the monster can attack int dist = specy->getAttackDistance(); mAttackPositions.push_back(AttackPosition(dist, 0, LEFT)); mAttackPositions.push_back(AttackPosition(-dist, 0, RIGHT)); mAttackPositions.push_back(AttackPosition(0, -dist, DOWN)); mAttackPositions.push_back(AttackPosition(0, dist, UP)); // Load default script loadScript(specy->getScript()); }
MonsterComponent::MonsterComponent(Entity &entity, MonsterClass *specy): mSpecy(specy), mOwner(nullptr) { LOG_DEBUG("Monster spawned! (id: " << mSpecy->getId() << ")."); auto *beingComponent = entity.getComponent<BeingComponent>(); auto *actorComponent = entity.getComponent<ActorComponent>(); actorComponent->setWalkMask(Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER); actorComponent->setBlockType(BLOCKTYPE_MONSTER); actorComponent->setSize(specy->getSize()); /* * Initialise the attribute structures. */ for (auto attrInfo : attributeManager->getAttributeScope(MonsterScope)) { beingComponent->createAttribute(attrInfo.first, *attrInfo.second); } /* * Set the attributes to the values defined by the associated monster * class with or without mutations as needed. */ int mutation = specy->getMutation(); for (auto &attribute : specy->getAttributes()) { double attributeValue = attribute.second; if (mutation != 0) { double factor = 100 + (rand() % (mutation * 2)) - mutation; attributeValue = attributeValue * factor / 100.0; } beingComponent->setAttribute(entity, attribute.first, attributeValue); } beingComponent->setGender(specy->getGender()); beingComponent->signal_died.connect(sigc::mem_fun(this, &MonsterComponent::monsterDied)); // Set positions relative to target from which the monster can attack int dist = specy->getAttackDistance(); mAttackPositions.push_back(AttackPosition(dist, 0, LEFT)); mAttackPositions.push_back(AttackPosition(-dist, 0, RIGHT)); mAttackPositions.push_back(AttackPosition(0, -dist, DOWN)); mAttackPositions.push_back(AttackPosition(0, dist, UP)); MonsterCombatComponent *combatComponent = new MonsterCombatComponent(entity, specy); entity.addComponent(combatComponent); double damageMutation = mutation ? (100.0 + (rand() % (mutation * 2)) - mutation) / 100.0 : 1.0; combatComponent->setDamageMutation(damageMutation); combatComponent->signal_damaged.connect( sigc::mem_fun(this, &MonsterComponent::receivedDamage)); }