Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Wind2009-Louse committed Jun 2, 2024
2 parents 8277673 + fe1ce4d commit 8b10e2f
Show file tree
Hide file tree
Showing 17 changed files with 268 additions and 218 deletions.
89 changes: 59 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,92 @@
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.

### 2.) Install Premake5 and Visual Studio 2022 (or later).
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`

44 changes: 21 additions & 23 deletions card.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -456,15 +454,15 @@ std::tuple<uint32, uint32> card::get_original_code_rule() const {
uint32 card::get_code() {
if(assume_type == ASSUME_CODE)
return assume_value;
if (temp.code != 0xffffffff)
if(temp.code != UINT32_MAX) // prevent recursion, return the former value
return temp.code;
effect_set effects;
uint32 code = std::get<0>(get_original_code_rule());
temp.code = code;
filter_effect(EFFECT_CHANGE_CODE, &effects);
if (effects.size())
code = effects.get_last()->get_value(this);
temp.code = 0xffffffff;
temp.code = UINT32_MAX;
return code;
}
// return: the current second card name
Expand Down Expand Up @@ -608,7 +606,7 @@ uint32 card::get_type() {
return data.type;
if(current.is_location(LOCATION_PZONE))
return TYPE_PENDULUM + TYPE_SPELL;
if (temp.type != 0xffffffff)
if(temp.type != UINT32_MAX) // prevent recursion, return the former value
return temp.type;
effect_set effects;
int32 type = data.type;
Expand All @@ -625,7 +623,7 @@ uint32 card::get_type() {
type = effects[i]->get_value(this);
temp.type = type;
}
temp.type = 0xffffffff;
temp.type = UINT32_MAX;
if (data.type & TYPE_TOKEN)
type |= TYPE_TOKEN;
return type;
Expand Down Expand Up @@ -993,7 +991,7 @@ uint32 card::get_level() {
return 0;
if(assume_type == ASSUME_LEVEL)
return assume_value;
if (temp.level != 0xffffffff)
if(temp.level != UINT32_MAX) // prevent recursion, return the former value
return temp.level;
effect_set effects;
int32 level = data.level;
Expand All @@ -1016,7 +1014,7 @@ uint32 card::get_level() {
level += up;
if(level < 1 && (get_type() & TYPE_MONSTER))
level = 1;
temp.level = 0xffffffff;
temp.level = UINT32_MAX;
return level;
}
uint32 card::get_rank() {
Expand All @@ -1026,7 +1024,7 @@ uint32 card::get_rank() {
return assume_value;
if(!(current.location & LOCATION_MZONE))
return data.level;
if (temp.level != 0xffffffff)
if(temp.level != UINT32_MAX) // prevent recursion, return the former value
return temp.level;
effect_set effects;
int32 rank = data.level;
Expand All @@ -1049,7 +1047,7 @@ uint32 card::get_rank() {
rank += up;
if(rank < 1 && (get_type() & TYPE_MONSTER))
rank = 1;
temp.level = 0xffffffff;
temp.level = UINT32_MAX;
return rank;
}
uint32 card::get_link() {
Expand Down Expand Up @@ -1108,7 +1106,7 @@ uint32 card::get_attribute() {
return assume_value;
if(!(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER) && !is_affected_by_effect(EFFECT_PRE_MONSTER))
return 0;
if (temp.attribute != 0xffffffff)
if(temp.attribute != UINT32_MAX) // prevent recursion, return the former value
return temp.attribute;
effect_set effects;
int32 attribute = data.attribute;
Expand All @@ -1128,7 +1126,7 @@ uint32 card::get_attribute() {
attribute = effects[i]->get_value(this);
temp.attribute = attribute;
}
temp.attribute = 0xffffffff;
temp.attribute = UINT32_MAX;
return attribute;
}
uint32 card::get_fusion_attribute(uint8 playerid) {
Expand Down Expand Up @@ -1178,7 +1176,7 @@ uint32 card::get_race() {
return assume_value;
if(!(data.type & TYPE_MONSTER) && !(get_type() & TYPE_MONSTER) && !is_affected_by_effect(EFFECT_PRE_MONSTER))
return 0;
if (temp.race != 0xffffffff)
if(temp.race != UINT32_MAX) // prevent recursion, return the former value
return temp.race;
effect_set effects;
int32 race = data.race;
Expand All @@ -1198,7 +1196,7 @@ uint32 card::get_race() {
race = effects[i]->get_value(this);
temp.race = race;
}
temp.race = 0xffffffff;
temp.race = UINT32_MAX;
return race;
}
uint32 card::get_link_race(uint8 playerid) {
Expand Down Expand Up @@ -1234,7 +1232,7 @@ uint32 card::get_grave_race(uint8 playerid) {
uint32 card::get_lscale() {
if(!current.is_location(LOCATION_PZONE))
return data.lscale;
if (temp.lscale != 0xffffffff)
if(temp.lscale != UINT32_MAX) // prevent recursion, return the former value
return temp.lscale;
effect_set effects;
int32 lscale = data.lscale;
Expand All @@ -1257,13 +1255,13 @@ uint32 card::get_lscale() {
lscale += up + upc;
if(lscale < 0 && current.pzone)
lscale = 0;
temp.lscale = 0xffffffff;
temp.lscale = UINT32_MAX;
return lscale;
}
uint32 card::get_rscale() {
if(!current.is_location(LOCATION_PZONE))
return data.rscale;
if (temp.rscale != 0xffffffff)
if(temp.rscale != UINT32_MAX) // prevent recursion, return the former value
return temp.rscale;
effect_set effects;
int32 rscale = data.rscale;
Expand All @@ -1286,7 +1284,7 @@ uint32 card::get_rscale() {
rscale += up + upc;
if(rscale < 0 && current.pzone)
rscale = 0;
temp.rscale = 0xffffffff;
temp.rscale = UINT32_MAX;
return rscale;
}
uint32 card::get_link_marker() {
Expand Down Expand Up @@ -3284,8 +3282,8 @@ int32 card::is_spsummonable_card() {
pduel->lua->add_param(pduel->game_field->core.reason_effect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(pduel->game_field->core.reason_player, PARAM_TYPE_INT);
pduel->lua->add_param(SUMMON_TYPE_SPECIAL, PARAM_TYPE_INT);
pduel->lua->add_param((void*)0, PARAM_TYPE_INT);
pduel->lua->add_param((void*)0, PARAM_TYPE_INT);
pduel->lua->add_param(0, PARAM_TYPE_INT);
pduel->lua->add_param(0, PARAM_TYPE_INT);
if(!eset[i]->check_value_condition(5))
return FALSE;
}
Expand All @@ -3303,8 +3301,8 @@ int32 card::is_fusion_summonable_card(uint32 summon_type) {
pduel->lua->add_param(pduel->game_field->core.reason_effect, PARAM_TYPE_EFFECT);
pduel->lua->add_param(pduel->game_field->core.reason_player, PARAM_TYPE_INT);
pduel->lua->add_param(summon_type, PARAM_TYPE_INT);
pduel->lua->add_param((void*)0, PARAM_TYPE_INT);
pduel->lua->add_param((void*)0, PARAM_TYPE_INT);
pduel->lua->add_param(0, PARAM_TYPE_INT);
pduel->lua->add_param(0, PARAM_TYPE_INT);
if(!eset[i]->check_value_condition(5))
return FALSE;
}
Expand Down
1 change: 1 addition & 0 deletions card.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "common.h"
#include "effectset.h"
#include "card_data.h"
#include "sort.h"
#include <set>
#include <map>
#include <unordered_set>
Expand Down
7 changes: 4 additions & 3 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -80,6 +77,10 @@ struct card_sort {
//Flip effect flags
#define NO_FLIP_EFFECT 0x10000

//Move to field flags
#define RETURN_TEMP_REMOVE_TO_FIELD 1
#define RETURN_TRAP_MONSTER_TO_SZONE 2

//Types
#define TYPE_MONSTER 0x1 //
#define TYPE_SPELL 0x2 //
Expand Down
1 change: 1 addition & 0 deletions duel.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define DUEL_H_

#include "common.h"
#include "sort.h"
#include "mtrandom.h"
#include <set>
#include <unordered_set>
Expand Down
4 changes: 2 additions & 2 deletions effect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ bool effect_sort_id(const effect* e1, const effect* e2) {
bool is_continuous_event(uint32 code) {
if (code & EVENT_CUSTOM)
return false;
else if (code & 0xf0000)
else if (code & 0xf0000) // EVENT_ADD_COUNTER, EVENT_REMOVE_COUNTER
return false;
else if (code & 0xf000)
else if (code & 0xf000) // EVENT_PHASE_START must be continuous, but other EVENT_PHASE must not be
return !!(code & EVENT_PHASE_START);
else
return continuous_event.find(code) != continuous_event.end();
Expand Down
Loading

0 comments on commit 8b10e2f

Please sign in to comment.