Files
CypherCore/Source/Game/Entities/Player/PlayerTaxi.cs
T
2023-05-21 19:01:22 -04:00

258 lines
9.8 KiB
C#

// Copyright (c) CypherCore <http://github.com/CypherCore> All rights reserved.
// Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information.
using Framework.Collections;
using Framework.Constants;
using Game.DataStorage;
using Game.Networking.Packets;
using System.Collections.Generic;
using System.Text;
using System;
namespace Game.Entities
{
public class PlayerTaxi
{
public byte[] m_taximask;
List<uint> m_TaxiDestinations = new();
uint m_flightMasterFactionId;
public void InitTaxiNodesForLevel(Race race, Class chrClass, uint level)
{
m_taximask = new byte[((CliDB.TaxiNodesStorage.GetNumRows() - 1) / (1 * 64) + 1) * 8];
// class specific initial known nodes
if (chrClass == Class.Deathknight)
{
var factionMask = Player.TeamForRace(race) == Team.Horde ? CliDB.HordeTaxiNodesMask : CliDB.AllianceTaxiNodesMask;
m_taximask = new byte[factionMask.Length];
for (int i = 0; i < factionMask.Length; ++i)
m_taximask[i] |= (byte)(CliDB.OldContinentsNodesMask[i] & factionMask[i]);
}
// race specific initial known nodes: capital and taxi hub masks
switch (race)
{
case Race.Human:
case Race.Dwarf:
case Race.NightElf:
case Race.Gnome:
case Race.Draenei:
case Race.Worgen:
case Race.PandarenAlliance:
SetTaximaskNode(2); // Stormwind, Elwynn
SetTaximaskNode(6); // Ironforge, Dun Morogh
SetTaximaskNode(26); // Lor'danel, Darkshore
SetTaximaskNode(27); // Rut'theran Village, Teldrassil
SetTaximaskNode(49); // Moonglade (Alliance)
SetTaximaskNode(94); // The Exodar
SetTaximaskNode(456); // Dolanaar, Teldrassil
SetTaximaskNode(457); // Darnassus, Teldrassil
SetTaximaskNode(582); // Goldshire, Elwynn
SetTaximaskNode(589); // Eastvale Logging Camp, Elwynn
SetTaximaskNode(619); // Kharanos, Dun Morogh
SetTaximaskNode(620); // Gol'Bolar Quarry, Dun Morogh
SetTaximaskNode(624); // Azure Watch, Azuremyst Isle
break;
case Race.Orc:
case Race.Undead:
case Race.Tauren:
case Race.Troll:
case Race.BloodElf:
case Race.Goblin:
case Race.PandarenHorde:
SetTaximaskNode(11); // Undercity, Tirisfal
SetTaximaskNode(22); // Thunder Bluff, Mulgore
SetTaximaskNode(23); // Orgrimmar, Durotar
SetTaximaskNode(69); // Moonglade (Horde)
SetTaximaskNode(82); // Silvermoon City
SetTaximaskNode(384); // The Bulwark, Tirisfal
SetTaximaskNode(402); // Bloodhoof Village, Mulgore
SetTaximaskNode(460); // Brill, Tirisfal Glades
SetTaximaskNode(536); // Sen'jin Village, Durotar
SetTaximaskNode(537); // Razor Hill, Durotar
SetTaximaskNode(625); // Fairbreeze Village, Eversong Woods
SetTaximaskNode(631); // Falconwing Square, Eversong Woods
break;
}
// new continent starting masks (It will be accessible only at new map)
switch (Player.TeamForRace(race))
{
case Team.Alliance:
SetTaximaskNode(100);
break;
case Team.Horde:
SetTaximaskNode(99);
break;
}
// level dependent taxi hubs
if (level >= 68)
SetTaximaskNode(213); //Shattered Sun Staging Area
}
public void LoadTaxiMask(string data)
{
m_taximask = new byte[((CliDB.TaxiNodesStorage.GetNumRows() - 1) / (1 * 64) + 1) * 8];
var split = new StringArray(data, ' ');
int index = 0;
for (var i = 0; index < m_taximask.Length && i != split.Length; ++i, ++index)
{
// load and set bits only for existing taxi nodes
if (uint.TryParse(split[i], out uint id))
m_taximask[index] = (byte)(CliDB.TaxiNodesMask[index] & id);
}
}
public void AppendTaximaskTo(ShowTaxiNodes data, bool all)
{
data.CanLandNodes = new byte[CliDB.TaxiNodesMask.Length];
data.CanUseNodes = new byte[CliDB.TaxiNodesMask.Length];
if (all)
{
Buffer.BlockCopy(CliDB.TaxiNodesMask, 0, data.CanLandNodes, 0, data.CanLandNodes.Length); // all existed nodes
Buffer.BlockCopy(CliDB.TaxiNodesMask, 0, data.CanUseNodes, 0, data.CanUseNodes.Length);
}
else
{
Buffer.BlockCopy(m_taximask, 0, data.CanLandNodes, 0, data.CanLandNodes.Length); // known nodes
Buffer.BlockCopy(m_taximask, 0, data.CanUseNodes, 0, data.CanUseNodes.Length);
}
}
public bool LoadTaxiDestinationsFromString(string values, Team team)
{
ClearTaxiDestinations();
var stringArray = new StringArray(values, ' ');
if (stringArray.Length > 0)
uint.TryParse(stringArray[0], out m_flightMasterFactionId);
for (var i = 1; i < stringArray.Length; ++i)
{
if (uint.TryParse(stringArray[i], out uint node))
AddTaxiDestination(node);
}
if (m_TaxiDestinations.Empty())
return true;
// Check integrity
if (m_TaxiDestinations.Count < 2)
return false;
for (int i = 1; i < m_TaxiDestinations.Count; ++i)
{
uint path;
Global.ObjectMgr.GetTaxiPath(m_TaxiDestinations[i - 1], m_TaxiDestinations[i], out path, out _);
if (path == 0)
return false;
}
// can't load taxi path without mount set (quest taxi path?)
if (Global.ObjectMgr.GetTaxiMountDisplayId(GetTaxiSource(), team, true) == 0)
return false;
return true;
}
public string SaveTaxiDestinationsToString()
{
if (m_TaxiDestinations.Empty())
return "";
Cypher.Assert(m_TaxiDestinations.Count >= 2);
StringBuilder ss = new();
ss.Append($"{m_flightMasterFactionId} ");
for (int i = 0; i < m_TaxiDestinations.Count; ++i)
ss.Append($"{m_TaxiDestinations[i]} ");
return ss.ToString();
}
public uint GetCurrentTaxiPath()
{
if (m_TaxiDestinations.Count < 2)
return 0;
uint path;
Global.ObjectMgr.GetTaxiPath(m_TaxiDestinations[0], m_TaxiDestinations[1], out path, out _);
return path;
}
public bool RequestEarlyLanding()
{
if (m_TaxiDestinations.Count <= 2)
return false;
// start from first destination - m_TaxiDestinations[0] is the current starting node
for (var i = 1; i < m_TaxiDestinations.Count; ++i)
{
if (IsTaximaskNodeKnown(m_TaxiDestinations[i]))
{
if (++i == m_TaxiDestinations.Count - 1)
return false; // if we are left with only 1 known node on the path don't change the spline, its our final destination anyway
m_TaxiDestinations.RemoveRange(i, m_TaxiDestinations.Count - i);
return true;
}
}
return false;
}
public FactionTemplateRecord GetFlightMasterFactionTemplate()
{
return CliDB.FactionTemplateStorage.LookupByKey(m_flightMasterFactionId);
}
public void SetFlightMasterFactionTemplateId(uint factionTemplateId)
{
m_flightMasterFactionId = factionTemplateId;
}
public bool IsTaximaskNodeKnown(uint nodeidx)
{
uint field = (nodeidx - 1) / 8;
uint submask = (uint)(1 << (int)((nodeidx - 1) % 8));
return (m_taximask[field] & submask) == submask;
}
public bool SetTaximaskNode(uint nodeidx)
{
uint field = (nodeidx - 1) / 8;
uint submask = (uint)(1 << (int)((nodeidx - 1) % 8));
if ((m_taximask[field] & submask) != submask)
{
m_taximask[field] |= (byte)submask;
return true;
}
else
return false;
}
public void ClearTaxiDestinations() { m_TaxiDestinations.Clear(); }
public void AddTaxiDestination(uint dest) { m_TaxiDestinations.Add(dest); }
void SetTaxiDestination(List<uint> nodes)
{
m_TaxiDestinations.Clear();
m_TaxiDestinations.AddRange(nodes);
}
public uint GetTaxiSource() { return m_TaxiDestinations.Empty() ? 0 : m_TaxiDestinations[0]; }
public uint GetTaxiDestination() { return m_TaxiDestinations.Count < 2 ? 0 : m_TaxiDestinations[1]; }
public uint NextTaxiDestination()
{
m_TaxiDestinations.RemoveAt(0);
return GetTaxiDestination();
}
public List<uint> GetPath() { return m_TaxiDestinations; }
public bool Empty() { return m_TaxiDestinations.Empty(); }
}
}