Skip to content

Commit

Permalink
Add support for character race and faction transfers.
Browse files Browse the repository at this point in the history
Based (loosely) on patch by Ner'zhul, DarkXuan, and darkshines@sakha.net.
Fixes issue #3429.

--HG--
branch : trunk
  • Loading branch information
silinoron committed Sep 5, 2010
1 parent de59ac3 commit be7d94f
Show file tree
Hide file tree
Showing 21 changed files with 760 additions and 15 deletions.
3 changes: 2 additions & 1 deletion THANKS
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ BlackCat0110, JuliuSZS, n4rk0, filip.havlicek, m.ax, laviniu, LordJZ, Scazzato88
svannon, jurkovic.nikola, Willian Krueger, BioHazard, Ille000, Erocoloco,
terrorbringer, antihrists, Havenard, scarymovie87, D3VIL, FaTe753, PrinceCreed,
spgm, Dakeyras, sombre88, 19Maxx83, moriquendu, Ille, breakerfly,
zthoreen, clement.roussel, p.alexej, Ceris, Nayre, Kiper, announce, thmarth
zthoreen, clement.roussel, p.alexej, Ceris, Nayre, Kiper, announce, thmarth,
Ner'zhul, DarkXuan
100 changes: 99 additions & 1 deletion sql/base/world_database.sql
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ INSERT INTO `command` VALUES
('character rename',2,'Syntax: .character rename [$name]\r\n\r\nMark selected in game or by $name in command character for rename at next login.'),
('character reputation',2,'Syntax: .character reputation [$player_name]\r\n\r\nShow reputation information for selected player or player find by $player_name.'),
('character titles',2,'Syntax: .character titles [$player_name]\r\n\r\nShow known titles list for selected player or player find by $player_name.'),
('character changefaction',2,'Syntax: .character changefaction $name\r\n\r\nChange character faction.'),
('character changerace',2,'Syntax: .character changerace $name\r\n\r\nChange character race.'),
('channel set public', 3, 'Syntax: .channel set public $channel $public\r\n\r\nChange password-changing ability for a channel. 1 for possible, 0 for GM only.'),
('combatstop',2,'Syntax: .combatstop [$playername]\r\nStop combat for selected character. If selected non-player then command applied to self. If $playername provided then attempt applied to online player $playername.'),
('cometome',3,'SYntax: .cometome $parameter\nMake selected creature come to your current location (new position not saved to DB).'),
Expand Down Expand Up @@ -436,7 +438,7 @@ INSERT INTO `command` VALUES
('instance listbinds',3,'Syntax: .instance listbinds\r\n Lists the binds of the selected player.'),
('instance savedata',3,'Syntax: .instance savedata\r\n Save the InstanceData for the current player''s map to the DB.'),
('instance stats',3,'Syntax: .instance stats\r\n Shows statistics about instances.'),
('instance unbind',3,'Syntax: .instance unbind <mapid|all> [difficulty]\r\n Clear all/some of player\'s binds'),
('instance unbind',3,'Syntax: .instance unbind <mapid|all> [difficulty]\r\n Clear all/some of player''s binds'),
('itemmove',2,'Syntax: .itemmove #sourceslotid #destinationslotid\r\n\r\nMove an item from slots #sourceslotid to #destinationslotid in your inventory\r\n\r\nNot yet implemented'),
('kick',2,'Syntax: .kick [$charactername] [$reason]\r\n\r\nKick the given character name from the world with or without reason. If no character name is provided then the selected player (except for yourself) will be kicked. If no reason is provided, default is \"No Reason\".'),
('learn',3,'Syntax: .learn #spell [all]\r\n\r\nSelected character learn a spell of id #spell. If ''all'' provided then all ranks learned.'),
Expand Down Expand Up @@ -7740,6 +7742,102 @@ INSERT INTO `player_classlevelstats` VALUES
/*!40000 ALTER TABLE `player_classlevelstats` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `player_factionchange_achievement`
--

DROP TABLE IF EXISTS `player_factionchange_achievement`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `player_factionchange_achievement` (
`alliance_id` int(8) NOT NULL,
`horde_id` int(8) NOT NULL,
PRIMARY KEY (`alliance_id`,`horde_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `player_factionchange_achievement`
--

LOCK TABLES `player_factionchange_achievement` WRITE;
/*!40000 ALTER TABLE `player_factionchange_achievement` DISABLE KEYS */;
/*!40000 ALTER TABLE `player_factionchange_achievement` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `player_factionchange_items`
--

DROP TABLE IF EXISTS `player_factionchange_items`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `player_factionchange_items` (
`race_A` int(8) NOT NULL,
`alliance_id` int(8) NOT NULL,
`commentA` text,
`race_H` int(8) NOT NULL,
`horde_id` int(8) NOT NULL,
`commentH` text,
PRIMARY KEY (`alliance_id`,`horde_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `player_factionchange_items`
--

LOCK TABLES `player_factionchange_items` WRITE;
/*!40000 ALTER TABLE `player_factionchange_items` DISABLE KEYS */;
/*!40000 ALTER TABLE `player_factionchange_items` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `player_factionchange_reputations`
--

DROP TABLE IF EXISTS `player_factionchange_reputations`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `player_factionchange_reputations` (
`alliance_id` int(8) NOT NULL,
`horde_id` int(8) NOT NULL,
PRIMARY KEY (`alliance_id`,`horde_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `player_factionchange_reputations`
--

LOCK TABLES `player_factionchange_reputations` WRITE;
/*!40000 ALTER TABLE `player_factionchange_reputations` DISABLE KEYS */;
/*!40000 ALTER TABLE `player_factionchange_reputations` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `player_factionchange_spells`
--

DROP TABLE IF EXISTS `player_factionchange_spells`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `player_factionchange_spells` (
`alliance_id` int(8) NOT NULL,
`horde_id` int(8) NOT NULL,
PRIMARY KEY (`alliance_id`,`horde_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `player_factionchange_spells`
--

LOCK TABLES `player_factionchange_spells` WRITE;
/*!40000 ALTER TABLE `player_factionchange_spells` DISABLE KEYS */;
/*!40000 ALTER TABLE `player_factionchange_spells` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `player_levelstats`
--
Expand Down
4 changes: 4 additions & 0 deletions sql/updates/9784_world_command.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
DELETE FROM `command` WHERE `name` IN ('character changefaction','character changerace');
INSERT INTO `command` VALUES
('character changefaction',2,'Syntax: .character changefaction $name\r\n\r\nChange character faction.'),
('character changerace',2,'Syntax: .character changerace $name\r\n\r\nChange character race.');
6 changes: 6 additions & 0 deletions sql/updates/9784_world_player_factionchange_achievement.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
DROP TABLE IF EXISTS `player_factionchange_achievement`;
CREATE TABLE `player_factionchange_achievement` (
`alliance_id` int(8) NOT NULL,
`horde_id` int(8) NOT NULL,
PRIMARY KEY (`alliance_id`,`horde_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
10 changes: 10 additions & 0 deletions sql/updates/9784_world_player_factionchange_items.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DROP TABLE IF EXISTS `player_factionchange_items`;
CREATE TABLE `player_factionchange_items` (
`race_A` int(8) NOT NULL,
`alliance_id` int(8) NOT NULL,
`commentA` text,
`race_H` int(8) NOT NULL,
`horde_id` int(8) NOT NULL,
`commentH` text,
PRIMARY KEY (`alliance_id`,`horde_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
6 changes: 6 additions & 0 deletions sql/updates/9784_world_player_factionchange_reputations.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
DROP TABLE IF EXISTS `player_factionchange_reputations`;
CREATE TABLE `player_factionchange_reputations` (
`alliance_id` int(8) NOT NULL,
`horde_id` int(8) NOT NULL,
PRIMARY KEY (`alliance_id`,`horde_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
6 changes: 6 additions & 0 deletions sql/updates/9784_world_player_factionchange_spells.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
DROP TABLE IF EXISTS `player_factionchange_spells`;
CREATE TABLE `player_factionchange_spells` (
`alliance_id` int(8) NOT NULL,
`horde_id` int(8) NOT NULL,
PRIMARY KEY (`alliance_id`,`horde_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
18 changes: 10 additions & 8 deletions src/server/game/Chat/Chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,16 @@ ChatCommand * ChatHandler::getCommandTable()

static ChatCommand characterCommandTable[] =
{
{ "customize", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterCustomizeCommand, "", NULL },
{ "deleted", SEC_GAMEMASTER, true, NULL, "", characterDeletedCommandTable},
{ "erase", SEC_CONSOLE, true, &ChatHandler::HandleCharacterEraseCommand, "", NULL },
{ "level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleCharacterLevelCommand, "", NULL },
{ "rename", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterRenameCommand, "", NULL },
{ "reputation", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterReputationCommand, "", NULL },
{ "titles", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterTitlesCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
{ "customize", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterCustomizeCommand, "", NULL },
{ "changefaction", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterChangeFactionCommand, "", NULL },
{ "changerace", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterChangeRaceCommand, "", NULL },
{ "deleted", SEC_GAMEMASTER, true, NULL, "", characterDeletedCommandTable},
{ "erase", SEC_CONSOLE, true, &ChatHandler::HandleCharacterEraseCommand, "", NULL },
{ "level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleCharacterLevelCommand, "", NULL },
{ "rename", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterRenameCommand, "", NULL },
{ "reputation", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterReputationCommand, "", NULL },
{ "titles", SEC_GAMEMASTER, true, &ChatHandler::HandleCharacterTitlesCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};

static ChatCommand channelSetCommandTable[] =
Expand Down
2 changes: 2 additions & 0 deletions src/server/game/Chat/Chat.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ class ChatHandler
bool HandleCastTargetCommand(const char *args);

bool HandleCharacterCustomizeCommand(const char * args);
bool HandleCharacterChangeFactionCommand(const char * args);
bool HandleCharacterChangeRaceCommand(const char * args);
bool HandleCharacterDeletedDeleteCommand(const char* args);
bool HandleCharacterDeletedListCommand(const char* args);
bool HandleCharacterDeletedRestoreCommand(const char* args);
Expand Down
55 changes: 55 additions & 0 deletions src/server/game/Chat/Commands/Level2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3254,6 +3254,61 @@ bool ChatHandler::HandleCharacterCustomizeCommand(const char* args)
return true;
}

bool ChatHandler::HandleCharacterChangeFactionCommand(const char * args)
{
Player* target;
uint64 target_guid;
std::string target_name;

if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
return false;

if(target)
{
// TODO : add text into database
PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str());
target->SetAtLoginFlag(AT_LOGIN_CHANGE_FACTION);
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '64' WHERE guid = %u", target->GetGUIDLow());
}
else
{
std::string oldNameLink = playerLink(target_name);

// TODO : add text into database
PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid));
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '64' WHERE guid = %u", GUID_LOPART(target_guid));
}

return true;
}

bool ChatHandler::HandleCharacterChangeRaceCommand(const char * args)
{
Player* target;
uint64 target_guid;
std::string target_name;
if(!extractPlayerTarget((char*)args,&target,&target_guid,&target_name))
return false;

if(target)
{
// TODO : add text into database
PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str());
target->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE);
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '128' WHERE guid = %u", target->GetGUIDLow());
}
else
{
std::string oldNameLink = playerLink(target_name);

// TODO : add text into database
PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(target_guid));
CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '128' WHERE guid = %u", GUID_LOPART(target_guid));
}

return true;
}

bool ChatHandler::HandleCharacterReputationCommand(const char* args)
{
Player* target;
Expand Down
17 changes: 15 additions & 2 deletions src/server/game/DataStores/DBCStores.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ static uint32 sTalentTabPages[MAX_CLASSES][3];
DBCStorage <TaxiNodesEntry> sTaxiNodesStore(TaxiNodesEntryfmt);
TaxiMask sTaxiNodesMask;
TaxiMask sOldContinentsNodesMask;
TaxiMask sHordeTaxiNodesMask;
TaxiMask sAllianceTaxiNodesMask;
TaxiMask sDeathKnightTaxiNodesMask;

// DBC used only for initialization sTaxiPathSetBySource at startup.
TaxiPathSetBySource sTaxiPathSetBySource;
Expand Down Expand Up @@ -515,11 +518,14 @@ void LoadDBCStores(const std::string& dataPath)
for (uint32 i = 1; i < sSpellStore.GetNumRows (); ++i)
if (SpellEntry const* sInfo = sSpellStore.LookupEntry (i))
for (int j=0; j < 3; ++j)
if (sInfo->Effect[j] == 123 /*SPELL_EFFECT_SEND_TAXI*/)
if (sInfo->Effect[j] == SPELL_EFFECT_SEND_TAXI)
spellPaths.insert(sInfo->EffectMiscValue[j]);

memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask));
memset(sOldContinentsNodesMask,0,sizeof(sTaxiNodesMask));
memset(sOldContinentsNodesMask,0,sizeof(sOldContinentsNodesMask));
memset(sHordeTaxiNodesMask,0,sizeof(sHordeTaxiNodesMask));
memset(sAllianceTaxiNodesMask,0,sizeof(sAllianceTaxiNodesMask));
memset(sDeathKnightTaxiNodesMask,0,sizeof(sDeathKnightTaxiNodesMask));
for (uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
{
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i);
Expand Down Expand Up @@ -549,6 +555,13 @@ void LoadDBCStores(const std::string& dataPath)
uint32 submask = 1<<((i-1)%32);
sTaxiNodesMask[field] |= submask;

if (node->MountCreatureID[0] && node->MountCreatureID[0] != 32981)
sHordeTaxiNodesMask[field] |= submask;
if (node->MountCreatureID[1] && node->MountCreatureID[1] != 32981)
sAllianceTaxiNodesMask[field] |= submask;
if (node->MountCreatureID[0] == 32981 || node->MountCreatureID[1] == 32981)
sDeathKnightTaxiNodesMask[field] |= submask;

// old continent node (+ nodes virtually at old continents, check explicitly to avoid loading map files for zone info)
if (node->map_id < 2 || i == 82 || i == 83 || i == 93 || i == 94)
sOldContinentsNodesMask[field] |= submask;
Expand Down
3 changes: 3 additions & 0 deletions src/server/game/DataStores/DBCStores.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ extern DBCStorage <TaxiNodesEntry> sTaxiNodesStore;
extern DBCStorage <TaxiPathEntry> sTaxiPathStore;
extern TaxiMask sTaxiNodesMask;
extern TaxiMask sOldContinentsNodesMask;
extern TaxiMask sHordeTaxiNodesMask;
extern TaxiMask sAllianceTaxiNodesMask;
extern TaxiMask sDeathKnightTaxiNodesMask;
extern TaxiPathSetBySource sTaxiPathSetBySource;
extern TaxiPathNodesByPath sTaxiPathNodesByPath;
extern DBCStorage <TotemCategoryEntry> sTotemCategoryStore;
Expand Down
11 changes: 10 additions & 1 deletion src/server/game/Entities/Player/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1654,8 +1654,17 @@ bool Player::BuildEnumData(QueryResult_AutoPtr result, WorldPacket * p_data)
char_flags |= CHARACTER_FLAG_DECLINED;

*p_data << uint32(char_flags); // character flags

// character customize flags
*p_data << uint32(atLoginFlags & AT_LOGIN_CUSTOMIZE ? CHAR_CUSTOMIZE_FLAG_CUSTOMIZE : CHAR_CUSTOMIZE_FLAG_NONE);
if (atLoginFlags & AT_LOGIN_CUSTOMIZE)
*p_data << uint32(CHAR_CUSTOMIZE_FLAG_CUSTOMIZE);
else if (atLoginFlags & AT_LOGIN_CHANGE_FACTION)
*p_data << uint32(CHAR_CUSTOMIZE_FLAG_FACTION);
else if (atLoginFlags & AT_LOGIN_CHANGE_RACE)
*p_data << uint32(CHAR_CUSTOMIZE_FLAG_RACE);
else
*p_data << uint32(CHAR_CUSTOMIZE_FLAG_NONE);

// First login
*p_data << uint8(atLoginFlags & AT_LOGIN_FIRST ? 1 : 0);

Expand Down
2 changes: 2 additions & 0 deletions src/server/game/Entities/Player/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,8 @@ enum AtLoginFlags
AT_LOGIN_CUSTOMIZE = 0x08,
AT_LOGIN_RESET_PET_TALENTS = 0x10,
AT_LOGIN_FIRST = 0x20,
AT_LOGIN_CHANGE_FACTION = 0x40,
AT_LOGIN_CHANGE_RACE = 0x80
};

typedef std::map<uint32, QuestStatusData> QuestStatusMap;
Expand Down

0 comments on commit be7d94f

Please sign in to comment.