Jump to content

[Patch] Support for npc on transport


Auntie Mangos

Recommended Posts

tested and bugged :)

need lots a fixes:

1. post tom_rus

2. this part:

@@ -726,6 +727,13 @@ bool ChatHandler::HandleGameObjectAddCommand(const char* args)
    float o = float(chr->GetOrientation());
    Map *map = chr->GetMap();

+    if(chr->GetTransport())
+    {
+        chr->GetTransport()->AddNpcPassager(id, chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
+        WorldDatabase.PQuery("INSERT INTO creature_transport (entry, npc_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO) values (%u, %u, %f, %f, %f, %f)", chr->GetTransport()->GetEntry(), id, chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
+        return true;
+    }
+

need move from ChatHandler::HandleGameObjectAddCommand to ChatHandler::HandleNpcAddCommand

3. and (maybe?) fill table?

Link to comment
Share on other sites

  • 40 years later...
  • Replies 73
  • Created
  • Last Reply

Top Posters In This Topic

Hi, i'm currently work on a implantation of npc on transports.

For now, we can spawn a npc on a transport with db support (new table, creature_transport).

I have make a little support for pet on transport, but it's no perfect (some bug).

We need a support for creature movement on transport (for fight on transport, for example).

But the major problem is, we must work with transport position base, and not a general base.

Patch link : http://filebin.ca/nwrgd/npc_transport.diff

SQL link : http://filebin.ca/bwtuon/creature_transport.sql

Link to comment
Share on other sites

Hello woweur,

Last time I looked into this problem about mobs on transports, I found that transports are just moving maps like 588 which is 'Transport: Menethil to Auberdine'. I could not take a look at your code since I cannot access filebin from here, but spawns could just be added to normal creature table with coords related to this moving map I think.

Then the movement packet sent has the movement related to the base map and transport entry has follower reference. Then when I tried to make a patch, I just added a column to transport table to know the map id and be able to make the movement packet properly. Btw I did stop because I did miss time and it was not as simple as I thought to make all movement handlers still work when mobs were on transports.

My 2 cents.

Neo2003

Link to comment
Share on other sites

  • 3 weeks later...
  • 3 weeks later...
Transport in not part if map system.. and as i can see boarded creatures too

so that creatures will be not be able to send broadcast packets and etc

Did you ever look at MapManager::Update()? Also, on retail, the same transport has a different GUID on two different maps - i.e. boat in Booty Bay.
Link to comment
Share on other sites

  • 4 weeks later...

UDB 0.12.0 (390) for MaNGOS 9763 with SD2 SQL for rev. 1677.

I couldn't apply this patch:

$ git apply npc_transport.diff

error: patch failed: src/game/Level12.cpp:42

error: src/game/Level12.cpp: patch does not apply

error: patch failed: src/game/ObjectAccessor.h:94

error: src/game/ObjectAccessor.h: patch does not apply

error: patch failed: src/game/Transports.cpp:559

error: src/game/Transports.cpp: patch does not apply

error: patch failed src/game/Unit.cpp:48

error: src/game/Unit.cpp: patch does not apply

Link to comment
Share on other sites

updated for 9913 revision

diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp
index ad9682f..f46c7d8 100644
--- a/src/game/Level2.cpp
+++ b/src/game/Level2.cpp
@@ -41,6 +41,7 @@
#include <iostream>
#include <fstream>
#include <map>
+#include "Transports.h"

#include "TargetedMovementGenerator.h"                      // for HandleNpcUnFollowCommand

@@ -726,6 +727,13 @@ bool ChatHandler::HandleGameObjectAddCommand(const char* args)
    float o = float(chr->GetOrientation());
    Map *map = chr->GetMap();

+    if(chr->GetTransport())
+    {
+        chr->GetTransport()->AddNpcPassager(id, chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
+        WorldDatabase.PQuery("INSERT INTO creature_transport (entry, npc_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO) values (%u, %u, %f, %f, %f, %f)", chr->GetTransport()->GetEntry(), id, chr->GetTransOffsetX(), chr->GetTransOffsetY(), chr->GetTransOffsetZ(), chr->GetTransOffsetO());
+        return true;
+    }
+
    GameObject* pGameObj = new GameObject;
    uint32 db_lowGUID = sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);

diff --git a/src/game/Map.cpp b/src/game/Map.cpp
index 206af48..fb742f2 100644
--- a/src/game/Map.cpp
+++ b/src/game/Map.cpp
@@ -768,7 +768,7 @@ void Map::Remove(Player *player, bool remove)

template<class T>
void
-Map::Remove(T *obj, bool remove)
+Map::Remove(T *obj, bool remove, bool changeMap)
{
    CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
    if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP )
@@ -790,7 +790,7 @@ Map::Remove(T *obj, bool remove)

    if(remove)
        obj->CleanupsBeforeDelete();
-    else
+    else if(!changeMap)
        obj->RemoveFromWorld();

    RemoveFromGrid(obj,grid,cell);
@@ -2274,10 +2274,10 @@ template void Map::Add(Creature *);
template void Map::Add(GameObject *);
template void Map::Add(DynamicObject *);

-template void Map::Remove(Corpse *,bool);
-template void Map::Remove(Creature *,bool);
-template void Map::Remove(GameObject *, bool);
-template void Map::Remove(DynamicObject *, bool);
+template void Map::Remove(Corpse *,bool,bool);
+template void Map::Remove(Creature *,bool,bool);
+template void Map::Remove(GameObject *, bool,bool);
+template void Map::Remove(DynamicObject *, bool,bool);

/* ******* Dungeon Instance Maps ******* */

diff --git a/src/game/Map.h b/src/game/Map.h
index 3acb881..b49024c 100644
--- a/src/game/Map.h
+++ b/src/game/Map.h
@@ -231,7 +231,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
        virtual bool Add(Player *);
        virtual void Remove(Player *, bool);
        template<class T> void Add(T *);
-        template<class T> void Remove(T *, bool);
+        template<class T> void Remove(T *, bool, bool changemap = false);

        virtual void Update(const uint32&);

diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index 55fc2d0..f3c0bb9 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -265,6 +265,12 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
                /*if (((Creature*)unit)->hasUnitState(UNIT_STAT_MOVING))
                    unit->m_movementInfo.SetMovementFlags(MOVEFLAG_FORWARD);*/

+                if(unit->m_transportGUID)
+                {
+                    unit->m_movementInfo.AddMovementFlag(MOVEFLAG_ONTRANSPORT);
+                    unit->m_movementInfo.SetTransportData(unit->m_transportGUID, unit->m_transportPosition[0], unit->m_transportPosition[1], unit->m_transportPosition[2], unit->m_transportPosition[3], 0, 0);
+                }
+
                if (((Creature*)unit)->canFly())
                {
                    // (ok) most seem to have this
diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h
index 2853d60..c8abce8 100644
--- a/src/game/ObjectAccessor.h
+++ b/src/game/ObjectAccessor.h
@@ -94,6 +94,7 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
        // FIXME: map local object with global search
        static Creature*   GetCreatureInWorld(ObjectGuid guid)   { return FindHelper<Creature>(guid); }
        static GameObject* GetGameObjectInWorld(ObjectGuid guid) { return FindHelper<GameObject>(guid); }
+        static Pet* GetPetInWorld(ObjectGuid guid) { return FindHelper<Pet>(guid); }

        // possible local search for specific object map
        static Unit* GetUnit(WorldObject const &, ObjectGuid guid);
diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp
index 95a5b4f..f8a4a35 100644
--- a/src/game/Pet.cpp
+++ b/src/game/Pet.cpp
@@ -28,6 +28,8 @@
#include "CreatureAI.h"
#include "Unit.h"
#include "Util.h"
+#include "Transports.h"
+#include "MapManager.h"

char const* petTypeSuffix[MAX_PET_TYPE] =
{
@@ -561,6 +563,48 @@ void Pet::Update(uint32 diff)
        default:
            break;
    }
+
+    // Ajout / delete des pets sur les transports
+    if(GetOwner() && GetOwner()->GetTypeId() == TYPEID_PLAYER)
+    {
+        Player* owner = ((Player*)GetOwner());
+        if(owner->GetTransport())
+        {
+            if(!m_transportGUID)
+            {
+                m_transportGUID = owner->GetTransport()->GetGUID();
+                m_transportPosition[0] = owner->GetTransOffsetX();
+                m_transportPosition[1] = owner->GetTransOffsetY();
+                m_transportPosition[2] = owner->GetTransOffsetZ();
+                m_transportPosition[3] = owner->GetTransOffsetO();
+                owner->GetTransport()->m_NpcPassagerSet.insert(GetGUID());
+            }
+            else
+            {
+                m_transportPosition[0] = owner->GetTransOffsetX();
+                m_transportPosition[1] = owner->GetTransOffsetY();
+                m_transportPosition[2] = owner->GetTransOffsetZ();
+                m_transportPosition[3] = owner->GetTransOffsetO();
+            }
+        }
+        else if(m_transportGUID)
+        {
+            for (MapManager::TransportSet::const_iterator iter = sMapMgr.m_Transports.begin(); iter != sMapMgr.m_Transports.end(); ++iter)
+            {
+                if ((*iter)->GetGUID() == m_transportGUID)
+                {
+                    (*iter)->m_NpcPassagerSet.erase(m_transportGUID);
+                    m_transportGUID = 0;
+                    m_transportPosition[0] = 0.00f;
+                    m_transportPosition[1] = 0.00f;
+                    m_transportPosition[2] = 0.00f;
+                    m_transportPosition[3] = 0.00f;
+                    break;
+                }
+            }
+        }
+    }
+
    Creature::Update(diff);
}

diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp
index b54152d..8bd8614 100644
--- a/src/game/Transports.cpp
+++ b/src/game/Transports.cpp
@@ -105,6 +105,18 @@ void MapManager::LoadTransports()
        //If we someday decide to use the grid to track transports, here:
        t->SetMap(sMapMgr.CreateMap(mapid, t));

+        // On spawn les npc liй au transport
+        QueryResult * npc_transport = WorldDatabase.PQuery("SELECT npc_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO FROM creature_transport WHERE entry = '%u'", entry);
+        if(npc_transport)
+        {
+            do
+            {
+                Field *fields = npc_transport->Fetch();
+                t->AddNpcPassager(fields[0].GetUInt32(), fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat());
+            } while( npc_transport->NextRow() );
+        }
+        delete npc_transport;
+
        //t->GetMap()->Add<GameObject>((GameObject *)t);
        ++count;
    } while(result->NextRow());
@@ -458,6 +470,32 @@ void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z)
    //player far teleport would try to create same instance, but we need it NOW for transport...
    //correct me if I'm wrong 
    Map * newMap = sMapMgr.CreateMap(newMapid, this);
