Currently, if both patrician of darkness and must attack effects were in play, th eturn player was still able to select an attack target among the monsters affected by the must attack effect, ignoring the selection performed by the opponent
No longer manage a Group's lifetime explicitly in native code, but instead leverage Lua's garbage collector to handle it's lifetime.
In this change, Groups will be stored internally in the core inside a weak table, so that they will still be reference-able when needed, but if no reference were to exist in Lua code, they will be subject to garbage collection.
Whenever a Group is used by native code, its wrapped by a owned_lua template class, this is akin to std::shared_ptr--It reference counts the usages of that group internally in the core, including managing it in the Lua registry index when in use, so that it won't be collected.
With this approach, the exponential memory usage growth caused by long running procedures due to the creation hundredths of thousands of groups per iteration, is mitigated, since the temporary groups will be reaped more frequently, as opposed to the old approach of them being cleared only after the topmost Lua function had finished executing.
For now a single GC step is triggered whenever the total number of groups is more than 2048--an arbitrary value that seems to work well enough, but which can be changed/optimized after proper profiling.
A major upgrade with this approach is the removal of the concept of Groups "kept alive" and having to "explicitly delete" them to make them outlive a Lua function execution, since they will now follow Lua's variables lifetime properly.
DUEL_FAST_EFFECT_IGNITION will treat any ignition effect as fast effect if they're the first in a chain, to match GOAT rulings, DUEL_OBSOLETE_IGNITION instead, now renamed to DUEL_OCG_OBSOLETE_IGNITION will behave as before, with ignition effects being only activateable in response to a summon, as it worked in ocg's master rule 1
Fixed the first in process_instant_event, where only the bits pertaining EVENT_PHASE_START were being checked, thus falsely filtering other events, similar case in process(Processors::AddChain)
Functions from the auxiliary library, assume the stack has always at least 5 empty slots, add macro ensure_luaL_stack to wrap every such call so that the stack is checked for enough free space beforehand. This will make mandatory to use the latest version of visual studio 2017 as minimum for windows (it was already being required for c++17 support regardless), as it needs the conformant c++ preprocessor option to be used.
If other processors were appended at the end of the battle step that could alter the returns buffer, the core could've interpreted the standalone battle phase not to have ended but instead another attack being declared or an effect being activated, thus possibly leading to an out of bound access
Avoid having to deal with UB while relying on signed integer overflow, add new value Processors::restart to be used in place of the -1 when "looping" a process (a value that when incremented by 1 will properly overflow to 0)
Properly implement 58c488de9e:
* If only one effect is providing EFFECT_MUST_ATTACK_MONSTER the attack selection proceeds as normal, with the turn player choosing the attack targets
* If multiple effects are providing EFFECT_MUST_ATTACK_MONSTER, the opponent choose the attack target like it did prior to the other change, if then the EFFECT_MUST_ATTACK_MONSTER effect applied on the selected monster was also applying to other monsters, the turn player will then choose among those monsters a valid attack target
Rewrite the whole ``process`` function of the processor to use instead tag dispatching on variant objects.
Each single processor message got rewritten as a struct, inheriting from a base templated Process struct, containing only the required data for that process, rather than using the generic structure that ended up needing to spam bitwise operations to pack as many arguments in a byte as possible. This makes things easier to follow and streamlines the addition of new processes:
- Define its struct with the parameters it expects by also providing a constructor
- If the process requires an answer, inherit it from ``Process<true>``, if it requires no answer, inherit it from ``Process<false>``
- Add such struct to the ``processors`` variant type
- Declare and implement its corresponding ``bool process(Processors::NewProcess& arg);`` function
Do the required changes to make Duel.AnnounceRace work with the new types and also any possible newly added type removing some hardcodings down the way and adding some extra checks, also apply the same updates to Duel.AnnounceAttribute
If one of such effect has no side effects (no count limit and no value function to execute) glob it with all the other effects, as whichever is picked won't affect the internal lua state and make the player choose the effect only when there is one of such effects that has a count limit or a function to execute.
The way they were changed made the core crash in the case of an EFFECT_ACTIVATE_COST being in play, reorder the sections so that first the EFFECT_TRAP_ACT_IN_HAND and co effects are evaluated and used, and then the cost is paid, so that there's no interference between it and the PROCESSOR_SELECT_OPTION
The core will read those effects' descriptions and prompt the user in the case where multiple of them are available.
It will also call the value function of the choosen effect so that a possible callback is doable (might be changed to a better approach)
Implement it natively rather than via lua, correctly handle the scenario where one of the xyz monsters to be overlaid has an effect to banish any card sent to the grave and it would be still applying if duel.sendtograve was called manually from the script
Properly implement this thing by using a specific effect flag rather than randomly reading the effect value (that could have been set for other purposes)
Add a separate ``set`` function and use memcpy to store/retrieve the data in the buffer, removes the raw cast to a reference that could have also lead to aligment issues.