Let's talk data


Hi all, today I'd like to catch you up on the state of the Duelists of the Roses remake. 


On February 28th, 2020 I had the bold idea to recreate the mechanics of Yu-Gi-Oh Duelists of the Roses in Unity. In less than 48 hours, I was successful in building mechanics, grid, type matchups, and 5 days later I was importing the card list from the official Yu-Gi-Oh Wiki; as a CSV, of course ;)

I believe the game wouldn't have been where it was today if I hadn't taken the route I had with the card database. Currently, every single card in the game is represented as a ScriptableObject in Unity. If you're not familiar with ScriptableObjects put simply: they make data in Unity easy. Have a class that needs to be referenced by multiple objects in the scene? ScriptableObjects let you represent that class an asset in the editor. This asset can be a store, it can represent a configured machine (more on that later), or can represent simple constants. The best part is that referencing them in the Unity Editor is just as simple as referencing a texture. 


So not only are all 600+ monster cards represented by ScriptableObjects in a folder in my Unity project, their card effects are also represented by ScriptableObjects. This is where it gets interesting.


I glanced over the card effects in my spreadsheet and outlined the types of effects I would need to represent as classes. For example:

- EffectModifyAttack

- EffectModifyDefense

- EffectChangeBattleResult

- EffectModifyLifepoints


And a base class to match:

public abstract class DORCardEffect : ScriptableObject



With ScriptableObjects, it just made sense to have a few configurable & reusable effect classes and instantiate and configure them as assets then assign them to the cards. However, as with any programming solution it is not always cookies and cream. There's been a lot of testing involved with each card effect I add. And of course, modifying the way one effect worked would also change the way others based on it would work. 


The initial sample section is the first 140 cards in the game. Out of those, about 60% are effect monsters with effects ranging from, "Transforms the occupied space into WASTELAND terrain when engaging in a battle." to "Select a spell card from your graveyard and revive it in your own summoning area."

I've started with the easy ones, the effects that you can create and configure currently are as follows: EffectBonusATK, EffectChangeBattleResult, EffectFlipCards, EffectModifyLP, EffectModifyATK, EffectSpellbindCard, EffectTransformMonsters, EffectTransformTerrain.


Every single one of these classes inherits from DORCardEffect and implements MINIMALLY abstract method PerformEffect. PerformEffect is where all the logic goes, and PerformEffect requires:


  • Host Card: The card that this effect was on when the game told it to execute
  • Grid Space: The full game grid, for searching


If applicable based on execution type:

  • Opposing Card: The card that Host Card is facing in battle. 
  • Battle Terrain: The grid spot that this battle is taking place.


Since each effect is also a ScriptableObject, the DORCardEffect class also includes parameters for narrowing down the effect execution parameters by card type, card stats, card attribute, and more. 


Let's see what this looks like in action.


I want to create an effect that tolls the player who controls this card 50 LP each time it's involved in a battle.

(All Screenshots Are Considered Work In Progress BTW....."Increase LP" is a lie. You can set numbers negative to deduct as you can see...but making the effects work is more important to me than making the lingo 100% at this time)


Sweet, you've created and named your first effect.


Once you select it you'll be greeted this HORRIFICLY SCARY looking inspector. I know it's ugly right now, but I've still got work to do on custom editors:




The parameters that you see in orange are BUILT IN to the DORCardEffect class. By extension, this class also includes overideable logic for processing these Target Parameters. There are also parameters for the host card to require a specific position or face.


The first thing we need to do is change the Effect Execution Time, or "When" the effect takes place:


And why not, let's fill in a description.


After that, let's fill in the "Effect Application Type"  which specifies to whom the effect will be applied.


There's a little more than needed here. In the case of this effect, we only use

  • Host Only - Applies to the player controlling the card's lifepoints
  • Opposing Player Cards - Applies to the opposing player's lifepoints
  • All Cards - Applies to both player's life points.

This enum is expanded and explored more in other effects.


And finally, we can skip all the way to the bottom and change the "Life Point Modification Amount" to -50




And now you have successfully defined an effect that can be then assigned to a card.



Now that you all are familiar with the cards and effects system, I'd like to start a discussion about opening this up to mods. It is possible to instantiate and save ScriptableObjects through the editor at runtime. However, mods will need to be loaded in at runtime from another file type. It would be possible to interject custom code for effects, but I think I'd rather have effects configured on the card and then let the engine properly assign the class & parameters. 

Files

DOR_PB1.app.zip 139 MB
Apr 01, 2020
DOR_PB1_Win32.zip 134 MB
Apr 03, 2020
DOR_PB1_Linux_x86_64.zip 140 MB
Apr 07, 2020

Get Yu-Gi-Oh Duelists of the Roses Remake (ALPHA)

Comments

Log in with itch.io to leave a comment.

This Is Awesome. I just started to update Duelist of roses cards to 2008. I am still in the DoR but Rewriting cards to make them better or make more sense has been fun. Maybe we could collaborate later if you want to. I can not code but I have been spending hours to update cards.

You've been modifying the original Duelists of the Roses? That's definitely interesting, I'd love to chat about that. Feel free to add me on Discord Axiom#6863