+    for(std::set<uint64>::iterator itr = m_NpcPassagerSet.begin(); itr != m_NpcPassagerSet.end()
+    {
+        std::set<uint64>::iterator it2 = itr;
+        ++itr;
+
+        uint64 guid = (*it2);
+        if(Creature* npc = sObjectAccessor.GetCreatureInWorld(guid))
+        {
+            npc->GetMap()->Remove(npc, false, true);
+            npc->SetMap(newMap);
+            newMap->Add(npc);
+            npc->Relocate(GetPositionX() + x, y + GetPositionY(), z + GetPositionZ());
+        }
+        else if(Pet* npc = sObjectAccessor.GetPetInWorld(guid))
+        {
+            npc->GetMap()->Remove((Creature*)npc, false, true);
+            npc->SetMap(newMap);
+            newMap->Add((Creature*)npc);
+            npc->Relocate(GetPositionX() + x, y + GetPositionY(), z + GetPositionZ());
+        }
+        else
+        {
+            m_NpcPassagerSet.erase(guid);
+            continue;
+        }
+    }
    SetMap(newMap);

    if(oldMap != newMap)
@@ -508,6 +546,37 @@ void Transport::Update(time_t /*p_time*/)
        else
        {
            Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z);
+            // On update les positions des npcs
+            for(std::set<uint64>::iterator itr = m_NpcPassagerSet.begin(); itr != m_NpcPassagerSet.end()
+            {
+                std::set<uint64>::iterator it2 = itr;
+                ++itr;
+
+                uint64 guid = (*it2);
+                if(Creature* npc = sObjectAccessor.GetCreatureInWorld(guid))
+                {
+                    float x, y, z, o;
+                    x = GetPositionX() + npc->m_transportPosition[0];
+                    y = GetPositionY() + npc->m_transportPosition[1];
+                    z = GetPositionY() + npc->m_transportPosition[2];
+                    o = GetOrientation() + npc->m_transportPosition[3];
+                    npc->Relocate(x, y, z);
+                }
+                else if(Pet* npc = sObjectAccessor.GetPetInWorld(guid))
+                {
+                    float x, y, z, o;
+                    x = GetPositionX() + npc->m_transportPosition[0];
+                    y = GetPositionY() + npc->m_transportPosition[1];
+                    z = GetPositionY() + npc->m_transportPosition[2];
+                    o = GetOrientation() + npc->m_transportPosition[3];
+                    npc->Relocate(x, y, z);
+                }
+                else
+                {
+                    m_NpcPassagerSet.erase(guid);
+                    continue;
+                }
+            }
        }

        /*
@@ -569,3 +638,73 @@ void Transport::DoEventIfAny(WayPointMap::value_type const& node, bool departure
        GetMap()->ScriptsStart(sEventScripts, eventid, this, this);
    }
}
+
+void Transport::AddNpcPassager(uint32 entry, float x, float y, float z, float o)
+{
+    Map* map = GetMap();
+    Creature* pCreature = new Creature;
+    if (!pCreature->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), this->GetPhaseMask(), entry, (uint32)this->GetGOInfo()->faction))
+    {
+        delete pCreature;
+        return;
+    }
+
+    pCreature->m_transportGUID = GetGUID();
+    pCreature->m_transportPosition[0] = x;
+    pCreature->m_transportPosition[1] = y;
+    pCreature->m_transportPosition[2] = z;
+    pCreature->m_transportPosition[3] = o;
+
+    pCreature->Relocate(GetPositionX() + x, y + GetPositionY(), z + GetPositionZ() , o + GetOrientation());
+
+    if(!pCreature->IsPositionValid())
+    {
+        sLog.outError("Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
+        delete pCreature;
+        return;
+    }
+
+    pCreature->AIM_Initialize();
+
+    map->Add(pCreature);
+    m_NpcPassagerSet.insert(pCreature->GetGUID());
+}
+
+void Transport::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const
+{
+    // Informations des npcs sur le transport
+    for(std::set<uint64>::const_iterator itr = m_NpcPassagerSet.begin(); itr != m_NpcPassagerSet.end()
+    {
+        std::set<uint64>::const_iterator it2 = itr;
+        ++itr;
+
+        uint64 guid = (*it2);
+        if(Creature* npc = sObjectAccessor.GetCreatureInWorld(guid))
+        {
+            float x, y, z, o;
+            x = GetPositionX() + npc->m_transportPosition[0];
+            y = GetPositionY() + npc->m_transportPosition[1];
+            z = GetPositionY() + npc->m_transportPosition[2];
+            o = GetOrientation() + npc->m_transportPosition[3];
+            npc->Relocate(x, y, z);
+            npc->BuildCreateUpdateBlockForPlayer(data, target);
+        }
+        else if(Pet* npc = sObjectAccessor.GetPetInWorld(guid))
+        {
+            float x, y, z, o;
+            x = GetPositionX() + npc->m_transportPosition[0];
+            y = GetPositionY() + npc->m_transportPosition[1];
+            z = GetPositionY() + npc->m_transportPosition[2];
+            o = GetOrientation() + npc->m_transportPosition[3];
+            npc->Relocate(x, y, z);
+            npc->BuildCreateUpdateBlockForPlayer(data, target);
+        }
+        else
+        {
+            m_NpcPassagerSet.erase(guid);
+            continue;
+        }
+    }
+
+    Object::BuildCreateUpdateBlockForPlayer(data, target);
+}
\\ No newline at end of file
diff --git a/src/game/Transports.h b/src/game/Transports.h
index bbaffbc..2f191fb 100644
--- a/src/game/Transports.h
+++ b/src/game/Transports.h
@@ -39,6 +39,10 @@ class Transport : public GameObject
        typedef std::set<Player*> PlayerSet;
        PlayerSet const& GetPassengers() const { return m_passengers; }

+        mutable std::set<uint64> m_NpcPassagerSet;
+        void AddNpcPassager(uint32 entry, float x, float y, float z, float o);
+        void BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const;
+
    private:
        struct WayPoint
        {
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 8585275..b572b21 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -48,6 +48,7 @@
#include "Traveller.h"
#include "VMapFactory.h"
#include "MovementGenerator.h"
+#include "Transports.h"

#include <math.h>
#include <stdarg.h>
@@ -251,6 +252,11 @@ Unit::Unit()
    // remove aurastates allowing special moves
    for(int i=0; i < MAX_REACTIVE; ++i)
        m_reactiveTimer[i] = 0;
+
+    // Transport data
+    m_transportGUID = 0;
+    for(int i = 0; i < 4; i++)
+        m_transportPosition[i] = 0.00f;
}

Unit::~Unit()
@@ -352,8 +358,16 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, SplineTy

    float moveTime = (float)Time;

-    WorldPacket data( SMSG_MONSTER_MOVE, (41 + GetPackGUID().size()) );
+    int opcode = m_transportGUID ? SMSG_MONSTER_MOVE_TRANSPORT : SMSG_MONSTER_MOVE;
+    WorldPacket data( opcode, (41 + GetPackGUID().size()) );
    data << GetPackGUID();
+
+      if(opcode == SMSG_MONSTER_MOVE_TRANSPORT)
+        {
+          data.appendPackGUID(m_transportGUID);
+          data << uint8(0);
+        }
+
    data << uint8(0);                                       // new in 3.1 bool, used to toggle MOVEFLAG2_UNK4 = 0x0040 on client side
    data << GetPositionX() << GetPositionY() << GetPositionZ();
    data << uint32(getMSTime());
@@ -390,7 +404,15 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, SplineTy

    data << uint32(moveTime);                               // Time in between points
    data << uint32(1);                                      // 1 single waypoint
-    data << NewPosX << NewPosY << NewPosZ;                  // the single waypoint Point B
+
+    if(opcode == SMSG_MONSTER_MOVE_TRANSPORT)
+    {
+        NewPosX = m_transportPosition[0];
+        NewPosY = m_transportPosition[1];
+        NewPosZ = m_transportPosition[2];
+    }
+
+    data << NewPosX << NewPosY << NewPosZ;                  // the single waypoint Point B

    va_end(vargs);

diff --git a/src/game/Unit.h b/src/game/Unit.h
index b516aae..7469e49 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -1814,6 +1814,10 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
        // Movement info
        MovementInfo m_movementInfo;

+        // Transport info
+        uint64 m_transportGUID;
+        float m_transportPosition[4];
+
    protected:
        explicit Unit ();

Link to comment
Share on other sites

Exactly, yad02. This patch is intended to add support for NPCs to be crew aboard ships, airships, and other transports.

If the bugs can be worked out and additional features implemented, we'll finally be able to perform some of the quests that involve combat aboard transports.

Plus, it'll be a lot less weird and spooky sailing completely alone. It feels like I'm on a ghost ship every time I go from Eastern Kingdoms to Kalimdor.

Link to comment
Share on other sites

  • 1 month later...

hi,

I'm not very much into mangos yet, (do only have sd2 experience until now) and I tried to implement this patch.

However it doesn't compile because of errors like: "Unit::GetVehicleGUID": No access to protected Member, whichs declaration was done in unit class (translatet this from german compile error message).

Now is this patch just outdatet (used tempuras version), or did I do anything wrong? I did tempuras fix, but don't know what to do with tomrus statement.

sorry again for I do not know much about mangos core yet (alway like to learn more though), hope someone can give me a hint.

PS: I heard the handling of creatures on transports is supposed to work with extra maps for the single transports. How much of this does mangos already support (if any)?

Link to comment
Share on other sites

PS: I heard the handling of creatures on transports is supposed to work with extra maps for the single transports. How much of this does mangos already support (if any)?

This is how it should work. Neither mangos nor this patch supports it, and since that is the proper way, this patch will probably never be accepted.

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use