diff --git a/zone/command.cpp b/zone/command.cpp index 3705124fc..15e2ecdfb 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2009,10 +2009,58 @@ void command_setlsinfo(Client *c, const Seperator *sep) void command_grid(Client *c, const Seperator *sep) { - if (strcasecmp("max", sep->arg[1]) == 0) - c->Message(0, "Highest grid ID in this zone: %d", database.GetHighestGrid(zone->GetZoneID())); - else if (strcasecmp("add", sep->arg[1]) == 0) - database.ModifyGrid(c, false,atoi(sep->arg[2]),atoi(sep->arg[3]), atoi(sep->arg[4]),zone->GetZoneID()); + if (strcasecmp("max", sep->arg[1]) == 0) { + c->Message(0, "Highest grid ID in this zone: %d", database.GetHighestGrid(zone->GetZoneID())); + } + else if (strcasecmp("add", sep->arg[1]) == 0) { + database.ModifyGrid(c, false, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), zone->GetZoneID()); + } + else if (strcasecmp("show", sep->arg[1]) == 0) { + + Mob *target = c->GetTarget(); + + if (!target || !target->IsNPC()) { + c->Message(0, "You need a NPC target!"); + return; + } + + std::string query = StringFormat( + "SELECT `x`, `y`, `z`, `heading`, `number`, `pause` " + "FROM `grid_entries` " + "WHERE `zoneid` = %u and `gridid` = %i " + "ORDER BY `number` ", + zone->GetZoneID(), + target->CastToNPC()->GetGrid() + ); + + auto results = database.QueryDatabase(query); + if (!results.Success()) { + c->Message(0, "Error querying database."); + c->Message(0, query.c_str()); + } + + if (results.RowCount() == 0) { + c->Message(0, "No grid found"); + return; + } + + /** + * Spawn grid nodes + */ + for (auto row = results.begin(); row != results.end(); ++row) { + auto node_position = glm::vec4(atof(row[0]), atof(row[1]), atof(row[2]), atof(row[3])); + + NPC *npc = NPC::SpawnGridNodeNPC( + target->GetCleanName(), + node_position, + static_cast(target->CastToNPC()->GetGrid()), + static_cast(atoi(row[4])), + static_cast(atoi(row[5])) + ); + npc->SetFlyMode(1); + npc->GMMove(node_position.x, node_position.y, node_position.z, node_position.w); + } + } else if (strcasecmp("delete", sep->arg[1]) == 0) database.ModifyGrid(c, true,atoi(sep->arg[2]),0,0,zone->GetZoneID()); else { @@ -4516,7 +4564,7 @@ void command_goto(Client *c, const Seperator *sep) else if (!(sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3))) c->Message(0, "Usage: #goto [x y z]"); else - c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), atof(sep->arg[1]), atof(sep->arg[2]), atof(sep->arg[3]), 0.0f); + c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), atof(sep->arg[1]), atof(sep->arg[2]), atof(sep->arg[3]), c->GetHeading()); } void command_iteminfo(Client *c, const Seperator *sep) diff --git a/zone/npc.cpp b/zone/npc.cpp index 29e2f20ef..156cb67fd 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -985,6 +985,49 @@ bool NPC::SpawnZoneController(){ return true; } +NPC * NPC::SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32 grid_id, uint32 grid_number, uint32 pause) { + auto npc_type = new NPCType; + memset(npc_type, 0, sizeof(NPCType)); + + sprintf(npc_type->name, "(%s)_%u", name.c_str(), grid_number); + sprintf(npc_type->lastname, "Number: %u Grid: %u Pause: %u", grid_number, grid_id, pause); + + npc_type->cur_hp = 4000000; + npc_type->max_hp = 4000000; + npc_type->race = 2254; + npc_type->gender = 2; + npc_type->class_ = 9; + npc_type->deity = 1; + npc_type->level = 200; + npc_type->npc_id = 0; + npc_type->loottable_id = 0; + npc_type->texture = 1; + npc_type->light = 1; + npc_type->size = 3; + npc_type->runspeed = 0; + npc_type->d_melee_texture1 = 1; + npc_type->d_melee_texture2 = 1; + npc_type->merchanttype = 1; + npc_type->bodytype = 1; + npc_type->show_name = true; + npc_type->STR = 150; + npc_type->STA = 150; + npc_type->DEX = 150; + npc_type->AGI = 150; + npc_type->INT = 150; + npc_type->WIS = 150; + npc_type->CHA = 150; + npc_type->findable = true; + + auto node_position = glm::vec4(position.x, position.y, position.z, position.w); + auto npc = new NPC(npc_type, nullptr, node_position, FlyMode1); + npc->GiveNPCTypeData(npc_type); + + entity_list.AddNPC(npc, true, true); + + return npc; +} + NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client* client) { if(spawncommand == 0 || spawncommand[0] == 0) { return 0; @@ -2715,5 +2758,4 @@ void NPC::ModifyStatsOnCharm(bool bRemoved) // the rest of the stats aren't cached, so lets just do these two instead of full CalcBonuses() SetAttackTimer(); CalcAC(); -} - +} \ No newline at end of file diff --git a/zone/npc.h b/zone/npc.h index a2cad8b95..0201d3b9f 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -110,6 +110,8 @@ public: virtual ~NPC(); + static NPC *SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32 grid_id, uint32 grid_number, uint32 pause); + //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); @@ -562,6 +564,8 @@ protected: bool raid_target; bool ignore_despawn; //NPCs with this set to 1 will ignore the despawn value in spawngroup + + private: uint32 loottable_id; bool skip_global_loot;