NPCObject* PersistentNpcFactory::_createPersistentNpc(DatabaseResult* result) { NPCObject* npc ; NpcIdentifier npcIdentifier; uint64 count = result->getRowCount(); result->GetNextRow(mNpcIdentifierBinding,(void*)&npcIdentifier); result->ResetRowIndex(); switch(npcIdentifier.mFamilyId) { case NpcFamily_Trainer: npc = new Trainer(); break; case NpcFamily_Filler: npc = new FillerNPC(); break; case NpcFamily_QuestGiver: npc = new QuestGiver(); break; default: { npc = new NPCObject(); gLogger->log(LogManager::DEBUG,"PersistentNpcFactory::createPersistent unknown Family %u",npcIdentifier.mFamilyId); } break; } Inventory* npcInventory = new Inventory(); npcInventory->setParent(npc); result->GetNextRow(mPersistentNpcBinding,(void*)npc); npc->mHam.mHealth.setCurrentHitPoints(500); npc->mHam.mAction.setCurrentHitPoints(500); npc->mHam.mMind.setCurrentHitPoints(500); npc->mHam.calcAllModifiedHitPoints(); // inventory npcInventory->setId(npc->mId + INVENTORY_OFFSET); npcInventory->setParentId(npc->mId); npcInventory->setModelString("object/tangible/inventory/shared_creature_inventory.iff"); npcInventory->setName("inventory"); npcInventory->setNameFile("item_n"); npcInventory->setTangibleGroup(TanGroup_Inventory); npcInventory->setTangibleType(TanType_CreatureInventory); npc->mEquipManager.addEquippedObject(CreatureEquipSlot_Inventory,npcInventory); npc->mTypeOptions = 0x108; //npc->setPvPStatus(npc->getPvPStatus() + CreaturePvPStatus_Attackable + CreaturePvPStatus_Aggressive); npc->setLoadState(LoadState_Attributes); // Save default direction, since player can make the npc change heading. npc->storeDefaultDirection(); return npc; }
Shuttle* ShuttleFactory::_createShuttle(DatabaseResult* result) { Shuttle* shuttle = new Shuttle(); Inventory* shuttleInventory = new Inventory(); shuttleInventory->setParent(shuttle); uint64 count = result->getRowCount(); result->GetNextRow(mShuttleBinding,(void*)shuttle); shuttle->mHam.mBattleFatigue = 0; shuttle->mHam.mHealth.setCurrentHitPoints(500); shuttle->mHam.mAction.setCurrentHitPoints(500); shuttle->mHam.mMind.setCurrentHitPoints(500); shuttle->mHam.calcAllModifiedHitPoints(); // inventory shuttleInventory->setId(shuttle->mId + INVENTORY_OFFSET); shuttleInventory->setParentId(shuttle->mId); shuttleInventory->setModelString("object/tangible/inventory/shared_creature_inventory.iff"); shuttleInventory->setName("inventory"); shuttleInventory->setNameFile("item_n"); shuttleInventory->setTangibleGroup(TanGroup_Inventory); shuttleInventory->setTangibleType(TanType_CreatureInventory); shuttle->mEquipManager.addEquippedObject(CreatureEquipSlot_Inventory,shuttleInventory); shuttle->setLoadState(LoadState_Loaded); shuttle->mPosture = 0; shuttle->mScale = 1.0; shuttle->setFaction("neutral"); shuttle->mTypeOptions = 0x100; // Here we can handle the initializing of shuttle states // First, a dirty test for the shuttles in Theed Spaceport. // No need to randomize departure times, since we can always travel from there. // We wan't them to go in sync, so one of them always are in the spaceport. // if (shuttle->mParentId == 1692104) #if defined(_MSC_VER) if (shuttle->mId == 47781511212) #else if (shuttle->mId == 47781511212LLU) #endif { shuttle->setShuttleState(ShuttleState_InPort); shuttle->setInPortTime(0); } #if defined (_MSC_VER) else if (shuttle->mId == 47781511214) // This is the "extra" shuttle. #else else if (shuttle->mId == 47781511214LLU) // This is the "extra" shuttle. #endif { shuttle->setShuttleState(ShuttleState_Away); shuttle->setAwayTime(0); } else { // Get a randowm value in the range [0 <-> InPortInterval + AwayInterval] in ticks. // The rand value will land in either the InPort or in the Away part of the values. // Use that state as initial state and set the value as time that have already expired. uint32 maxInPortAndAwayIntervalTime = shuttle->getInPortInterval() + shuttle->getAwayInterval(); uint32 shuttleTimeExpired = static_cast<uint32>(gRandom->getRand() / RAND_MAX) * (maxInPortAndAwayIntervalTime); if (shuttleTimeExpired <= shuttle->getInPortInterval()) { // gLogger->log(LogManager::DEBUG,"Shuttle start InPort, time expired %u", shuttleTimeExpired); shuttle->setShuttleState(ShuttleState_InPort); shuttle->setInPortTime(shuttleTimeExpired); } else { // gLogger->log(LogManager::DEBUG,"Shuttle start Away, time expired %u", shuttleTimeExpired - shuttle->getInPortInterval()); shuttle->setShuttleState(ShuttleState_Away); shuttle->setAwayTime(shuttleTimeExpired - shuttle->getInPortInterval()); // Set the part corresponding to this state only. } } return shuttle; }
NPCObject* NonPersistentNpcFactory::createNonPersistentNpc(DatabaseResult* result, uint64 templateId, uint64 npcNewId, uint32 familyId, uint64 controllingObject) { NPCObject* npc; switch(familyId) { case NpcFamily_Trainer: { npc = new Trainer(); } break; case NpcFamily_Filler: { npc = new FillerNPC(); } break; case NpcFamily_QuestGiver: { npc = new QuestGiver(); } break; case NpcFamily_AttackableObject: { // Stuff like Debris. npc = new AttackableStaticNpc(); } break; case NpcFamily_AttackableCreatures: { // gLogger->logMsgF("NonPersistentNpcFactory::_createNonPersistentNpc() Created a NpcFamily_AttackableCreatures", MSG_NORMAL); // Stuff like npc's and womp rats :). npc = new AttackableCreature(templateId); } break; case NpcFamily_NaturalLairs: { // First time lairs. // gLogger->logMsgF("NonPersistentNpcFactory::createNonPersistentNpc() Created a NpcFamily_NaturalLairs", MSG_NORMAL); //Lairs are not supported here, at least not yet. assert(false && "NonPersistentNpcFactory::createNonPersistent NpcFamily_NaturalLairs Lairs are not supported here yet."); npc = new LairObject(templateId); } break; default: { gLogger->logMsgF("NonPersistentNpcFactory::createNonPersistent unknown Family %u",MSG_HIGH,familyId); assert(false && "NonPersistentNpcFactory::createNonPersistent unknown family"); npc = new NPCObject(); } break; } // Set the new temporarily id. npc->setId(npcNewId); // Register object with WorldManager. gWorldManager->addObject(npc, true); Inventory* npcInventory = new Inventory(); npcInventory->setCapacity(50);//we want to be able to fill something in our inventory npcInventory->setParent(npc); uint64 count = result->getRowCount(); result->GetNextRow(mNonPersistentNpcBinding,(void*)npc); // The template for this creature, in case of a respawn. npc->mNpcTemplateId = templateId; // Should bet fetched from attributes, these will do as defaults. npc->mHam.mHealth.setCurrentHitPoints(500); npc->mHam.mAction.setCurrentHitPoints(500); npc->mHam.mMind.setCurrentHitPoints(500); npc->mHam.calcAllModifiedHitPoints(); // inventory npcInventory->setId(npc->mId + 1); npcInventory->setParentId(npc->mId); npcInventory->setModelString("object/tangible/inventory/shared_creature_inventory.iff"); npcInventory->setName("inventory"); npcInventory->setNameFile("item_n"); npcInventory->setTangibleGroup(TanGroup_Inventory); npcInventory->setTangibleType(TanType_CreatureInventory); npc->mEquipManager.addEquippedObject(CreatureEquipSlot_Inventory,npcInventory); if (npc->getNpcFamily() == NpcFamily_AttackableObject) { // Dynamic spawned pve-enabled "static" creatures like debris. npc->setType(ObjType_Creature); npc->setCreoGroup(CreoGroup_AttackableObject); npc->mTypeOptions = 0x0; // Let's start as non-attackable. // npc->togglePvPStateOn((CreaturePvPStatus)(CreaturePvPStatus_Attackable)); } else if (npc->getNpcFamily() == NpcFamily_NaturalLairs) { //Lairs are not supported here, at least not yet. assert(false && "NonPersistentNpcFactory::createNonPersistent NpcFamily_NaturalLairs Lairs not supported here yet"); // Dynamic spawned pve-enabled "static" creatures like lairs. npc->setType(ObjType_Creature); // This will ensure the use of the single H(am) bar. npc->setCreoGroup(CreoGroup_AttackableObject); npc->mTypeOptions = 0x0; npc->togglePvPStateOn((CreaturePvPStatus)(CreaturePvPStatus_Attackable)); // npc->mHam.mHealth.setCurrentHitPoints(5000); // npc->mHam.mHealth.setMaxHitPoints(5000); // npc->mHam.mHealth.setBaseHitPoints(5000); // npc->mHam.calcAllModifiedHitPoints(); // Let's put some credits in the inventory. // npcInventory->setCredits((gRandom->getRand()%25) + 10); // gLogger->logMsgF("NonPersistentNpcFactory::createNonPersistentNpc() WOW, I'm a lair", MSG_NORMAL); } else if (npc->getNpcFamily() == NpcFamily_AttackableCreatures) { // Dynamic spawned pve-enabled creatures. npc->setType(ObjType_Creature); npc->setCreoGroup(CreoGroup_Creature); npc->mTypeOptions = 0x0; if (gWorldConfig->isTutorial()) { npc->togglePvPStateOn((CreaturePvPStatus)(CreaturePvPStatus_Attackable + CreaturePvPStatus_Aggressive + CreaturePvPStatus_Enemy )); } else { npc->togglePvPStateOn((CreaturePvPStatus)(CreaturePvPStatus_Attackable)); } AttackableCreature* attackableNpc = dynamic_cast<AttackableCreature*>(npc); assert(attackableNpc && "NonPersistentNpcFactory::createNonPersistent unable to cast npc to AttackableCreature instance"); // Fix this later // Also set the owner (lair) who's controlling this creature. attackableNpc->setLairId(controllingObject); Weapon* defaultWeapon = new Weapon(); defaultWeapon->setId(gWorldManager->getRandomNpId()); defaultWeapon->setParentId(npc->mId); defaultWeapon->setModelString("object/weapon/melee/unarmed/shared_unarmed_default_player.iff"); defaultWeapon->setGroup(WeaponGroup_Unarmed); defaultWeapon->setEquipSlotMask(CreatureEquipSlot_Weapon); defaultWeapon->addInternalAttribute("weapon_group","1"); npc->mEquipManager.setDefaultWeapon(defaultWeapon); npc->mEquipManager.equipDefaultWeapon(); // Weapon to use should be gotten from attibutes or whereever we find that kind of info. // This little fellow may need a gun. Weapon* pistol = new Weapon(); pistol->setId(gWorldManager->getRandomNpId()); pistol->setParentId(npc->mId); pistol->setModelString("object/weapon/ranged/pistol/shared_pistol_cdef.iff"); pistol->setGroup(WeaponGroup_Pistol); pistol->setEquipSlotMask(CreatureEquipSlot_Weapon); pistol->addInternalAttribute("weapon_group","32"); attackableNpc->setPrimaryWeapon(pistol); // A saber can be handy, too. Weapon* saber = new Weapon(); saber->setId(gWorldManager->getRandomNpId()); saber->setParentId(npc->mId); saber->setModelString("object/weapon/melee/sword/shared_sword_lightsaber_vader.iff"); saber->setGroup(WeaponGroup_2h); saber->setEquipSlotMask(CreatureEquipSlot_Weapon); saber->addInternalAttribute("weapon_group","4"); attackableNpc->setSecondaryWeapon(saber); if (gWorldConfig->isTutorial()) { attackableNpc->equipPrimaryWeapon(); } else { // attackableNpc->equipSecondaryWeapon(); } // Should be handle by "loot manager" // Let's put some credits in the inventory. npcInventory->setCredits((gRandom->getRand()%25) + 10); } else { npc->mTypeOptions = 0x108; } npc->setLoadState(LoadState_Attributes); // Save default direction, since player can make the npc change heading. // Can't apply this to a dynamically created npc. // npc->storeDefaultDirection(); return npc; }
void NonPersistentNpcFactory::handleDatabaseJobComplete(void* ref,DatabaseResult* result) { QueryNonPersistentNpcFactory* asyncContainer = reinterpret_cast<QueryNonPersistentNpcFactory*>(ref); switch(asyncContainer->mQueryType) { case NonPersistentNpcQuery_Attributes: { // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() AT NonPersistentNpcQuery_Attributes:", MSG_NORMAL); Object* object = gWorldManager->getObjectById(asyncContainer->mId); if (object) { _buildAttributeMap(object,result); if (object->getLoadState() == LoadState_Loaded && asyncContainer->mOfCallback) { // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() Invoking mOfCallback->handleObjectReady(npc)", MSG_NORMAL); asyncContainer->mOfCallback->handleObjectReady(object); } else { // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() Invoking NOTHING", MSG_NORMAL); } } else { gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() Object is GONE", MSG_NORMAL); } } break; //============================================================================= // // Upgrade version for use of the correct DB. // //============================================================================= case NonPersistentNpcQuery_LairTemplate: { // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() AT NonPersistentNpcQuery_LairTemplate:", MSG_NORMAL); NpcLairEntityEx lair; DataBinding* lairSpawnBinding = mDatabase->CreateDataBinding(9); lairSpawnBinding->addField(DFT_uint64,offsetof(NpcLairEntityEx,mCreatureSpwanRegion),8,0); lairSpawnBinding->addField(DFT_uint64,offsetof(NpcLairEntityEx,mTemplateId),8,1); lairSpawnBinding->addField(DFT_uint32,offsetof(NpcLairEntityEx,mCreatureGroup),4,2); lairSpawnBinding->addField(DFT_uint32,offsetof(NpcLairEntityEx,mNumberOfLairs),4,3); lairSpawnBinding->addField(DFT_float,offsetof(NpcLairEntityEx,mSpawnPosX),4,4); lairSpawnBinding->addField(DFT_float,offsetof(NpcLairEntityEx,mSpawnPosZ),4,5); lairSpawnBinding->addField(DFT_float,offsetof(NpcLairEntityEx,mSpawnDirY),4,6); lairSpawnBinding->addField(DFT_float,offsetof(NpcLairEntityEx,mSpawnDirW),4,7); lairSpawnBinding->addField(DFT_uint32,offsetof(NpcLairEntityEx,mFamily),4,8); DataBinding* lairSpawnNpcBinding = mDatabase->CreateDataBinding(4); lairSpawnNpcBinding->addField(DFT_bstring,offsetof(NPCObject,mModel),255,9); lairSpawnNpcBinding->addField(DFT_bstring,offsetof(NPCObject,mSpecies),255,10); lairSpawnNpcBinding->addField(DFT_bstring,offsetof(NPCObject,mSpeciesGroup),255,11); lairSpawnNpcBinding->addField(DFT_bstring,offsetof(NPCObject,mFaction),32,12); uint64 count = result->getRowCount(); result->GetNextRow(lairSpawnBinding,&lair); // Let's create the lair. // We save the lairs-type... that's kinda a template for the complete lair. LairObject* npc = new LairObject(asyncContainer->mTemplateId); // Set the new if of this temp object. npc->setId(asyncContainer->mId); // Register object with WorldManager. gWorldManager->addObject(npc, true); // May need the height also, in case of pre set (fixed) spawn position. npc->mPosition.x = lair.mSpawnPosX; npc->mPosition.z = lair.mSpawnPosZ; if (npc->getParentId() == 0) { // Heightmap only works outside. npc->mPosition.y = npc->getHeightAt2DPosition(lair.mSpawnPosX, lair.mSpawnPosZ, true); } else { // We do not have support for handling creatures inside. assert(false && "NonPersistentNpcFactory::handleDatabaseJobComplete NonPersistentNpcQuery_LairTemplate No support for handling creatures inside"); npc->mPosition.y = 0; } npc->mDirection.y = lair.mSpawnDirY; npc->mDirection.w = lair.mSpawnDirW; // Let's get the spawn area. const Anh_Math::Rectangle spawnArea = gWorldManager->getSpawnArea(lair.mCreatureSpwanRegion); // lair.mCreatureSpwanRegion npc->setSpawnArea(spawnArea); result->ResetRowIndex(); result->GetNextRow(lairSpawnNpcBinding,(void*)npc ); mDatabase->DestroyDataBinding(lairSpawnBinding); mDatabase->DestroyDataBinding(lairSpawnNpcBinding); Inventory* npcInventory = new Inventory(); npcInventory->setParent(npc); npc->mHam.mHealth.setCurrentHitPoints(500); npc->mHam.mAction.setCurrentHitPoints(500); npc->mHam.mMind.setCurrentHitPoints(500); npc->mHam.calcAllModifiedHitPoints(); // inventory npcInventory->setId(npc->mId + 1); npcInventory->setParentId(npc->mId); npcInventory->setModelString("object/tangible/inventory/shared_creature_inventory.iff"); npcInventory->setName("inventory"); npcInventory->setNameFile("item_n"); npcInventory->setTangibleGroup(TanGroup_Inventory); npcInventory->setTangibleType(TanType_CreatureInventory); npc->mEquipManager.addEquippedObject(CreatureEquipSlot_Inventory,npcInventory); npc->setType(ObjType_Creature); // This will ensure the use of the single H(am) bar. npc->setCreoGroup(CreoGroup_AttackableObject); npc->mTypeOptions = 0x0; npc->togglePvPStateOn((CreaturePvPStatus)(CreaturePvPStatus_Attackable)); // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() Attempting to get the creature templates for group %u used by this lair.", MSG_NORMAL, lair.mCreatureGroup); QueryNonPersistentNpcFactory* asContainer = new QueryNonPersistentNpcFactory(asyncContainer->mOfCallback, NonPersistentNpcQuery_LairCreatureTemplates, asyncContainer->mTemplateId, asyncContainer->mId); // Do not transfer object refs, use the handle, i.e. asyncContainer->mId // asContainer->mObject = npc; mDatabase->ExecuteSqlAsync(this, asContainer, "SELECT creature_groups.creature_id " "FROM creature_groups " "WHERE creature_groups.creature_group_id=%u;",lair.mCreatureGroup); } break; case NonPersistentNpcQuery_LairCreatureTemplates: { // Get the lair object. LairObject* npc = dynamic_cast<LairObject*>(gWorldManager->getObjectById(asyncContainer->mId)); assert(npc && "NonPersistentNpcFactory::handleDatabaseJobComplete NonPersistentNpcQuery_LairCreatureTemplates WorldManager unable to find object id"); uint64 creatureTemplateId; DataBinding* creatureTemplateBinding = mDatabase->CreateDataBinding(1); creatureTemplateBinding->addField(DFT_uint64,0,8,0); uint64 count = result->getRowCount(); int32 spawnRateInc = 100/static_cast<uint32>(count); int32 spawnRate = -1; for (uint64 i = 0; i < count; i++) { result->GetNextRow(creatureTemplateBinding, &creatureTemplateId); // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() Creature template %"PRIu64" used by lair ", MSG_NORMAL, creatureTemplateId); npc->setCreatureTemplate((uint32)i, creatureTemplateId); spawnRate += spawnRateInc; npc->setCreatureSpawnRate((uint32)i, (uint32)spawnRate); } if (count > 0 && spawnRate < 99) { npc->setCreatureSpawnRate(static_cast<uint32>(count) - 1, 99); } mDatabase->DestroyDataBinding(creatureTemplateBinding); // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() Attempting to get the Attributes", MSG_NORMAL); QueryNonPersistentNpcFactory* asContainer = new QueryNonPersistentNpcFactory(asyncContainer->mOfCallback,NonPersistentNpcQuery_Attributes, 0, npc->getId()); mDatabase->ExecuteSqlAsync(this,asContainer,"SELECT attributes.name,lair_attributes.value,attributes.internal" " FROM lair_attributes" " INNER JOIN attributes ON (lair_attributes.attribute_id = attributes.id)" " WHERE lair_attributes.lair_id = %"PRIu64" ORDER BY lair_attributes.order", asyncContainer->mTemplateId); } break; case NonPersistentNpcQuery_NpcTemplate: { // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() AT NonPersistentNpcQuery_NpcTemplate:", MSG_NORMAL); NPCObject* npc = _createNonPersistentNpc(result, asyncContainer->mTemplateId, asyncContainer->mId, asyncContainer->mParentObjectId); assert(npc); // Spawn related data. npc->setCellIdForSpawn(asyncContainer->mSpawnCellId); npc->setSpawnPosition(asyncContainer->mSpawnPosition); npc->setSpawnDirection(asyncContainer->mSpawnDirection); npc->setRespawnDelay(asyncContainer->mRespawnDelay); if( npc->getLoadState() == LoadState_Loaded && asyncContainer->mOfCallback) { // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() Invoking mOfCallback->handleObjectReady(npc)", MSG_NORMAL); asyncContainer->mOfCallback->handleObjectReady(npc); } else if (npc->getLoadState() == LoadState_Attributes) { QueryNonPersistentNpcFactory* asContainer = new QueryNonPersistentNpcFactory(asyncContainer->mOfCallback,NonPersistentNpcQuery_Attributes, 0, npc->getId()); // gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() Invoking NonPersistentNpcQuery_Attributes NPC ID = %"PRIu64"", MSG_NORMAL, npc->getId()); mDatabase->ExecuteSqlAsync(this,asContainer,"SELECT attributes.name,non_persistent_npc_attributes.value,attributes.internal" " FROM non_persistent_npc_attributes" " INNER JOIN attributes ON (non_persistent_npc_attributes.attribute_id = attributes.id)" " WHERE non_persistent_npc_attributes.npc_id = %"PRIu64" ORDER BY non_persistent_npc_attributes.order", asyncContainer->mTemplateId); } } break; default: { gLogger->logMsgF("NonPersistentNpcFactory::handleDatabaseJobComplete() UNKNOWN query = %u\n", MSG_NORMAL, asyncContainer->mQueryType); } break; } delete asyncContainer; }