mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-12-23 03:40:05 +00:00
commit
4caca07856
@ -56,6 +56,17 @@ void ChunkManager::removePlayer(std::pair<int, int> chunkPos, CNSocket* sock) {
|
||||
// TODO: if players and NPCs are empty, free chunk and remove it from surrounding views
|
||||
}
|
||||
|
||||
void ChunkManager::removeNPC(std::pair<int, int> chunkPos, int32_t id) {
|
||||
if (!checkChunk(chunkPos))
|
||||
return; // do nothing if chunk doesn't even exist
|
||||
|
||||
Chunk* chunk = chunks[chunkPos];
|
||||
|
||||
chunk->NPCs.erase(id); // gone
|
||||
|
||||
// TODO: if players and NPCs are empty, free chunk and remove it from surrounding views
|
||||
}
|
||||
|
||||
bool ChunkManager::checkChunk(std::pair<int, int> chunk) {
|
||||
return chunks.find(chunk) != chunks.end();
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ namespace ChunkManager {
|
||||
void addNPC(int posX, int posY, int32_t id);
|
||||
void addPlayer(int posX, int posY, CNSocket* sock);
|
||||
void removePlayer(std::pair<int, int> chunkPos, CNSocket* sock);
|
||||
void removeNPC(std::pair<int, int> chunkPos, int32_t id);
|
||||
bool checkChunk(std::pair<int, int> chunk);
|
||||
std::pair<int, int> grabChunk(int posX, int posY);
|
||||
std::vector<Chunk*> grabChunks(std::pair<int, int> chunkPos);
|
||||
|
@ -16,6 +16,14 @@ const float CN_EP_RANK_3 = 0.5f;
|
||||
const float CN_EP_RANK_4 = 0.3f;
|
||||
const float CN_EP_RANK_5 = 0.29f;
|
||||
|
||||
// NPC classes
|
||||
enum NPCClass {
|
||||
NPC_BASE = 0,
|
||||
NPC_MOB = 1,
|
||||
NPC_BUS = 2,
|
||||
NPC_EGG = 3
|
||||
};
|
||||
|
||||
// nano powers
|
||||
enum {
|
||||
EST_NONE = 0,
|
||||
|
@ -5,6 +5,7 @@
|
||||
class BaseNPC {
|
||||
public:
|
||||
sNPCAppearanceData appearanceData;
|
||||
NPCClass npcClass;
|
||||
|
||||
BaseNPC() {};
|
||||
BaseNPC(int x, int y, int z, int type) {
|
||||
@ -20,4 +21,7 @@ public:
|
||||
// hopefully no collisions happen :eyes:
|
||||
appearanceData.iNPC_ID = (int32_t)rand();
|
||||
};
|
||||
BaseNPC(int x, int y, int z, int type, NPCClass classType) : BaseNPC(x, y, z, type) {
|
||||
npcClass = classType;
|
||||
}
|
||||
};
|
||||
|
@ -33,15 +33,30 @@ void NPCManager::init() {
|
||||
void NPCManager::addNPC(std::vector<Chunk*> viewableChunks, int32_t id) {
|
||||
BaseNPC* npc = NPCs[id];
|
||||
|
||||
// create struct
|
||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
||||
enterData.NPCAppearanceData = npc->appearanceData;
|
||||
switch (npc->npcClass) {
|
||||
case NPC_BUS:
|
||||
INITSTRUCT(sP_FE2CL_TRANSPORTATION_ENTER, enterBusData);
|
||||
enterBusData.AppearanceData = { 3, npc->appearanceData.iNPC_ID, npc->appearanceData.iNPCType, npc->appearanceData.iX, npc->appearanceData.iY, npc->appearanceData.iZ };
|
||||
|
||||
for (Chunk* chunk : viewableChunks) {
|
||||
for (CNSocket* sock : chunk->players) {
|
||||
// send to socket
|
||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
for (Chunk* chunk : viewableChunks) {
|
||||
for (CNSocket* sock : chunk->players) {
|
||||
// send to socket
|
||||
sock->sendPacket((void*)&enterBusData, P_FE2CL_TRANSPORTATION_ENTER, sizeof(sP_FE2CL_TRANSPORTATION_ENTER));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// create struct
|
||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
||||
enterData.NPCAppearanceData = npc->appearanceData;
|
||||
|
||||
for (Chunk* chunk : viewableChunks) {
|
||||
for (CNSocket* sock : chunk->players) {
|
||||
// send to socket
|
||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,21 +81,38 @@ void NPCManager::removeNPC(int32_t id) {
|
||||
Chunk* chunk = ChunkManager::chunks[pos];
|
||||
chunk->NPCs.erase(id);
|
||||
|
||||
// create struct
|
||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
||||
exitData.iNPC_ID = id;
|
||||
switch (entity->npcClass) {
|
||||
case NPC_BUS:
|
||||
INITSTRUCT(sP_FE2CL_TRANSPORTATION_EXIT, exitBusData);
|
||||
exitBusData.eTT = 3;
|
||||
exitBusData.iT_ID = id;
|
||||
|
||||
// remove it from the clients
|
||||
for (Chunk* chunk : ChunkManager::grabChunks(pos)) {
|
||||
for (CNSocket* sock : chunk->players) {
|
||||
// send to socket
|
||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
for (Chunk* chunk : ChunkManager::grabChunks(pos)) {
|
||||
for (CNSocket* sock : chunk->players) {
|
||||
// send to socket
|
||||
sock->sendPacket((void*)&exitBusData, P_FE2CL_TRANSPORTATION_EXIT, sizeof(sP_FE2CL_TRANSPORTATION_EXIT));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_MOB:
|
||||
// remove from mob list if it's a mob
|
||||
if (MobManager::Mobs.find(id) != MobManager::Mobs.end())
|
||||
MobManager::Mobs.erase(id);
|
||||
// fall through
|
||||
default:
|
||||
// create struct
|
||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
||||
exitData.iNPC_ID = id;
|
||||
|
||||
// remove from mob list if it's a mob
|
||||
if (MobManager::Mobs.find(id) != MobManager::Mobs.end())
|
||||
MobManager::Mobs.erase(id);
|
||||
// remove it from the clients
|
||||
for (Chunk* chunk : ChunkManager::grabChunks(pos)) {
|
||||
for (CNSocket* sock : chunk->players) {
|
||||
// send to socket
|
||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// finally, remove it from the map and free it
|
||||
NPCs.erase(id);
|
||||
@ -89,6 +121,24 @@ void NPCManager::removeNPC(int32_t id) {
|
||||
std::cout << "npc removed!" << std::endl;
|
||||
}
|
||||
|
||||
void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z) {
|
||||
BaseNPC* npc = NPCs[id];
|
||||
|
||||
std::pair<int, int> oldPos = ChunkManager::grabChunk(npc->appearanceData.iX, npc->appearanceData.iY);
|
||||
npc->appearanceData.iX = X;
|
||||
npc->appearanceData.iY = Y;
|
||||
npc->appearanceData.iZ = Z;
|
||||
std::pair<int, int> newPos = ChunkManager::grabChunk(X, Y);
|
||||
|
||||
// nothing to be done
|
||||
if (newPos == oldPos)
|
||||
return;
|
||||
|
||||
// pull NPC from old chunk and add to new chunk
|
||||
ChunkManager::removeNPC(oldPos, npc->appearanceData.iNPC_ID);
|
||||
ChunkManager::addNPC(X, Y, npc->appearanceData.iNPC_ID);
|
||||
}
|
||||
|
||||
void NPCManager::npcVendorBuy(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_VENDOR_ITEM_BUY))
|
||||
return; // malformed packet
|
||||
|
@ -22,6 +22,7 @@ namespace NPCManager {
|
||||
|
||||
void addNPC(std::vector<Chunk*> viewableChunks, int32_t);
|
||||
void removeNPC(int32_t);
|
||||
void updateNPCPosition(int32_t, int X, int Y, int Z);
|
||||
|
||||
void npcBarkHandler(CNSocket* sock, CNPacketData* data);
|
||||
void npcSummonHandler(CNSocket* sock, CNPacketData* data);
|
||||
|
@ -27,6 +27,7 @@ void PlayerManager::init() {
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_LAUNCHER, PlayerManager::launchPlayer);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ZIPLINE, PlayerManager::ziplinePlayer);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVEPLATFORM, PlayerManager::movePlatformPlayer);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVETRANSPORTATION, PlayerManager::moveSliderPlayer);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SLOPE, PlayerManager::moveSlopePlayer);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GOTO, PlayerManager::gotoPlayer);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SET_VALUE, PlayerManager::setSpecialPlayer);
|
||||
@ -79,7 +80,6 @@ void PlayerManager::removePlayer(CNSocket* key) {
|
||||
}
|
||||
|
||||
void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
|
||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
||||
INITSTRUCT(sP_FE2CL_PC_EXIT, exitPlayer);
|
||||
|
||||
// for chunks that need the player to be removed from
|
||||
@ -87,8 +87,20 @@ void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket*
|
||||
|
||||
// remove NPCs
|
||||
for (int32_t id : chunk->NPCs) {
|
||||
exitData.iNPC_ID = id;
|
||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
BaseNPC* npc = NPCManager::NPCs[id];
|
||||
switch (npc->npcClass) {
|
||||
case NPC_BUS:
|
||||
INITSTRUCT(sP_FE2CL_TRANSPORTATION_EXIT, exitBusData);
|
||||
exitBusData.eTT = 3;
|
||||
exitBusData.iT_ID = id;
|
||||
sock->sendPacket((void*)&exitBusData, P_FE2CL_TRANSPORTATION_EXIT, sizeof(sP_FE2CL_TRANSPORTATION_EXIT));
|
||||
break;
|
||||
default:
|
||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
||||
exitData.iNPC_ID = id;
|
||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// remove players from eachother
|
||||
@ -105,14 +117,24 @@ void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket*
|
||||
}
|
||||
|
||||
void PlayerManager::addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
|
||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
||||
INITSTRUCT(sP_FE2CL_PC_NEW, newPlayer);
|
||||
|
||||
for (Chunk* chunk : chunks) {
|
||||
// add npcs
|
||||
for (int32_t id : chunk->NPCs) {
|
||||
enterData.NPCAppearanceData = NPCManager::NPCs[id]->appearanceData;
|
||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
BaseNPC* npc = NPCManager::NPCs[id];
|
||||
switch (npc->npcClass) {
|
||||
case NPC_BUS:
|
||||
INITSTRUCT(sP_FE2CL_TRANSPORTATION_ENTER, enterBusData);
|
||||
enterBusData.AppearanceData = { 3, npc->appearanceData.iNPC_ID, npc->appearanceData.iNPCType, npc->appearanceData.iX, npc->appearanceData.iY, npc->appearanceData.iZ };
|
||||
sock->sendPacket((void*)&enterBusData, P_FE2CL_TRANSPORTATION_ENTER, sizeof(sP_FE2CL_TRANSPORTATION_ENTER));
|
||||
break;
|
||||
default:
|
||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
||||
enterData.NPCAppearanceData = NPCManager::NPCs[id]->appearanceData;
|
||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add players
|
||||
@ -528,6 +550,37 @@ void PlayerManager::movePlatformPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
sendToViewable(sock, (void*)&platResponse, P_FE2CL_PC_MOVEPLATFORM, sizeof(sP_FE2CL_PC_MOVEPLATFORM));
|
||||
}
|
||||
|
||||
void PlayerManager::moveSliderPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_MOVETRANSPORTATION))
|
||||
return; // ignore the malformed packet
|
||||
|
||||
sP_CL2FE_REQ_PC_MOVETRANSPORTATION* sliderData = (sP_CL2FE_REQ_PC_MOVETRANSPORTATION*)data->buf;
|
||||
updatePlayerPosition(sock, sliderData->iX, sliderData->iY, sliderData->iZ, sliderData->iAngle);
|
||||
|
||||
uint64_t tm = getTime();
|
||||
|
||||
INITSTRUCT(sP_FE2CL_PC_MOVETRANSPORTATION, sliderResponse);
|
||||
|
||||
sliderResponse.iPC_ID = players[sock].plr->iID;
|
||||
sliderResponse.iCliTime = sliderData->iCliTime;
|
||||
sliderResponse.iSvrTime = tm;
|
||||
sliderResponse.iX = sliderData->iX;
|
||||
sliderResponse.iY = sliderData->iY;
|
||||
sliderResponse.iZ = sliderData->iZ;
|
||||
sliderResponse.iAngle = sliderData->iAngle;
|
||||
sliderResponse.fVX = sliderData->fVX;
|
||||
sliderResponse.fVY = sliderData->fVY;
|
||||
sliderResponse.fVZ = sliderData->fVZ;
|
||||
sliderResponse.iLcX = sliderData->iLcX;
|
||||
sliderResponse.iLcY = sliderData->iLcY;
|
||||
sliderResponse.iLcZ = sliderData->iLcZ;
|
||||
sliderResponse.iSpeed = sliderData->iSpeed;
|
||||
sliderResponse.cKeyValue = sliderData->cKeyValue;
|
||||
sliderResponse.iT_ID = sliderData->iT_ID;
|
||||
|
||||
sendToViewable(sock, (void*)&sliderResponse, P_FE2CL_PC_MOVETRANSPORTATION, sizeof(sP_FE2CL_PC_MOVETRANSPORTATION));
|
||||
}
|
||||
|
||||
void PlayerManager::moveSlopePlayer(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_SLOPE))
|
||||
return; // ignore the malformed packet
|
||||
|
@ -44,6 +44,7 @@ namespace PlayerManager {
|
||||
void launchPlayer(CNSocket* sock, CNPacketData* data);
|
||||
void ziplinePlayer(CNSocket* sock, CNPacketData* data);
|
||||
void movePlatformPlayer(CNSocket* sock, CNPacketData* data);
|
||||
void moveSliderPlayer(CNSocket* sock, CNPacketData* data);
|
||||
void moveSlopePlayer(CNSocket* sock, CNPacketData* data);
|
||||
void gotoPlayer(CNSocket* sock, CNPacketData* data);
|
||||
void setSpecialPlayer(CNSocket* sock, CNPacketData* data);
|
||||
|
@ -263,19 +263,7 @@ void TableData::constructPath(nlohmann::json::iterator _pathData) {
|
||||
for (_point++; _point != pathPoints.end(); _point++) {
|
||||
point = _point.value();
|
||||
WarpLocation coords = { point["iX"] , point["iY"] , point["iZ"] };
|
||||
// Calculate distance between this point and the last
|
||||
int dXY = hypot(last.x - coords.x, last.y - coords.y); // XY plane distance
|
||||
int distanceBetween = hypot(dXY, last.z - coords.z); // total distance
|
||||
int lerps = distanceBetween / (int)pathData["iMonkeySpeed"]; // integer division to ensure a whole number of in-between points
|
||||
for (int i = 0; i < lerps; i++) {
|
||||
WarpLocation lerp;
|
||||
// lerp math
|
||||
float frac = (i + 1) * 1.0f / (lerps + 1);
|
||||
lerp.x = (last.x * (1.0f - frac)) + (coords.x * frac);
|
||||
lerp.y = (last.y * (1.0f - frac)) + (coords.y * frac);
|
||||
lerp.z = (last.z * (1.0f - frac)) + (coords.z * frac);
|
||||
points.push(lerp); // add lerp'd point to the queue
|
||||
}
|
||||
TransportManager::lerp(&points, last, coords, pathData["iMonkeySpeed"]);
|
||||
points.push(coords); // add keyframe to the queue
|
||||
last = coords; // update start pos
|
||||
}
|
||||
|
@ -4,17 +4,31 @@
|
||||
#include "TransportManager.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <cmath>
|
||||
|
||||
std::map<int32_t, TransportRoute> TransportManager::Routes;
|
||||
std::map<int32_t, TransportLocation> TransportManager::Locations;
|
||||
std::map<int32_t, std::queue<WarpLocation>> TransportManager::SkywayPaths;
|
||||
std::unordered_map<CNSocket*, std::queue<WarpLocation>> TransportManager::SkywayQueues;
|
||||
std::unordered_map<int32_t, std::queue<WarpLocation>> TransportManager::NPCQueues;
|
||||
|
||||
void TransportManager::init() {
|
||||
REGISTER_SHARD_TIMER(tickSkywaySystem, 1000);
|
||||
REGISTER_SHARD_TIMER(tickTransportationSystem, 1000);
|
||||
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION, transportRegisterLocationHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_WARP_USE_TRANSPORTATION, transportWarpHandler);
|
||||
|
||||
BaseNPC* bus = new BaseNPC(220447, 162431, -3650, 1, NPC_BUS);
|
||||
NPCManager::NPCs[bus->appearanceData.iNPC_ID] = bus;
|
||||
ChunkManager::addNPC(bus->appearanceData.iX, bus->appearanceData.iY, bus->appearanceData.iNPC_ID);
|
||||
std::queue<WarpLocation> busPoints;
|
||||
WarpLocation start = { bus->appearanceData.iX, bus->appearanceData.iY, -3650 };
|
||||
WarpLocation end = { 220441, 188102, -3653 };
|
||||
busPoints.push(start);
|
||||
TransportManager::lerp(&busPoints, start, end, 1000);
|
||||
busPoints.push(end);
|
||||
TransportManager::lerp(&busPoints, end, start, 1000);
|
||||
NPCQueues[bus->appearanceData.iNPC_ID] = busPoints;
|
||||
}
|
||||
|
||||
void TransportManager::transportRegisterLocationHandler(CNSocket* sock, CNPacketData* data) {
|
||||
@ -174,13 +188,17 @@ void TransportManager::transportWarpHandler(CNSocket* sock, CNPacketData* data)
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC));
|
||||
}
|
||||
|
||||
void TransportManager::tickTransportationSystem(CNServer* serv, time_t currTime) {
|
||||
stepNPCPathing();
|
||||
stepSkywaySystem();
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through every socket that has broomstick points queued up, and advance to the next point.
|
||||
* If the player has disconnected or finished the route, clean up and remove them from the queue.
|
||||
*/
|
||||
void TransportManager::tickSkywaySystem(CNServer* serv, time_t currTime) {
|
||||
void TransportManager::stepSkywaySystem() {
|
||||
|
||||
//std::cout << SkywayQueue.size();
|
||||
// using an unordered map so we can remove finished players in one iteration
|
||||
std::unordered_map<CNSocket*, std::queue<WarpLocation>>::iterator it = SkywayQueues.begin();
|
||||
while (it != SkywayQueues.end()) {
|
||||
@ -228,3 +246,94 @@ void TransportManager::tickSkywaySystem(CNServer* serv, time_t currTime) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransportManager::stepNPCPathing() {
|
||||
|
||||
// all NPC pathing queues
|
||||
std::unordered_map<int32_t, std::queue<WarpLocation>>::iterator it = NPCQueues.begin();
|
||||
while (it != NPCQueues.end()) {
|
||||
|
||||
std::queue<WarpLocation>* queue = &it->second;
|
||||
|
||||
BaseNPC* npc = nullptr;
|
||||
if (NPCManager::NPCs.find(it->first) != NPCManager::NPCs.end())
|
||||
npc = NPCManager::NPCs[it->first];
|
||||
|
||||
if (npc == nullptr) {
|
||||
// pluck out dead path + update iterator
|
||||
it = NPCQueues.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
WarpLocation point = queue->front(); // get point
|
||||
queue->pop(); // remove point from front of queue
|
||||
|
||||
// calculate displacement
|
||||
int dXY = hypot(point.x - npc->appearanceData.iX, point.y - npc->appearanceData.iY); // XY plane distance
|
||||
int distanceBetween = hypot(dXY, point.z - npc->appearanceData.iZ); // total distance
|
||||
|
||||
// update NPC location to update viewables
|
||||
NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, point.x, point.y, point.z);
|
||||
|
||||
// get chunks in view
|
||||
auto chunk = ChunkManager::grabChunk(npc->appearanceData.iX, npc->appearanceData.iY);
|
||||
auto chunks = ChunkManager::grabChunks(chunk);
|
||||
|
||||
switch (npc->npcClass) {
|
||||
case NPC_BUS:
|
||||
INITSTRUCT(sP_FE2CL_TRANSPORTATION_MOVE, busMove);
|
||||
busMove.eTT = 3;
|
||||
busMove.iT_ID = npc->appearanceData.iNPC_ID;
|
||||
busMove.iMoveStyle = 0; // ???
|
||||
busMove.iToX = point.x;
|
||||
busMove.iToY = point.y;
|
||||
busMove.iToZ = point.z;
|
||||
busMove.iSpeed = distanceBetween; // set to distance to match how monkeys work
|
||||
|
||||
// send packet to players in view
|
||||
for (Chunk* chunk : chunks) {
|
||||
for (CNSocket* s : chunk->players) {
|
||||
s->sendPacket(&busMove, P_FE2CL_TRANSPORTATION_MOVE, sizeof(sP_FE2CL_TRANSPORTATION_MOVE));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
INITSTRUCT(sP_FE2CL_NPC_MOVE, move);
|
||||
move.iNPC_ID = npc->appearanceData.iNPC_ID;
|
||||
move.iMoveStyle = 0; // ???
|
||||
move.iToX = point.x;
|
||||
move.iToY = point.y;
|
||||
move.iToZ = point.z;
|
||||
move.iSpeed = 600; // TODO: figure out a way to make this variable
|
||||
|
||||
// send packet to players in view
|
||||
for (Chunk* chunk : chunks) {
|
||||
for (CNSocket* s : chunk->players) {
|
||||
s->sendPacket(&move, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
queue->push(point); // move processed point to the back to maintain cycle
|
||||
it++; // go to next entry in map
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Linearly interpolate between two points and insert the results into a queue.
|
||||
*/
|
||||
void TransportManager::lerp(std::queue<WarpLocation>* queue, WarpLocation start, WarpLocation end, int gapSize) {
|
||||
int dXY = hypot(end.x - start.x, end.y - start.y); // XY plane distance
|
||||
int distanceBetween = hypot(dXY, end.z - start.z); // total distance
|
||||
int lerps = distanceBetween / gapSize; // integer division to ensure a whole number of in-between points
|
||||
for (int i = 0; i < lerps; i++) {
|
||||
WarpLocation lerp;
|
||||
// lerp math
|
||||
float frac = (i + 1) * 1.0f / (lerps + 1);
|
||||
lerp.x = (start.x * (1.0f - frac)) + (end.x * frac);
|
||||
lerp.y = (start.y * (1.0f - frac)) + (end.y * frac);
|
||||
lerp.z = (start.z * (1.0f - frac)) + (end.z * frac);
|
||||
queue->push(lerp); // add lerp'd point
|
||||
}
|
||||
}
|
||||
|
@ -20,11 +20,16 @@ namespace TransportManager {
|
||||
extern std::map<int32_t, TransportLocation> Locations;
|
||||
extern std::map<int32_t, std::queue<WarpLocation>> SkywayPaths; // predefined skyway paths with points
|
||||
extern std::unordered_map<CNSocket*, std::queue<WarpLocation>> SkywayQueues; // player sockets with queued broomstick points
|
||||
extern std::unordered_map<int32_t, std::queue<WarpLocation>> NPCQueues; // NPC ids with queued pathing points
|
||||
|
||||
void init();
|
||||
|
||||
void transportRegisterLocationHandler(CNSocket* sock, CNPacketData* data);
|
||||
void transportWarpHandler(CNSocket* sock, CNPacketData* data);
|
||||
void transportRegisterLocationHandler(CNSocket*, CNPacketData*);
|
||||
void transportWarpHandler(CNSocket*, CNPacketData*);
|
||||
|
||||
void tickSkywaySystem(CNServer* serv, time_t currTime);
|
||||
void tickTransportationSystem(CNServer*, time_t);
|
||||
void stepNPCPathing();
|
||||
void stepSkywaySystem();
|
||||
|
||||
void lerp(std::queue<WarpLocation>*, WarpLocation, WarpLocation, int);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user