Commit 6934ed76 authored by nanahira's avatar nanahira

Merge branch 'master' of github.com:Fluorohydride/ygopro-core into develop

parents 74520eb0 cd23edd2
......@@ -4,6 +4,8 @@
The core logic and lua script processor of YGOPro. This library can be made external of the project and used to power server technologies. It maintains a state engine that is manipulated by Lua scripts using manipulation functions it exposes.
## Compiling
See [ygopro wiki](https://github.com/Fluorohydride/ygopro/wiki).
### 1.) Download Fluorohydride/ygopro
Start by downloading the most parent of the source code. The team developing this project are the de facto edge and experts in our community. The most up-to-date `ocgcore` is a compiled dll version of the `Fluorohydride/ygopro/ocgcore` folders project.
......@@ -11,56 +13,83 @@ Start by downloading the most parent of the source code. The team developing thi
Download premake5.exe, put it in `c:\windows` or a similar folder that is globally accessible via `cmd` or PowerShell. Install Visual Studio 2022, it is the system used for the guide because other parts of the project use C# and most the development team are Windows users.
### 3.) Download dependencies
Dependencies are absent from the main project. There is information on how to build them but the easiest thing to do is to download the following folders from a [soarqin/ygopro](https://github.com/soarqin/ygopro) fork and simply copy them into the `Fluorohydride/ygopro` folder.
* event
* freetype
* irrlicht
* lua
* sqlite3
### 4.) Create the project files
Run the following commands from the command line in the `Fluorohydride/ygopro` folder.
` premake5 vs2022 `
`premake5 vs2022`
If you are not using Visual Studio 2022 or higher, make necessary adjustments. In the file system open `Fluorohydride/ygopro/build` folder open the `ygo` project.
If you are not using Visual Studio 2022 or higher, make necessary adjustments. In the file system open `Fluorohydride/ygopro/build` folder open the `ygopro` project.
### 5.) Build the system
Make sure the code actually compiles. Compile them in the following order one by one:
* lua
* sqlite3
* ocgcore
This should provide you with `ocgcore.lib` in the build output folder. `YGOCore` requires a `*.dll`; in `ocgcore` project properties change it to a dynamically linked library. Recompile, it should fail with an error indicating missing dependencies. Right click the project, add an existing file. Add `lua.lib` from the build folder to the project. It should now compile.
## Exposed Functions
These three function need to be provided to the core so it can get card and database information.
- `void set_script_reader(script_reader f);` : Interface provided returns scripts based on number that corresponds to a lua file, send in a string.
The 3 functions need to be provided to the core so it can get card and database information.
- `void set_script_reader(script_reader f);`
Interface provided returns scripts based on number that corresponds to a lua file, send in a string.
- `void set_card_reader(card_reader f);` : Interface provided function that provides database information from the `data` table of `cards.cdb`.
- `void set_card_reader(card_reader f);`
Interface provided function that provides database information from the `data` table of `cards.cdb`.
- `void set_message_handler(message_handler f);` : Interface provided function that handles errors
- `void set_message_handler(message_handler f);`
Interface provided function that handles error messages.
These functions create the game itself and then manipulate it.
- `ptr create_duel(uint32 seed);` : Create a the instance of the duel using a random number.
- `void start_duel(ptr pduel, int32 options);` : Starts the duel
- `void end_duel(ptr pduel);` : ends the duel
- `void set_player_info(ptr pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount);` sets the duel up
- `void get_log_message(ptr pduel, byte* buf);`
- `int32 get_message(ptr pduel, byte* buf);`
- `int32 process(ptr pduel);` : do a game tick
- `void new_card(ptr pduel, uint32 code, uint8 owner, uint8 playerid, uint8 location, uint8 sequence, uint8 position);` : add a card to the duel state.
- `void new_tag_card(ptr pduel, uint32 code, uint8 owner, uint8 location);` : add a new card to the tag pool.
- `int32 query_card(ptr pduel, uint8 playerid, uint8 location, uint8 sequence, int32 query_flag, byte* buf, int32 use_cache);` : find out about a card in a specific spot.
- `int32 query_field_count(ptr pduel, uint8 playerid, uint8 location);` : Get the number of cards in a specific field/zone.
- `int32 query_field_card(ptr pduel, uint8 playerid, uint8 location, int32 query_flag, byte* buf, int32 use_cache);`
- `int32 query_field_info(ptr pduel, byte* buf);`
- `void set_responsei(ptr pduel, int32 value);`
- `void set_responseb(ptr pduel, byte* buf);`
- `int32 preload_script(ptr pduel, char* script, int32 len);`
- `intptr_t create_duel(uint_fast32_t seed);`
Create a the instance of the duel with a PRNG seed.
- `void start_duel(intptr_t pduel, int32 options);`
Start the duel.
- `void end_duel(intptr_t pduel);`
End the duel.
- `void set_player_info(intptr_t pduel, int32 playerid, int32 lp, int32 startcount, int32 drawcount);`
Set up the duel information.
- `void get_log_message(intptr_t pduel, char* buf);`
- `int32 get_message(intptr_t pduel, byte* buf);`
- `int32 process(intptr_t pduel);`
Do a game tick.
- `void new_card(intptr_t pduel, uint32 code, uint8 owner, uint8 playerid, uint8 location, uint8 sequence, uint8 position);`
Add a card to the duel state.
- `void new_tag_card(intptr_t pduel, uint32 code, uint8 owner, uint8 location);`
Add a new card to the tag pool.
- `int32 query_field_card(intptr_t pduel, uint8 playerid, uint8 location, uint32 query_flag, byte* buf, int32 use_cache);`
Get a card in a specific location.
- `int32 query_field_count(intptr_t pduel, uint8 playerid, uint8 location);`
Get the number of cards in a specific location.
- `int32 query_field_card(intptr_t pduel, uint8 playerid, uint8 location, uint32 query_flag, byte* buf, int32 use_cache);`
Get all cards in some location.
- `int32 query_field_info(intptr_t pduel, byte* buf);`
- `void set_responsei(intptr_t pduel, int32 value);`
- `void set_responseb(intptr_t pduel, byte* buf);`
- `int32 preload_script(intptr_t pduel, const char* script, int32 len);`
# Lua functions
`interpreter.cpp`
- `libcard.cpp`
- `libdebug.cpp`
- `libduel.cpp`
- `libeffect.cpp`
- `libgroup.cpp`
......@@ -23,9 +23,7 @@ const std::unordered_map<uint32, uint32> card::second_code = {
{CARD_HERMOS, 10000070u}
};
bool card_sort::operator()(void* const & p1, void* const & p2) const {
card* c1 = (card*)p1;
card* c2 = (card*)p2;
bool card_sort::operator()(card* const& c1, card* const& c2) const {
return c1->cardid < c2->cardid;
}
bool card_state::is_location(int32 loc) const {
......
......@@ -11,6 +11,7 @@
#include "common.h"
#include "effectset.h"
#include "card_data.h"
#include "sort.h"
#include <set>
#include <map>
#include <unordered_set>
......
......@@ -42,9 +42,6 @@ typedef signed char int8;
#ifndef NULL
#define NULL 0
#endif
struct card_sort {
bool operator()(void* const & c1, void* const & c2) const;
};
#define CURRENT_RULE 5
......
......@@ -9,6 +9,7 @@
#define DUEL_H_
#include "common.h"
#include "sort.h"
#include "mtrandom.h"
#include <set>
#include <unordered_set>
......
......@@ -613,19 +613,19 @@ int32 field::is_location_useable(uint32 playerid, uint32 location, uint32 sequen
return TRUE;
}
/**
* Return usable count in zone of playerid's MZONE or SZONE(0~4) when uplayer moves pcard to playerid's field (can be negative).
* for LOCATION_MZONE, "usable" means not used, not disabled, satisfying EFFECT_MUST_USE_MZONE, satisfying EFFECT_MAX_MZONE
* for LOCATION_SZONE, "usable" means not used, not disabled, satisfying EFFECT_MAX_SZONE
* Return usable count in `zone` when `uplayer` moves `pcard` to the MZONE or SZONE(0~4) of `playerid` (can be negative).
* For LOCATION_MZONE, "usable" means not used, not disabled, satisfying EFFECT_MUST_USE_MZONE, satisfying EFFECT_MAX_MZONE.
* For LOCATION_SZONE, "usable" means not used, not disabled, satisfying EFFECT_MAX_SZONE.
*
* @param pcard the card about to move
* @param playerid the target player
* @param location LOCATION_MZONE or LOCATION_SZONE
* @param uplayer the request player, PLAYER_NONE means ignoring EFFECT_MUST_USE_MZONE of uplayer, ignoring EFFECT_MAX_MZONE, EFFECT_MAX_SZONE of playerid
* @param reason location reason
* @param zone specified zones, 0xff by default
* @param list storing unavailable or unspecified zones
* @param pcard the card about to move
* @param playerid target player
* @param location LOCATION_MZONE or LOCATION_SZONE
* @param uplayer request player, PLAYER_NONE means ignoring EFFECT_MUST_USE_MZONE of uplayer, ignoring EFFECT_MAX_MZONE, EFFECT_MAX_SZONE of playerid
* @param reason location reason
* @param zone specified zones, default: 0xff
* @param list storing unavailable or unspecified zones
*
* @return usable count in zone of playerid's MZONE or SZONE(0~4) (can be negative)
* @return usable count in the MZONE or SZONE(0~4) of `playerid` (can be negative)
*/
int32 field::get_useable_count(card* pcard, uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32 zone, uint32* list) {
if(location == LOCATION_MZONE && pcard && pcard->current.location == LOCATION_EXTRA)
......@@ -634,8 +634,8 @@ int32 field::get_useable_count(card* pcard, uint8 playerid, uint8 location, uint
return get_useable_count_other(pcard, playerid, location, uplayer, reason, zone, list);
}
/**
* @param pcard the card about to move from Extra Deck (nullptr means any card in Extra Deck)
* @return usable count in zone of playerid's MZONE for pcard
* @param pcard the card about to move from Extra Deck (nullptr means any card in Extra Deck)
* @return usable count in the MZONE of `playerid`
*/
int32 field::get_useable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone, uint32* list) {
bool use_temp_card = false;
......@@ -654,8 +654,8 @@ int32 field::get_useable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer
return useable_count;
}
/**
* @return the number of available grids in zone of playerid's MZONE for pcard sp_summoned by playerid
* for LOCATION_MZONE, "available" means not used, not disabled, satisfying EFFECT_MUST_USE_MZONE
* @return the number of available slots in `zone` when `pcard` is sp_summoned to the MZONE of `playerid`
* For LOCATION_MZONE, "available" means not used, not disabled, satisfying EFFECT_MUST_USE_MZONE.
*/
int32 field::get_spsummonable_count(card* pcard, uint8 playerid, uint32 zone, uint32* list) {
if(pcard->current.location == LOCATION_EXTRA)
......@@ -664,8 +664,8 @@ int32 field::get_spsummonable_count(card* pcard, uint8 playerid, uint32 zone, ui
return get_tofield_count(pcard, playerid, LOCATION_MZONE, playerid, LOCATION_REASON_TOFIELD, zone, list);
}
/**
* @param pcard the card about to move from Extra Deck (nullptr means any card in Extra Deck)
* @return the number of available grids in zone of playerid's MZONE for pcard
* @param pcard the card about to move from Extra Deck (nullptr means any card in Extra Deck)
* @return the number of available slots in `zone` when `pcard` is sp_summoned to the MZONE of `playerid` by `uplayer`
*/
int32 field::get_spsummonable_count_fromex(card* pcard, uint8 playerid, uint8 uplayer, uint32 zone, uint32* list) {
bool use_temp_card = false;
......@@ -684,7 +684,7 @@ int32 field::get_spsummonable_count_fromex(card* pcard, uint8 playerid, uint8 up
return spsummonable_count;
}
/**
* @return usable count in zone of Main MZONE or SZONE(0~4)
* @return usable count in `zone` of Main MZONE or SZONE(0~4)
*/
int32 field::get_useable_count_other(card* pcard, uint8 playerid, uint8 location, uint8 uplayer, uint32 reason, uint32 zone, uint32* list) {
int32 count = get_tofield_count(pcard, playerid, location, uplayer, reason, zone, list);
......@@ -698,7 +698,7 @@ int32 field::get_useable_count_other(card* pcard, uint8 playerid, uint8 location
return count;
}
/**
* @return the number of available grids in zone of Main MZONE or SZONE(0~4)
* @return the number of available slots in `zone` of Main MZONE or SZONE(0~4)
* for LOCATION_MZONE, "available" means not used, not disabled, satisfying EFFECT_MUST_USE_MZONE
* for LOCATION_SZONE, "available" means not used, not disabled
*/
......@@ -754,11 +754,11 @@ int32 field::get_spsummonable_count_fromex_rule4(card* pcard, uint8 playerid, ui
return count;
}
/**
* @param playerid the target player
* @param uplayer the request player, PLAYER_NONE means ignoring EFFECT_MAX_MZONE
* @param reason location reason
* @param playerid target player
* @param uplayer request player, PLAYER_NONE means ignoring EFFECT_MAX_MZONE
* @param reason location reason
*
* @return the remaining count in playerid's MZONE after applying EFFECT_MAX_MZONE (can be negative).
* @return the remaining count in the MZONE of `playerid` after applying EFFECT_MAX_MZONE (can be negative).
*/
int32 field::get_mzone_limit(uint8 playerid, uint8 uplayer, uint32 reason) {
uint32 used_flag = player[playerid].used_location;
......@@ -787,11 +787,11 @@ int32 field::get_mzone_limit(uint8 playerid, uint8 uplayer, uint32 reason) {
return limit;
}
/**
* @param playerid the target player
* @param uplayer the request player, PLAYER_NONE means ignoring EFFECT_MAX_SZONE
* @param reason location reason
* @param playerid target player
* @param uplayer request player, PLAYER_NONE means ignoring EFFECT_MAX_SZONE
* @param reason location reason
*
* @return the remaining count in playerid's SZONE(0~4) after applying EFFECT_MAX_SZONE.
* @return the remaining count in the SZONE(0~4) of `playerid` after applying EFFECT_MAX_SZONE.
*/
int32 field::get_szone_limit(uint8 playerid, uint8 uplayer, uint32 reason) {
uint32 used_flag = player[playerid].used_location;
......@@ -835,11 +835,11 @@ uint32 field::get_rule_zone_fromex(int32 playerid, card* pcard) {
}
}
/**
* @param playerid the target player
* @param uplayer the request player, PLAYER_NONE means ignoring EFFECT_MUST_USE_MZONE of uplayer
* @param reason location reason
* @param pcard the card about to move
* @param flag storing the zones in MZONE blocked by EFFECT_MUST_USE_MZONE
* @param playerid target player
* @param uplayer request player, PLAYER_NONE means ignoring EFFECT_MUST_USE_MZONE of uplayer
* @param reason location reason
* @param pcard the card about to move
* @param flag storing the zones in MZONE blocked by EFFECT_MUST_USE_MZONE
*/
void field::filter_must_use_mzone(uint8 playerid, uint8 uplayer, uint32 reason, card* pcard, uint32* flag) {
effect_set eset;
......
......@@ -303,6 +303,7 @@ struct processor {
int32 summon_count[2]{};
uint8 extra_summon[2]{};
int32 spe_effect[2]{};
int32 last_select_hint[2]{ 0 };
int32 duel_options{ 0 };
int32 duel_rule{ CURRENT_RULE }; //current rule: 5, Master Rule 2020
uint32 copy_reset{ 0 };
......
......@@ -9,6 +9,7 @@
#define GROUP_H_
#include "common.h"
#include "sort.h"
#include <set>
#include <list>
......
......@@ -2094,7 +2094,7 @@ int32 scriptlib::duel_get_location_count_fromex(lua_State *L) {
}
return 2;
}
// Return the number of available grids in playerid's Main MZONE and Extra MZONE
// Return the number of available slots in the Main MZONE and Extra MZONE of `playerid`.
int32 scriptlib::duel_get_usable_mzone_count(lua_State *L) {
check_param_count(L, 1);
uint32 playerid = (uint32)lua_tointeger(L, 1);
......@@ -3703,12 +3703,24 @@ int32 scriptlib::duel_hint(lua_State * L) {
if(htype == HINT_OPSELECTED)
playerid = 1 - playerid;
duel* pduel = interpreter::get_duel_info(L);
if(htype == HINT_SELECTMSG)
pduel->game_field->core.last_select_hint[playerid] = desc;
pduel->write_buffer8(MSG_HINT);
pduel->write_buffer8(htype);
pduel->write_buffer8(playerid);
pduel->write_buffer32(desc);
return 0;
}
int32 scriptlib::duel_get_last_select_hint(lua_State* L) {
duel* pduel = interpreter::get_duel_info(L);
uint8 playerid = pduel->game_field->core.reason_player;
if(lua_gettop(L) >= 1)
playerid = (uint8)lua_tointeger(L, 1);
if(playerid != 0 && playerid != 1)
return 0;
lua_pushinteger(L, pduel->game_field->core.last_select_hint[playerid]);
return 1;
}
int32 scriptlib::duel_hint_selection(lua_State *L) {
check_param_count(L, 1);
check_param(L, PARAM_TYPE_GROUP, 1);
......@@ -4963,6 +4975,7 @@ static const struct luaL_Reg duellib[] = {
{ "CheckRemoveOverlayCard", scriptlib::duel_check_remove_overlay_card },
{ "RemoveOverlayCard", scriptlib::duel_remove_overlay_card },
{ "Hint", scriptlib::duel_hint },
{ "GetLastSelectHint", scriptlib::duel_get_last_select_hint },
{ "HintSelection", scriptlib::duel_hint_selection },
{ "SelectEffectYesNo", scriptlib::duel_select_effect_yesno },
{ "SelectYesNo", scriptlib::duel_select_yesno },
......
......@@ -569,6 +569,7 @@ public:
static int32 duel_remove_overlay_card(lua_State *L);
static int32 duel_hint(lua_State *L);
static int32 duel_get_last_select_hint(lua_State *L);
static int32 duel_hint_selection(lua_State *L);
static int32 duel_select_effect_yesno(lua_State *L);
static int32 duel_select_yesno(lua_State *L);
......
#ifndef SORT_H_
#define SORT_H_
class card;
struct card_sort {
bool operator()(card* const& c1, card* const& c2) const;
};
#endif /* SORT_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment