I am trying to create a system of melee weapons for a future game that I am making. Most of the required components have been done and are working as intended. The initial hierarchy where no problems are experienced is shown as below:
- StarterPack (StarterPack)
- Sword (Tool)
- MeleeWeaponScript (Script) --The melee weapon system framework goes here.
- Handle (UnionOperation)
- (LocalScript)
- (Sounds)
- Values (Folder) --For storing the weapon's basic statistics like Damage and Knockback
- (Animations)
- (RemoteEvents)
I am now trying to transfer over the framework in MeleeWeaponScript
into a ModuleScript (which I am not experienced in using yet). The ModuleScript will handle the basics of all melee weapons in the game. This will be in case a future update of the game requires any change in the melee weapon system and that I don’t have to change the MeleeWeaponScript in all of my melee weapons one-by-one. Below is the new hierarchy:
- ServerScriptService (ServerScriptService)
- StandardMeleeWeapon (ModuleScript) --The melee weapon system framework is now here.
- StarterPack (StarterPack)
- Sword (Tool)
- MeleeWeaponScript (Script) --This Script now gets the framework from the ModuleScript through a require() for it to work
--All components other than MeleeWeaponScript in the Sword Tool are unchanged.
- Handle (UnionOperation)
- (LocalScript)
- (Sounds)
- Values (Folder) --Still for storing the weapon's basic statistics like Damage and Knockback
- (Animations)
- (RemoteEvents)
Before the inclusion of the StandardMeleeWeapon
ModuleScript, the structure of MeleeWeaponScript
was as follows:
--Variables here to control the sword. Many are initialised at this point as they are relatives with the required instances.
local function cooldown()
--Handling cooldown of the sword after it has been unsheathed or swung to prevent overly rapid use of sword.
end
local function onEquip()
--Handling unsheathing.
end
local function onUnequip()
--Handling sheathing.
end
tool.Charge.OnServerEvent:Connect(function()
--Charging up attacks, if the weapon permits charged attacks. (Communication with LocalScript required for listening to player's inputs)
end)
tool.Releasing.OnServerEvent:Connect(function()
--Releasing charged attacks, if the weapon permits charged attacks. (Communication with LocalScript required for listening to player's inputs)
end)
local function onActivate()
--For if the weapon does not permit charged attacks.
end
local function hit(otherPart)
--Handling for when the sword hits something, be it another player or an obstacle.
end
tool.Equipped:Connect(onEquip)
tool.Unequipped:Connect(onUnequip)
tool.Activated:Connect(onActivate)
tool.Handle.Touched:Connect(hit)
With the StandardMeleeWeapon
ModuleScript added, its structure is as follows, being highly similar to MeleeWeaponScript
before the inclusion of the ModuleScript:
local standardMeleeWeapon = {}
--Same variables here to control the melee weapon that requires this ModuleScript. Much less variables are initialised as the ModuleScript is not a relative with the required instances.
function standardMeleeWeapon:coolDown()
--Unaltered from initial MeleeWeaponScript that did not require a ModuleScript.
end
function standardMeleeWeapon:onEquip(TOOL)
tool = TOOL
--The variables are now initialised in here, using tool as the reference instance as it is a relative to the required instances.
end
function standardMeleeWeapon:onUnequip()
--Unaltered from initial MeleeWeaponScript that did not require a ModuleScript.
end
function standardMeleeWeapon:onCharge()
--Unaltered from initial MeleeWeaponScript that did not require a ModuleScript.
end
function standardMeleeWeapon:onRelease()
--Unaltered from initial MeleeWeaponScript that did not require a ModuleScript.
end
function standardMeleeWeapon:onActivate()
--Mostly unaltered, save for a print statement for debugging purposes.
print(player) --Prints the name of the current player who activated this sword.
end
function standardMeleeWeapon:hit(otherPart)
--Mostly unaltered, save for a print statement for debugging purposes.
--After checking if the otherPart is part of a character controlled by a player from another team or if the player using this sword is in a neutral team (against everyone else), this part runs.
print(tostring(player) .. " has hit " .. tostring(victimPlayer))
--A further part, same as that in the original MeleeWeaponScript, subjects the victimPlayer's character to a BodyVelocity to simulate knockback from the weapon upon being hit.
end
return standardMeleeWeapon
With the ModuleScript, MeleeWeaponScript
is now as follows:
local tool = script.Parent
local function init()
meleeWeaponModule = require(game:GetService("ServerScriptService").StandardMeleeWeapon)
meleeWeaponModule:onEquip(tool)
tool.Charge.OnServerEvent:Connect(meleeWeaponModule.onCharge)
tool.Release.OnServerEvent:Connect(meleeWeaponModule.onRelease)
tool.Unequipped:Connect(meleeWeaponModule.onUnequip)
tool.Activated:Connect(meleeWeaponModule.onActivate)
tool.Handle.Touched:Connect(function (otherPart)
meleeWeaponModule:hit(otherPart)
end)
end
tool.Equipped:Connect(init)
With this implementation, three problems now arise:
- When hitting an enemy character with the ModuleScript reliant sword while the enemy is also holding the ModuleScript reliant sword, the enemy is subject to the intended knockback. However, there is a significant chance that the attacking player is subject to a (unintended) great amount of knockback, flinging them several hundred studs away from the scene. The lines are printed upon the initial hit:
Attacker has hit Victim
Attacker has hit Attacker
-
Anytime a player character (say A in this case) equips the ModuleScript sword, all control everyone else has on their own ModuleScript sword is relinquished to player A. If anyone else tries to use the sword, A (instead of that someone else, as it should be) swings their sword. This ‘remote control’ seems to stop if the they unequip and re-equip their sword, with them now gaining control of their sword but everyone else, including A, losing control over their own ModuleScript sword.
-
If a player character uneqiups and re-equips again, activating the sword calls
print(player)
in the ModuleScript’sonActivate()
function multiple times in a single click with the weapon out. The exact number the player’s name getting printed being how many times the player character has equipped the weapon throughout their life. This number is reset to zero upon their death when the character gets a new copy of the sword from the StarterPack upon starting a new life.
Problems 1 and 2 only seem to happen if both the attacking player and victim player are holding the ModuleScript reliant sword. If either the attacking or victim player is wielding the non-ModuleScript sword or not wielding anything at all, problems 1 and 2 do not happen.
How should I go about solving all three problems? Is my idea of ModuleScripts to achieve such a purpose flawed?
Thank you very much for reading and possibly assisting me on the matter.