How to organize type of move classes?

I am making a battlegrounds game and I was wondering how I should organize the type of moves, since I was thinking about using OOP and composition.

This is how I was thinking of doing it
Capture

So all of these types of moves are in the replicated storage and they will all be classes to make up the type of move.

Here is a template for my one of my characters

--!strict
--[Components]
local Super = require(game.ReplicatedStorage.CharacterData.Classes.Characters.Abstracts.Super)
local Awakened = require(game.ReplicatedStorage.CharacterData.Classes.Characters.Abstracts.Awakened)
local SpecialSuper = require(game.ReplicatedStorage.CharacterData.Classes.Specials.Super)

--[Types]
local types = require(game.ReplicatedStorage.Functions.Types)

--[Animations]
local universalAnimations = game.ReplicatedStorage.CharacterData.Animations.UniversalAnimations
local animations = game.ReplicatedStorage.CharacterData.Animations.CharacterAnimations.Template

local Template = {}
Template.__index = Template

local generalAnimations : types.GeneralAnimations = {
	Idle = animations.General.Idle,
	Walk = animations.General.Walk,
	Sprint = animations.General.Sprint,
	Block = animations.General.Block,
	Jump = universalAnimations.Other.Jump
}

local DashAnimations : types.DashAnimations = {
	Forward = animations.General.ForwardDash,
	Back = universalAnimations.Dashes.Back,
	Left = universalAnimations.Dashes.Left,
	Right = universalAnimations.Dashes.Right
}

local combo : types.combo = {
	One = animations.M1[1],
	Two = animations.M1[2],
	Three = animations.M1[3],
	Four = animations.M1[4],
}

local comboFinishers : types.comboFinishers = {
	Slam = animations.M1.Slam,
	Uppercut = animations.M1.Uppercut
}

local m1Animations : types.M1Animations = {
	Combo = combo,
	ComboFinishers = comboFinishers
}

local awakening : types.Awakening = {
	Name = 'test',
	Animation = animations.Awakening,
	DestroysEnviroment = false
}

local Special1 : types.Special = {
	Name = 'Special1',
	Animation = animations.Specials.Regular[1],
	Cooldown = 0,
}

local Special2 : types.Special = {
	Name = 'Special2',
	Animation = animations.Specials.Regular[2],
	Cooldown = 0,
}

local Special3 : types.Special = {
	Name = 'Special3',
	Animation = animations.Specials.Regular[3],
	Cooldown = 0,
}

local Special4 : types.Special = {
	Name = 'Special4',
	Animation = animations.Specials.Regular[4],
	Cooldown = 0,
}

local AwakenedSpecial1 : types.Special = {
	Name = 'Special1',
	Animation = animations.Specials.Awakened[1],
	Cooldown = 0,
}

local AwakenedSpecial2 : types.Special = {
	Name = 'Special2',
	Animation = animations.Specials.Awakened[2],
	Cooldown = 0,
}

local AwakenedSpecial3 : types.Special = {
	Name = 'Special3',
	Animation = animations.Specials.Awakened[3],
	Cooldown = 0,
}

local AwakenedSpecial4 : types.Special = {
	Name = 'Special4',
	Animation = animations.Specials.Awakened[4],
	Cooldown = 0,
}

local regularSpecials = {
	Special1 = {
		SpecialSuper.new(Special1)
	},
	Special2 = {
		SpecialSuper.new(Special2)
	},
	Special3 = {
		SpecialSuper.new(Special3)
	},
	Special4 = {
		SpecialSuper.new(Special4)
	},
}

local awakenedSpecials = {
	Special1 = {
		SpecialSuper.new(AwakenedSpecial1)
	},
	Special2 = {
		SpecialSuper.new(AwakenedSpecial2)
	},
	Special3 = {
		SpecialSuper.new(AwakenedSpecial3)
	},
	Special4 = {
		SpecialSuper.new(AwakenedSpecial4)
	},
}


Template.new = function()
	return setmetatable({
		Super = Super.new('Template', generalAnimations, m1Animations, DashAnimations),
		Awakening = Awakened.new(awakening),
		Specials = {
			Regular = regularSpecials,
			Awakened = awakenedSpecials,
		}
	}, Template)	
end

Template.__toString = function()
	return Template
end

return Template

So I was wondering if it is the best way to store the types of moves or is there a more efficient way of doing things?

And here is a template for one of the moves.

--!strict
local Super = require(game.ReplicatedStorage.CharacterData.Classes.Specials.Super)

local types = require(game.ReplicatedStorage.Functions.Types)

local Damaging = {}
Damaging.__index = Damaging

Damaging.new = function(special : types.Special, damage : number)
	return setmetatable({
		Super.new(special),
		Damage = damage
	}, Damaging);
end

function Damaging:Activate(other : Player) end

return Damaging

That’s a considerable number of classes you’d have to make and a lot of boilerplate to write. You could make a single generic “Move” or “Special” class with a set of reusable behavior components such as damage, healing, AOE, ragdoll, etc. This makes it 1. more readable and 2. easier to add new moves.

1 Like

I do have a generic move class, it is called super

--!strict
local types = require(game.ReplicatedStorage.Functions.Types)
local specialEvent = game.ReplicatedStorage.Events.Special

local Super = {}
Super.__index = Super

Super.new = function(special : types.Special)
	return setmetatable(special, Super);
end

function Super:Activate(player : Player, ...) end

return Super

Do you think I should add components like damage, healing, AOE, and ragdoll to this and remove the other scripts and just make a mega script, or what should I do?

I do think it would be a lot simpler to use states within that class rather than having a bunch of separate modules for each attribute a move would apply. At least that’s what I can gather you are doing from the screenshot you provided. I would probably refactor to do that if I were you.

1 Like