[2.0] WCS - A combat system framework

Starter Params are arguments passed to skill’s :Start() method. All things you pass there get passed to OnStartClient() and OnStartServer(). You can also validate those arguments using param validators, and reject the skill startup if the required parameters are invalid.

After a bit (a lot) of trial and error along with help from your explanation, i figured it out. Thanks! such an awesome framework!

1 Like

Holdable skills do not pass constructor arguments in the .new function

function HoldableSkill:constructor(Props)
	super.constructor(self, Props)
	self.HoldTimer = Timer.new(10)
	self._internal_skillType = SkillType.Holdable
	if isServerContext() then
		self._internal_janitor:Add(self.HoldTimer.completed:Connect(function()
			return self:GetState().IsActive and self:End()
		end), "Disconnect")
	end
	self._internal_janitor:Add(self.HoldTimer, "destroy")
	self:_internal_init()
end

Here is the regular skill constructor for comparison:

function SkillBase:constructor(Props, ...)
	local Args = { ... }
	self._internal_janitor = Janitor.new()
	self._internal_id = nextId()
	self.Janitor = Janitor.new()
	self.CooldownTimer = Timer.new(1)
...

Noted! Going to release a fix soon

2 Likes

Hello, I have a problem. Why is this function returning nil?

(Following is a section of the Client script):

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local Player = Players.LocalPlayer

local Modules = ReplicatedStorage.Modules

local Skills = Modules.Skills
local Movesets = Modules.Movesets
local StatusEffects = Modules.StatusEffects

local Attack = require(Skills.Attack)
local WCS = require(Modules.WCS)

local Client = WCS.CreateClient()
local Character = WCS.Character

local keys = {Enum.KeyCode.One, Enum.KeyCode.Two, Enum.KeyCode.Three}

function getCurrentWCS_Character()
	local characterModel = Player.Character or Player.CharacterAdded:Wait()
	if not characterModel then return end
	
	return Character.GetCharacterFromInstance(characterModel)
end

UserInputService.InputBegan:Connect(function(Input:InputObject, GameProcessed:boolean)
	if GameProcessed then return end
	if Input.UserInputState ~= Enum.UserInputState.Begin then return end
	
	local character = getCurrentWCS_Character() -- This is returning nil idk why
	assert(character, "Character is nil, how'd that happen?")
	if not character then return end

	if Input.UserInputType == Enum.UserInputType.MouseButton1 then
		if Player.Team.Name == "Cursed" then
			Character:GetSkillFromConstructor(Attack):Start("Weak")
		end
	end
end)

Edit: Added a bit of the script

Player doesn’t seem to be defined in the top of your script. Try defining Player as game.Players.LocalPlayer at the top (assuming this is a LocalScript)

1 Like

I accidentally left that part out, sorry, the function isn’t returning the variable correctly so I’m wondering if it’s the Character variable at fault here

use Character.GetLocalCharacter() instead of that getCurrentWCS_Character function

1 Like

Thanks! (I’ll be using that now) But that wasn’t what solved the problem. Turns out there was a line of code that was interfering with the character in the Character script.

Moral of the Story:

Always check if your script interferes with another.

Edit: grammar

Nevermind, completely misunderstood my solution (and code), I don’t know how but I managed to fix it again…

Is there any reason Skill:GetName() returns nil? I been trying to use it for a GUI. The only workaround I can find is to do this.

local Skill = WCS.RegisterSkill("hi")
Skill.Name ="hi"

Hi, did you ever make this in a lua release?

Hi, did you ever post some example .rbxl?

Thanks

I’ve also been having problems validating messages. this will probably take a lot of time figuring out all the features

nevermind, i figured it out already. Was not easy but I’m surprised it was short. it just requires a function to be true.

it seems like you’re trying to use a method on class itself, not a class instance !!

Here’s part of my GUI script that I use. It works (although only with the workaround I mentioned before)

	local skills = WCS_Character:GetMoveset().Skills
	warn(skills)
	for i, v in (skills) do
		if i > 1 and i < 6 then
			local clone = template:Clone()
			clone.Name = v:GetName()
			clone.Visible=true
			clone.Parent = gui.Skills
			clone.Text = v:GetName()
			if UIS:GetLastInputType()==Enum.UserInputType.Gamepad1 then
				if i==2 then
					clone.Number.Text = "L1"
				elseif i==3 then
					clone.Number.Text = "L2"
				elseif i==4 then
					clone.Number.Text = "R1"
				elseif i==5 then
					clone.Number.Text = "R2"
				end
			else
				clone.Number.Text = tostring(i - 1)
			end

			clone.Description.Text=v.Description or ""
		end
		if i==9 then
			local UltimateText = gui.Ultimate.Text
			UltimateText.Text=v:GetName() or ""
		end
	end

Here’s what it prints out. It’s as expected.
image

It may seem just regular, but I never did the "Skill.Name = " workaround for the M1 skill or Evasive skill (edit: forgot to show, but basically many other skills without that workaround), yet they are printed correctly. For some reason though, they still return as nil when I do :GetName() on them.

Here is what happened when I removed the workaround mentioned earlier in the “chaos blast” skill.
image

I looked in documentation and saw :GetMovesetSkills(), which I think you may have been referencing to earlier, but when printed it seems to print the character map? (and the first skill, but only the first skill)

image

I found that tostring(Skill) works, but… would be nice to have better options than that. I’m not sure if there’s bugs or if it’s a problem related to how I coded everything.

Moveset.Skills is an array of skill constructors, not skill instances. GetMovesetSkills() returns an array of skill instances that belong to current moveset, so you should use that !!

although if you only really need names, tostring works just fine. every skill constructor has a __tostring metamethod defined

Thank you! I thought :GetMovesetSkills() was supposed to be the same thing as :GetMoveset().Skills. I did see that :GetMovesetSkills() was fetching {Skills} instead of {SkillsImpl} but thought that it was some sort of bug.