Ez a modifikáció csak a 8600-as revtől mükődik.
Nos kezdjük az adatbázissal:
Importáljuk ez a pár sort a world adatbázisba:
-- ----------------------------
-- Tábla szerkezet `custom_character_movepaths`
-- ----------------------------
DROP TABLE IF EXISTS `custom_character_movepaths`;
CREATE TABLE `custom_character_movepaths` (
`PathID` int(11) NOT NULL default '0',
`TravelOrder` int(11) NOT NULL default '0',
`x` float default NULL,
`y` float default NULL,
`z` float default NULL,
`mount` int(11) default NULL,
`move` tinyint(4) default NULL,
`spawn` int(11) default NULL,
`mode` smallint(6) default NULL,
`emote` int(11) default NULL,
`wait` int(11) default NULL,
PRIMARY KEY (`PathID`,`TravelOrder`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Jöjjön a scriptünk:
flight.cpp:
#include "ScriptPCH.h"
bool GossipHello_npc_player_wp(Player *player, Creature *_creature)
{
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "Repulni szeretnek!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 20);
player->SEND_GOSSIP_MENU(1, _creature->GetGUID());
return true;
}
bool GossipSelect_npc_player_wp(Player *player, Creature *_creature, uint32 sender, uint32 action )
{
if (sender != GOSSIP_SENDER_MAIN)
return false;
if (action == GOSSIP_ACTION_INFO_DEF + 20)
{
player->playerControlledMovement = new PlayerControlledMovement(player);
player->Unmount();
player->SetPosition(_creature->GetPositionX(), _creature->GetPositionY(), _creature->GetPositionZ(), _creature->GetOrientation(), true);
player->PlayerTalkClass->CloseGossip();
player->playerControlledMovement->LoadPath(3);
player->PlayerControlledMovementEnabled = true;
}
return true;
}
void AddSC_npc_player_wp()
{
Script *newscript;
newscript = new Script;
newscript->Name = "npc_player_wp";
newscript->pGossipHello = &GossipHello_npc_player_wp;
newscript->pGossipSelect = &GossipSelect_npc_player_wp;
newscript->RegisterSelf();
}
Ezt a scriptet másoljuk be az src/server/scripts/Custom mappába
src/server/scripts/CMakeLists.txt-be ilesszük be ezt a sort:
Custom/flight.cpp
Nyíssuk meg az src/server/game/Scripting/Scriptloader.cpp-t
//custom alá ilesszük be ezt:
[code]
void AddSC_npc_player_wp();
A következő //custom alá pedig ezt:
AddSC_npc_player_wp();
Mentsük el.
Nah és most jön a core modifikáció:
Hozzunk létre az src/server/game-ban egy flight mappát.
Hozzunk létre egy PlayerControlledMovement.h -t a flight mappába aminek a tartalma:
#pragma once
class Node{
public:
Node();
float x;
float y;
float z;
int mount;
int move;
int mode;
int part;
};
typedef std::list<Node *> Nodes;
class PlayerControlledMovement
{
protected:
Player * me;
public:
int flyAnimTimer;
int failedUpdatesCounter;
bool finish;
float oldPosX;
float oldPosY;
float oldPosZ;
void Finish();
int part;
Nodes nodes;
Node * activeNode;
int nodesLenght;
PlayerControlledMovement(Player *p);
void MoveToPoint(Node * n, bool forceSlow);
void Update(uint32 diff);
void LoadPath(int pathid);
Node * GetNextNode(Node * n);
};
Hozzunk létre egy PlayerControlledMovement.cpp -t a flight mappába aminek a tartalma:
#include "pchdef.h"
#include "PlayerControlledMovement.h"
#include "PointMovementGenerator.h"
#include "ScriptPCH.h"
#include "Creature.h"
#include <stdio.h>
#include <time.h>
#include <list>
extern DatabaseType WorldDatabase;
Node::Node() {}
PlayerControlledMovement::PlayerControlledMovement(Player *p)
{
me = p;
}
void PlayerControlledMovement::Finish()
{
me->GetMotionMaster()->Clear();
if(activeNode->mode == 6)
{
Node * n = new Node();
n->x = me->GetPositionX();
n->y = me->GetPositionY();
n->z = me->GetPositionZ();
n->mode = 6;
n->mount = activeNode->mount;
n->move = true;
n->part = nodesLenght;
me->CastSpell(me, 45472, true);
}
me->SetClientControl(me, true);
me->RemoveAurasDueToSpell(60865);
if (activeNode->mount != 0)
me->RemoveAurasDueToSpell(activeNode->mount);
me->PlayerControlledMovementEnabled = false;
me->SetFlying(false);
finish = false;
}
void PlayerControlledMovement::Update(uint32 diff)
{
if ((me->GetPositionX()- activeNode->x) < 5 && (me->GetPositionX()- activeNode->x) > -5
&& (me->GetPositionY() - activeNode->y) < 5 && (me->GetPositionY() - activeNode->y) > -5
&& (me->GetPositionZ() - activeNode->z) < 5 && (me->GetPositionZ() - activeNode->z) > -5)
{
if (nodesLenght != activeNode->part)
{
MoveToPoint(GetNextNode(activeNode), false);
}
else
Finish();
}
else
{
if (oldPosX == me->GetPositionX() && oldPosY == me->GetPositionY() && oldPosZ == me->GetPositionZ())
{
failedUpdatesCounter++;
if (failedUpdatesCounter == 5)
{
if (nodesLenght != activeNode->part)
MoveToPoint(GetNextNode(activeNode), false);
else
MoveToPoint(activeNode, true);
}
}
else
failedUpdatesCounter = 0;
oldPosX = me->GetPositionX();
oldPosY = me->GetPositionY();
oldPosZ = me->GetPositionZ();
}
if (me->isInCombat())
Finish();
if (finish)
{
if (activeNode->mode == 6 && flyAnimTimer <= diff)
{
if (SpellEntry const *spellInfo = sSpellStore.LookupEntry( 60865 ))
{
Aura * aura = Aura::TryCreate(spellInfo, me, me);
aura->SetDuration(10000);
}
flyAnimTimer = 9000;
}
else if (activeNode->mode == 6)
flyAnimTimer -= diff;
if (activeNode->mount != 0)
{
if (!me->HasAura(activeNode->mount))
{
if(!me->IsMounted())
{
me->RemoveAllAuras();
if (SpellEntry const *spellInfo = sSpellStore.LookupEntry( activeNode->mount ))
Aura::TryCreate(spellInfo, me, me);
}
}
}
else
{
if (me->GetMountID() != 0)
{
me->Unmount();
}
}
}
}
void PlayerControlledMovement::MoveToPoint(Node * n, bool forceSlow)
{
if (n->move == 0)
me->SetClientControl(me, false);
else
me->SetClientControl(me, true);
if (n->mode == 6)
{
me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE);
flyAnimTimer = 0;
me->SetFlying(true);
}
else
{
me->SetFlying(false);
me->RemoveUnitMovementFlag(MOVEMENTFLAG_FLY_MODE);
}
activeNode = n;
oldPosX = me->GetPositionX();
oldPosZ = me->GetPositionZ();
oldPosY = me->GetPositionY();
failedUpdatesCounter = 0;
float speed;
switch (activeNode->mode)
{
case 1:
speed = 1.0f;
break;
case 2:
speed = 3.0f;
break;
case 3:
speed = 6.5f;
break;
case 4:
speed = 8.0f;
break;
case 5:
speed = 10.0f;
break;
case 6:
speed = 25.0f;
break;
default:
speed = 1.0f;
break;
}
if (!forceSlow)
me->GetMotionMaster()->MoveCharge(n->x, n->y, n->z, speed, EVENT_CHARGE);
else
me->GetMotionMaster()->MovePoint(me->GetGUIDLow(), n->x, n->y, n->z);
}
Node * PlayerControlledMovement::GetNextNode(Node * n)
{
Nodes::iterator j;
for (j = nodes.begin(); j != nodes.end(); ++j)
{
Node * nod = *j;
if (nod->part == n->part + 1)
{
if (n->mount != nod->mount)
me->RemoveAurasDueToSpell(n->mount);
return nod;
}
}
}
void PlayerControlledMovement::LoadPath(int pathid)
{
QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT x, y, z, mount, move, mode FROM custom_character_movepaths WHERE PathID = %u ORDER BY TravelOrder ASC", pathid);
// 0 1 2 3 4 5
if(result)
{
nodes.clear();
int i = 0;
do
{
Field *fields = result->Fetch();
i++;
Node * n = new Node();
n->part = i;
n->x = fields[0].GetFloat();
n->y = fields[1].GetFloat();
n->z = fields[2].GetFloat();
n->mount = fields[3].GetInt32();
n->move = fields[4].GetInt32();
n->mode = fields[5].GetInt32();
nodes.push_back(n);
if (i == 1)
MoveToPoint(n, false);
} while (result->NextRow());
nodesLenght = i;
}
}
Nyíssuk meg a player.h-t és a +-jelesekkel egészítsük ki:
#include "ReputationMgr.h"
#include "BattleGround.h"
#include "DBCEnums.h"
#include "LFG.h"
+ #include "PlayerControlledMovement.h"
#include<string>
#include<vector>
class Player : public Unit, public GridObject<Player>
{
friend class WorldSession;
friend void Item::AddToUpdateQueueOf(Player *player);
friend void Item::RemoveFromUpdateQueueOf(Player *player);
public:
explicit Player (WorldSession *session);
~Player ();
+ PlayerControlledMovement * playerControlledMovement;
+ bool PlayerControlledMovementEnabled;
void CleanupsBeforeDelete(bool finalCleanup = true);
static UpdateMask updateVisualBits;
static void InitVisibleBits();
void AddToWorld();
Nyíssuk meg a player.cpp-t és a +-jelesekkel egészítsük ki:
Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputationMgr(this)
{
+ PlayerControlledMovementEnabled = false;
m_speakTime = 0;
m_speakCount = 0;
m_objectType |= TYPEMASK_PLAYER;
m_objectTypeId = TYPEID_PLAYER;
m_valuesCount = PLAYER_END;
void Player::Update(uint32 p_time)
{
if (!IsInWorld())
return;
+ if (PlayerControlledMovementEnabled == true)
+ playerControlledMovement->Update(p_time);
// undelivered mail
if (m_nextMailDelivereTime && m_nextMailDelivereTime <= time(NULL))
{
SendNewMail();
++unReadMails;
// It will be recalculate at mailbox open (for unReadMails important non-0 until mailbox open, it also will be recalculated)
m_nextMailDelivereTime = 0;
}
Mentés.
Következő lépés:
src/server/scripts/Cmakelist.txt-be ilesszük be az alábbi sort a 94.sorba:
${CMAKE_SOURCE_DIR}/src/server/game/flight
src/server/scripts/game/Cmakelist.txt-be ilesszük be ezeket:
flight/PlayerControlledMovement.h
flight/PlayerControlledMovement.cpp
Majd a 226. sorba:
${CMAKE_SOURCE_DIR}/src/server/game/flight
És az utolsó lépés:
make
make install
NPC a scripthez:
INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `faction_A`, `faction_H`, `npcflag`, `speed`, `scale`, `rank`, `mindmg`, `maxdmg`, `dmgschool`, `attackpower`, `dmg_multiplier`, `baseattacktime`, `rangeattacktime`, `unit_class`, `unit_flags`, `dynamicflags`, `family`, `trainer_type`, `trainer_spell`, `trainer_class`, `trainer_race`, `minrangedmg`, `maxrangedmg`, `rangedattackpower`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `Health_mod`, `Mana_mod`, `Armor_mod`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `equipment_id`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `WDBVerified`) values('100000','0','0','0','0','0','28766','0','0','0','Joseph','AirPort','','0','80','80','2','35','35','1','1','1','0','0','0','0','0','1','0','0','2','0','0','0','0','0','0','0','0','0','0','7','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','','0','3','1.77381','5.50826','1','0','0','0','0','0','0','0','0','1','0','0','0','npc_player_wp','11403');
Szerver restart és .npc add 100000
A leírást készítette, Drestor ![/code]
Commandok a scripthez. (http://www.skyne.gnome-lak.hu/index.php?option=com_content&view=article&id=5:parancsok-az-egyedi-repuelesi-utvonalhoz&catid=1:scriptek&Itemid=2)
.flight add
.flight mod
.flight del