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.
117 lines
3.8 KiB
117 lines
3.8 KiB
#include "lua/modules/player.hpp" |
|
|
|
#include <optional> |
|
|
|
#include <sol/sol.hpp> |
|
|
|
#include "engine/point.hpp" |
|
#include "engine/random.hpp" |
|
#include "inv.h" |
|
#include "items.h" |
|
#include "lua/metadoc.hpp" |
|
#include "player.h" |
|
|
|
namespace devilution { |
|
namespace { |
|
|
|
void InitPlayerUserType(sol::state_view &lua) |
|
{ |
|
sol::usertype<Player> playerType = lua.new_usertype<Player>(sol::no_constructor); |
|
LuaSetDocReadonlyProperty(playerType, "name", "string", |
|
"Player's name (readonly)", |
|
&Player::name); |
|
LuaSetDocFn(playerType, "addExperience", "(experience: integer, monsterLevel: integer = nil)", |
|
"Adds experience to this player based on the current game mode", |
|
[](Player &player, uint32_t experience, std::optional<int> monsterLevel) { |
|
if (monsterLevel.has_value()) { |
|
player.addExperience(experience, *monsterLevel); |
|
} else { |
|
player.addExperience(experience); |
|
} |
|
}); |
|
LuaSetDocProperty(playerType, "characterLevel", "number", |
|
"Character level (writeable)", |
|
&Player::getCharacterLevel, &Player::setCharacterLevel); |
|
LuaSetDocFn(playerType, "addItem", "(itemId: integer, count: integer = 1)", |
|
"Add an item to the player's inventory", |
|
[](Player &player, int itemId, std::optional<int> count) -> bool { |
|
const _item_indexes itemIndex = static_cast<_item_indexes>(itemId); |
|
const int itemCount = count.value_or(1); |
|
for (int i = 0; i < itemCount; i++) { |
|
Item tempItem {}; |
|
SetupAllItems(player, tempItem, itemIndex, AdvanceRndSeed(), 1, 1, true, false); |
|
if (!AutoPlaceItemInInventory(player, tempItem, true)) { |
|
return false; |
|
} |
|
} |
|
CalcPlrInv(player, true); |
|
return true; |
|
}); |
|
LuaSetDocFn(playerType, "hasItem", "(itemId: integer)", |
|
"Check if the player has an item with the given ID", |
|
[](const Player &player, int itemId) -> bool { |
|
return HasInventoryOrBeltItemWithId(player, static_cast<_item_indexes>(itemId)); |
|
}); |
|
LuaSetDocFn(playerType, "removeItem", "(itemId: integer, count: integer = 1)", |
|
"Remove an item from the player's inventory", |
|
[](Player &player, int itemId, std::optional<int> count) -> int { |
|
const _item_indexes targetId = static_cast<_item_indexes>(itemId); |
|
const int itemCount = count.value_or(1); |
|
int removed = 0; |
|
|
|
// Remove from inventory |
|
for (int i = player._pNumInv - 1; i >= 0 && removed < itemCount; i--) { |
|
if (player.InvList[i].IDidx == targetId) { |
|
player.RemoveInvItem(i); |
|
removed++; |
|
} |
|
} |
|
|
|
// Remove from belt if needed |
|
for (int i = MaxBeltItems - 1; i >= 0 && removed < itemCount; i--) { |
|
if (!player.SpdList[i].isEmpty() && player.SpdList[i].IDidx == targetId) { |
|
player.RemoveSpdBarItem(i); |
|
removed++; |
|
} |
|
} |
|
|
|
if (removed > 0) { |
|
CalcPlrInv(player, true); |
|
} |
|
|
|
return removed; |
|
}); |
|
LuaSetDocFn(playerType, "restoreFullLife", "()", |
|
"Restore player's HP to maximum", |
|
[](Player &player) { |
|
player._pHitPoints = player._pMaxHP; |
|
player._pHPBase = player._pMaxHPBase; |
|
}); |
|
LuaSetDocFn(playerType, "restoreFullMana", "()", |
|
"Restore player's mana to maximum", |
|
[](Player &player) { |
|
player._pMana = player._pMaxMana; |
|
player._pManaBase = player._pMaxManaBase; |
|
}); |
|
} |
|
} // namespace |
|
|
|
sol::table LuaPlayerModule(sol::state_view &lua) |
|
{ |
|
InitPlayerUserType(lua); |
|
sol::table table = lua.create_table(); |
|
LuaSetDocFn(table, "self", "()", |
|
"The current player", |
|
[]() { |
|
return MyPlayer; |
|
}); |
|
LuaSetDocFn(table, "walk_to", "(x: integer, y: integer)", |
|
"Walk to the given coordinates", |
|
[](int x, int y) { |
|
NetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, Point { x, y }); |
|
}); |
|
|
|
return table; |
|
} |
|
|
|
} // namespace devilution
|
|
|