You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2438 lines
86 KiB
2438 lines
86 KiB
|
10 months ago
|
#include "Server.h"
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
namespace DAPI {
|
||
|
|
Server::Server()
|
||
|
|
: FPS(20)
|
||
|
|
{
|
||
|
|
output.open("output.csv");
|
||
|
|
data = std::make_unique<GameData>();
|
||
|
|
for (int x = -8; x < 9; x++) {
|
||
|
|
switch (x) {
|
||
|
|
case 8:
|
||
|
|
panelScreenCheck[std::make_pair(x, 3)] = true;
|
||
|
|
break;
|
||
|
|
case 7:
|
||
|
|
for (int y = 2; y < 5; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case 6:
|
||
|
|
for (int y = 1; y < 6; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case 5:
|
||
|
|
for (int y = 0; y < 7; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case 4:
|
||
|
|
for (int y = -1; y < 8; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
for (int y = -2; y < 9; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
for (int y = -3; y < 8; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case 1:
|
||
|
|
for (int y = -4; y < 7; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case 0:
|
||
|
|
for (int y = -5; y < 6; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case -1:
|
||
|
|
for (int y = -6; y < 5; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case -2:
|
||
|
|
for (int y = -7; y < 4; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case -3:
|
||
|
|
for (int y = -8; y < 3; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case -4:
|
||
|
|
for (int y = -7; y < 2; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case -5:
|
||
|
|
for (int y = -6; y < 1; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case -6:
|
||
|
|
for (int y = -5; y < 0; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case -7:
|
||
|
|
for (int y = -4; y < -1; y++)
|
||
|
|
panelScreenCheck[std::make_pair(x, y)] = true;
|
||
|
|
break;
|
||
|
|
case -8:
|
||
|
|
panelScreenCheck[std::make_pair(x, -3)] = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::update()
|
||
|
|
{
|
||
|
|
if (isConnected()) {
|
||
|
|
updateGameData();
|
||
|
|
protoClient.transmitMessages();
|
||
|
|
protoClient.receiveMessages();
|
||
|
|
processMessages();
|
||
|
|
} else {
|
||
|
|
checkForConnections();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool Server::isConnected() const
|
||
|
|
{
|
||
|
|
return protoClient.isConnected();
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::processMessages()
|
||
|
|
{
|
||
|
|
bool issuedCommand = false;
|
||
|
|
while (protoClient.messageQueueSize()) {
|
||
|
|
auto message = protoClient.getNextMessage();
|
||
|
|
if (message.get() == nullptr)
|
||
|
|
return;
|
||
|
|
if (message->has_endofqueue())
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (message->has_command() && !issuedCommand) {
|
||
|
|
auto command = message->command();
|
||
|
|
if (command.has_move() && this->OKToAct()) {
|
||
|
|
auto moveMessage = command.move();
|
||
|
|
this->move(moveMessage.targetx(), moveMessage.targety());
|
||
|
|
} else if (command.has_talk() && this->OKToAct()) {
|
||
|
|
auto talkMessage = command.talk();
|
||
|
|
this->talk(talkMessage.targetx(), talkMessage.targety());
|
||
|
|
} else if (command.has_option() && this->data->stextflag) {
|
||
|
|
auto option = command.option();
|
||
|
|
this->selectStoreOption(static_cast<StoreOption>(command.option().option()));
|
||
|
|
} else if (command.has_buyitem()) {
|
||
|
|
auto buyItem = command.buyitem();
|
||
|
|
this->buyItem(buyItem.id());
|
||
|
|
} else if (command.has_sellitem()) {
|
||
|
|
auto sellItem = command.sellitem();
|
||
|
|
this->sellItem(sellItem.id());
|
||
|
|
} else if (command.has_rechargeitem()) {
|
||
|
|
auto rechargeItem = command.rechargeitem();
|
||
|
|
this->rechargeItem(rechargeItem.id());
|
||
|
|
} else if (command.has_repairitem()) {
|
||
|
|
auto repairItem = command.repairitem();
|
||
|
|
this->repairItem(repairItem.id());
|
||
|
|
} else if (command.has_attackmonster()) {
|
||
|
|
auto attackMonster = command.attackmonster();
|
||
|
|
this->attackMonster(attackMonster.index());
|
||
|
|
} else if (command.has_attackxy()) {
|
||
|
|
auto attackXY = command.attackxy();
|
||
|
|
this->attackXY(attackXY.x(), attackXY.y());
|
||
|
|
} else if (command.has_operateobject()) {
|
||
|
|
auto operateObject = command.operateobject();
|
||
|
|
this->operateObject(operateObject.index());
|
||
|
|
} else if (command.has_usebeltitem()) {
|
||
|
|
auto useBeltItem = command.usebeltitem();
|
||
|
|
this->useBeltItem(useBeltItem.slot());
|
||
|
|
} else if (command.has_togglecharactersheet()) {
|
||
|
|
auto toggleCharacterSheet = command.togglecharactersheet();
|
||
|
|
this->toggleCharacterScreen();
|
||
|
|
} else if (command.has_increasestat()) {
|
||
|
|
auto increaseStat = command.increasestat();
|
||
|
|
this->increaseStat(static_cast<CommandType>(increaseStat.stat()));
|
||
|
|
} else if (command.has_getitem()) {
|
||
|
|
auto getItem = command.getitem();
|
||
|
|
this->getItem(getItem.id());
|
||
|
|
} else if (command.has_setspell()) {
|
||
|
|
auto setSpell = command.setspell();
|
||
|
|
this->setSpell(setSpell.spellid(), static_cast<devilution::SpellType>(setSpell.spelltype()));
|
||
|
|
} else if (command.has_castmonster()) {
|
||
|
|
auto castMonster = command.castmonster();
|
||
|
|
this->castSpell(castMonster.index());
|
||
|
|
} else if (command.has_toggleinventory()) {
|
||
|
|
this->toggleInventory();
|
||
|
|
} else if (command.has_putincursor()) {
|
||
|
|
auto putInCursor = command.putincursor();
|
||
|
|
this->putInCursor(putInCursor.id());
|
||
|
|
} else if (command.has_putcursoritem()) {
|
||
|
|
auto putCursorItem = command.putcursoritem();
|
||
|
|
this->putCursorItem(putCursorItem.target());
|
||
|
|
} else if (command.has_dropcursoritem()) {
|
||
|
|
this->dropCursorItem();
|
||
|
|
} else if (command.has_useitem()) {
|
||
|
|
auto useItem = command.useitem();
|
||
|
|
this->useItem(useItem.id());
|
||
|
|
} else if (command.has_identifystoreitem()) {
|
||
|
|
auto identifyStoreItem = command.identifystoreitem();
|
||
|
|
this->identifyStoreItem(identifyStoreItem.id());
|
||
|
|
} else if (command.has_castxy()) {
|
||
|
|
auto castXY = command.castxy();
|
||
|
|
this->castSpell(castXY.x(), castXY.y());
|
||
|
|
} else if (command.has_cancelqtext()) {
|
||
|
|
this->cancelQText();
|
||
|
|
} else if (command.has_disarmtrap()) {
|
||
|
|
auto disarmTrap = command.disarmtrap();
|
||
|
|
this->disarmTrap(disarmTrap.index());
|
||
|
|
} else if (command.has_skillrepair()) {
|
||
|
|
auto skillRepair = command.skillrepair();
|
||
|
|
this->skillRepair(skillRepair.id());
|
||
|
|
} else if (command.has_skillrecharge()) {
|
||
|
|
auto skillRecharge = command.skillrecharge();
|
||
|
|
this->skillRecharge(skillRecharge.id());
|
||
|
|
} else if (command.has_togglemenu()) {
|
||
|
|
this->toggleMenu();
|
||
|
|
} else if (command.has_savegame()) {
|
||
|
|
this->saveGame();
|
||
|
|
} else if (command.has_quit()) {
|
||
|
|
this->quit();
|
||
|
|
} else if (command.has_clearcursor()) {
|
||
|
|
this->clearCursor();
|
||
|
|
} else if (command.has_identifyitem()) {
|
||
|
|
auto identifyItem = command.identifyitem();
|
||
|
|
this->identifyItem(identifyItem.id());
|
||
|
|
}
|
||
|
|
issuedCommand = true;
|
||
|
|
if (command.has_setfps()) {
|
||
|
|
auto setfps = command.setfps();
|
||
|
|
this->setFPS(setfps.fps());
|
||
|
|
issuedCommand = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::checkForConnections()
|
||
|
|
{
|
||
|
|
if (isConnected())
|
||
|
|
return;
|
||
|
|
if (!listening) {
|
||
|
|
protoClient.initListen();
|
||
|
|
listening = false;
|
||
|
|
}
|
||
|
|
protoClient.checkForConnection();
|
||
|
|
if (!protoClient.isConnected())
|
||
|
|
return;
|
||
|
|
protoClient.stopListen();
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::updateGameData()
|
||
|
|
{
|
||
|
|
std::vector<int> itemsModified;
|
||
|
|
|
||
|
|
auto fullFillItemInfo = [&](int itemID, devilution::Item *item) {
|
||
|
|
itemsModified.push_back(itemID);
|
||
|
|
|
||
|
|
data->itemList[itemID].ID = itemID;
|
||
|
|
data->itemList[itemID]._iSeed = item->_iSeed;
|
||
|
|
data->itemList[itemID]._iCreateInfo = item->_iCreateInfo;
|
||
|
|
data->itemList[itemID]._itype = static_cast<int>(item->_itype);
|
||
|
|
data->itemList[itemID]._ix = item->position.x;
|
||
|
|
data->itemList[itemID]._iy = item->position.y;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iIdentified = item->_iIdentified;
|
||
|
|
data->itemList[itemID]._iMagical = item->_iMagical;
|
||
|
|
strcpy_s(data->itemList[itemID]._iName, item->_iName);
|
||
|
|
if (data->itemList[itemID]._iIdentified) {
|
||
|
|
strcpy_s(data->itemList[itemID]._iIName, item->_iIName);
|
||
|
|
|
||
|
|
data->itemList[itemID]._iFlags = static_cast<int>(item->_iFlags);
|
||
|
|
data->itemList[itemID]._iPrePower = item->_iPrePower;
|
||
|
|
data->itemList[itemID]._iSufPower = item->_iSufPower;
|
||
|
|
data->itemList[itemID]._iPLDam = item->_iPLDam;
|
||
|
|
data->itemList[itemID]._iPLToHit = item->_iPLToHit;
|
||
|
|
data->itemList[itemID]._iPLAC = item->_iPLAC;
|
||
|
|
data->itemList[itemID]._iPLStr = item->_iPLStr;
|
||
|
|
data->itemList[itemID]._iPLMag = item->_iPLMag;
|
||
|
|
data->itemList[itemID]._iPLDex = item->_iPLDex;
|
||
|
|
data->itemList[itemID]._iPLVit = item->_iPLVit;
|
||
|
|
data->itemList[itemID]._iPLFR = item->_iPLFR;
|
||
|
|
data->itemList[itemID]._iPLLR = item->_iPLLR;
|
||
|
|
data->itemList[itemID]._iPLMR = item->_iPLMR;
|
||
|
|
data->itemList[itemID]._iPLMana = item->_iPLMana;
|
||
|
|
data->itemList[itemID]._iPLHP = item->_iPLHP;
|
||
|
|
data->itemList[itemID]._iPLDamMod = item->_iPLDamMod;
|
||
|
|
data->itemList[itemID]._iPLGetHit = item->_iPLGetHit;
|
||
|
|
data->itemList[itemID]._iPLLight = item->_iPLLight;
|
||
|
|
data->itemList[itemID]._iSplLvlAdd = item->_iSplLvlAdd;
|
||
|
|
data->itemList[itemID]._iFMinDam = item->_iFMinDam;
|
||
|
|
data->itemList[itemID]._iFMaxDam = item->_iFMaxDam;
|
||
|
|
data->itemList[itemID]._iLMinDam = item->_iLMinDam;
|
||
|
|
data->itemList[itemID]._iLMaxDam = item->_iLMaxDam;
|
||
|
|
} else {
|
||
|
|
strcpy_s(data->itemList[itemID]._iName, item->_iName);
|
||
|
|
|
||
|
|
data->itemList[itemID]._iFlags = -1;
|
||
|
|
data->itemList[itemID]._iPrePower = -1;
|
||
|
|
data->itemList[itemID]._iSufPower = -1;
|
||
|
|
data->itemList[itemID]._iPLDam = -1;
|
||
|
|
data->itemList[itemID]._iPLToHit = -1;
|
||
|
|
data->itemList[itemID]._iPLAC = -1;
|
||
|
|
data->itemList[itemID]._iPLStr = -1;
|
||
|
|
data->itemList[itemID]._iPLMag = -1;
|
||
|
|
data->itemList[itemID]._iPLDex = -1;
|
||
|
|
data->itemList[itemID]._iPLVit = -1;
|
||
|
|
data->itemList[itemID]._iPLFR = -1;
|
||
|
|
data->itemList[itemID]._iPLLR = -1;
|
||
|
|
data->itemList[itemID]._iPLMR = -1;
|
||
|
|
data->itemList[itemID]._iPLMana = -1;
|
||
|
|
data->itemList[itemID]._iPLHP = -1;
|
||
|
|
data->itemList[itemID]._iPLDamMod = -1;
|
||
|
|
data->itemList[itemID]._iPLGetHit = -1;
|
||
|
|
data->itemList[itemID]._iPLLight = -1;
|
||
|
|
data->itemList[itemID]._iSplLvlAdd = -1;
|
||
|
|
data->itemList[itemID]._iFMinDam = -1;
|
||
|
|
data->itemList[itemID]._iFMaxDam = -1;
|
||
|
|
data->itemList[itemID]._iLMinDam = -1;
|
||
|
|
data->itemList[itemID]._iLMaxDam = -1;
|
||
|
|
}
|
||
|
|
data->itemList[itemID]._iClass = item->_iClass;
|
||
|
|
data->itemList[itemID]._iCurs = item->_iCurs;
|
||
|
|
if (item->_itype == devilution::ItemType::Gold)
|
||
|
|
data->itemList[itemID]._ivalue = item->_ivalue;
|
||
|
|
else
|
||
|
|
data->itemList[itemID]._ivalue = -1;
|
||
|
|
data->itemList[itemID]._iMinDam = item->_iMinDam;
|
||
|
|
data->itemList[itemID]._iMaxDam = item->_iMaxDam;
|
||
|
|
data->itemList[itemID]._iAC = item->_iAC;
|
||
|
|
data->itemList[itemID]._iMiscId = item->_iMiscId;
|
||
|
|
data->itemList[itemID]._iSpell = static_cast<int>(item->_iSpell);
|
||
|
|
|
||
|
|
data->itemList[itemID]._iCharges = item->_iCharges;
|
||
|
|
data->itemList[itemID]._iMaxCharges = item->_iMaxCharges;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iDurability = item->_iDurability;
|
||
|
|
data->itemList[itemID]._iMaxDur = item->_iMaxDur;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iMinStr = item->_iMinStr;
|
||
|
|
data->itemList[itemID]._iMinMag = item->_iMinMag;
|
||
|
|
data->itemList[itemID]._iMinDex = item->_iMinDex;
|
||
|
|
data->itemList[itemID]._iStatFlag = item->_iStatFlag;
|
||
|
|
data->itemList[itemID].IDidx = item->IDidx;
|
||
|
|
};
|
||
|
|
|
||
|
|
auto partialFillItemInfo = [&](int itemID, devilution::Item *item) {
|
||
|
|
itemsModified.push_back(itemID);
|
||
|
|
|
||
|
|
data->itemList[itemID].ID = itemID;
|
||
|
|
data->itemList[itemID]._iSeed = item->_iSeed;
|
||
|
|
data->itemList[itemID]._iCreateInfo = item->_iCreateInfo;
|
||
|
|
data->itemList[itemID]._itype = static_cast<int>(item->_itype);
|
||
|
|
data->itemList[itemID]._ix = item->position.x;
|
||
|
|
data->itemList[itemID]._iy = item->position.y;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iIdentified = item->_iIdentified;
|
||
|
|
data->itemList[itemID]._iMagical = item->_iMagical;
|
||
|
|
strcpy_s(data->itemList[itemID]._iName, item->_iName);
|
||
|
|
if (data->itemList[itemID]._iIdentified)
|
||
|
|
strcpy_s(data->itemList[itemID]._iIName, item->_iIName);
|
||
|
|
else
|
||
|
|
strcpy_s(data->itemList[itemID]._iName, item->_iName);
|
||
|
|
data->itemList[itemID]._iFlags = -1;
|
||
|
|
data->itemList[itemID]._iPrePower = -1;
|
||
|
|
data->itemList[itemID]._iSufPower = -1;
|
||
|
|
data->itemList[itemID]._iPLDam = -1;
|
||
|
|
data->itemList[itemID]._iPLToHit = -1;
|
||
|
|
data->itemList[itemID]._iPLAC = -1;
|
||
|
|
data->itemList[itemID]._iPLStr = -1;
|
||
|
|
data->itemList[itemID]._iPLMag = -1;
|
||
|
|
data->itemList[itemID]._iPLDex = -1;
|
||
|
|
data->itemList[itemID]._iPLVit = -1;
|
||
|
|
data->itemList[itemID]._iPLFR = -1;
|
||
|
|
data->itemList[itemID]._iPLLR = -1;
|
||
|
|
data->itemList[itemID]._iPLMR = -1;
|
||
|
|
data->itemList[itemID]._iPLMana = -1;
|
||
|
|
data->itemList[itemID]._iPLHP = -1;
|
||
|
|
data->itemList[itemID]._iPLDamMod = -1;
|
||
|
|
data->itemList[itemID]._iPLGetHit = -1;
|
||
|
|
data->itemList[itemID]._iPLLight = -1;
|
||
|
|
data->itemList[itemID]._iSplLvlAdd = -1;
|
||
|
|
data->itemList[itemID]._iFMinDam = -1;
|
||
|
|
data->itemList[itemID]._iFMaxDam = -1;
|
||
|
|
data->itemList[itemID]._iLMinDam = -1;
|
||
|
|
data->itemList[itemID]._iLMaxDam = -1;
|
||
|
|
data->itemList[itemID]._iClass = item->_iClass;
|
||
|
|
data->itemList[itemID]._iCurs = item->_iCurs;
|
||
|
|
if (item->_itype == devilution::ItemType::Gold)
|
||
|
|
data->itemList[itemID]._ivalue = item->_ivalue;
|
||
|
|
else
|
||
|
|
data->itemList[itemID]._ivalue = -1;
|
||
|
|
data->itemList[itemID]._iMinDam = -1;
|
||
|
|
data->itemList[itemID]._iMaxDam = -1;
|
||
|
|
data->itemList[itemID]._iAC = -1;
|
||
|
|
data->itemList[itemID]._iMiscId = item->_iMiscId;
|
||
|
|
data->itemList[itemID]._iSpell = static_cast<int>(item->_iSpell);
|
||
|
|
|
||
|
|
data->itemList[itemID]._iCharges = -1;
|
||
|
|
data->itemList[itemID]._iMaxCharges = -1;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iDurability = -1;
|
||
|
|
data->itemList[itemID]._iMaxDur = -1;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iMinStr = -1;
|
||
|
|
data->itemList[itemID]._iMinMag = -1;
|
||
|
|
data->itemList[itemID]._iMinDex = -1;
|
||
|
|
data->itemList[itemID]._iStatFlag = -1;
|
||
|
|
data->itemList[itemID].IDidx = item->IDidx;
|
||
|
|
};
|
||
|
|
|
||
|
|
auto isOnScreen = [&](int x, int y) {
|
||
|
|
int dx = devilution::Players[devilution::MyPlayerId].position.tile.x - x;
|
||
|
|
int dy = devilution::Players[devilution::MyPlayerId].position.tile.y - y;
|
||
|
|
if (!devilution::CharFlag && !devilution::invflag) {
|
||
|
|
if (dy > 0) {
|
||
|
|
if (dx < 1 && abs(dx) + abs(dy) < 11) {
|
||
|
|
return true;
|
||
|
|
} else if (dx > 0 && abs(dx) + abs(dy) < 12) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if ((dx > -1 || dy == 0) && abs(dx) + abs(dy) < 11) {
|
||
|
|
return true;
|
||
|
|
} else if ((dx < 0 && dy != 0) && abs(dx) + abs(dy) < 12) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if ((devilution::CharFlag && !devilution::invflag) || (!devilution::CharFlag && devilution::invflag)) {
|
||
|
|
return panelScreenCheck[std::make_pair(dx, dy)];
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
};
|
||
|
|
|
||
|
|
auto message = std::make_unique<dapi::message::Message>();
|
||
|
|
auto update = message->mutable_frameupdate();
|
||
|
|
|
||
|
|
data->player = devilution::MyPlayerId;
|
||
|
|
update->set_player(data->player);
|
||
|
|
|
||
|
|
data->stextflag = static_cast<char>(devilution::ActiveStore);
|
||
|
|
update->set_stextflag(data->stextflag);
|
||
|
|
data->pauseMode = devilution::PauseMode;
|
||
|
|
update->set_pausemode(data->pauseMode);
|
||
|
|
if (devilution::sgpCurrentMenu != nullptr)
|
||
|
|
data->menuOpen = true;
|
||
|
|
else
|
||
|
|
data->menuOpen = false;
|
||
|
|
update->set_menuopen(data->menuOpen);
|
||
|
|
data->pcurs = devilution::pcurs;
|
||
|
|
update->set_cursor(devilution::pcurs);
|
||
|
|
data->chrflag = devilution::CharFlag;
|
||
|
|
update->set_chrflag(devilution::CharFlag);
|
||
|
|
data->invflag = devilution::invflag;
|
||
|
|
update->set_invflag(devilution::invflag);
|
||
|
|
data->qtextflag = devilution::qtextflag;
|
||
|
|
update->set_qtextflag(devilution::qtextflag);
|
||
|
|
if (!devilution::setlevel)
|
||
|
|
data->currlevel = static_cast<int>(devilution::currlevel);
|
||
|
|
else
|
||
|
|
data->currlevel = static_cast<int>(devilution::setlvlnum);
|
||
|
|
update->set_currlevel(data->currlevel);
|
||
|
|
data->setlevel = static_cast<bool>(devilution::setlevel);
|
||
|
|
update->set_setlevel(devilution::setlevel);
|
||
|
|
if (devilution::qtextflag) {
|
||
|
|
std::stringstream qtextss;
|
||
|
|
for (auto &line : devilution::TextLines)
|
||
|
|
qtextss << line;
|
||
|
|
update->set_qtext(qtextss.str().c_str());
|
||
|
|
}
|
||
|
|
else
|
||
|
|
update->set_qtext("");
|
||
|
|
update->set_fps(FPS);
|
||
|
|
if (!devilution::gbIsMultiplayer)
|
||
|
|
update->set_gamemode(0);
|
||
|
|
else
|
||
|
|
update->set_gamemode(1);
|
||
|
|
|
||
|
|
update->set_gndifficulty(devilution::sgGameInitInfo.nDifficulty);
|
||
|
|
|
||
|
|
int range = 10;
|
||
|
|
if (devilution::MyPlayer->isWalking()) {
|
||
|
|
range = 11;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int x = 0; x < 112; x++) {
|
||
|
|
for (int y = 0; y < 112; y++) {
|
||
|
|
if (isOnScreen(x, y)) {
|
||
|
|
auto dpiece = update->add_dpiece();
|
||
|
|
dpiece->set_type(devilution::dPiece[x][y]);
|
||
|
|
dpiece->set_solid(HasAnyOf(devilution::SOLData[dpiece->type()], devilution::TileProperties::Solid));
|
||
|
|
dpiece->set_x(x);
|
||
|
|
dpiece->set_y(y);
|
||
|
|
dpiece->set_stopmissile(HasAnyOf(devilution::SOLData[dpiece->type()], devilution::TileProperties::BlockMissile));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < devilution::numtrigs; i++) {
|
||
|
|
if (isOnScreen(devilution::trigs[i].position.x, devilution::trigs[i].position.y)) {
|
||
|
|
auto trigger = update->add_triggerdata();
|
||
|
|
trigger->set_lvl(devilution::trigs[i]._tlvl);
|
||
|
|
trigger->set_x(devilution::trigs[i].position.x);
|
||
|
|
trigger->set_y(devilution::trigs[i].position.y);
|
||
|
|
trigger->set_type(devilution::trigs[i]._tmsg);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < MAXQUESTS; i++) {
|
||
|
|
auto quest = update->add_questdata();
|
||
|
|
quest->set_id(i);
|
||
|
|
if (devilution::Quests[i]._qactive == 2)
|
||
|
|
quest->set_state(devilution::Quests[i]._qactive);
|
||
|
|
else
|
||
|
|
quest->set_state(0);
|
||
|
|
|
||
|
|
if (devilution::currlevel == devilution::Quests[i]._qlevel && devilution::Quests[i]._qslvl != 0 && devilution::Quests[i]._qactive != devilution::quest_state::QUEST_NOTAVAIL) {
|
||
|
|
auto trigger = update->add_triggerdata();
|
||
|
|
trigger->set_lvl(devilution::Quests[i]._qslvl);
|
||
|
|
trigger->set_x(devilution::Quests[i].position.x);
|
||
|
|
trigger->set_y(devilution::Quests[i].position.y);
|
||
|
|
trigger->set_type(1029);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
data->storeList.clear();
|
||
|
|
if (devilution::ActiveStore != devilution::TalkID::None) {
|
||
|
|
for (int i = 0; i < 24; i++) {
|
||
|
|
if (devilution::TextLine[i].isSelectable()) {
|
||
|
|
if (!strcmp(devilution::TextLine[i].text.c_str(), "Talk to Cain") || !strcmp(devilution::TextLine[i].text.c_str(), "Talk to Farnham") || !strcmp(devilution::TextLine[i].text.c_str(), "Talk to Pepin") || !strcmp(devilution::TextLine[i].text.c_str(), "Talk to Gillian") || !strcmp(devilution::TextLine[i].text.c_str(), "Talk to Ogden") || !strcmp(devilution::TextLine[i].text.c_str(), "Talk to Griswold") || !strcmp(devilution::TextLine[i].text.c_str(), "Talk to Adria") || !strcmp(devilution::TextLine[i].text.c_str(), "Talk to Wirt"))
|
||
|
|
data->storeList.push_back(StoreOption::TALK);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "Identify an item"))
|
||
|
|
data->storeList.push_back(StoreOption::IDENTIFYANITEM);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "Say goodbye") || !strcmp(devilution::TextLine[i].text.c_str(), "Say Goodbye") || !strcmp(devilution::TextLine[i].text.c_str(), "Leave Healer's home") || !strcmp(devilution::TextLine[i].text.c_str(), "Leave the shop") || !strcmp(devilution::TextLine[i].text.c_str(), "Leave the shack") || !strcmp(devilution::TextLine[i].text.c_str(), "Leave the tavern") || !strcmp(devilution::TextLine[i].text.c_str(), "Leave"))
|
||
|
|
data->storeList.push_back(StoreOption::EXIT);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "Receive healing"))
|
||
|
|
data->storeList.push_back(StoreOption::HEAL);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "Buy items"))
|
||
|
|
data->storeList.push_back(StoreOption::BUYITEMS);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "What have you got?"))
|
||
|
|
data->storeList.push_back(StoreOption::WIRTPEEK);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "Buy basic items"))
|
||
|
|
data->storeList.push_back(StoreOption::BUYBASIC);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "Buy premium items"))
|
||
|
|
data->storeList.push_back(StoreOption::BUYPREMIUM);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "Sell items"))
|
||
|
|
data->storeList.push_back(StoreOption::SELL);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "Repair items"))
|
||
|
|
data->storeList.push_back(StoreOption::REPAIR);
|
||
|
|
else if (!strcmp(devilution::TextLine[i].text.c_str(), "Recharge staves"))
|
||
|
|
data->storeList.push_back(StoreOption::RECHARGE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (devilution::ActiveStore) {
|
||
|
|
case devilution::TalkID::HealerBuy:
|
||
|
|
case devilution::TalkID::StorytellerIdentifyShow:
|
||
|
|
case devilution::TalkID::NoMoney:
|
||
|
|
case devilution::TalkID::NoRoom:
|
||
|
|
case devilution::TalkID::SmithBuy:
|
||
|
|
case devilution::TalkID::StorytellerIdentify:
|
||
|
|
case devilution::TalkID::SmithPremiumBuy:
|
||
|
|
case devilution::TalkID::SmithRepair:
|
||
|
|
case devilution::TalkID::SmithSell:
|
||
|
|
case devilution::TalkID::WitchBuy:
|
||
|
|
case devilution::TalkID::WitchRecharge:
|
||
|
|
case devilution::TalkID::WitchSell:
|
||
|
|
case devilution::TalkID::Gossip:
|
||
|
|
data->storeList.push_back(StoreOption::BACK);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (auto &option : data->storeList)
|
||
|
|
update->add_storeoption(static_cast<int>(option));
|
||
|
|
|
||
|
|
data->groundItems.clear();
|
||
|
|
|
||
|
|
for (int i = 0; i < 4; i++) {
|
||
|
|
auto playerData = update->add_playerdata();
|
||
|
|
|
||
|
|
data->playerList[i].InvBody.clear();
|
||
|
|
|
||
|
|
data->playerList[i].pnum = i;
|
||
|
|
playerData->set_pnum(i);
|
||
|
|
|
||
|
|
memcpy(data->playerList[i]._pName, devilution::Players[i]._pName, 32);
|
||
|
|
playerData->set__pname(data->playerList[i]._pName);
|
||
|
|
|
||
|
|
for (int j = 0; j < MAXINV; j++)
|
||
|
|
data->playerList[i].InvList[j] = -1;
|
||
|
|
|
||
|
|
if (devilution::MyPlayerId == i) {
|
||
|
|
data->playerList[i]._pmode = devilution::Players[i]._pmode;
|
||
|
|
data->playerList[i].plrlevel = devilution::Players[i].plrlevel;
|
||
|
|
data->playerList[i]._px = devilution::Players[i].position.tile.x;
|
||
|
|
data->playerList[i]._py = devilution::Players[i].position.tile.y;
|
||
|
|
data->playerList[i]._pfutx = devilution::Players[i].position.future.x;
|
||
|
|
data->playerList[i]._pfuty = devilution::Players[i].position.future.y;
|
||
|
|
data->playerList[i]._pdir = static_cast<int>(devilution::Players[i]._pdir);
|
||
|
|
|
||
|
|
data->playerList[i]._pRSpell = static_cast<int>(devilution::Players[i]._pRSpell);
|
||
|
|
data->playerList[i]._pRSplType = static_cast<char>(devilution::Players[i]._pRSplType);
|
||
|
|
|
||
|
|
memcpy(data->playerList[i]._pSplLvl, devilution::Players[i]._pSplLvl, sizeof(data->playerList[i]._pSplLvl));
|
||
|
|
data->playerList[i]._pMemSpells = devilution::Players[i]._pMemSpells;
|
||
|
|
data->playerList[i]._pAblSpells = devilution::Players[i]._pAblSpells;
|
||
|
|
data->playerList[i]._pScrlSpells = devilution::Players[i]._pScrlSpells;
|
||
|
|
|
||
|
|
data->playerList[i]._pClass = static_cast<char>(devilution::Players[i]._pClass);
|
||
|
|
|
||
|
|
data->playerList[i]._pStrength = devilution::Players[i]._pStrength;
|
||
|
|
data->playerList[i]._pBaseStr = devilution::Players[i]._pBaseStr;
|
||
|
|
data->playerList[i]._pMagic = devilution::Players[i]._pMagic;
|
||
|
|
data->playerList[i]._pBaseMag = devilution::Players[i]._pBaseMag;
|
||
|
|
data->playerList[i]._pDexterity = devilution::Players[i]._pDexterity;
|
||
|
|
data->playerList[i]._pBaseDex = devilution::Players[i]._pBaseDex;
|
||
|
|
data->playerList[i]._pVitality = devilution::Players[i]._pVitality;
|
||
|
|
data->playerList[i]._pBaseVit = devilution::Players[i]._pBaseVit;
|
||
|
|
|
||
|
|
data->playerList[i]._pStatPts = devilution::Players[i]._pStatPts;
|
||
|
|
|
||
|
|
data->playerList[i]._pDamageMod = devilution::Players[i]._pDamageMod;
|
||
|
|
|
||
|
|
data->playerList[i]._pHitPoints = devilution::Players[i]._pHitPoints;
|
||
|
|
data->playerList[i]._pMaxHP = devilution::Players[i]._pMaxHP;
|
||
|
|
data->playerList[i]._pMana = devilution::Players[i]._pMana;
|
||
|
|
data->playerList[i]._pMaxMana = devilution::Players[i]._pMaxMana;
|
||
|
|
data->playerList[i]._pLevel = devilution::Players[i].getCharacterLevel();
|
||
|
|
data->playerList[i]._pExperience = devilution::Players[i]._pExperience;
|
||
|
|
|
||
|
|
data->playerList[i]._pArmorClass = devilution::Players[i]._pArmorClass;
|
||
|
|
|
||
|
|
data->playerList[i]._pMagResist = devilution::Players[i]._pMagResist;
|
||
|
|
data->playerList[i]._pFireResist = devilution::Players[i]._pFireResist;
|
||
|
|
data->playerList[i]._pLightResist = devilution::Players[i]._pLghtResist;
|
||
|
|
|
||
|
|
data->playerList[i]._pGold = devilution::Players[i]._pGold;
|
||
|
|
|
||
|
|
for (int j = 0; j < NUM_INVLOC; j++) {
|
||
|
|
if (devilution::Players[i].InvBody[j]._itype == devilution::ItemType::None) {
|
||
|
|
data->playerList[i].InvBody[j] = -1;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
int itemID = static_cast<int>(data->itemList.size());
|
||
|
|
for (int k = 0; k < data->itemList.size(); k++) {
|
||
|
|
if (data->itemList[k].compare(devilution::Players[i].InvBody[j])) {
|
||
|
|
itemID = k;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (itemID == data->itemList.size())
|
||
|
|
data->itemList.push_back(ItemData {});
|
||
|
|
fullFillItemInfo(itemID, &devilution::Players[i].InvBody[j]);
|
||
|
|
data->playerList[i].InvBody[j] = itemID;
|
||
|
|
}
|
||
|
|
bool used[40] = { false };
|
||
|
|
for (int j = 0; j < MAXINV; j++) {
|
||
|
|
auto index = devilution::Players[i].InvGrid[j];
|
||
|
|
if (index != 0) {
|
||
|
|
int itemID = static_cast<int>(data->itemList.size());
|
||
|
|
for (int k = 0; k < data->itemList.size(); k++) {
|
||
|
|
if (data->itemList[k].compare(devilution::Players[i].InvList[abs(index) - 1])) {
|
||
|
|
itemID = k;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
data->playerList[i].InvGrid[j] = itemID;
|
||
|
|
if (!used[abs(index) - 1]) {
|
||
|
|
if (itemID == data->itemList.size())
|
||
|
|
data->itemList.push_back(ItemData {});
|
||
|
|
fullFillItemInfo(itemID, &devilution::Players[i].InvList[abs(index) - 1]);
|
||
|
|
used[abs(index) - 1] = true;
|
||
|
|
data->playerList[i].InvList[abs(index) - 1] = itemID;
|
||
|
|
}
|
||
|
|
} else
|
||
|
|
data->playerList[i].InvGrid[j] = -1;
|
||
|
|
}
|
||
|
|
for (int j = 0; j < MAXSPD; j++) {
|
||
|
|
if (devilution::Players[i].SpdList[j]._itype == devilution::ItemType::None) {
|
||
|
|
data->playerList[i].SpdList[j] = -1;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
int itemID = static_cast<int>(data->itemList.size());
|
||
|
|
for (int k = 0; k < data->itemList.size(); k++) {
|
||
|
|
if (data->itemList[k].compare(devilution::Players[i].SpdList[j])) {
|
||
|
|
itemID = k;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (itemID == data->itemList.size())
|
||
|
|
data->itemList.push_back(ItemData {});
|
||
|
|
fullFillItemInfo(itemID, &devilution::Players[i].SpdList[j]);
|
||
|
|
data->playerList[i].SpdList[j] = itemID;
|
||
|
|
}
|
||
|
|
if (devilution::pcurs < 12)
|
||
|
|
data->playerList[i].HoldItem = -1;
|
||
|
|
else {
|
||
|
|
int itemID = static_cast<int>(data->itemList.size());
|
||
|
|
for (int j = 0; j < data->itemList.size(); j++) {
|
||
|
|
if (data->itemList[j].compare(devilution::Players[i].HoldItem)) {
|
||
|
|
itemID = j;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (itemID == data->itemList.size())
|
||
|
|
data->itemList.push_back(ItemData {});
|
||
|
|
partialFillItemInfo(itemID, &devilution::Players[i].HoldItem);
|
||
|
|
data->playerList[i].HoldItem = itemID;
|
||
|
|
}
|
||
|
|
|
||
|
|
data->playerList[i]._pIMinDam = devilution::Players[i]._pIMinDam;
|
||
|
|
data->playerList[i]._pIMaxDam = devilution::Players[i]._pIMaxDam;
|
||
|
|
data->playerList[i]._pIBonusDam = devilution::Players[i]._pIBonusDam;
|
||
|
|
data->playerList[i]._pIAC = devilution::Players[i]._pIAC;
|
||
|
|
data->playerList[i]._pIBonusToHit = devilution::Players[i]._pIBonusToHit;
|
||
|
|
data->playerList[i]._pIBonusAC = devilution::Players[i]._pIBonusAC;
|
||
|
|
data->playerList[i]._pIBonusDamMod = devilution::Players[i]._pIBonusDamMod;
|
||
|
|
data->playerList[i].pManaShield = devilution::Players[i].pManaShield;
|
||
|
|
} else if (devilution::IsTileLit(devilution::Point { devilution::Players[i].position.tile.x, devilution::Players[i].position.tile.y })) {
|
||
|
|
data->playerList[i]._pmode = devilution::Players[i]._pmode;
|
||
|
|
data->playerList[i].plrlevel = devilution::Players[i].plrlevel;
|
||
|
|
data->playerList[i]._px = devilution::Players[i].position.tile.x;
|
||
|
|
data->playerList[i]._py = devilution::Players[i].position.tile.y;
|
||
|
|
data->playerList[i]._pfutx = devilution::Players[i].position.future.x;
|
||
|
|
data->playerList[i]._pfuty = devilution::Players[i].position.future.y;
|
||
|
|
data->playerList[i]._pdir = static_cast<int>(devilution::Players[i]._pdir);
|
||
|
|
|
||
|
|
data->playerList[i]._pRSpell = -1;
|
||
|
|
data->playerList[i]._pRSplType = 4;
|
||
|
|
|
||
|
|
memset(data->playerList[i]._pSplLvl, 0, 64);
|
||
|
|
data->playerList[i]._pMemSpells = -1;
|
||
|
|
data->playerList[i]._pAblSpells = -1;
|
||
|
|
data->playerList[i]._pScrlSpells = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pClass = static_cast<char>(devilution::Players[i]._pClass);
|
||
|
|
|
||
|
|
data->playerList[i]._pStrength = -1;
|
||
|
|
data->playerList[i]._pBaseStr = -1;
|
||
|
|
data->playerList[i]._pMagic = -1;
|
||
|
|
data->playerList[i]._pBaseMag = -1;
|
||
|
|
data->playerList[i]._pDexterity = -1;
|
||
|
|
data->playerList[i]._pBaseDex = -1;
|
||
|
|
data->playerList[i]._pVitality = -1;
|
||
|
|
data->playerList[i]._pBaseVit = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pStatPts = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pDamageMod = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pHitPoints = devilution::Players[i]._pHitPoints;
|
||
|
|
data->playerList[i]._pMaxHP = devilution::Players[i]._pMaxHP;
|
||
|
|
data->playerList[i]._pMana = -1;
|
||
|
|
data->playerList[i]._pMaxMana = -1;
|
||
|
|
data->playerList[i]._pLevel = devilution::Players[i].getCharacterLevel();
|
||
|
|
data->playerList[i]._pExperience = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pArmorClass = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pMagResist = -1;
|
||
|
|
data->playerList[i]._pFireResist = -1;
|
||
|
|
data->playerList[i]._pLightResist = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pGold = -1;
|
||
|
|
|
||
|
|
for (int j = 0; j < NUM_INVLOC; j++)
|
||
|
|
data->playerList[i].InvBody[j] = -1;
|
||
|
|
for (int j = 0; j < MAXINV; j++)
|
||
|
|
data->playerList[i].InvGrid[j] = -1;
|
||
|
|
for (int j = 0; j < MAXSPD; j++)
|
||
|
|
data->playerList[i].SpdList[j] = -1;
|
||
|
|
data->playerList[i].HoldItem = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pIMinDam = -1;
|
||
|
|
data->playerList[i]._pIMaxDam = -1;
|
||
|
|
data->playerList[i]._pIBonusDam = -1;
|
||
|
|
data->playerList[i]._pIAC = -1;
|
||
|
|
data->playerList[i]._pIBonusToHit = -1;
|
||
|
|
data->playerList[i]._pIBonusAC = -1;
|
||
|
|
data->playerList[i]._pIBonusDamMod = -1;
|
||
|
|
data->playerList[i].pManaShield = devilution::Players[i].pManaShield;
|
||
|
|
} else {
|
||
|
|
data->playerList[i]._pmode = 0;
|
||
|
|
data->playerList[i].plrlevel = -1;
|
||
|
|
data->playerList[i]._px = -1;
|
||
|
|
data->playerList[i]._py = -1;
|
||
|
|
data->playerList[i]._pfutx = -1;
|
||
|
|
data->playerList[i]._pfuty = -1;
|
||
|
|
data->playerList[i]._pdir = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pRSpell = -1;
|
||
|
|
data->playerList[i]._pRSplType = -1;
|
||
|
|
|
||
|
|
memset(data->playerList[i]._pSplLvl, 0, 64);
|
||
|
|
data->playerList[i]._pMemSpells = -1;
|
||
|
|
data->playerList[i]._pAblSpells = -1;
|
||
|
|
data->playerList[i]._pScrlSpells = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pClass = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pStrength = -1;
|
||
|
|
data->playerList[i]._pBaseStr = -1;
|
||
|
|
data->playerList[i]._pMagic = -1;
|
||
|
|
data->playerList[i]._pBaseMag = -1;
|
||
|
|
data->playerList[i]._pDexterity = -1;
|
||
|
|
data->playerList[i]._pBaseDex = -1;
|
||
|
|
data->playerList[i]._pVitality = -1;
|
||
|
|
data->playerList[i]._pBaseVit = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pStatPts = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pDamageMod = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pHitPoints = -1;
|
||
|
|
data->playerList[i]._pMaxHP = -1;
|
||
|
|
data->playerList[i]._pMana = -1;
|
||
|
|
data->playerList[i]._pMaxMana = -1;
|
||
|
|
data->playerList[i]._pLevel = devilution::Players[i].getCharacterLevel();
|
||
|
|
data->playerList[i]._pExperience = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pArmorClass = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pMagResist = -1;
|
||
|
|
data->playerList[i]._pFireResist = -1;
|
||
|
|
data->playerList[i]._pLightResist = -1;
|
||
|
|
data->playerList[i]._pIBonusToHit = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pGold = -1;
|
||
|
|
for (int j = 0; j < NUM_INVLOC; j++)
|
||
|
|
data->playerList[i].InvBody[j] = -1;
|
||
|
|
for (int j = 0; j < MAXINV; j++)
|
||
|
|
data->playerList[i].InvGrid[j] = -1;
|
||
|
|
for (int j = 0; j < MAXSPD; j++)
|
||
|
|
data->playerList[i].SpdList[j] = -1;
|
||
|
|
data->playerList[i].HoldItem = -1;
|
||
|
|
|
||
|
|
data->playerList[i]._pIMinDam = -1;
|
||
|
|
data->playerList[i]._pIMaxDam = -1;
|
||
|
|
data->playerList[i]._pIBonusDam = -1;
|
||
|
|
data->playerList[i]._pIAC = -1;
|
||
|
|
data->playerList[i]._pIBonusToHit = -1;
|
||
|
|
data->playerList[i]._pIBonusAC = -1;
|
||
|
|
data->playerList[i]._pIBonusDamMod = -1;
|
||
|
|
data->playerList[i].pManaShield = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
playerData->set__pmode(data->playerList[i]._pmode);
|
||
|
|
playerData->set_plrlevel(data->playerList[i].plrlevel);
|
||
|
|
playerData->set__px(data->playerList[i]._px);
|
||
|
|
playerData->set__py(data->playerList[i]._py);
|
||
|
|
playerData->set__pfutx(data->playerList[i]._pfutx);
|
||
|
|
playerData->set__pfuty(data->playerList[i]._pfuty);
|
||
|
|
playerData->set__pdir(data->playerList[i]._pdir);
|
||
|
|
|
||
|
|
playerData->set__prspell(data->playerList[i]._pRSpell);
|
||
|
|
playerData->set__prspltype(data->playerList[i]._pRSplType);
|
||
|
|
|
||
|
|
for (int j = 0; j < 64; j++)
|
||
|
|
playerData->add__pspllvl(data->playerList[i]._pSplLvl[j]);
|
||
|
|
playerData->set__pmemspells(data->playerList[i]._pMemSpells);
|
||
|
|
playerData->set__pablspells(data->playerList[i]._pAblSpells);
|
||
|
|
playerData->set__pscrlspells(data->playerList[i]._pScrlSpells);
|
||
|
|
|
||
|
|
playerData->set__pclass(data->playerList[i]._pClass);
|
||
|
|
|
||
|
|
playerData->set__pstrength(data->playerList[i]._pStrength);
|
||
|
|
playerData->set__pbasestr(data->playerList[i]._pBaseStr);
|
||
|
|
playerData->set__pmagic(data->playerList[i]._pMagic);
|
||
|
|
playerData->set__pbasemag(data->playerList[i]._pBaseMag);
|
||
|
|
playerData->set__pdexterity(data->playerList[i]._pDexterity);
|
||
|
|
playerData->set__pbasedex(data->playerList[i]._pBaseDex);
|
||
|
|
playerData->set__pvitality(data->playerList[i]._pVitality);
|
||
|
|
playerData->set__pbasevit(data->playerList[i]._pBaseVit);
|
||
|
|
|
||
|
|
playerData->set__pstatpts(data->playerList[i]._pStatPts);
|
||
|
|
|
||
|
|
playerData->set__pdamagemod(data->playerList[i]._pDamageMod);
|
||
|
|
|
||
|
|
playerData->set__phitpoints(data->playerList[i]._pHitPoints);
|
||
|
|
playerData->set__pmaxhp(data->playerList[i]._pMaxHP);
|
||
|
|
playerData->set__pmana(data->playerList[i]._pMana);
|
||
|
|
playerData->set__pmaxmana(data->playerList[i]._pMaxMana);
|
||
|
|
playerData->set__plevel(data->playerList[i]._pLevel);
|
||
|
|
playerData->set__pexperience(data->playerList[i]._pExperience);
|
||
|
|
|
||
|
|
playerData->set__parmorclass(data->playerList[i]._pArmorClass);
|
||
|
|
|
||
|
|
playerData->set__pmagresist(data->playerList[i]._pMagResist);
|
||
|
|
playerData->set__pfireresist(data->playerList[i]._pFireResist);
|
||
|
|
playerData->set__plightresist(data->playerList[i]._pLightResist);
|
||
|
|
|
||
|
|
playerData->set__pgold(data->playerList[i]._pGold);
|
||
|
|
for (int j = 0; j < NUM_INVLOC; j++)
|
||
|
|
playerData->add_invbody(data->playerList[i].InvBody[j]);
|
||
|
|
for (int j = 0; j < MAXINV; j++)
|
||
|
|
playerData->add_invlist(data->playerList[i].InvList[j]);
|
||
|
|
for (int j = 0; j < MAXINV; j++)
|
||
|
|
playerData->add_invgrid(data->playerList[i].InvGrid[j]);
|
||
|
|
for (int j = 0; j < MAXSPD; j++)
|
||
|
|
playerData->add_spdlist(data->playerList[i].SpdList[j]);
|
||
|
|
playerData->set_holditem(data->playerList[i].HoldItem);
|
||
|
|
|
||
|
|
playerData->set__pimindam(data->playerList[i]._pIMinDam);
|
||
|
|
playerData->set__pimaxdam(data->playerList[i]._pIMaxDam);
|
||
|
|
playerData->set__pibonusdam(data->playerList[i]._pIBonusDam);
|
||
|
|
playerData->set__piac(data->playerList[i]._pIAC);
|
||
|
|
playerData->set__pibonustohit(data->playerList[i]._pIBonusToHit);
|
||
|
|
playerData->set__pibonusac(data->playerList[i]._pIBonusAC);
|
||
|
|
playerData->set__pibonusdammod(data->playerList[i]._pIBonusDamMod);
|
||
|
|
playerData->set_pmanashield(data->playerList[i].pManaShield);
|
||
|
|
}
|
||
|
|
|
||
|
|
auto emptyFillItemInfo = [&](int itemID, devilution::Item *item) {
|
||
|
|
itemsModified.push_back(itemID);
|
||
|
|
|
||
|
|
data->itemList[itemID].ID = itemID;
|
||
|
|
data->itemList[itemID]._iSeed = item->_iSeed;
|
||
|
|
data->itemList[itemID]._iCreateInfo = item->_iCreateInfo;
|
||
|
|
data->itemList[itemID]._itype = static_cast<int>(item->_itype);
|
||
|
|
data->itemList[itemID]._ix = -1;
|
||
|
|
data->itemList[itemID]._iy = -1;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iIdentified = -1;
|
||
|
|
data->itemList[itemID]._iMagical = -1;
|
||
|
|
strcpy_s(data->itemList[itemID]._iName, "");
|
||
|
|
strcpy_s(data->itemList[itemID]._iIName, "");
|
||
|
|
data->itemList[itemID]._iFlags = -1;
|
||
|
|
data->itemList[itemID]._iPrePower = -1;
|
||
|
|
data->itemList[itemID]._iSufPower = -1;
|
||
|
|
data->itemList[itemID]._iPLDam = -1;
|
||
|
|
data->itemList[itemID]._iPLToHit = -1;
|
||
|
|
data->itemList[itemID]._iPLAC = -1;
|
||
|
|
data->itemList[itemID]._iPLStr = -1;
|
||
|
|
data->itemList[itemID]._iPLMag = -1;
|
||
|
|
data->itemList[itemID]._iPLDex = -1;
|
||
|
|
data->itemList[itemID]._iPLVit = -1;
|
||
|
|
data->itemList[itemID]._iPLFR = -1;
|
||
|
|
data->itemList[itemID]._iPLLR = -1;
|
||
|
|
data->itemList[itemID]._iPLMR = -1;
|
||
|
|
data->itemList[itemID]._iPLMana = -1;
|
||
|
|
data->itemList[itemID]._iPLHP = -1;
|
||
|
|
data->itemList[itemID]._iPLDamMod = -1;
|
||
|
|
data->itemList[itemID]._iPLGetHit = -1;
|
||
|
|
data->itemList[itemID]._iPLLight = -1;
|
||
|
|
data->itemList[itemID]._iSplLvlAdd = -1;
|
||
|
|
data->itemList[itemID]._iFMinDam = -1;
|
||
|
|
data->itemList[itemID]._iFMaxDam = -1;
|
||
|
|
data->itemList[itemID]._iLMinDam = -1;
|
||
|
|
data->itemList[itemID]._iLMaxDam = -1;
|
||
|
|
data->itemList[itemID]._iClass = -1;
|
||
|
|
data->itemList[itemID]._ivalue = -1;
|
||
|
|
data->itemList[itemID]._iMinDam = -1;
|
||
|
|
data->itemList[itemID]._iMaxDam = -1;
|
||
|
|
data->itemList[itemID]._iAC = -1;
|
||
|
|
data->itemList[itemID]._iMiscId = -1;
|
||
|
|
data->itemList[itemID]._iSpell = -1;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iCharges = -1;
|
||
|
|
data->itemList[itemID]._iMaxCharges = -1;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iDurability = -1;
|
||
|
|
data->itemList[itemID]._iMaxDur = -1;
|
||
|
|
|
||
|
|
data->itemList[itemID]._iMinStr = -1;
|
||
|
|
data->itemList[itemID]._iMinMag = -1;
|
||
|
|
data->itemList[itemID]._iMinDex = -1;
|
||
|
|
data->itemList[itemID]._iStatFlag = -1;
|
||
|
|
data->itemList[itemID].IDidx = item->IDidx;
|
||
|
|
};
|
||
|
|
|
||
|
|
for (int i = 0; i < devilution::ActiveItemCount; i++) {
|
||
|
|
int itemID = static_cast<int>(data->itemList.size());
|
||
|
|
for (int j = 0; j < data->itemList.size(); j++) {
|
||
|
|
if (data->itemList[j].compare(devilution::Items[devilution::ActiveItems[i]])) {
|
||
|
|
itemID = j;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (devilution::dItem[devilution::Items[devilution::ActiveItems[i]].position.x][devilution::Items[devilution::ActiveItems[i]].position.y] != static_cast<char>(devilution::ActiveItems[i] + 1))
|
||
|
|
continue;
|
||
|
|
if (itemID == data->itemList.size())
|
||
|
|
data->itemList.push_back(ItemData {});
|
||
|
|
int dx = devilution::Players[devilution::MyPlayerId].position.tile.x - devilution::Items[devilution::ActiveItems[i]].position.x;
|
||
|
|
int dy = devilution::Players[devilution::MyPlayerId].position.tile.y - devilution::Items[devilution::ActiveItems[i]].position.y;
|
||
|
|
if (dy > 0) {
|
||
|
|
if (dx < 1 && abs(dx) + abs(dy) < 11) {
|
||
|
|
partialFillItemInfo(itemID, &devilution::Items[devilution::ActiveItems[i]]);
|
||
|
|
data->groundItems.push_back(itemID);
|
||
|
|
} else if (dx > 0 && abs(dx) + abs(dy) < 12) {
|
||
|
|
partialFillItemInfo(itemID, &devilution::Items[devilution::ActiveItems[i]]);
|
||
|
|
data->groundItems.push_back(itemID);
|
||
|
|
} else
|
||
|
|
emptyFillItemInfo(itemID, &devilution::Items[devilution::ActiveItems[i]]);
|
||
|
|
} else {
|
||
|
|
if ((dx > -1 || dy == 0) && abs(dx) + abs(dy) < 11) {
|
||
|
|
partialFillItemInfo(itemID, &devilution::Items[devilution::ActiveItems[i]]);
|
||
|
|
data->groundItems.push_back(itemID);
|
||
|
|
} else if ((dx < 0 && dy != 0) && abs(dx) + abs(dy) < 12) {
|
||
|
|
partialFillItemInfo(itemID, &devilution::Items[devilution::ActiveItems[i]]);
|
||
|
|
data->groundItems.push_back(itemID);
|
||
|
|
} else
|
||
|
|
emptyFillItemInfo(itemID, &devilution::Items[devilution::ActiveItems[i]]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
data->storeItems.clear();
|
||
|
|
int storeLoopMax = 0;
|
||
|
|
devilution::Item *currentItem;
|
||
|
|
bool useiValue = false;
|
||
|
|
bool shiftValue = false;
|
||
|
|
switch (devilution::ActiveStore) {
|
||
|
|
case devilution::TalkID::StorytellerIdentify:
|
||
|
|
case devilution::TalkID::WitchSell:
|
||
|
|
case devilution::TalkID::WitchRecharge:
|
||
|
|
case devilution::TalkID::SmithSell:
|
||
|
|
case devilution::TalkID::SmithRepair:
|
||
|
|
storeLoopMax = 48;
|
||
|
|
currentItem = &devilution::PlayerItems[0];
|
||
|
|
useiValue = true;
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::WitchBuy:
|
||
|
|
storeLoopMax = devilution::NumWitchItemsHf;
|
||
|
|
currentItem = &devilution::WitchItems[0];
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::SmithBuy:
|
||
|
|
storeLoopMax = devilution::NumSmithBasicItemsHf;
|
||
|
|
currentItem = &devilution::SmithItems[0];
|
||
|
|
useiValue = true;
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::HealerBuy:
|
||
|
|
storeLoopMax = devilution::NumHealerItemsHf;
|
||
|
|
currentItem = &devilution::HealerItems[0];
|
||
|
|
useiValue = true;
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::SmithPremiumBuy:
|
||
|
|
storeLoopMax = devilution::NumSmithItemsHf;
|
||
|
|
currentItem = &devilution::PremiumItems[0];
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::BoyBuy:
|
||
|
|
storeLoopMax = 1;
|
||
|
|
currentItem = &devilution::BoyItem;
|
||
|
|
shiftValue = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
for (int i = 0; i < storeLoopMax; i++) {
|
||
|
|
if (currentItem->_itype != devilution::ItemType::None) {
|
||
|
|
int itemID = static_cast<int>(data->itemList.size());
|
||
|
|
|
||
|
|
for (auto &item : data->itemList) {
|
||
|
|
if (item.compare(*currentItem)) {
|
||
|
|
itemID = item.ID;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (itemID == static_cast<int>(data->itemList.size())) {
|
||
|
|
data->itemList.push_back(ItemData {});
|
||
|
|
fullFillItemInfo(itemID, currentItem);
|
||
|
|
}
|
||
|
|
if (useiValue)
|
||
|
|
data->itemList[itemID]._ivalue = currentItem->_ivalue;
|
||
|
|
else if (shiftValue)
|
||
|
|
data->itemList[itemID]._ivalue = currentItem->_iIvalue + (currentItem->_iIvalue >> 1);
|
||
|
|
else
|
||
|
|
data->itemList[itemID]._ivalue = currentItem->_iIvalue;
|
||
|
|
if (data->itemList[itemID]._ivalue != 0) {
|
||
|
|
data->storeItems.push_back(itemID);
|
||
|
|
update->add_storeitems(itemID);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
currentItem++;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (devilution::currlevel != 0) {
|
||
|
|
for (auto &townerData : data->townerList) {
|
||
|
|
strcpy_s(townerData._tName, "");
|
||
|
|
townerData._tx = -1;
|
||
|
|
townerData._ty = -1;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
for (auto i = 0; i < NUM_TOWNERS; i++) {
|
||
|
|
auto townerID = data->townerList.size();
|
||
|
|
for (int j = 0; j < data->townerList.size(); j++) {
|
||
|
|
if (data->townerList[j]._ttype == devilution::Towners[i]._ttype) {
|
||
|
|
townerID = j;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (townerID == data->townerList.size())
|
||
|
|
data->townerList.push_back(TownerData {});
|
||
|
|
data->townerList[townerID].ID = static_cast<int>(townerID);
|
||
|
|
if (isOnScreen(devilution::Towners[i].position.x, devilution::Towners[i].position.y)) {
|
||
|
|
data->townerList[townerID]._ttype = devilution::Towners[i]._ttype;
|
||
|
|
data->townerList[townerID]._tx = devilution::Towners[i].position.x;
|
||
|
|
data->townerList[townerID]._ty = devilution::Towners[i].position.y;
|
||
|
|
// might rework this and just change the type in data.
|
||
|
|
if (devilution::Towners[i].name.size() < 31) {
|
||
|
|
memcpy(data->townerList[townerID]._tName, devilution::Towners[i].name.data(), devilution::Towners[i].name.size());
|
||
|
|
data->townerList[townerID]._tName[devilution::Towners[i].name.size()] = '\0';
|
||
|
|
}
|
||
|
|
// strcpy_s(data->townerList[townerID]._tName, devilution::Towners[i].name); old code but with devilution subbed in for reference.
|
||
|
|
} else {
|
||
|
|
data->townerList[townerID]._ttype = static_cast<devilution::_talker_id>(devilution::Towners[i]._ttype);
|
||
|
|
data->townerList[townerID]._tx = -1;
|
||
|
|
data->townerList[townerID]._ty = -1;
|
||
|
|
strcpy_s(data->townerList[townerID]._tName, "");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (auto &townie : data->townerList) {
|
||
|
|
auto townerData = update->add_townerdata();
|
||
|
|
townerData->set_id(townie.ID);
|
||
|
|
if (townie._tx != -1)
|
||
|
|
townerData->set__ttype(static_cast<int>(townie._ttype));
|
||
|
|
else
|
||
|
|
townerData->set__ttype(-1);
|
||
|
|
townerData->set__tx(townie._tx);
|
||
|
|
townerData->set__ty(townie._ty);
|
||
|
|
townerData->set__tname(townie._tName);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (auto &itemID : itemsModified)
|
||
|
|
// for (auto& item : data->itemList)
|
||
|
|
{
|
||
|
|
auto &item = data->itemList[itemID];
|
||
|
|
auto itemData = update->add_itemdata();
|
||
|
|
itemData->set_id(item.ID);
|
||
|
|
itemData->set__itype(item._itype);
|
||
|
|
itemData->set__ix(item._ix);
|
||
|
|
itemData->set__iy(item._iy);
|
||
|
|
itemData->set__iidentified(item._iIdentified);
|
||
|
|
itemData->set__imagical(item._iMagical);
|
||
|
|
itemData->set__iname(item._iName);
|
||
|
|
itemData->set__iiname(item._iIName);
|
||
|
|
itemData->set__iclass(item._iClass);
|
||
|
|
itemData->set__icurs(item._iCurs);
|
||
|
|
itemData->set__ivalue(item._ivalue);
|
||
|
|
itemData->set__imindam(item._iMinDam);
|
||
|
|
itemData->set__imaxdam(item._iMaxDam);
|
||
|
|
itemData->set__iac(item._iAC);
|
||
|
|
itemData->set__iflags(item._iFlags);
|
||
|
|
itemData->set__imiscid(item._iMiscId);
|
||
|
|
itemData->set__ispell(item._iSpell);
|
||
|
|
itemData->set__icharges(item._iCharges);
|
||
|
|
itemData->set__imaxcharges(item._iMaxCharges);
|
||
|
|
itemData->set__idurability(item._iDurability);
|
||
|
|
itemData->set__imaxdur(item._iMaxDur);
|
||
|
|
itemData->set__ipldam(item._iPLDam);
|
||
|
|
itemData->set__ipltohit(item._iPLToHit);
|
||
|
|
itemData->set__iplac(item._iPLAC);
|
||
|
|
itemData->set__iplstr(item._iPLStr);
|
||
|
|
itemData->set__iplmag(item._iPLMag);
|
||
|
|
itemData->set__ipldex(item._iPLDex);
|
||
|
|
itemData->set__iplvit(item._iPLVit);
|
||
|
|
itemData->set__iplfr(item._iPLFR);
|
||
|
|
itemData->set__ipllr(item._iPLLR);
|
||
|
|
itemData->set__iplmr(item._iPLMR);
|
||
|
|
itemData->set__iplmana(item._iPLMana);
|
||
|
|
itemData->set__iplhp(item._iPLHP);
|
||
|
|
itemData->set__ipldammod(item._iPLDamMod);
|
||
|
|
itemData->set__iplgethit(item._iPLGetHit);
|
||
|
|
itemData->set__ipllight(item._iPLLight);
|
||
|
|
itemData->set__ispllvladd(item._iSplLvlAdd);
|
||
|
|
itemData->set__ifmindam(item._iFMinDam);
|
||
|
|
itemData->set__ifmaxdam(item._iFMaxDam);
|
||
|
|
itemData->set__ilmindam(item._iLMinDam);
|
||
|
|
itemData->set__ilmaxdam(item._iLMaxDam);
|
||
|
|
itemData->set__iprepower(item._iPrePower);
|
||
|
|
itemData->set__isufpower(item._iSufPower);
|
||
|
|
itemData->set__iminstr(item._iMinStr);
|
||
|
|
itemData->set__iminmag(item._iMinMag);
|
||
|
|
itemData->set__imindex(item._iMinDex);
|
||
|
|
itemData->set__istatflag(item._iStatFlag);
|
||
|
|
itemData->set_ididx(item.IDidx);
|
||
|
|
}
|
||
|
|
for (auto &itemID : data->groundItems)
|
||
|
|
update->add_grounditemid(itemID);
|
||
|
|
|
||
|
|
for (int i = 0; i < devilution::ActiveMonsterCount; i++) {
|
||
|
|
if (isOnScreen(devilution::Monsters[devilution::ActiveMonsters[i]].position.tile.x, devilution::Monsters[devilution::ActiveMonsters[i]].position.tile.y) && devilution::HasAnyOf(devilution::dFlags[devilution::Monsters[devilution::ActiveMonsters[i]].position.tile.x][devilution::Monsters[devilution::ActiveMonsters[i]].position.tile.y], devilution::DungeonFlag::Lit) && !(devilution::Monsters[devilution::ActiveMonsters[i]].flags & 0x01)) {
|
||
|
|
auto m = update->add_monsterdata();
|
||
|
|
m->set_index(devilution::ActiveMonsters[i]);
|
||
|
|
m->set_x(devilution::Monsters[devilution::ActiveMonsters[i]].position.tile.x);
|
||
|
|
m->set_y(devilution::Monsters[devilution::ActiveMonsters[i]].position.tile.y);
|
||
|
|
m->set_futx(devilution::Monsters[devilution::ActiveMonsters[i]].position.future.x);
|
||
|
|
m->set_futy(devilution::Monsters[devilution::ActiveMonsters[i]].position.future.y);
|
||
|
|
m->set_type(devilution::Monsters[devilution::ActiveMonsters[i]].type().type);
|
||
|
|
m->set_name(devilution::Monsters[devilution::ActiveMonsters[i]].data().name.c_str());
|
||
|
|
m->set_mode(static_cast<int>(devilution::Monsters[devilution::ActiveMonsters[i]].mode));
|
||
|
|
m->set_unique(static_cast<bool>(devilution::Monsters[devilution::ActiveMonsters[i]].isUnique()));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
auto fillObject = [&](int index, devilution::Object &ob) {
|
||
|
|
auto o = update->add_objectdata();
|
||
|
|
o->set_type(ob._otype);
|
||
|
|
o->set_x(ob.position.x);
|
||
|
|
o->set_y(ob.position.y);
|
||
|
|
o->set_shrinetype(-1);
|
||
|
|
o->set_solid(ob._oSolidFlag);
|
||
|
|
o->set_doorstate(-1);
|
||
|
|
o->set_selectable(ob.selectionRegion != devilution::SelectionRegion::None ? true : false);
|
||
|
|
o->set_index(index);
|
||
|
|
switch (static_cast<devilution::_object_id>(ob._otype)) {
|
||
|
|
case devilution::_object_id::OBJ_BARRELEX:
|
||
|
|
o->set_type(static_cast<int>(devilution::_object_id::OBJ_BARREL));
|
||
|
|
break;
|
||
|
|
case devilution::_object_id::OBJ_SHRINEL:
|
||
|
|
case devilution::_object_id::OBJ_SHRINER:
|
||
|
|
if (ob.selectionRegion != devilution::SelectionRegion::None)
|
||
|
|
o->set_shrinetype(ob._oVar1);
|
||
|
|
break;
|
||
|
|
case devilution::_object_id::OBJ_L1LDOOR:
|
||
|
|
case devilution::_object_id::OBJ_L1RDOOR:
|
||
|
|
case devilution::_object_id::OBJ_L2LDOOR:
|
||
|
|
case devilution::_object_id::OBJ_L2RDOOR:
|
||
|
|
case devilution::_object_id::OBJ_L3LDOOR:
|
||
|
|
case devilution::_object_id::OBJ_L3RDOOR:
|
||
|
|
o->set_doorstate(ob._oVar4);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (devilution::Players[devilution::MyPlayerId]._pClass == devilution::HeroClass::Rogue)
|
||
|
|
o->set_trapped(ob._oTrapFlag);
|
||
|
|
else
|
||
|
|
o->set_trapped(false);
|
||
|
|
};
|
||
|
|
|
||
|
|
auto fillMissile = [&](devilution::Missile &ms) {
|
||
|
|
auto m = update->add_missiledata();
|
||
|
|
m->set_type(static_cast<int>(ms._mitype));
|
||
|
|
m->set_x(ms.position.tile.x);
|
||
|
|
m->set_y(ms.position.tile.y);
|
||
|
|
m->set_xvel(ms.position.velocity.deltaX);
|
||
|
|
m->set_yvel(ms.position.velocity.deltaY);
|
||
|
|
bool addSource = false;
|
||
|
|
switch (ms.sourceType()) {
|
||
|
|
case devilution::MissileSource::Monster:
|
||
|
|
if (isOnScreen(ms.sourceMonster()->position.tile.x, ms.sourceMonster()->position.tile.y)) {
|
||
|
|
m->set_sx(ms.sourceMonster()->position.tile.x);
|
||
|
|
m->set_sy(ms.sourceMonster()->position.tile.y);
|
||
|
|
} else {
|
||
|
|
m->set_sx(-1);
|
||
|
|
m->set_sy(-1);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case devilution::MissileSource::Player:
|
||
|
|
if (isOnScreen(ms.sourcePlayer()->position.tile.x, ms.sourcePlayer()->position.tile.y)) {
|
||
|
|
m->set_sx(ms.sourcePlayer()->position.tile.x);
|
||
|
|
m->set_sy(ms.sourcePlayer()->position.tile.y);
|
||
|
|
} else {
|
||
|
|
m->set_sx(-1);
|
||
|
|
m->set_sy(-1);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
m->set_sx(-1);
|
||
|
|
m->set_sy(-1);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
if (devilution::Players[devilution::MyPlayerId].plrlevel != 0) {
|
||
|
|
for (int i = 0; i < devilution::ActiveObjectCount; i++) {
|
||
|
|
if (isOnScreen(devilution::Objects[devilution::ActiveObjects[i]].position.x, devilution::Objects[devilution::ActiveObjects[i]].position.y) && devilution::dObject[devilution::Objects[devilution::ActiveObjects[i]].position.x][devilution::Objects[devilution::ActiveObjects[i]].position.y] == devilution::ActiveObjects[i] + 1) {
|
||
|
|
fillObject(devilution::ActiveObjects[i], devilution::Objects[devilution::ActiveObjects[i]]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (auto& missile : devilution::Missiles) {
|
||
|
|
if (isOnScreen(missile.position.tile.x, missile.position.tile.y))
|
||
|
|
fillMissile(missile);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < MAXPORTAL; i++) {
|
||
|
|
if (devilution::Portals[i].open && (devilution::Portals[i].level == devilution::Players[devilution::MyPlayerId].plrlevel) && isOnScreen(devilution::Portals[i].position.x, devilution::Portals[i].position.y)) {
|
||
|
|
auto tp = update->add_portaldata();
|
||
|
|
tp->set_x(devilution::Portals[i].position.x);
|
||
|
|
tp->set_y(devilution::Portals[i].position.y);
|
||
|
|
tp->set_player(i);
|
||
|
|
} else if (devilution::Portals[i].open && 0 == devilution::Players[devilution::MyPlayerId].plrlevel && isOnScreen(devilution::PortalTownPosition[i].x, devilution::PortalTownPosition[i].y)) {
|
||
|
|
auto tp = update->add_portaldata();
|
||
|
|
tp->set_x(devilution::PortalTownPosition[i].x);
|
||
|
|
tp->set_y(devilution::PortalTownPosition[i].y);
|
||
|
|
tp->set_player(i);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protoClient.queueMessage(std::move(message));
|
||
|
|
}
|
||
|
|
|
||
|
|
bool Server::isOnScreen(int x, int y)
|
||
|
|
{
|
||
|
|
bool returnValue = false;
|
||
|
|
int dx = data->playerList[data->player]._px - x;
|
||
|
|
int dy = data->playerList[data->player]._py - y;
|
||
|
|
if (!devilution::CharFlag) {
|
||
|
|
if (dy > 0) {
|
||
|
|
if (dx < 1 && abs(dx) + abs(dy) < 11)
|
||
|
|
returnValue = true;
|
||
|
|
else if (dx > 0 && abs(dx) + abs(dy) < 12)
|
||
|
|
returnValue = true;
|
||
|
|
} else {
|
||
|
|
if ((dx > -1 || dy == 0) && abs(dx) + abs(dy) < 11)
|
||
|
|
returnValue = true;
|
||
|
|
else if ((dx < 0 && dy != 0) && abs(dx) + abs(dy) < 12)
|
||
|
|
returnValue = true;
|
||
|
|
}
|
||
|
|
} else if (devilution::CharFlag) {
|
||
|
|
returnValue = panelScreenCheck[std::make_pair(dx, dy)];
|
||
|
|
}
|
||
|
|
return returnValue;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool Server::OKToAct()
|
||
|
|
{
|
||
|
|
return !data->stextflag && data->pcurs == 1 && !data->qtextflag;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::move(int x, int y)
|
||
|
|
{
|
||
|
|
devilution::NetSendCmdLoc(devilution::MyPlayerId, true, devilution::_cmd_id::CMD_WALKXY, devilution::Point { x, y });
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::talk(int x, int y)
|
||
|
|
{
|
||
|
|
int index;
|
||
|
|
for (index = 0; index < NUM_TOWNERS; index++) {
|
||
|
|
if (devilution::Towners[index].position.x == x && devilution::Towners[index].position.y == y)
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (index != NUM_TOWNERS)
|
||
|
|
devilution::NetSendCmdLocParam1(true, devilution::_cmd_id::CMD_TALKXY, devilution::Point { x, y }, index);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::selectStoreOption(StoreOption option)
|
||
|
|
{
|
||
|
|
switch (option) {
|
||
|
|
case StoreOption::TALK:
|
||
|
|
switch (devilution::ActiveStore) {
|
||
|
|
case devilution::TalkID::Witch:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::OldTextLine = 12;
|
||
|
|
devilution::TownerId = devilution::_talker_id::TOWN_WITCH;
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::Witch;
|
||
|
|
devilution::StartStore(devilution::TalkID::Gossip);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case StoreOption::IDENTIFYANITEM:
|
||
|
|
if (devilution::ActiveStore == devilution::TalkID::Storyteller) {
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::StorytellerIdentify);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case StoreOption::EXIT:
|
||
|
|
switch (devilution::ActiveStore) {
|
||
|
|
case devilution::TalkID::Barmaid:
|
||
|
|
case devilution::TalkID::Boy:
|
||
|
|
case devilution::TalkID::BoyBuy:
|
||
|
|
case devilution::TalkID::Drunk:
|
||
|
|
case devilution::TalkID::Healer:
|
||
|
|
case devilution::TalkID::Smith:
|
||
|
|
case devilution::TalkID::Storyteller:
|
||
|
|
case devilution::TalkID::Tavern:
|
||
|
|
case devilution::TalkID::Witch:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::ActiveStore = devilution::TalkID::None;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case StoreOption::BUYITEMS:
|
||
|
|
switch (devilution::ActiveStore) {
|
||
|
|
case devilution::TalkID::Witch:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::WitchBuy);
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::Healer:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::HealerBuy);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case StoreOption::BUYBASIC:
|
||
|
|
if (devilution::ActiveStore == devilution::TalkID::Smith) {
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::SmithBuy);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case StoreOption::BUYPREMIUM:
|
||
|
|
if (devilution::ActiveStore == devilution::TalkID::Smith) {
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::SmithPremiumBuy);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case StoreOption::SELL:
|
||
|
|
switch (devilution::ActiveStore) {
|
||
|
|
case devilution::TalkID::Smith:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::SmithSell);
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::Witch:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::WitchSell);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case StoreOption::REPAIR:
|
||
|
|
if (devilution::ActiveStore == devilution::TalkID::Smith) {
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::SmithRepair);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case StoreOption::RECHARGE:
|
||
|
|
if (devilution::ActiveStore == devilution::TalkID::Witch) {
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::WitchRecharge);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case StoreOption::WIRTPEEK:
|
||
|
|
if (devilution::ActiveStore == devilution::TalkID::Boy) {
|
||
|
|
if (50 <= devilution::Players[devilution::MyPlayerId]._pGold) {
|
||
|
|
devilution::TakePlrsMoney(50);
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::BoyBuy);
|
||
|
|
} else {
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::Boy;
|
||
|
|
devilution::OldTextLine = 18;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
devilution::StartStore(devilution::TalkID::NoMoney);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case StoreOption::BACK:
|
||
|
|
switch (devilution::ActiveStore) {
|
||
|
|
case devilution::TalkID::SmithRepair:
|
||
|
|
case devilution::TalkID::SmithSell:
|
||
|
|
case devilution::TalkID::SmithBuy:
|
||
|
|
case devilution::TalkID::SmithPremiumBuy:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::Smith);
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::WitchBuy:
|
||
|
|
case devilution::TalkID::WitchSell:
|
||
|
|
case devilution::TalkID::WitchRecharge:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::Witch);
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::HealerBuy:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::Healer);
|
||
|
|
break;
|
||
|
|
case devilution::TalkID::StorytellerIdentify:
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
devilution::StartStore(devilution::TalkID::Storyteller);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::buyItem(int itemID)
|
||
|
|
{
|
||
|
|
int idx;
|
||
|
|
|
||
|
|
if (devilution::ActiveStore == devilution::TalkID::WitchBuy) {
|
||
|
|
|
||
|
|
idx = -1;
|
||
|
|
|
||
|
|
for (int i = 0; i < 20; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::WitchItems[i])) {
|
||
|
|
idx = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (idx == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
|
||
|
|
devilution::OldTextLine = devilution::CurrentTextLine;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
devilution::OldActiveStore = devilution::ActiveStore;
|
||
|
|
|
||
|
|
|
||
|
|
if (!devilution::PlayerCanAfford(devilution::WitchItems[idx]._iIvalue)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoMoney);
|
||
|
|
return;
|
||
|
|
} else if (devilution::StoreAutoPlace(devilution::WitchItems[idx], true)) {
|
||
|
|
if (idx < 3)
|
||
|
|
devilution::WitchItems[idx]._iSeed = devilution::AdvanceRndSeed();
|
||
|
|
|
||
|
|
devilution::TakePlrsMoney(devilution::Players[devilution::MyPlayerId].HoldItem._iIvalue);
|
||
|
|
|
||
|
|
|
||
|
|
if (idx >= 3) {
|
||
|
|
if (idx == devilution::NumWitchItemsHf - 1)
|
||
|
|
devilution::WitchItems[devilution::NumWitchItemsHf - 1].clear();
|
||
|
|
else {
|
||
|
|
for (; !devilution::WitchItems[idx + 1].isEmpty(); idx++) {
|
||
|
|
devilution::WitchItems[idx] = std::move(devilution::WitchItems[idx + 1]);
|
||
|
|
}
|
||
|
|
devilution::WitchItems[idx].clear();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
devilution::CalcPlrInv(*devilution::MyPlayer, true);
|
||
|
|
} else {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoRoom);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
devilution::StartStore(devilution::OldActiveStore);
|
||
|
|
} else if (devilution::ActiveStore == devilution::TalkID::SmithBuy) {
|
||
|
|
idx = -1;
|
||
|
|
|
||
|
|
for (int i = 0; i < 20; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::SmithItems[i])) {
|
||
|
|
idx = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (idx == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
|
||
|
|
devilution::OldTextLine = devilution::CurrentTextLine;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::SmithBuy;
|
||
|
|
|
||
|
|
if (!devilution::PlayerCanAfford(devilution::SmithItems[idx]._iIvalue)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoMoney);
|
||
|
|
return;
|
||
|
|
} else if (!devilution::StoreAutoPlace(devilution::SmithItems[idx], false)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoRoom);
|
||
|
|
} else {
|
||
|
|
devilution::TakePlrsMoney(devilution::SmithItems[idx]._iIvalue);
|
||
|
|
if (devilution::SmithItems[idx]._iMagical == devilution::item_quality::ITEM_QUALITY_NORMAL)
|
||
|
|
devilution::SmithItems[idx]._iIdentified = false;
|
||
|
|
devilution::StoreAutoPlace(devilution::SmithItems[idx], true);
|
||
|
|
if (idx == devilution::NumSmithBasicItemsHf - 1) {
|
||
|
|
devilution::SmithItems[devilution::NumSmithBasicItemsHf - 1].clear();
|
||
|
|
} else {
|
||
|
|
for (; !devilution::SmithItems[idx + 1].isEmpty(); idx++) {
|
||
|
|
devilution::SmithItems[idx] = std::move(devilution::SmithItems[idx + 1]);
|
||
|
|
}
|
||
|
|
devilution::SmithItems[idx].clear();
|
||
|
|
}
|
||
|
|
devilution::CalcPlrInv(*devilution::MyPlayer, true);
|
||
|
|
devilution::StartStore(devilution::OldActiveStore);
|
||
|
|
}
|
||
|
|
} else if (devilution::ActiveStore == devilution::TalkID::SmithPremiumBuy) {
|
||
|
|
int idx = -1;
|
||
|
|
for (int i = 0; i < 20; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::PremiumItems[i])) {
|
||
|
|
idx = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (idx == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
|
||
|
|
devilution::OldTextLine = devilution::CurrentTextLine;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::SmithBuy;
|
||
|
|
|
||
|
|
if (!devilution::PlayerCanAfford(devilution::PremiumItems[idx]._iIvalue)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoMoney);
|
||
|
|
return;
|
||
|
|
} else if (!devilution::StoreAutoPlace(devilution::PremiumItems[idx], false)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoRoom);
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
devilution::TakePlrsMoney(devilution::PremiumItems[idx]._iIvalue);
|
||
|
|
if (devilution::PremiumItems[idx]._iMagical == devilution::item_quality::ITEM_QUALITY_NORMAL)
|
||
|
|
devilution::PremiumItems[idx]._iIdentified = false;
|
||
|
|
devilution::StoreAutoPlace(devilution::PremiumItems[idx], true);
|
||
|
|
if (idx == devilution::NumSmithBasicItemsHf - 1) {
|
||
|
|
devilution::PremiumItems[devilution::NumSmithBasicItemsHf - 1].clear();
|
||
|
|
} else {
|
||
|
|
for (; !devilution::PremiumItems[idx + 1].isEmpty(); idx++) {
|
||
|
|
devilution::PremiumItems[idx] = std::move(devilution::PremiumItems[idx + 1]);
|
||
|
|
}
|
||
|
|
devilution::PremiumItems[idx].clear();
|
||
|
|
}
|
||
|
|
devilution::CalcPlrInv(*devilution::MyPlayer, true);
|
||
|
|
devilution::StartStore(devilution::OldActiveStore);
|
||
|
|
}
|
||
|
|
} else if (devilution::ActiveStore == devilution::TalkID::HealerBuy) {
|
||
|
|
idx = -1;
|
||
|
|
|
||
|
|
for (int i = 0; i < 20; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::HealerItems[i])) {
|
||
|
|
idx = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (idx == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
|
||
|
|
devilution::OldTextLine = devilution::CurrentTextLine;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::HealerBuy;
|
||
|
|
|
||
|
|
if (!devilution::PlayerCanAfford(devilution::HealerItems[idx]._iIvalue)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoMoney);
|
||
|
|
return;
|
||
|
|
} else if (!devilution::StoreAutoPlace(devilution::HealerItems[idx], false)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoRoom);
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
if (!devilution::gbIsMultiplayer) {
|
||
|
|
if (idx < 2)
|
||
|
|
devilution::HealerItems[idx]._iSeed = devilution::AdvanceRndSeed();
|
||
|
|
} else {
|
||
|
|
if (idx < 3)
|
||
|
|
devilution::HealerItems[idx]._iSeed = devilution::AdvanceRndSeed();
|
||
|
|
}
|
||
|
|
|
||
|
|
devilution::TakePlrsMoney(devilution::HealerItems[idx]._iIvalue);
|
||
|
|
if (devilution::HealerItems[idx]._iMagical == devilution::item_quality::ITEM_QUALITY_NORMAL)
|
||
|
|
devilution::HealerItems[idx]._iIdentified = false;
|
||
|
|
devilution::StoreAutoPlace(devilution::HealerItems[idx], true);
|
||
|
|
|
||
|
|
if (!devilution::gbIsMultiplayer) {
|
||
|
|
if (idx < 2)
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
if (idx < 3)
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (idx == 19) {
|
||
|
|
devilution::HealerItems[19].clear();
|
||
|
|
} else {
|
||
|
|
for (; !devilution::HealerItems[idx + 1].isEmpty(); idx++) {
|
||
|
|
devilution::HealerItems[idx] = std::move(devilution::HealerItems[idx + 1]);
|
||
|
|
}
|
||
|
|
devilution::HealerItems[idx].clear();
|
||
|
|
}
|
||
|
|
CalcPlrInv(*devilution::MyPlayer, true);
|
||
|
|
devilution::StartStore(devilution::OldActiveStore);
|
||
|
|
} else if (devilution::ActiveStore == devilution::TalkID::BoyBuy) {
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::BoyBuy;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
devilution::OldTextLine = 10;
|
||
|
|
|
||
|
|
int price = devilution::BoyItem._iIvalue;
|
||
|
|
if (devilution::gbIsHellfire)
|
||
|
|
price -= devilution::BoyItem._iIvalue / 4;
|
||
|
|
else
|
||
|
|
price += devilution::BoyItem._iIvalue / 2;
|
||
|
|
|
||
|
|
if (!devilution::PlayerCanAfford(price)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoMoney);
|
||
|
|
return;
|
||
|
|
} else if (!devilution::StoreAutoPlace(devilution::BoyItem, false)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoRoom);
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
devilution::TakePlrsMoney(price);
|
||
|
|
devilution::StoreAutoPlace(devilution::BoyItem, true);
|
||
|
|
devilution::BoyItem.clear();
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::Boy;
|
||
|
|
devilution::OldTextLine = 12;
|
||
|
|
}
|
||
|
|
devilution::StartStore(devilution::OldActiveStore);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::sellItem(int itemID)
|
||
|
|
{
|
||
|
|
int idx;
|
||
|
|
|
||
|
|
if (devilution::ActiveStore != devilution::TalkID::WitchSell &&devilution::ActiveStore != devilution::TalkID::SmithSell)
|
||
|
|
return;
|
||
|
|
|
||
|
|
idx = -1;
|
||
|
|
|
||
|
|
for (int i = 0; i < 48; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::PlayerItems[i])) {
|
||
|
|
idx = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (idx == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
|
||
|
|
devilution::OldTextLine = devilution::CurrentTextLine;
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::SmithSell;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
|
||
|
|
if (!devilution::StoreGoldFit(devilution::PlayerItems[idx])) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoRoom);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
devilution::Player &myPlayer = *devilution::MyPlayer;
|
||
|
|
|
||
|
|
if (devilution::PlayerItemIndexes[idx] >= 0)
|
||
|
|
myPlayer.RemoveInvItem(devilution::PlayerItemIndexes[idx]);
|
||
|
|
else
|
||
|
|
myPlayer.RemoveSpdBarItem(-(devilution::PlayerItemIndexes[idx] + 1));
|
||
|
|
|
||
|
|
int cost = devilution::PlayerItems[idx]._iIvalue;
|
||
|
|
devilution::CurrentItemIndex--;
|
||
|
|
if (idx != devilution::CurrentItemIndex) {
|
||
|
|
while (idx < devilution::CurrentItemIndex) {
|
||
|
|
devilution::PlayerItems[idx] = devilution::PlayerItems[idx + 1];
|
||
|
|
devilution::PlayerItemIndexes[idx] = devilution::PlayerItemIndexes[idx + 1];
|
||
|
|
idx++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
devilution::AddGoldToInventory(myPlayer, cost);
|
||
|
|
|
||
|
|
myPlayer._pGold += cost;
|
||
|
|
devilution::StartStore(devilution::OldActiveStore);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::rechargeItem(int itemID)
|
||
|
|
{
|
||
|
|
int idx;
|
||
|
|
|
||
|
|
if (devilution::ActiveStore != devilution::TalkID::WitchRecharge)
|
||
|
|
return;
|
||
|
|
|
||
|
|
idx = -1;
|
||
|
|
|
||
|
|
for (int i = 0; i < 20; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::PlayerItems[i])) {
|
||
|
|
idx = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (idx == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::WitchRecharge;
|
||
|
|
devilution::OldTextLine = devilution::CurrentTextLine;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
|
||
|
|
int price = devilution::PlayerItems[idx]._iIvalue;
|
||
|
|
|
||
|
|
if (!devilution::PlayerCanAfford(price)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoMoney);
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
devilution::PlayerItems[idx]._iCharges = devilution::PlayerItems[idx]._iMaxCharges;
|
||
|
|
|
||
|
|
devilution::Player &myPlayer = *devilution::MyPlayer;
|
||
|
|
|
||
|
|
int8_t i = devilution::PlayerItemIndexes[idx];
|
||
|
|
if (i < 0) {
|
||
|
|
myPlayer.InvBody[devilution::inv_body_loc::INVLOC_HAND_LEFT]._iCharges = myPlayer.InvBody[devilution::inv_body_loc::INVLOC_HAND_LEFT]._iMaxCharges;
|
||
|
|
devilution::NetSendCmdChItem(true, devilution::inv_body_loc::INVLOC_HAND_LEFT);
|
||
|
|
} else {
|
||
|
|
myPlayer.InvList[i]._iCharges = myPlayer.InvList[i]._iMaxCharges;
|
||
|
|
devilution::NetSyncInvItem(myPlayer, i);
|
||
|
|
}
|
||
|
|
|
||
|
|
devilution::TakePlrsMoney(price);
|
||
|
|
devilution::CalcPlrInv(myPlayer, true);
|
||
|
|
devilution::StartStore(devilution::OldActiveStore);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::repairItem(int itemID)
|
||
|
|
{
|
||
|
|
int idx;
|
||
|
|
|
||
|
|
if (devilution::ActiveStore != devilution::TalkID::SmithRepair)
|
||
|
|
return;
|
||
|
|
|
||
|
|
idx = -1;
|
||
|
|
|
||
|
|
for (int i = 0; i < 20; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::PlayerItems[i])) {
|
||
|
|
idx = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (idx == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::SmithRepair;
|
||
|
|
devilution::OldTextLine = devilution::CurrentTextLine;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
|
||
|
|
int price = devilution::PlayerItems[idx]._iIvalue;
|
||
|
|
|
||
|
|
if (!devilution::PlayerCanAfford(price)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoMoney);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
devilution::PlayerItems[idx]._iDurability = devilution::PlayerItems[idx]._iMaxDur;
|
||
|
|
|
||
|
|
int8_t i = devilution::PlayerItemIndexes[idx];
|
||
|
|
|
||
|
|
devilution::Player &myPlayer = *devilution::MyPlayer;
|
||
|
|
|
||
|
|
if (i < 0) {
|
||
|
|
if (i == -1)
|
||
|
|
myPlayer.InvBody[devilution::inv_body_loc::INVLOC_HEAD]._iDurability = myPlayer.InvBody[devilution::inv_body_loc::INVLOC_HEAD]._iMaxDur;
|
||
|
|
if (i == -2)
|
||
|
|
myPlayer.InvBody[devilution::inv_body_loc::INVLOC_CHEST]._iDurability = myPlayer.InvBody[devilution::inv_body_loc::INVLOC_CHEST]._iMaxDur;
|
||
|
|
if (i == -3)
|
||
|
|
myPlayer.InvBody[devilution::inv_body_loc::INVLOC_HAND_LEFT]._iDurability = myPlayer.InvBody[devilution::inv_body_loc::INVLOC_HAND_LEFT]._iMaxDur;
|
||
|
|
if (i == -4)
|
||
|
|
myPlayer.InvBody[devilution::inv_body_loc::INVLOC_HAND_RIGHT]._iDurability = myPlayer.InvBody[devilution::inv_body_loc::INVLOC_HAND_RIGHT]._iMaxDur;
|
||
|
|
devilution::TakePlrsMoney(price);
|
||
|
|
devilution::StartStore(devilution::OldActiveStore);
|
||
|
|
}
|
||
|
|
|
||
|
|
myPlayer.InvList[i]._iDurability = myPlayer.InvList[i]._iMaxDur;
|
||
|
|
devilution::TakePlrsMoney(price);
|
||
|
|
devilution::StartStore(devilution::OldActiveStore);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::attackMonster(int index)
|
||
|
|
{
|
||
|
|
if (index < 0 || 199 < index)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (!isOnScreen(devilution::Monsters[index].position.tile.x, devilution::Monsters[index].position.tile.y))
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (devilution::M_Talker(devilution::Monsters[index]))
|
||
|
|
devilution::NetSendCmdParam1(true, devilution::_cmd_id::CMD_ATTACKID, index);
|
||
|
|
else if (devilution::Players[devilution::MyPlayerId].InvBody[devilution::inv_body_loc::INVLOC_HAND_LEFT]._itype == devilution::ItemType::Bow || devilution::Players[devilution::MyPlayerId].InvBody[devilution::inv_body_loc::INVLOC_HAND_RIGHT]._itype == devilution::ItemType::Bow)
|
||
|
|
devilution::NetSendCmdParam1(true, devilution::_cmd_id::CMD_RATTACKID, index);
|
||
|
|
else
|
||
|
|
devilution::NetSendCmdParam1(true, devilution::_cmd_id::CMD_ATTACKID, index);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::attackXY(int x, int y)
|
||
|
|
{
|
||
|
|
if (!isOnScreen(x, y))
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (devilution::Players[devilution::MyPlayerId].InvBody[devilution::inv_body_loc::INVLOC_HAND_LEFT]._itype == devilution::ItemType::Bow || devilution::Players[devilution::MyPlayerId].InvBody[devilution::inv_body_loc::INVLOC_HAND_RIGHT]._itype == devilution::ItemType::Bow)
|
||
|
|
devilution::NetSendCmdLoc(devilution::MyPlayerId, true, devilution::_cmd_id::CMD_RATTACKXY, devilution::Point { x, y });
|
||
|
|
else
|
||
|
|
devilution::NetSendCmdLoc(devilution::MyPlayerId, true, devilution::_cmd_id::CMD_SATTACKXY, devilution::Point { x, y });
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::operateObject(int index)
|
||
|
|
{
|
||
|
|
if (index < 0 || 126 < index)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (!isOnScreen(devilution::Objects[index].position.x, devilution::Objects[index].position.y))
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
bool found = false;
|
||
|
|
for (int i = 0; i < devilution::ActiveObjectCount; i++) {
|
||
|
|
if (devilution::ActiveObjects[i] == index) {
|
||
|
|
found = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!found)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::NetSendCmdLocParam1(true, devilution::_cmd_id::CMD_OPOBJXY, devilution::Point { devilution::Objects[index].position.x, devilution::Objects[index].position.y }, index);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::useBeltItem(int slot)
|
||
|
|
{
|
||
|
|
if (slot < 0 || 7 < slot)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (devilution::Players[devilution::MyPlayerId].SpdList[slot]._itype == devilution::ItemType::None)
|
||
|
|
return;
|
||
|
|
|
||
|
|
int cii = slot + 47;
|
||
|
|
devilution::UseInvItem(cii);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::toggleCharacterScreen()
|
||
|
|
{
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::CharFlag = !devilution::CharFlag;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::increaseStat(CommandType commandType)
|
||
|
|
{
|
||
|
|
int maxValue = 0;
|
||
|
|
|
||
|
|
if (devilution::Players[devilution::MyPlayerId]._pStatPts == 0)
|
||
|
|
return;
|
||
|
|
|
||
|
|
switch (commandType) {
|
||
|
|
case CommandType::ADDSTR:
|
||
|
|
switch (static_cast<devilution::HeroClass>(devilution::Players[devilution::MyPlayerId]._pClass)) {
|
||
|
|
case devilution::HeroClass::Warrior:
|
||
|
|
maxValue = 250;
|
||
|
|
break;
|
||
|
|
case devilution::HeroClass::Rogue:
|
||
|
|
maxValue = 55;
|
||
|
|
break;
|
||
|
|
case devilution::HeroClass::Sorcerer:
|
||
|
|
maxValue = 45;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (devilution::Players[devilution::MyPlayerId]._pBaseStr < maxValue) {
|
||
|
|
devilution::NetSendCmdParam1(true, devilution::_cmd_id::CMD_ADDSTR, 1);
|
||
|
|
devilution::Players[devilution::MyPlayerId]._pStatPts -= 1;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case CommandType::ADDMAG:
|
||
|
|
switch (static_cast<devilution::HeroClass>(devilution::Players[devilution::MyPlayerId]._pClass)) {
|
||
|
|
case devilution::HeroClass::Warrior:
|
||
|
|
maxValue = 50;
|
||
|
|
break;
|
||
|
|
case devilution::HeroClass::Rogue:
|
||
|
|
maxValue = 70;
|
||
|
|
break;
|
||
|
|
case devilution::HeroClass::Sorcerer:
|
||
|
|
maxValue = 250;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (devilution::Players[devilution::MyPlayerId]._pBaseMag < maxValue) {
|
||
|
|
devilution::NetSendCmdParam1(true, devilution::_cmd_id::CMD_ADDMAG, 1);
|
||
|
|
devilution::Players[devilution::MyPlayerId]._pStatPts -= 1;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case CommandType::ADDDEX:
|
||
|
|
switch (static_cast<devilution::HeroClass>(devilution::Players[devilution::MyPlayerId]._pClass)) {
|
||
|
|
case devilution::HeroClass::Warrior:
|
||
|
|
maxValue = 60;
|
||
|
|
break;
|
||
|
|
case devilution::HeroClass::Rogue:
|
||
|
|
maxValue = 250;
|
||
|
|
break;
|
||
|
|
case devilution::HeroClass::Sorcerer:
|
||
|
|
maxValue = 85;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (devilution::Players[devilution::MyPlayerId]._pBaseDex < maxValue) {
|
||
|
|
devilution::NetSendCmdParam1(true, devilution::_cmd_id::CMD_ADDDEX, 1);
|
||
|
|
devilution::Players[devilution::MyPlayerId]._pStatPts -= 1;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case CommandType::ADDVIT:
|
||
|
|
switch (static_cast<devilution::HeroClass>(devilution::Players[devilution::MyPlayerId]._pClass)) {
|
||
|
|
case devilution::HeroClass::Warrior:
|
||
|
|
maxValue = 100;
|
||
|
|
break;
|
||
|
|
case devilution::HeroClass::Rogue:
|
||
|
|
maxValue = 80;
|
||
|
|
break;
|
||
|
|
case devilution::HeroClass::Sorcerer:
|
||
|
|
maxValue = 80;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (devilution::Players[devilution::MyPlayerId]._pBaseVit < maxValue) {
|
||
|
|
devilution::NetSendCmdParam1(true, devilution::_cmd_id::CMD_ADDVIT, 1);
|
||
|
|
devilution::Players[devilution::MyPlayerId]._pStatPts -= 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::getItem(int itemID)
|
||
|
|
{
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
bool found = false;
|
||
|
|
|
||
|
|
for (auto i = 0; i < data->groundItems.size(); i++) {
|
||
|
|
if (data->groundItems[i] == itemID)
|
||
|
|
found = true;
|
||
|
|
if (found)
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!found)
|
||
|
|
return;
|
||
|
|
|
||
|
|
auto itemData = data->itemList[itemID];
|
||
|
|
|
||
|
|
if (!isOnScreen(itemData._ix, itemData._iy))
|
||
|
|
return;
|
||
|
|
|
||
|
|
int index = -1;
|
||
|
|
for (int i = 0; i < devilution::ActiveItemCount; i++) {
|
||
|
|
if (itemData.compare(devilution::Items[devilution::ActiveItems[i]]))
|
||
|
|
index = devilution::ActiveItems[i];
|
||
|
|
|
||
|
|
if (index != -1)
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (index == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (devilution::invflag)
|
||
|
|
devilution::NetSendCmdLocParam1(true, devilution::_cmd_id::CMD_GOTOGETITEM, devilution::Point { itemData._ix, itemData._iy }, index);
|
||
|
|
else
|
||
|
|
devilution::NetSendCmdLocParam1(true, devilution::_cmd_id::CMD_GOTOAGETITEM, devilution::Point { itemData._ix, itemData._iy }, index);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::setSpell(int spellID, devilution::SpellType spellType)
|
||
|
|
{
|
||
|
|
if (spellID == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
switch (spellType) {
|
||
|
|
case devilution::SpellType::Skill:
|
||
|
|
if (!(devilution::Players[devilution::MyPlayerId]._pAblSpells & (1 << (spellID - 1))))
|
||
|
|
return;
|
||
|
|
break;
|
||
|
|
case devilution::SpellType::Spell:
|
||
|
|
if (!(devilution::Players[devilution::MyPlayerId]._pMemSpells & (1 << (spellID - 1))))
|
||
|
|
return;
|
||
|
|
break;
|
||
|
|
case devilution::SpellType::Scroll:
|
||
|
|
if (!(devilution::Players[devilution::MyPlayerId]._pScrlSpells & (1 << (spellID - 1))))
|
||
|
|
return;
|
||
|
|
break;
|
||
|
|
case devilution::SpellType::Charges:
|
||
|
|
if ((devilution::Players[devilution::MyPlayerId].InvBody[4]._iSpell != static_cast<devilution::SpellID>(spellID) && devilution::Players[devilution::MyPlayerId].InvBody[5]._iSpell != static_cast<devilution::SpellID>(spellID)) || (devilution::Players[devilution::MyPlayerId].InvBody[4]._iCharges == 0 && devilution::Players[devilution::MyPlayerId].InvBody[5]._iCharges == 0))
|
||
|
|
return;
|
||
|
|
break;
|
||
|
|
case devilution::SpellType::Invalid:
|
||
|
|
default:
|
||
|
|
return;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
devilution::Players[devilution::MyPlayerId]._pRSpell = static_cast<devilution::SpellID>(spellID);
|
||
|
|
devilution::Players[devilution::MyPlayerId]._pRSplType = static_cast<devilution::SpellType>(spellType);
|
||
|
|
//*force_redraw = 255; // TODO: Is this line needed in devilutionX? If so, what is it?
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::castSpell(int index)
|
||
|
|
{
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::pcursmonst = index;
|
||
|
|
devilution::PlayerUnderCursor = nullptr;
|
||
|
|
devilution::cursPosition = devilution::Point { devilution::Monsters[index].position.tile.x, devilution::Monsters[index].position.tile.y };
|
||
|
|
|
||
|
|
devilution::CheckPlrSpell(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::toggleInventory()
|
||
|
|
{
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::invflag = !devilution::invflag;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::putInCursor(int itemID)
|
||
|
|
{
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (data->itemList.size() <= itemID)
|
||
|
|
return;
|
||
|
|
|
||
|
|
auto item = data->itemList[itemID];
|
||
|
|
int mx, my;
|
||
|
|
|
||
|
|
mx = 0;
|
||
|
|
my = 0;
|
||
|
|
for (int i = 0; i < 55; i++) {
|
||
|
|
if (i < 7) {
|
||
|
|
if (item.compare(devilution::Players[devilution::MyPlayerId].InvBody[i]) && devilution::Players[devilution::MyPlayerId].InvBody[i]._itype != devilution::ItemType::None) {
|
||
|
|
if (!devilution::invflag)
|
||
|
|
return;
|
||
|
|
|
||
|
|
switch (static_cast<EquipSlot>(i)) {
|
||
|
|
case EquipSlot::HEAD:
|
||
|
|
mx = devilution::InvRect[0].position.x + 1;
|
||
|
|
my = devilution::InvRect[0].position.y - 1;
|
||
|
|
break;
|
||
|
|
case EquipSlot::LEFTRING:
|
||
|
|
mx = devilution::InvRect[4].position.x + 1;
|
||
|
|
my = devilution::InvRect[4].position.y - 1;
|
||
|
|
break;
|
||
|
|
case EquipSlot::RIGHTRING:
|
||
|
|
mx = devilution::InvRect[5].position.x + 1;
|
||
|
|
my = devilution::InvRect[5].position.y - 1;
|
||
|
|
break;
|
||
|
|
case EquipSlot::AMULET:
|
||
|
|
mx = devilution::InvRect[6].position.x + 1;
|
||
|
|
my = devilution::InvRect[6].position.y - 1;
|
||
|
|
break;
|
||
|
|
case EquipSlot::LEFTHAND:
|
||
|
|
mx = devilution::InvRect[7].position.x + 1;
|
||
|
|
my = devilution::InvRect[7].position.y - 1;
|
||
|
|
break;
|
||
|
|
case EquipSlot::RIGHTHAND:
|
||
|
|
mx = devilution::InvRect[13].position.x + 1;
|
||
|
|
my = devilution::InvRect[13].position.y - 1;
|
||
|
|
break;
|
||
|
|
case EquipSlot::BODY:
|
||
|
|
mx = devilution::InvRect[19].position.x + 1;
|
||
|
|
my = devilution::InvRect[19].position.y - 1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
} else if (i < 47) {
|
||
|
|
if (item.compare(devilution::Players[devilution::MyPlayerId].InvList[i - 7]) && devilution::Players[devilution::MyPlayerId].InvList[i - 7]._itype != devilution::ItemType::None && i - 7 < devilution::Players[devilution::MyPlayerId]._pNumInv) {
|
||
|
|
if (!devilution::invflag)
|
||
|
|
return;
|
||
|
|
|
||
|
|
for (int rect_index = 0; rect_index < 40; rect_index++) {
|
||
|
|
if (devilution::Players[devilution::MyPlayerId].InvGrid[rect_index] == i - 6) {
|
||
|
|
int index = rect_index + 25;
|
||
|
|
mx = devilution::InvRect[index].position.x + 1;
|
||
|
|
my = devilution::InvRect[index].position.y - 1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
if (item.compare(devilution::Players[devilution::MyPlayerId].SpdList[i - 47]) && devilution::Players[devilution::MyPlayerId].SpdList[i - 47]._itype != devilution::ItemType::None) {
|
||
|
|
int index = 18 + i;
|
||
|
|
mx = 210 + (i - 47) * 30;
|
||
|
|
my = 370;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (mx != 0 && my != 0)
|
||
|
|
devilution::CheckInvCut(*devilution::MyPlayer, devilution::Point { mx, my }, false, false);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::putCursorItem(int location)
|
||
|
|
{
|
||
|
|
int mx, my;
|
||
|
|
EquipSlot equipLocation = static_cast<EquipSlot>(location);
|
||
|
|
|
||
|
|
if (!data->invflag)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (12 <= data->pcurs && equipLocation <= EquipSlot::BELT8) {
|
||
|
|
mx = 0;
|
||
|
|
my = 0;
|
||
|
|
switch (equipLocation) {
|
||
|
|
case EquipSlot::HEAD:
|
||
|
|
mx = devilution::InvRect[0].position.x + 1;
|
||
|
|
my = devilution::InvRect[0].position.y - 1;
|
||
|
|
break;
|
||
|
|
case EquipSlot::LEFTRING:
|
||
|
|
mx = devilution::InvRect[4].position.x + 2;
|
||
|
|
my = devilution::InvRect[4].position.y - 20;
|
||
|
|
break;
|
||
|
|
case EquipSlot::RIGHTRING:
|
||
|
|
mx = devilution::InvRect[5].position.x + 2;
|
||
|
|
my = devilution::InvRect[5].position.y - 20;
|
||
|
|
break;
|
||
|
|
case EquipSlot::AMULET:
|
||
|
|
mx = devilution::InvRect[6].position.x + 2;
|
||
|
|
my = devilution::InvRect[6].position.y - 20;
|
||
|
|
break;
|
||
|
|
case EquipSlot::LEFTHAND:
|
||
|
|
mx = devilution::InvRect[7].position.x + 1;
|
||
|
|
my = devilution::InvRect[7].position.y - 1;
|
||
|
|
break;
|
||
|
|
case EquipSlot::RIGHTHAND:
|
||
|
|
mx = devilution::InvRect[13].position.x + 1;
|
||
|
|
my = devilution::InvRect[13].position.y - 1;
|
||
|
|
break;
|
||
|
|
case EquipSlot::BODY:
|
||
|
|
mx = devilution::InvRect[19].position.x + 1;
|
||
|
|
my = devilution::InvRect[19].position.y - 1;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
if (equipLocation < EquipSlot::BELT1) {
|
||
|
|
int index = 18 + location;
|
||
|
|
mx = devilution::InvRect[index].position.x + 2;
|
||
|
|
my = devilution::InvRect[index].position.y - 20;
|
||
|
|
} else {
|
||
|
|
int index = 18 + location;
|
||
|
|
mx = 210 + (location - 47) * 30;
|
||
|
|
my = 370;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
devilution::CheckInvPaste(*devilution::MyPlayer, devilution::Point { mx, my });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::dropCursorItem()
|
||
|
|
{
|
||
|
|
if (!isOnScreen(devilution::Players[devilution::MyPlayerId].position.tile.x, devilution::Players[devilution::MyPlayerId].position.tile.y))
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (12 <= data->pcurs) {
|
||
|
|
devilution::NetSendCmdPItem(true, devilution::_cmd_id::CMD_PUTITEM, devilution::Point { devilution::Players[devilution::MyPlayerId].position.tile.x, devilution::Players[devilution::MyPlayerId].position.tile.y }, devilution::MyPlayer->HoldItem);
|
||
|
|
devilution::NewCursor(devilution::cursor_id::CURSOR_HAND);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::useItem(int itemID)
|
||
|
|
{
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (data->itemList.size() <= itemID)
|
||
|
|
return;
|
||
|
|
|
||
|
|
auto itemData = data->itemList[itemID];
|
||
|
|
for (int i = 0; i < 8; i++) {
|
||
|
|
if (devilution::Players[devilution::MyPlayerId].SpdList[i]._itype != devilution::ItemType::None && itemData.compare(devilution::Players[devilution::MyPlayerId].SpdList[i])) {
|
||
|
|
useBeltItem(i);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < devilution::Players[devilution::MyPlayerId]._pNumInv; i++) {
|
||
|
|
if (devilution::Players[devilution::MyPlayerId].InvList[i]._itype != devilution::ItemType::None && itemData.compare(devilution::Players[devilution::MyPlayerId].InvList[i])) {
|
||
|
|
devilution::UseInvItem(i + 7);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::identifyStoreItem(int itemID)
|
||
|
|
{
|
||
|
|
int id;
|
||
|
|
|
||
|
|
if (devilution::ActiveStore != devilution::TalkID::StorytellerIdentify)
|
||
|
|
return;
|
||
|
|
|
||
|
|
id = -1;
|
||
|
|
|
||
|
|
for (int i = 0; i < 20; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::PlayerItems[i])) {
|
||
|
|
id = i;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (id == -1)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::PlaySFX(devilution::SfxID::MenuSelect);
|
||
|
|
|
||
|
|
devilution::OldActiveStore = devilution::TalkID::StorytellerIdentify;
|
||
|
|
devilution::OldTextLine = devilution::CurrentTextLine;
|
||
|
|
devilution::OldScrollPos = devilution::ScrollPos;
|
||
|
|
|
||
|
|
if (!devilution::PlayerCanAfford(devilution::PlayerItems[id]._iIvalue)) {
|
||
|
|
devilution::StartStore(devilution::TalkID::NoMoney);
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
devilution::Player &myPlayer = *devilution::MyPlayer;
|
||
|
|
|
||
|
|
int idx = devilution::PlayerItemIndexes[idx];
|
||
|
|
if (idx < 0) {
|
||
|
|
if (idx == -1)
|
||
|
|
myPlayer.InvBody[devilution::INVLOC_HEAD]._iIdentified = true;
|
||
|
|
if (idx == -2)
|
||
|
|
myPlayer.InvBody[devilution::INVLOC_CHEST]._iIdentified = true;
|
||
|
|
if (idx == -3)
|
||
|
|
myPlayer.InvBody[devilution::INVLOC_HAND_LEFT]._iIdentified = true;
|
||
|
|
if (idx == -4)
|
||
|
|
myPlayer.InvBody[devilution::INVLOC_HAND_RIGHT]._iIdentified = true;
|
||
|
|
if (idx == -5)
|
||
|
|
myPlayer.InvBody[devilution::INVLOC_RING_LEFT]._iIdentified = true;
|
||
|
|
if (idx == -6)
|
||
|
|
myPlayer.InvBody[devilution::INVLOC_RING_RIGHT]._iIdentified = true;
|
||
|
|
if (idx == -7)
|
||
|
|
myPlayer.InvBody[devilution::INVLOC_AMULET]._iIdentified = true;
|
||
|
|
} else {
|
||
|
|
myPlayer.InvList[idx]._iIdentified = true;
|
||
|
|
}
|
||
|
|
devilution::PlayerItems[id]._iIdentified = true;
|
||
|
|
devilution::TakePlrsMoney(devilution::PlayerItems[id]._iIvalue);
|
||
|
|
devilution::CalcPlrInv(myPlayer, true);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::castSpell(int x, int y)
|
||
|
|
{
|
||
|
|
if (!OKToAct())
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (!isOnScreen(x, y))
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::pcursmonst = -1;
|
||
|
|
devilution::PlayerUnderCursor = nullptr;
|
||
|
|
devilution::cursPosition = devilution::Point { x, y };
|
||
|
|
|
||
|
|
devilution::CheckPlrSpell(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::cancelQText()
|
||
|
|
{
|
||
|
|
if (!data->qtextflag)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::qtextflag = FALSE;
|
||
|
|
data->qtextflag = false;
|
||
|
|
devilution::stream_stop();
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::setFPS(int newFPS)
|
||
|
|
{
|
||
|
|
FPS = newFPS;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::disarmTrap(int index)
|
||
|
|
{
|
||
|
|
if (data->pcurs != devilution::cursor_id::CURSOR_DISARM)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (static_cast<devilution::HeroClass>(data->playerList[data->player]._pClass) != devilution::HeroClass::Rogue)
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::NetSendCmdLocParam1(true, devilution::_cmd_id::CMD_DISARMXY, devilution::Point { devilution::Objects[index].position.x, devilution::Objects[index].position.y }, index);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::skillRepair(int itemID)
|
||
|
|
{
|
||
|
|
if (data->pcurs != devilution::cursor_id::CURSOR_REPAIR)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (static_cast<devilution::HeroClass>(data->playerList[data->player]._pClass) != devilution::HeroClass::Warrior)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (!data->invflag)
|
||
|
|
return;
|
||
|
|
|
||
|
|
for (int i = 0; i < 7; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::Players[devilution::MyPlayerId].InvBody[i])) {
|
||
|
|
devilution::DoRepair(*devilution::MyPlayer, i);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for (int i = 0; i < MAXINV; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::Players[devilution::MyPlayerId].InvList[i])) {
|
||
|
|
devilution::DoRepair(*devilution::MyPlayer, i + 7);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::skillRecharge(int itemID)
|
||
|
|
{
|
||
|
|
if (static_cast<devilution::cursor_id>(data->pcurs) != devilution::cursor_id::CURSOR_RECHARGE)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (static_cast<devilution::HeroClass>(data->playerList[data->player]._pClass) != devilution::HeroClass::Sorcerer)
|
||
|
|
return;
|
||
|
|
|
||
|
|
for (int i = 0; i < 7; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::Players[devilution::MyPlayerId].InvBody[i])) {
|
||
|
|
devilution::DoRecharge(*devilution::MyPlayer, i);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for (int i = 0; i < MAXINV; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::Players[devilution::MyPlayerId].InvList[i])) {
|
||
|
|
devilution::DoRecharge(*devilution::MyPlayer, i + 7);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::toggleMenu()
|
||
|
|
{
|
||
|
|
devilution::qtextflag = false;
|
||
|
|
if (!devilution::gmenu_is_active())
|
||
|
|
devilution::gamemenu_on();
|
||
|
|
else
|
||
|
|
devilution::gamemenu_off();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::saveGame()
|
||
|
|
{
|
||
|
|
if (devilution::gbIsMultiplayer || !devilution::gmenu_is_active())
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::gmenu_presskeys(SDLK_KP_ENTER);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::quit()
|
||
|
|
{
|
||
|
|
if (!devilution::gmenu_is_active())
|
||
|
|
return;
|
||
|
|
|
||
|
|
devilution::gmenu_presskeys(SDLK_UP);
|
||
|
|
devilution::gmenu_presskeys(SDLK_KP_ENTER);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::clearCursor()
|
||
|
|
{
|
||
|
|
if (devilution::pcurs == static_cast<int>(devilution::cursor_id::CURSOR_REPAIR) || devilution::pcurs == static_cast<int>(devilution::cursor_id::CURSOR_DISARM) || devilution::pcurs == static_cast<int>(devilution::cursor_id::CURSOR_RECHARGE) || devilution::pcurs == static_cast<int>(devilution::cursor_id::CURSOR_IDENTIFY))
|
||
|
|
devilution::NewCursor(devilution::cursor_id::CURSOR_HAND);
|
||
|
|
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Server::identifyItem(int itemID)
|
||
|
|
{
|
||
|
|
if (static_cast<devilution::cursor_id>(data->pcurs) != devilution::cursor_id::CURSOR_IDENTIFY)
|
||
|
|
return;
|
||
|
|
|
||
|
|
if (!data->invflag)
|
||
|
|
return;
|
||
|
|
|
||
|
|
for (int i = 0; i < 7; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::Players[devilution::MyPlayerId].InvBody[i])) {
|
||
|
|
devilution::CheckIdentify(*devilution::MyPlayer, i);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for (int i = 0; i < MAXINV; i++) {
|
||
|
|
if (data->itemList[itemID].compare(devilution::Players[devilution::MyPlayerId].InvList[i])) {
|
||
|
|
devilution::CheckIdentify(*devilution::MyPlayer, i + 7);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} // namespace DAPI
|