Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- math.randomseed(tick()) --set math.randomseed to tick
- local Battle = {FinishedAttacking = true}
- --dummy variables
- local CameraShaker = require(game:GetService('ReplicatedStorage').ModuleScripts.CameraShaker);
- local Difficulty;
- local OneMore = false
- local Player = game.Players.LocalPlayer;
- local PlayerGui = Player.PlayerGui;
- local Character = Player.Character or Player.CharacterAdded:Wait();
- local RichText = require(PlayerGui:WaitForChild('RichText'))
- --note: for attacks that hit everyone, do the effect on all targets and then damage
- --useful variables
- local ReplicatedStorage = game:GetService('ReplicatedStorage')
- local Music = game:GetService('ReplicatedStorage'):WaitForChild('Music');
- local Shouts = ReplicatedStorage:WaitForChild('Shouts')
- local Items = ReplicatedStorage:WaitForChild('ModuleScripts'):WaitForChild('Items');
- Items = require(Items);
- local Attacks = ReplicatedStorage:WaitForChild("ModuleScripts"):WaitForChild('Attacks')
- Attacks = require(Attacks)
- local Personas = ReplicatedStorage:WaitForChild("ModuleScripts"):WaitForChild('PersonaList')
- Personas = require(Personas)
- local EnemyAPI = require(ReplicatedStorage:WaitForChild("ModuleScripts"):WaitForChild'EnemyAPI')
- local Effects = require(ReplicatedStorage:WaitForChild'ModuleScripts':WaitForChild('Effects'))
- local UIS = game:GetService('UserInputService');
- local E = Enum;
- local CollectionService = game:GetService('CollectionService');
- local Shake = ReplicatedStorage:WaitForChild('ModuleScripts'):WaitForChild('Shake')
- Shake = require(Shake);
- function recalculateHipHeight(TargetModel)
- local bottomOfHumanoidRootPart = TargetModel.HumanoidRootPart.Position.Y - (1/2 * TargetModel.HumanoidRootPart.Size.Y)
- local bottomOfFoot = TargetModel.LeftFoot.Position.Y - (1/2 * TargetModel.LeftFoot.Size.Y) -- Left or right. Chose left arbitrarily
- local newHipHeight = bottomOfHumanoidRootPart - bottomOfFoot
- return newHipHeight
- end
- local K = E.KeyCode;
- impwarn = warn;
- impprint = print;
- local currentTween;
- if not _G.Dev then
- warn = function() end;
- print = function() end;
- --print = function() end;
- end
- function Battle:InvisibleParty()
- self.InvisiblePartyFlag = not self.InvisiblePartyFlag;
- if (self.InvisiblePartyFlag) then
- for i, v in pairs(self.PartyContainer:GetChildren()) do
- v.PrimaryPart.Anchored = true
- v:SetPrimaryPartCFrame(v:GetPrimaryPartCFrame() - Vector3.new(0,200, 0))
- end
- Character:SetPrimaryPartCFrame(Character:GetPrimaryPartCFrame() - Vector3.new(0, 200, 0))
- else
- for i, v in pairs(self.PartyContainer:GetChildren()) do
- v:SetPrimaryPartCFrame(v:GetPrimaryPartCFrame() + Vector3.new(0,200, 0))
- v.PrimaryPart.Anchored = false
- end
- Character:SetPrimaryPartCFrame(Character:GetPrimaryPartCFrame() + Vector3.new(0, 200, 0))
- end
- end
- function Battle:InvisibleEnemies()
- self.InvisibleEnemiesFlag = not self.InvisibleEnemiesFlag;
- if (self.InvisibleEnemiesFlag) then
- for i, v in pairs(self.EnemyContainer:GetChildren()) do
- v.PrimaryPart.Anchored = true
- v:SetPrimaryPartCFrame(v:GetPrimaryPartCFrame() - Vector3.new(0,200, 0))
- end
- else
- for i, v in pairs(self.EnemyContainer:GetChildren()) do
- v:SetPrimaryPartCFrame(v:GetPrimaryPartCFrame() + Vector3.new(0,200, 0))
- v.PrimaryPart.Anchored = false;
- end
- end
- end
- function Battle:EndBattleProtocol(NoHealth, NHealth, force)
- if force or (NoHealth == #self.Enemies or NHealth == #self.Characters) then
- CurrentCameraShake:StopSustained(1)
- spawn(function()
- wait(1)
- CurrentCameraShake:Stop()
- end)
- self:EndBattle();
- for i, v in pairs(Character.Humanoid:GetPlayingAnimationTracks()) do
- v:Stop(); --stop all playing animations, the default animator will replay animations again so it doesn't matter'
- end
- local PLighting = ReplicatedStorage:FindFirstChild('Previous Lighting');
- if (PLighting) then
- for i, v in pairs(PLighting:GetChildren()) do
- pcall(function()
- game:GetService('Lighting')[v.Name] = v.Value;
- end)
- end
- end
- self.BattleArea:Destroy();
- for i, v in pairs(game:GetService'Lighting':GetChildren()) do
- if (v.ClassName:match('Effect') and v.Name ~= 'e') then
- v.Enabled = true
- end
- end
- Character:SetPrimaryPartCFrame(self.PositionBeforeBattle)
- Character:WaitForChild('HumanoidRootPart').Anchored = false;
- pcall(StopAnimation, nil, Character:WaitForChild('Humanoid'))
- _G.Music:Resume();
- return true, script:Destroy(); --self destruct script just to be safe
- end
- end
- repeat wait() until _G.BattleAnnouncement;
- --stupid shit
- function GS(s)
- return game:GetService(s)
- end
- function playAnimOnModel(m, Anim, waittime)
- if (not m) then return nil end
- local m2 = m:Clone();
- m2.Parent = workspace;
- local CFThingToDisconnect = game:GetService('RunService').RenderStepped:Connect(function(Step)
- for i, v in pairs(m:GetChildren()) do
- if (not v:FindFirstChild('originalCFrame') and v:IsA('BasePart')) then
- local CF = Instance.new('CFrameValue', v)
- CF.Name = 'originalCFrame';
- CF.Value = v.CFrame;
- end
- for i,x in pairs(m2:GetChildren()) do
- if (v.Name == x.Name and v:IsA('BasePart')) then
- v.CFrame = x.CFrame;
- --
- end
- end
- end
- end)
- if (not Anim) then CFThingToDisconnect:Disconnect(); return nil end
- local anim = m2:WaitForChild('Humanoid'):LoadAnimation(Anim);
- anim:Play()
- --
- if (waittime) then
- wait(waittime)
- end
- --
- spawn(function(s)
- wait(anim.Length+0.25)
- CFThingToDisconnect:Disconnect();
- for i, v in pairs(m:GetChildren()) do
- if (v:FindFirstChild('originalCFrame')) then
- v.CFrame = v.originalCFrame.Value;
- --
- end
- end
- end)
- --
- --
- --
- m2:Destroy();
- return true;
- end
- function showMaskSteal()
- local ViewportFrame = PlayerGui:WaitForChild('MaskStealAnimation'):WaitForChild('ViewportFrame')
- local XYZ = ViewportFrame;
- for i = 1, 0, -0.25 do
- GS('RunService').RenderStepped:Wait()
- XYZ.ImageTransparency = i;
- end
- local MaskSteal = GS'ReplicatedStorage':WaitForChild('AnimationAssets'):WaitForChild('Mask Steal');
- local A1 = ViewportFrame:WaitForChild('maskSteal'):WaitForChild('person1');
- local B1 = ViewportFrame:WaitForChild('maskSteal'):WaitForChild('person2');
- playAnimOnModel(A1, MaskSteal.person1, nil)
- playAnimOnModel(B1, MaskSteal.person2, nil)
- --playAnimOnModel(animModel, Anim, waittime)
- spawn(function(xyz) --to prevent people from doing the stuffs
- wait(2.4)
- for i = 0, 1, 0.25 do
- GS('RunService').RenderStepped:Wait()
- XYZ.ImageTransparency = i;
- end
- end)
- spawn(function(xyztwo)
- wait(1.25)
- ReplicatedStorage.Music:WaitForChild('Glass Shattering'):Play();
- end)
- wait(2.1)
- --
- return true
- end
- BattleInfo = { --Independant turns for every character.
- EnemyTurns = {}; --one for the enemies
- PlayerTurns = {}; --one for the player. this allows for rakukaja to turn on/off not when it's Akira's turn
- EnemyActions = {};
- MemberActions = {};
- MemberAnimations = {};
- SelectedPersonaAttack = nil;
- BattleStage = 'Main'; --using general identifiers for battlestage
- SelectedMember = 0; --Default to 0 so we can know this is the start of the battle.
- }
- function Battle:GetFirstLivingEnemy()
- for i, v in pairs(self.Enemies) do
- if v.Health > 0 then
- return i, v;
- end
- end
- end
- function Battle:showOneMore()
- ReplicatedStorage.Music:WaitForChild('Explosion'):Play();
- PlayerGui.OneMore.Frame.BackgroundTransparency = 0;
- spawn(function(x)
- for i = 0, 1, 0.1 do
- wait();
- PlayerGui.OneMore.Frame.BackgroundTransparency = i;
- end
- end)
- PlayerGui.OneMore.ViewportFrame.ImageTransparency = 0;
- wait(1.15)
- for i = 0, 1, 0.1 do
- wait()
- PlayerGui.OneMore.ViewportFrame.ImageTransparency = i;
- end
- end
- function Battle:MoveCameraToCharacter(i, varia)
- if (currentTween) then currentTween:Cancel(); currentTween = nil; end
- varia = typeof(varia) == 'table' and varia or {};
- local pointTo = varia.PointTo
- local instant = varia.Instant or varia.instant;
- local yield = varia.Yield or varia.yield;
- local Char = self:GetCharacterFromID(i);
- local SpawnCFValue = Char.PrimaryPart.CFrame;
- local SpawnLookVector = SpawnCFValue.LookVector * 8.5;
- local ROT = CFrame.Angles(CFrame.new(SpawnLookVector + SpawnCFValue.Position, Char.PrimaryPart.Position):ToEulerAnglesXYZ());
- local RealCFValue = CFrame.new(SpawnLookVector)-- * ROT
- local CFValue = RealCFValue.Position + Char.PrimaryPart.CFrame.p
- if (pointTo) then
- CFValue = CFrame.new(CFValue) * CFrame.Angles(CFrame.new(CFValue, typeof(pointTo) == 'Instance' and pointTo.Position or pointTo):ToEulerAnglesXYZ())
- else
- CFValue = CFrame.new(CFValue) * ROT
- end
- currentTween = Tween(workspace.CurrentCamera, TweenInfo.new(instant and 0.1 or 0.25), {CFrame = CFValue})
- currentTween = currentTween:Play();
- local x = yield and wait(0.25);
- return true
- end
- --face camera towards players if not ambush, if ambush then just move the reticle --iiifat
- --add zeroes
- local function safetyZero(num, places)
- --
- --
- places = places or 2
- num = num or 1
- return ('0'):rep(#tostring(places)-#tostring(num))..tostring(num)
- end
- function Battle:GetEnemyFromID(i, returnChar)
- --iterate over all enemies in the enemies table
- for index, value in pairs(self.Enemies) do
- if (value.Health > 0 and index >= i) then --if the ID is invalid, then return the first available enemy
- if (returnChar) then
- return self.EnemyContainer:WaitForChild(tostring(index))
- else
- return index, value
- end
- end
- end
- end
- function Battle:MoveCameraToEnemy(i, yield, offset)
- --let's use getChildren for this, we'll switch to an ID-based system in case the game gets confused with their sorting for some reason
- local Char = self.EnemyContainer[tostring(i)]--:GetChildren()[i]
- local SpawnCFValue = Char.PrimaryPart.CFrame--self.EnemySpawns['Spawn'..i].CFrame;
- local SpawnLookVector = SpawnCFValue.LookVector * (8.5 * (Char.PrimaryPart.Size.Y / 1.459))
- local ROT = CFrame.Angles(CFrame.new(SpawnLookVector + SpawnCFValue.Position, Char.PrimaryPart.Position):ToEulerAnglesXYZ());
- local RealCFValue = CFrame.new(SpawnLookVector) * ROT
- local CFValue = RealCFValue + Char.PrimaryPart.CFrame.p;
- Tween(workspace.CurrentCamera, TweenInfo.new(0.25), {CFrame = CFValue}):Play();
- local x = yield and wait(0.25);
- return true;
- end
- DifficultyModifiers = { --difficulty modifiers to get rates of exchange
- Safety = {
- DamageRecieved=0.5;
- DamageDealt=2.0;
- Experience=3.0;
- Money=5.0;
- };
- Easy = {
- DamageRecieved=0.75;
- DamageDealt=1.5;
- Experience=1.5;
- Money=1.5;
- };
- Normal = {
- DamageRecieved=1.0;
- DamageDealt=1.0;
- Experience=1.0;
- Money=1.0;
- };
- Hard = {
- DamageRecieved=1.15;
- DamageDealt=0.9;
- Experience=1.0;
- Money=1.0;
- };
- Merciless={
- DamageRecieved=1.25;
- DamageDealt=0.8;
- Experience=0.77;
- Money=0.67;
- };
- Satanic = {
- DamageRecieved = 1.35;
- DamageDealt = 0.71;
- Experience = 0.765;
- Money = 0.625;
- }
- }
- --function to turn any table into a table ready for battle, can be used as many times as needed
- local Dropped;
- function Metatable(t)
- for i,v in pairs(t) do
- if (not v.MaxHealth) and (v.Attacks) then
- v.MaxHealth = v.Health;
- end
- if (not v.Persona) then
- v.ID = i;
- print('Name:', v.Name);
- for i,v in pairs(v) do
- if (i ~= 'Name') then
- if (typeof(v) == 'table') then
- for x, v in pairs(v) do
- print(i..'.'..x..':', v)
- end
- else
- print(i..':', v)
- end
- end
- end
- local Likings = require(game:GetService('ReplicatedStorage').ModuleScripts.Dialogue.PersonaLikings);
- v.Personality = Likings[math.random(1, #Likings)].Type
- local ShouldDropItem = math.random() < (math.random(1, math.random(100)))/100
- if (not Dropped and ShouldDropItem) then
- local ViableItemsList = {};
- for i, v in pairs(Items) do
- if ( (v.HP or v.SP) and v.Price and v.NoBattle) then
- ViableItemsList[#ViableItemsList+1] = i;
- end
- end
- local SelectedItem = ViableItemsList[math.random(1, #ViableItemsList)];
- v.BoundItem = SelectedItem;
- end
- end
- local mt = setmetatable(v, {});
- mt.__index = v;
- function v:GetHealth()
- return self.Health;
- end
- function v:SubtractHealth(amt)
- if (typeof(amt) == 'string') then
- if (amt:lower() == 'all') then amt = self.MaxHealth end;
- if (amt:lower() == 'half') then amt = self.Health/2 end;
- end
- self.Health = math.floor(math.clamp(self.Health - amt, 0, math.huge));
- return self.Health;
- end
- function v:Heal(amt, dismiss)
- --impwarn("amount:", amt)
- amt = amt or 0;
- amt = tostring(amt):lower() == 'half' and self.MaxHealth/2 or amt;
- amt = tostring(amt):lower() == 'max' and math.huge or 100;
- self.Health = math.ceil(math.clamp(self.Health + amt, 0, self.MaxHealth));
- if (not dismiss) then
- if (amt < self.MaxHealth*0.356789) then
- local Audio = ReplicatedStorage:WaitForChild('SFX'):WaitForChild('LowHeal');
- Audio = Audio:Clone();
- Audio.Parent = PlayerGui;
- Audio.PlayOnRemove = true;
- Audio:Destroy();
- else
- local Audio = ReplicatedStorage:WaitForChild('SFX'):WaitForChild('LowHeal');
- Audio = Audio:Clone();
- Audio.Parent = PlayerGui;
- Audio.PlayOnRemove = true;
- Audio:Destroy();
- end;
- end
- return self.Health;
- end
- function v:BuffDamage(amt)
- self.AddedAttack = self.AddedAttack+amt;
- return self.AddedAttack;
- end
- function v:AddDebuff(table)
- print('Added debuff:', table.Name or #self.Debuffs+1);
- table.Length = table.Length+1;
- self.Debuffs = self.Debuffs or {};
- self.Debuffs[table.Name or #self.Debuffs+1] = table
- end
- function v:BuffDefense(amt)
- self.AddedDefense = self.AddedDefense+amt;
- return self.AddedDefense;
- end
- function v:SubtractAmmo()
- local EquippedGun = Items[self.Equipped.Gun];
- if (self.Ammo == -1) then self.Ammo = EquippedGun.Ammo-1; return self.Ammo; end;
- self.Ammo = self.Ammo - 1;
- return self.Ammo;
- end
- function v:GetAmmo()
- local EquippedGun = Items[self.Equipped.Gun];
- if (self.Ammo == -1) then self.Ammo = EquippedGun.Ammo end;
- return self.Ammo;
- end
- function v:SubtractSP(amt)
- self.SP = self.SP and math.clamp(self.SP-amt, 0, self.MaxSP or 100) or 0
- end
- function v:AddSP(amt)
- self.SP = self.SP and math.clamp(self.SP+amt, 0, self.MaxSP or 100) or 0
- end
- function v:concatKey(sep)
- local str = '';
- for i, v in pairs(self) do
- str = str..string.format('%s - %s%s\n', tostring(i), tostring(v), sep or ', ')
- end
- return str
- end
- end
- end
- --functions for animations
- --function to get enemies from strings
- function getPersonaFromString(s, r)
- local n = Personas[s];
- local newTable = {};
- --two layer-deep unpack monkaW
- for i, v in pairs(n) do
- if (typeof(v) == 'table') then
- newTable[i] = {};
- for z,v in pairs(v) do
- newTable[i][z] = v;
- end
- else
- newTable[i] = v;
- end
- end
- return newTable;
- end
- --useless but useful get attacks function
- function getAttack(n)
- return Attacks[n]
- end
- --modify damage function to calculate HP costs based on max health
- function modifyDamage(n,mx)
- return math.ceil(mx - (((100-n)/100)*mx))
- end
- function Battle:getCharacterOnRight(iv, include_dead)
- for i, v in pairs(Battle.Characters) do
- if (i > iv)
- and ((include_dead and v.Health > 0) or not include_dead) then
- return i
- end
- end
- return iv
- end
- function Battle:getCharacterOnLeft(iv, include_dead)
- for i, v in pairs(Battle.Characters) do
- if (i < iv) and ((include_dead and v.Health > 0) or not include_dead) then
- return i
- end
- end
- return iv
- end
- function Battle:GetEnemy(mode, iv)
- mode = mode:lower()
- for i, v in pairs(self.Enemies) do
- local compL = i < iv --I sincerely have no idea why this happens.
- local compR = i > iv;
- local comp;
- if (mode == 'l') then
- for i = iv, 0, -1 do
- if (not self.Enemies[i]) then
- return iv; --if there is no enemy before one
- elseif --[[(not checkIncapacitated(self.Enemies[i])) and]] i ~= iv and self.Enemies[i].Health > 0 then
- return i
- end
- end
- elseif (mode == 'r') then
- comp = compR;
- end
- if (comp) and v.Health > 0 then
- return i;
- end
- end
- return iv;
- end
- function Battle:GetCharacter(mode, iv, include_dead)
- mode = mode:lower()
- for i, v in pairs(self.Characters) do
- local compL = i > iv;
- local compR = i < iv;
- local comp;
- if (mode == 'l') then
- comp = compL;
- elseif (mode == 'r') then
- comp = compR;
- end
- if (not include_dead and v.Health > 0) or include_dead then
- if (comp) then
- return i;
- end
- end
- end
- return iv;
- end
- --animation functon for humanoid objects
- function LoadAnimation(AnimationObject, Target)
- if (BattleInfo.MemberAnimations[Target]) then --if the humanoid was already used as a target
- if (BattleInfo.MemberAnimations[Target][tostring(AnimationObject.AnimationId)]) then --check if the humanoid already loaded the animation object
- return BattleInfo.MemberAnimations[Target][tostring(AnimationObject.AnimationId)] --return the animation track if so
- else --otherwise
- BattleInfo.MemberAnimations[Target][tostring(AnimationObject.AnimationId)] = Target:LoadAnimation(AnimationObject) --make animationobject point to the animationtrack
- return BattleInfo.MemberAnimations[Target][tostring(AnimationObject.AnimationId)] --return the animation track
- end
- else --if the humanoid is fresh
- BattleInfo.MemberAnimations[Target] = {}; --set the humanoid to point to an animation storage table
- BattleInfo.MemberAnimations[Target][tostring(AnimationObject.AnimationId)] = Target:LoadAnimation(AnimationObject) --save animation to table
- return BattleInfo.MemberAnimations[Target][tostring(AnimationObject.AnimationId)] --return animation
- end
- end
- function Battle:LoadAnimation(...)
- return LoadAnimation(...)
- end
- function StopAnimation(Animation, Target)
- -- MemberAnimations -> [Table (Humanoid Object/Target)] -> AnimationObject Name == AnimationTrack
- --MemberAnimations -> Table -> Animation Object -> Animation Track
- Animation = typeof(Animation) == "string" and {Name = Animation} or Animation;
- for i, v in pairs(Target:GetPlayingAnimationTracks()) do
- if (v.Name == Animation.Name) then
- v:Stop();
- end
- end
- return warn('Couldn\'t find animation', Animation.Name)
- end
- function animationStatus(Animation, Humanoid)
- for i, v in pairs(Humanoid:GetPlayingAnimationTracks()) do
- if (v.Name:lower() == Animation.Name:lower()) then
- --impwarn('Found animation track.')
- return v;
- end
- end
- return false
- end
- --personaify function to make text randomly black or white with random rotation
- function personaIfy(text)
- local MAX = 3;
- local str='';
- local NONCOUNT = 1;
- local LastPersonaIfied = false;
- for i = 0, #text do
- if (math.random() < 0.5 and MAX ~= 0 and LastPersonaIfied ~= true and NONCOUNT >= 2) then
- NONCOUNT = 0;
- MAX=MAX-1
- LastPersonaIfied = true;
- str = str..'<TextColor3=Black><Rotation='..math.random(-5, 5)..'><BackgroundTransparency=0>'..text:sub(i,i)..'<TextColor3=White><BackgroundTransparency=1><Rotation=0>'
- else
- NONCOUNT = NONCOUNT+1;
- LastPersonaIfied = false;
- str = str..text:sub(i,i)
- end
- end
- return str
- end
- local StageDirections = { --utilize stage directions in order to make going forward and backwards easier
- Main = {}; --we don't include main because that could lead to any direction. the main screen will look messy at the start
- PersonaAttackList = {Back = 'Main', Next = 'PersonaTarget'};
- Shoot = {Back = 'Main'};
- Item = {Back = 'Main', Next = 'ItemSelect'};
- PersonaChange = {Back = 'PersonaAttackList'}
- }
- --get character from number ID
- function Battle:GetCharacterFromID(id)
- if (id == 1) then return Character end;
- if (typeof(id) == 'table') then
- for i, v in pairs(self.Characters) do
- if (v == id) then
- if (v.Name == self.Characters[1].Name) then
- return Character, i;
- else
- return self.PartyContainer:WaitForChild(v.Name), i
- end
- end
- end
- elseif (typeof(id) == 'string') then
- for i, v in pairs(self.Characters) do
- if (v.Name == id) then
- return (i == 1 and Character or self.PartyContainer:WaitForChild(v.Name)), i
- end
- end
- end
- if (self.Characters and self.Characters[id]) then --if the id is valid
- return workspace:WaitForChild('Party Container'):WaitForChild(self.Characters[id].Name)
- end
- return 0;
- end
- function Battle:GetEnemyFromName(id)
- if (self.Enemies and self.Enemies[id]) then
- if (typeof(id) == 'number') then
- return workspace:WaitForChild('Enemy Container'):WaitForChild(id)
- elseif (typeof(id) == 'string') then
- for i, v in pairs(workspace:WaitForChild('Enemy Container'):GetChildren()) do
- if (v:WaitForChild('PersonaName').Value:lower() == id:lower()) then --bad idea because duplicates will be there
- return v;
- end
- end
- end
- end
- end
- --persona create function
- function RemoveAllPersonas(Transition)
- CurrentPersonaThing = nil;
- for i, v in pairs(CollectionService:GetTagged('PersonaObject')) do
- local x = v;
- if (Transition) then
- for i, v in pairs(v:GetDescendants()) do
- spawn(function()
- if v:IsA('BasePart') or v:IsA('Decal') then
- for i = v.Transparency, 1, 0.1 do
- wait();
- v.Transparency = i;
- end
- end
- x:Destroy()
- end)
- end
- else
- v:Destroy()
- end
- print'Persona Removed.'
- end
- end
- function Battle:createPersona(rf, summonall, t)
- if (not summonall) then
- RemoveAllPersonas();
- end
- if (not self.Ambush) then
- self:CharacterPositionButWithPersona(nil, nil, rf);
- end
- CurrentPersonaThing = nil;
- local Sona = game:GetService('ReplicatedStorage'):WaitForChild('Personas'):WaitForChild(self.Characters[t or BattleInfo.SelectedMember].Persona.Name):Clone()
- local n = self.Characters[t or BattleInfo.SelectedMember].Persona.CustomSize or {};
- local H = Sona:WaitForChild('Humanoid');
- H.BodyDepthScale.Value = (n.Depth or 2);
- H.BodyHeightScale.Value = (n.Height or 2);
- H.BodyProportionScale.Value = (n.Proportions or 1);
- H.BodyTypeScale.Value = (n.Type or 1.75);
- H.BodyWidthScale.Value = (n.Width or 2);
- H.HeadScale.Value = (n.Head or 2);
- local bodyColors = Sona:WaitForChild('Body Colors')
- local bodyColor = Color3.fromRGB(4, 175, 236)
- --2,2, 1, 1.75, 2, 2
- do --BodyProperties
- bodyColors.HeadColor3 = bodyColor
- bodyColors.LeftArmColor3 = bodyColor
- bodyColors.LeftLegColor3 = bodyColor
- bodyColors.RightArmColor3 = bodyColor
- bodyColors.RightLegColor3 = bodyColor
- bodyColors.TorsoColor3 = bodyColor
- end
- local pl = Instance.new('PointLight')
- pl.Brightness = math.abs(math.sin(tick())*10)
- pl.Range = math.abs(math.sin(tick())*16)
- for i, v in pairs(Sona:GetDescendants()) do
- if v:IsA('BasePart') then
- v.Transparency = 0.7;
- if (not v:FindFirstAncestorWhichIsA('Accessory') and not v:FindFirstAncestorWhichIsA('Hat')) then
- v.Material = Enum.Material.ForceField
- end
- end
- if (v.Name == 'HumanoidRootPart') then--
- v.Transparency = 1;
- pl.Parent = v;
- end
- end
- CollectionService:AddTag(Sona, "PersonaObject");
- Sona.Name = "Persona";
- if ((t or BattleInfo.SelectedMember) == 1) then
- Sona.Parent = workspace;--game.Players.LocalPlayer.Character;
- Sona:WaitForChild('HumanoidRootPart').Anchored = true;
- while Sona.Parent and not Sona.Parent:IsA('Folder') do
- if (Sona.Parent:IsA('Folder')) then break end;
- pl.Brightness = math.abs(math.sin(tick())*10)
- pl.Range = math.abs(math.sin(tick())*16)
- wait()
- if (not CurrentPersonaThing) and Sona:FindFirstChild('Humanoid') then
- LoadAnimation(game:GetService('ReplicatedStorage').AnimationAssets['Hover Animation']:WaitForChild('HoverAnimation'), Sona.Humanoid):Play()
- end
- local T = Sona.PrimaryPart or Sona:FindFirstChild('HumanoidRootPart') or Sona:FindFirstChild('Torso');
- if (not Sona.Parent) then break end;
- if (Sona.PrimaryPart) then
- Sona:SetPrimaryPartCFrame(CFrame.new((game.Players.LocalPlayer.Character.UpperTorso.CFrame.lookVector * -3.5) + game.Players.LocalPlayer.Character.UpperTorso.CFrame.p + Vector3.new(0, math.sin(tick()), 0)) * CFrame.Angles(self.PartySpawns:WaitForChild('Spawn'..(t or BattleInfo.SelectedMember)).CFrame:toEulerAnglesXYZ()) + Vector3.new(0, 5, 0))
- end
- if (summonall) then
- return Sona;
- end
- end
- else
- Sona.Parent = workspace;--workspace:WaitForChild('Party Container'):WaitForChild(self.Characters[t or BattleInfo.SelectedMember].Name);
- local xyz = workspace:WaitForChild('Party Container'):WaitForChild(self.Characters[t or BattleInfo.SelectedMember].Name)
- Sona:WaitForChild('HumanoidRootPart').Anchored = true;
- while Sona.Parent and not Sona.Parent:IsA('Folder') do
- pl.Brightness = math.abs(math.sin(tick())*10)
- pl.Range = math.abs(math.sin(tick())*16)
- if (Sona.Parent:IsA('Folder') or Sona.Parent == nil) then break end;
- wait()
- if (not CurrentPersonaThing) and (Sona:FindFirstChild('Humanoid')) then
- --
- --CurrentPersonaThing:Play(game:GetService('ReplicatedStorage').AnimationAssets['Hover Animation']:WaitForChild('HoverAnimation'));
- LoadAnimation(game:GetService('ReplicatedStorage').AnimationAssets['Hover Animation']:WaitForChild('HoverAnimation'), Sona.Humanoid):Play()
- end
- local T = Sona.PrimaryPart or Sona:FindFirstChild('HumanoidRootPart') or Sona:FindFirstChild('Torso');
- local Torso = xyz.PrimaryPart;
- if (Sona.PrimaryPart) then
- Sona:SetPrimaryPartCFrame(CFrame.new((xyz.UpperTorso.CFrame.lookVector * -7) + xyz.UpperTorso.CFrame.p + Vector3.new(0, math.sin(tick()), 0)) * CFrame.Angles(self.PartySpawns:WaitForChild('Spawn'..(t or BattleInfo.SelectedMember)).CFrame:toEulerAnglesXYZ()) + Vector3.new(0, 5, 0));
- elseif (T) then
- T.CFrame = (CFrame.new((Torso.CFrame.lookVector * -7) + Torso.CFrame.p) * CFrame.Angles(Torso.CFrame:toEulerAnglesXYZ()) + Vector3.new(0, math.sin(tick()), 0) + Vector3.new(0, 5, 0))
- end
- if (summonall) then
- return Sona;
- end
- end
- end
- end
- --global tween function
- function Tween(obj, ti, goalTable)
- if (not obj) then error('invalid object'); end;
- if (not ti) then error('invalid tween info'); end;
- if (not goalTable) then error('invalid goal table'); end;
- local TS = game:GetService('TweenService');
- return game:GetService('TweenService'):Create(obj, ti, goalTable);
- end
- --camera functions
- function Battle:CharacterPositionButWithPersona(t, lookAt, inst, ofst, vertoffset)
- --impwarn('Started new thread!')
- --impwarn('B1')
- lookAt = typeof(lookAt) == 'CFrame' and {CFrame = lookAt} or (typeof(lookAt) == 'Instance' and {CFrame = lookAt.CFrame})
- if (currentTween) then currentTween:Cancel(); currentTween = nil; end;
- local C = Battle.Characters[t or BattleInfo.SelectedMember];
- local OBJ = nil;
- --impwarn('B2')
- if ((t or BattleInfo.SelectedMember) <=1) then
- OBJ = game.Players.LocalPlayer.Character;
- else
- OBJ = workspace:WaitForChild('Party Container'):WaitForChild(C.Name)
- end
- --impwarn('B3')
- local OBJ2 = OBJ.PrimaryPart or self.BattleArea:WaitForChild(self.Ambush and 'Ambush Spawns' or 'Spawns')['Party Spawns']:WaitForChild('Spawn'..(t or BattleInfo.SelectedMember))
- --impwarn(OBJ2)
- local Equation = CFrame.new(OBJ2.CFrame.lookVector * -(ofst or 20) + --[[workspace.CurrentCamera.CFrame]]OBJ2.CFrame.RightVector*9) * CFrame.Angles(OBJ2.CFrame:toEulerAnglesXYZ()) + OBJ2.Position + Vector3.new(0,10,0);
- --impwarn('B5')
- local X,Y,Z = CFrame.new(Equation.Position + (not lookAt and OBJ2.CFrame.RightVector*-6.5 or Vector3.new(0,0,0)), OBJ2.Position + Vector3.new(0, (vertoffset or 7.5), 0)):ToEulerAnglesXYZ();
- Equation = CFrame.new(Equation.Position) * (
- not lookAt and CFrame.Angles(X,Y,Z) or
- CFrame.Angles(
- CFrame.new(workspace.CurrentCamera.CFrame.Position, lookAt.CFrame.Position):ToEulerAnglesXYZ())
- )
- --impwarn('B6')
- currentTween = Tween(workspace.CurrentCamera, TweenInfo.new(not lookAt and not inst and 1 or 0, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, false, 0), {CFrame = Equation})
- currentTween:Play(); --* CFrame.Angles(workspace.CurrentCamera.CFrame:ToEulerAnglesXYZ());
- --impwarn('B7')
- wait()
- end
- function Battle:CharacterPosition(player, inverse, start)
- if (currentTween) then currentTween:Cancel(); currentTween = nil; end
- player = player or BattleInfo.SelectedMember
- local C = self.Characters[player];
- local Keyword = self.BattleArea:WaitForChild(self.Ambush and 'Ambush Spawns' or 'Spawns')
- local OBJ = nil;
- if (player <=1) then
- OBJ = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait();
- else
- OBJ = workspace:WaitForChild('Party Container'):WaitForChild(C.Name)
- end
- OBJ = OBJ.PrimaryPart;
- local c = inverse and Keyword['Enemy Spawns']:WaitForChild('Spawn1') or OBJ
- local mp = (not inverse) and -9 or 6.25
- local RightVector = (not inverse) and 11.25 or 0;
- if (not start) then
- local CF = CFrame.new((OBJ.CFrame.lookVector * mp) + OBJ.CFrame.rightVector*RightVector)+ OBJ.Position + Vector3.new(0,OBJ.Parent.Humanoid.HipHeight+0.24,0)
- currentTween = Tween(
- workspace.CurrentCamera,
- TweenInfo.new(0.2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, false, 0),
- {
- CFrame = CF *
- CFrame.Angles(CFrame.new(CF.Position, OBJ.Position):ToEulerAnglesXYZ())
- }
- )
- currentTween:Play();
- else
- local CF = CFrame.new((OBJ.CFrame.lookVector * mp) + OBJ.CFrame.rightVector*RightVector)+ OBJ.Position + Vector3.new(0,OBJ.Parent.Humanoid.HipHeight+0.24,0)
- workspace.CurrentCamera.CFrame = CF *
- CFrame.Angles(CFrame.new(CF.Position, OBJ.Position):ToEulerAnglesXYZ())
- end
- end
- function Battle:CharacterAttacked(player)
- player = player or BattleInfo.SelectedMember
- local C = self.Characters[player];
- local Keyword = self.BattleArea:WaitForChild(self.Ambush and 'Ambush Spawns' or 'Spawns')
- local OBJ = nil;
- if (player <=1) then
- OBJ = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait();
- else
- OBJ = workspace:WaitForChild('Party Container'):WaitForChild(C.Name)
- end
- local Increase = 8.5
- OBJ = OBJ.PrimaryPart--Keyword['Party Spawns']:WaitForChild('Spawn'..(player))
- local c = OBJ
- local mp = 7
- workspace.CurrentCamera.CFrame = CFrame.new(OBJ.CFrame.lookVector*-mp + OBJ.CFrame.rightVector*2.5) * CFrame.Angles(c.CFrame:toEulerAnglesXYZ()) + OBJ.Position --+ Vector3.new(0,Increase, 0)
- local Formula = workspace.CurrentCamera.CFrame.LookVector * -10 + workspace.CurrentCamera.CFrame.Position;
- Tween(workspace.CurrentCamera, TweenInfo.new(5, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {
- CFrame = CFrame.new(Formula) * CFrame.Angles(CFrame.new(Formula, OBJ.Position):ToEulerAnglesXYZ())
- }):Play();
- wait(1.15)
- end
- function Battle:PartyAttacked()
- local Root = Player.Character.PrimaryPart
- local Keyword = self.BattleArea:WaitForChild(self.Ambush and 'Ambush Spawns' or 'Spawns')
- Keyword = Keyword["Party Spawns"];
- local SpawnOne = Keyword:GetChildren()[1];
- local SpawnTwo = Keyword:GetChildren()[#Keyword:GetChildren()];
- local mp = 11
- local Half = SpawnOne.CFrame:Lerp(SpawnTwo.CFrame, .5)
- Half = {CFrame = Half, Position = Half.Position}
- print(typeof(Half))
- workspace.CurrentCamera.CFrame =
- (CFrame.new(
- Half.CFrame.LookVector*-mp
- +
- Half.CFrame.rightVector*
- 2.5
- ) + Vector3.new(0, Root.Parent.Humanoid.HipHeight + 4.5, 0)) *
- CFrame.Angles(
- Half.CFrame:toEulerAnglesXYZ()
- ) +
- Half.Position --+ Vector3.new(0,Increase, 0)
- local Formula = workspace.CurrentCamera.CFrame.LookVector * -10 + workspace.CurrentCamera.CFrame.Position;
- Tween(workspace.CurrentCamera, TweenInfo.new(5, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {
- CFrame = CFrame.new(Formula) * CFrame.Angles(CFrame.new(Formula, Half.Position):ToEulerAnglesXYZ())
- }):Play();
- end
- function isCloserToPosition(p, op, modulofactor, clamp)
- p = p.CFrame;
- local p1 = math.abs(((-p.RightVector + p.Position) - op.Position).Magnitude);
- local p2 = math.abs(((p.RightVector + p.Position) - op.Position).Magnitude);
- if (math.floor(p1) > math.floor(p2)) then --if the other part is closer to the right side
- return 'Right', math.clamp(p2/(modulofactor or 1), -clamp, clamp);
- else --if the other part is closer to the left side
- return 'Left', math.clamp(p1/(modulofactor or 1), -clamp, clamp);
- end
- end
- function Battle:CharacterAttacking(player, target, crit, mhit)
- player = player or BattleInfo.SelectedMember
- local C = self.Characters[player];
- local Keyword = self.BattleArea:WaitForChild(self.Ambush and 'Ambush Spawns' or 'Spawns')
- local OBJ = nil;
- if (player <=1) then
- OBJ = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait();
- else
- OBJ = workspace:WaitForChild('Party Container'):WaitForChild(C.Name)
- end
- local Increase = 8.5
- OBJ = OBJ.PrimaryPart--Keyword['Party Spawns']:WaitForChild('Spawn'..(player))
- local ClosestTo, shiftFactor = isCloserToPosition(OBJ, target, 10, 2)
- if (mhit) then
- local Keyword = Keyword['Enemy Spawns']
- local CF = Keyword:GetChildren()[1].CFrame:Lerp(Keyword:GetChildren()[#Keyword:GetChildren()].CFrame, 0.5)
- target = {CFrame = CF, Position = CF.Position}
- end
- local c = OBJ
- local mp = 5--(ClosestTo == 'Right' and 1 or 5)
- local RV = (ClosestTo == 'Right' and -shiftFactor-5 or 5+shiftFactor)--move closer to the left if the attacked person is too far to the right
- workspace.CurrentCamera.CFrame = CFrame.new(Vector3.new(0,6.5,0)+OBJ.CFrame.lookVector*-mp + OBJ.CFrame.rightVector*(crit and 0 or RV)) * CFrame.Angles(CFrame.new(c.CFrame--[[:toEulerAnglesXYZ()]].Position, target.CFrame.Position):ToEulerAnglesXYZ()) + OBJ.Position --+ Vector3.new(0,Increase, 0)
- wait();
- local Formula = workspace.CurrentCamera.CFrame.LookVector * -(crit and -5 or 5) + workspace.CurrentCamera.CFrame.Position;
- Tween(workspace.CurrentCamera, TweenInfo.new(2, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut), {
- CFrame = CFrame.new(Formula) * CFrame.Angles(CFrame.new(Formula, target.CFrame.Position):ToEulerAnglesXYZ())
- }):Play();
- wait(1.25)
- end
- --functions for battle
- function getNextStage()
- for i, v in pairs(StageDirections) do
- if (i == BattleInfo.BattleStage) then
- return v.Next;
- end
- end
- return nil;
- end
- function getPreviousStage()
- for i, v in pairs(StageDirections) do
- if (i == BattleInfo.BattleStage) then
- return v.Next;
- end
- end
- return nil;
- end
- w = warn;
- function Battle:selectViableMember(RefillMembers)
- if (self.BattleFinished) then return 1 end;
- if (not self.AvailableUsers) then
- self.AvailableUsers = {};
- end
- local AvailableUsers = self.AvailableUsers;
- if (not BattleInfo.TotalTurn) then
- BattleInfo.TotalTurn = 0;
- end
- print('Baton Count:', self.BatonCount or 0);
- if (self.BatonPass) then
- self.BatonCount = self.BatonCount + 1;
- if (self.BatonCount == 1) then
- showLabel('Attack and Recovery increased!')
- elseif (self.BatonCount == 2) then
- showLabel('Attack and Recovery greatly increased!')
- elseif (self.BatonCount == 3) then
- showLabel('Attack and Recovery massively increased!')
- elseif (self.BatonCount == 4) then
- showLabel('Attack and Recovery tremendously increased!')
- end
- local OBT = self.BatonPass;
- self.BatonPass = nil;
- return OBT
- end
- if (self.OneMore) then
- Battle:showOneMore()
- return BattleInfo.SelectedMember;
- end
- for i, v in pairs(self.Characters) do
- v.BatonPassed = false;
- end
- self.BatonCount = 0;
- --use X prefix to describe enemies
- --Add all ids to one table so we can determine their agility for turn order
- if (not self.Ambush) then
- if (BattleInfo.TotalTurn == 0) then
- spawn(function()
- local RandomAppraisals = {"Awesome, Joker! We have the first strike! Make it good!", "Alright Joker, we have the upper hand! Don't mess it up!", "Alright team, you know what to do!", "Slay them all!", "Cut down their family tree!"}
- if (self.Boss) then
- RandomAppraisals = {'Alright team, stay calm! I know this one\'s strong, but think your actions through!'}
- end;
- local WeakAppraisals = {}
- local lv = 0;
- for i, v in pairs(self.Enemies) do
- lv = lv + (v.Level or 0);
- end
- lv = (lv/#self.Enemies) --get average of enemies
- local clv = 0;
- for i, v in pairs(self.Characters) do
- clv = clv + (v.Level or 0);
- end
- clv = (clv/#self.Characters);
- if (clv - lv > 5) then
- for i, v in pairs(not self.Boss and WeakAppraisals or {}) do
- RandomAppraisals[#RandomAppraisals+1] = v;
- end
- elseif (clv - lv < -5) then
- RandomAppraisals = not self.Boss and {
- string.format("Joker, be cautious! %s very strong!", #self.Enemies > 1 and "These guys are" or "This guy is");
- string.format("Joker, be careful! %s tough..", #self.Enemies > 1 and "These ones're" or "This one's");
- string.format("Joker, be careful! We may have the upper hand, but %s tough!", #self.Enemies > 1 and "These ones're" or "This one's");
- string.format("Be cautious, everyone! %s tough!", #self.Enemies > 1 and "These ones're" or "This one's")
- } or RandomAppraisals;
- end
- _G.BattleAnnouncement(RandomAppraisals[math.random(1, #RandomAppraisals)], ReplicatedStorage:WaitForChild('Party Members'):WaitForChild('Yuki'))
- end)
- -- for i, v in pairs(self.Characters) do
- --
- -- AvailableUsers[#AvailableUsers+1] = {i, 7000-(math.random(1, 500))}
- -- end
- end
- elseif (BattleInfo.TotalTurn == 0) then
- for i, v in pairs(self.Enemies) do
- AvailableUsers[#AvailableUsers+1] = {"X"..v.ID, 7000-(math.random(1, 500))}
- end
- end
- if (RefillMembers) then
- self.knockedChar = false;
- --impwarn("Refilling...")
- BattleInfo.EnemyActions = {};
- BattleInfo.MemberActions = {};
- for i, v in pairs(self.Characters) do --character personas dont have an agility stat yet SIKE THEY DO NOW
- BattleInfo.PlayerTurns[i] = BattleInfo.PlayerTurns[i] or 1
- local Incapacitated = checkIncapacitated(v, nil, BattleInfo.PlayerTurns[i] or 1);
- if (not BattleInfo.MemberActions[i]) --[[and (not checkIncapacitated(v, nil, BattleInfo.PlayerTurns[i]))]] then
- AvailableUsers[#AvailableUsers+1] = {i, v.Persona.Stats.Agility};
- elseif Incapacitated then
- impprint('Player was incapacitated. Skipping turn and adding one.')
- BattleInfo.PlayerTurns[i] = BattleInfo.PlayerTurns[i] and (BattleInfo.PlayerTurns[i]+1)or 1
- end
- end
- for i, v in pairs(self.Enemies) do
- if (v.TurnCount) then
- v.CTC = v.CTC or 1;
- end
- BattleInfo.EnemyTurns[v.ID] = BattleInfo.EnemyTurns[v.ID] or 1
- local Incapacitated = checkIncapacitated(v, nil, BattleInfo.EnemyTurns[v.ID] or 1);
- if (not BattleInfo.EnemyActions[i]) and (not Incapacitated) then
- if (v.TurnCount and v.CTC <= v.TurnCount) then
- for i = 0, v.TurnCount do
- --NO WONDER IT DIDNT WORK, IT ONLY DID IT FOR TURN COUNTS ONLY WHAT
- AvailableUsers[#AvailableUsers+1] = {'X'..v.ID, (v.EnemyStats or v.Stats).Agility};
- end
- elseif (not v.TurnCount) and (not BattleInfo.EnemyActions[v.ID]) and (not Incapacitated) then
- AvailableUsers[#AvailableUsers+1] = {'X'..v.ID, (v.EnemyStats or v.Stats).Agility};
- end
- elseif Incapacitated then
- impprint('Enemy was incapacitated. Skipping turn and adding one.', "Name:", v.Name, "ID", v.ID or 0)
- local oa = BattleInfo.EnemyTurns[i] or 1;
- BattleInfo.EnemyTurns[i] = BattleInfo.EnemyTurns[i] and (BattleInfo.EnemyTurns[i]+1) or 1
- impwarn('Previously:', oa, 'Now:', BattleInfo.EnemyTurns[i])
- end
- end
- end
- --sort the table based on their agility. convert all strings to numbers and then place in the table if the string's numbers are valid
- for i, v in pairs(AvailableUsers) do
- impprint('Before Turn Order:', table.concat(v, ', '))
- end
- table.sort(AvailableUsers, function(a, b)
- local newA = a[2];
- local newB = b[2];
- return newA > newB
- end)
- for i, v in pairs(AvailableUsers) do
- impprint('After Turn Order:', table.concat(v, ', '))
- end
- local CharacterCount = 0;
- local y = tostring(AvailableUsers[1][1]);
- --hehe
- BattleInfo.TotalTurn = BattleInfo.TotalTurn + 1;
- for i, v in pairs(self.Enemies) do
- v.Debuffs = v.Debuffs or {};
- local Enemy = v;
- for i, v in pairs(v.Debuffs) do
- if (v.TurnAdded and v.TurnAdded + v.Length < (BattleInfo.EnemyTurns[Enemy.ID] or 0)) then
- Battle:MoveCameraToEnemy(Enemy.ID)
- if (v.Name ~= 'Down') then
- showLabel(v.Name..'has worn off!', 2.5)
- else
- Battle.HoldUpped = false;
- end
- v.Debuffs[i] = nil;
- else
- impwarn("");
- impwarn("Debuff Data:");
- impwarn("Receiver Name:", Enemy.Name, "Debuff Name:", v.Name, "::", "TurnAdded:", v.TurnAdded, "Length:", v.Length, "Finishing Turn:", v.TurnAdded + v.Length, "Current Turn:", BattleInfo.TotalTurn, "\n")
- end
- end
- end
- for i, v in pairs(self.Characters) do
- v.Debuffs = v.Debuffs or {};
- local Character = v;
- for i, v in pairs(v.Debuffs) do
- if (v.TurnAdded and v.TurnAdded + v.Length < (BattleInfo.PlayerTurns[i] or 0)) then
- Battle:MoveCameraToCharacter(i)
- if (v.Name ~= 'Down') then
- showLabel(v.Name..'has worn off!', 2.5)
- end
- v.Debuffs[i] = nil;
- else
- impwarn("");
- impwarn("Debuff Data (Player):")
- impwarn("Receiver Name:", Character.Name, "Debuff Name:", v.Name, "::", "TurnAdded:", v.TurnAdded, "Length:", v.Length, "Finishing Turn:", v.TurnAdded + v.Length, "Current Turn:", BattleInfo.TotalTurn, "\n")
- end
- end
- end
- if (tostring(AvailableUsers[1][1]):match('X')) then
- warn("X Found!");
- return self.Enemies[tonumber(AvailableUsers[1][1]:match('(%d+)'))]
- else
- warn("X Not Found!");
- return tonumber(AvailableUsers[1][1])
- end
- end
- local Technicals = {
- wind = {burn = true};
- physical = {frozen = true, shock = true};
- nuclear = {frozen = true, burning = true, shock = true};
- psychic = {confuse = true, fear = true, despair = true, rage = true, brainwash = true};
- } --Technicals
- local CMS = require(game:GetService('Players').LocalPlayer:WaitForChild('PlayerScripts'):WaitForChild('PlayerModule'):WaitForChild('ControlModule'));
- local KeypadTranslations = { --translate alternative inputs to base inputs for easier coding within the UserInputService InputBegan
- Y = 'Z';
- X = 'X';
- A = 'V';
- }
- function Battle:RemoveHealthbars()
- for i, v in pairs(CollectionService:GetTagged('TemporaryAdornee')) do
- v:Destroy();
- end
- end
- function Battle:AdorneeHealth(type)
- -- if ((BattleInfo.SelectedPersonaAttack.Type == 'Kaja' or BattleInfo.SelectedPersonaAttack.Type == 'Buff') and BattleInfo.SelectedPersonaAttack.Type2 ~= 'Debuff') or BattleInfo.BattleStage == 'BatonPass' then
- -- local Guy = self.Characters[BattleInfo.SelectedEnemyGuy];
- -- PlayerGui:WaitForChild('HealthBar').Adornee = self:GetCharacterFromID(BattleInfo.SelectedEnemyGuy).PrimaryPart;
- -- PlayerGui.HealthBar.Frame.Frame.Frame.Size = UDim2.new(math.clamp(Guy.Health/Guy.MaxHealth-0.05, 0, math.huge), 0, 0.6, 0)
- -- PlayerGui.HealthBar.HealthLabel.Text = tostring(Guy.Health)
- -- else
- -- local Guy = self.Enemies[BattleInfo.SelectedEnemyGuy];
- --
- -- PlayerGui:WaitForChild('HealthBar').Adornee = self:GetEnemyFromName(BattleInfo.SelectedEnemyGuy, true).PrimaryPart;
- -- PlayerGui.HealthBar.Frame.Frame.Frame.Size = UDim2.new(math.clamp(Guy.Health/Guy.MaxHealth-0.05, 0, math.huge), 0, 0.6, 0)
- -- PlayerGui.HealthBar.WeakLabel.Visible = Guy.Weak and Guy.Weak[BattleInfo.SelectedPersonaAttack.Type] or false
- -- PlayerGui.HealthBar.HealthLabel.Text = tostring(Guy.Health)
- -- end
- if (BattleInfo.SelectedPersonaAttack) then
- if (BattleInfo.SelectedPersonaAttack.Heals) then
- for i, v in pairs(self.Characters) do
- local newHealthBar = PlayerGui:WaitForChild('HealthBar'):Clone();
- if (v.ID) then
- local IDValue = Instance.new('StringValue', newHealthBar);
- IDValue.Name = "Enemy";
- IDValue.Value = tostring(v.ID);
- end
- newHealthBar.Parent = self:GetCharacterFromID(i).PrimaryPart;
- newHealthBar.Adornee = newHealthBar.Parent;
- newHealthBar.HealthLabel.Text = v.Health;
- newHealthBar.Frame.Frame.Frame.Size = UDim2.new(math.clamp(v.Health/v.MaxHealth-0.05, 0, math.huge), 0, 0.6, 0)
- newHealthBar.WeakLabel.Visible = (not not v.Persona.Weak[BattleInfo.SelectedPersonaAttack.Type])
- CollectionService:AddTag(newHealthBar, 'TemporaryAdornee')
- end
- elseif (BattleInfo.SelectedPersonaAttack.Damages) then
- for i, v in pairs(self.Enemies) do
- if (v.Health > 0) then
- local newHealthBar = PlayerGui:WaitForChild('HealthBar'):Clone();
- if (v.ID) then
- local IDValue = Instance.new('StringValue', newHealthBar);
- IDValue.Name = "Enemy";
- IDValue.Value = tostring(v.ID);
- end
- newHealthBar.Parent = self:GetEnemyFromName(v.ID, true).PrimaryPart;
- newHealthBar.Adornee = newHealthBar.Parent;
- newHealthBar.HealthLabel.Text = v.Health;
- newHealthBar.Frame.Frame.Frame.Size = UDim2.new(math.clamp(v.Health/v.MaxHealth-0.05, 0, math.huge), 0, 0.6, 0)
- if (v.Weak) then
- newHealthBar.WeakLabel.Visible = (not not v.Weak[BattleInfo.SelectedPersonaAttack.Type])
- end
- CollectionService:AddTag(newHealthBar, 'TemporaryAdornee')
- end
- end
- elseif (BattleInfo.SelectedPersonaAttack.Type2 ~= 'Debuff') and (tonumber(BattleInfo.SelectedEnemyGuy)) and (BattleInfo.SelectedPersonaAttack.Type == 'Kaja' or BattleInfo.SelectedPersonaAttack.Type == 'Buff') then
- local C = self:GetCharacterFromID(BattleInfo.SelectedEnemyGuy)
- if (C.PrimaryPart) then
- print("Yes Primary Part");
- local newHealthBar = PlayerGui:WaitForChild('HealthBar'):Clone();
- local IDValue = Instance.new('StringValue', newHealthBar);
- IDValue.Name = "Player";
- IDValue.Value = tostring(BattleInfo.SelectedEnemyGuy);
- newHealthBar.Parent = C.PrimaryPart;
- newHealthBar.Adornee = newHealthBar.Parent;
- newHealthBar.HealthLabel.Text = self.Characters[BattleInfo.SelectedEnemyGuy].Health
- newHealthBar.Frame.Frame.Frame.Size = UDim2.new(math.clamp(self.Characters[BattleInfo.SelectedEnemyGuy].Health/self.Characters[BattleInfo.SelectedEnemyGuy].MaxHealth-0.05, 0, math.huge), 0, 0.6, 0)
- CollectionService:AddTag(newHealthBar, 'TemporaryAdornee')
- end
- else
- local Guy = self.Enemies[BattleInfo.SelectedEnemyGuy];
- if (self:GetEnemyFromName(BattleInfo.SelectedEnemyGuy, true).PrimaryPart) and Guy.Health > 0 then
- print("Yes Primary Part");
- local newHealthBar = PlayerGui:WaitForChild('HealthBar'):Clone();
- local IDValue = Instance.new('StringValue', newHealthBar);
- IDValue.Name = "Enemy";
- IDValue.Value = tostring(BattleInfo.SelectedEnemyGuy);
- newHealthBar.Parent = self:GetEnemyFromName(BattleInfo.SelectedEnemyGuy, true).PrimaryPart;
- newHealthBar.Adornee = newHealthBar.Parent;
- newHealthBar.HealthLabel.Text = Guy.Health
- newHealthBar.Frame.Frame.Frame.Size = UDim2.new(math.clamp(Guy.Health/Guy.MaxHealth-0.05, 0, math.huge), 0, 0.6, 0)
- newHealthBar.WeakLabel.Visible = (not not Guy.Weak[BattleInfo.SelectedPersonaAttack.Type])
- CollectionService:AddTag(newHealthBar, 'TemporaryAdornee')
- end
- end
- end
- return true;
- end
- function Battle:TweenHealth(t)
- local ty = tonumber(PlayerGui.HealthBar.HealthLabel.Text);
- local waitTime = t--(ty - Guy.Health) * 1/60
- for i, v in pairs(CollectionService:GetTagged('TemporaryAdornee')) do
- local Guy;
- if (v:FindFirstChild("Enemy")) then
- Guy = self.Enemies[tonumber(v.Enemy.Value)];
- elseif (v:FindFirstChild("Player")) then
- Guy = self.Characters[tonumber(v.Player.Value)]
- end
- v.Frame.Frame.Frame:TweenSize(UDim2.new(math.clamp(Guy.Health/Guy.MaxHealth-0.05, 0, math.huge), 0, 0.6, 0), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, waitTime, true)
- v.HealthLabel.Text = Guy.Health;
- end
- -- for i = ty, Guy.Health, -1 do
- --
- -- if (i < Guy.Health) then
- --
- -- break; --so no infinite loops
- -- end
- -- wait(1/60)
- -- PlayerGui.HealthBar.HealthLabel.Text = i;
- -- end
- wait(waitTime)
- end
- function Battle:AmbushPosition(t)
- workspace.CurrentCamera.CFrame = self.BattleArea.Cameras.AmbushCamera.CFrame;
- --return Tween(workspace.CurrentCamera, TweenInfo.new(tonumber(t) or 0.25, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, false, 0), {CFrame = self.BattleArea.Cameras.AmbushCamera.CFrame}):Play();
- end
- function checkIncapacitated(t, isdown, abc)
- if (t) then
- if (t.Debuffs) then
- local y = t; -- if (v.Health > 0) and (not v.Debuffs.Down) and (not v.Debuffs.Sleep) and (not v.Debuffs.Shock) and (not v.Debuffs.Confused) and (not v.Debuffs.Dizzy) and (not v.Debuffs.Fear) then
- local t = t.Debuffs;
- if ((not isdown and t.Down) or t.Sleep or t.Shock or t.Confused or t.Fear or y.Health <= 0) then
- if (not t.Down) and (y.Health > 0) then
- return (math.random() < 0.25) and false or true -- 25% chance to be able to act even when debuffed (but not downed)
- end
- if abc and (t.Down and t.Down.Length + t.Down.TurnAdded <= abc+1) then
- return false --so they can have a turn, they get up, then they attack. epic!!
- end
- return true;
- end
- else
- t.Debuffs = {};
- end
- if (t.Health <= 0) then
- return true;
- end
- else
- warn('error in checkIncapacitated')
- end
- return false
- end
- function Battle:NewTurn()
- local DC = 0;
- local LivingEnemies = 0;
- for i, v in pairs(self.Enemies) do
- if (v.Health > 0) then
- if (v.Debuffs and v.Debuffs.Down) then
- DC = DC+1;
- end
- LivingEnemies = LivingEnemies + 1;
- end
- end
- impwarn(DC, LivingEnemies, 'downcount & living enemies')
- if (DC == LivingEnemies) and DC > 0 and not Battle.HoldUpped then
- self.OneMore = false;
- end
- for i, v in pairs(ReplicatedStorage:WaitForChild('AnimationAssets'):WaitForChild('CritAnim'):GetChildren()) do
- if (tonumber(BattleInfo.SelectedMember) and tonumber(BattleInfo.SelectedMember) ~= 0) then
- --impwarn('mem:', BattleInfo.SelectedMember);
- local Z = Battle:GetCharacterFromID(BattleInfo.SelectedMember):FindFirstChild('Humanoid', true);
- local Y = animationStatus(v, Z);
- if (Y) then
- Y:AdjustWeight(1, 2)
- StopAnimation(v, Z)
- end
- end
- end
- CurrentCameraShake.RotationInfluence = Vector3.new(0.1, 0.1, 0)
- coroutine.wrap(function()
- wait();
- self:RemoveHealthbars();
- end)();
- if (self.BattleFinished) then return nil end;
- CMS:Disable()
- if (not (self.Characters[1].Debuffs.Down or self.Characters[1].Health == 0)) and (DC == LivingEnemies) and DC > 0 and not Battle.HoldUpped then
- --Hold Up
- CurrentCameraShake.RotationInfluence = Vector3.new(0.05, 0.05, 0)
- RemoveAllPersonas(true);
- local stateType = Enum.HumanoidStateType
- print('HOLD UP!')
- local CFrames = {};
- for i, v in pairs(self.Characters) do
- if (i ~= 1) then
- v = Battle:GetCharacterFromID(i)
- for i, v in pairs(v:GetDescendants()) do
- if v:IsA('BasePart') then
- v.Velocity = Vector3.new(0,0,0)
- v.RotVelocity = Vector3.new(0,0,0)
- end
- end
- CFrames[i] = v and v:GetPrimaryPartCFrame() or error ("improper coding idiot")
- v.Humanoid:SetStateEnabled(stateType.FallingDown, false)
- v.Humanoid:SetStateEnabled(stateType.Ragdoll, false)
- --impwarn(v);
- local PrimaryPart = v.PrimaryPart;
- PrimaryPart.Anchored = false;
- wait(.1)
- v.Humanoid:MoveTo(PrimaryPart.CFrame.LookVector*7 + PrimaryPart.Position)
- end
- end --movecameratoenemy
- for i, v in pairs(Character:GetDescendants()) do
- if v:IsA('BasePart') then
- v.Velocity = Vector3.new(0,0,0)
- v.RotVelocity = Vector3.new(0,0,0)
- end
- end
- CFrames[1] = Character:GetPrimaryPartCFrame();
- Character.Humanoid:SetStateEnabled(stateType.FallingDown, false)
- Character.Humanoid:SetStateEnabled(stateType.Ragdoll, false)
- wait(.1);
- Character.PrimaryPart.Anchored = false;
- Character.Humanoid:MoveTo(Character.PrimaryPart.CFrame.LookVector*7 + Character.PrimaryPart.CFrame.Position)
- Character.Humanoid.MoveToFinished:Wait()
- local ColorCorrection = Instance.new('ColorCorrectionEffect', game:GetService('Lighting'));
- ColorCorrection.Name = "BattleEffect";
- local Length = 1;
- Tween(ColorCorrection, TweenInfo.new(Length), {Brightness = -0.45}):Play();
- Battle.OtherMusic = game:GetService('ReplicatedStorage').Music['Negotiation']:Clone();
- Battle.OtherMusic.Volume = 0;
- Battle.OtherMusic.Parent = Player.PlayerGui;
- Battle.OtherMusic:Play();
- local Vol = self.Music.Volume;
- for i = self.Music.Volume, 0, -0.075 do
- self.Music.Volume = i;
- Battle.OtherMusic.Volume = Battle.OtherMusic.Volume + (Vol - i)
- wait();
- end
- self.Music:Pause();
- local Input;
- BattleInfo.SelectedEnemyGuy = Battle:GetFirstLivingEnemy();
- local SEG = BattleInfo.SelectedEnemyGuy;
- local Char = self:GetEnemyFromName(BattleInfo.SelectedEnemyGuy, true);
- Battle:CharacterPositionButWithPersona(1, Char.PrimaryPart, true, 11, 3.5) --(t, lookAt, inst, ofst)
- local Part;
- Part = not (Part and Part:Destroy()) and Instance.new('Part')
- Part.Anchored = true;
- Part.Transparency = 1;
- Part.CFrame = Char:GetPrimaryPartCFrame() + Vector3.new(0,5,0);
- Part.CanCollide = false;
- Part.Parent = workspace;
- do --create new scope so other scopes cannot access these current local scopes.
- for i, v in pairs(self.PartyContainer:GetChildren()) do
- local Part = Instance.new('Part')
- Part.Anchored = true;
- Part.Transparency = 1;
- Part.CFrame = v:GetPrimaryPartCFrame() + Vector3.new(0,5,0);
- Part.CanCollide = false;
- Part.Parent = workspace;
- local PointLight = Instance.new('PointLight')
- PointLight.Color = Color3.fromRGB(206, 200, 131)
- PointLight.Range = 4;
- PointLight.Brightness = 32.25;
- PointLight.Parent = Part;
- end
- local Part = Instance.new('Part')
- Part.Anchored = true;
- Part.Transparency = 1;
- Part.CFrame = Character:GetPrimaryPartCFrame() + Vector3.new(0,5,0);
- Part.CanCollide = false;
- Part.Parent = workspace;
- local PointLight = Instance.new('PointLight')
- PointLight.Color = Color3.fromRGB(206, 200, 131)
- PointLight.Range = 4;
- PointLight.Brightness = 32.25;
- PointLight.Parent = Part;
- end
- local PointLight = Instance.new('PointLight')
- PointLight.Color = Color3.fromRGB(206, 200, 131)
- PointLight.Range = 4;
- PointLight.Brightness = 32.25;
- PointLight.Parent = Part;
- local lastInput;
- self.OtherMusic = Battle.OtherMusic;
- repeat
- Input = (typeof(lastInput or true) ~= 'boolean' and lastInput) or UIS.InputBegan:Wait()
- if (Input == 'MessedUp') then
- for i, v in pairs(self.Characters) do
- v = Battle:GetCharacterFromID(i);
- v:SetPrimaryPartCFrame(CFrames[i]);
- end
- local Index = PlayerGui:FindFirstChild('BattleChoices', true) and PlayerGui:FindFirstChild('BattleChoices', true):Destroy() or nil;
- local OtherIndex = PlayerGui:FindFirstChild('BattleBox', true) and PlayerGui:FindFirstChild('BattleBox', true):Destroy() or nil;
- Part = Part and Part:Destroy();
- local Length = 0.25;
- Tween(ColorCorrection, TweenInfo.new(Length), {Brightness = 0}):Play();
- Input = true; Battle.HoldUpped = true; break;
- end
- if (Input.KeyCode == Enum.KeyCode.Z) then
- local Index = PlayerGui:FindFirstChild('BattleChoices', true) and PlayerGui:FindFirstChild('BattleChoices', true):Destroy() or nil;
- local OtherIndex = PlayerGui:FindFirstChild('BattleBox', true) and PlayerGui:FindFirstChild('BattleBox', true):Destroy() or nil;
- for i, v in pairs(self.Characters) do
- v = Battle:GetCharacterFromID(i);
- v:SetPrimaryPartCFrame(CFrames[i]);
- end
- Part = Part and Part:Destroy();
- local Length = 0.25;
- Tween(ColorCorrection, TweenInfo.new(Length), {Brightness = 0}):Play();
- Input = true; Battle.HoldUpped = true; break;
- elseif (Enum.KeyCode.X == Input.KeyCode) then --cursed
- Tween(workspace.CurrentCamera, TweenInfo.new(0.5, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, false, 0), {CFrame = self.BattleArea.Cameras.AmbushCamera.CFrame}):Play();
- local Index = PlayerGui:FindFirstChild('BattleChoices', true) and PlayerGui:FindFirstChild('BattleChoices', true):Destroy() or nil;
- local OtherIndex = PlayerGui:FindFirstChild('BattleBox', true) and PlayerGui:FindFirstChild('BattleBox', true):Destroy() or nil;
- self.Music:Resume();
- for i = 0, Vol, 0.075 do
- self.Music.Volume = i;
- Battle.OtherMusic.Volume = Battle.OtherMusic.Volume - i;
- wait();
- end
- for i, v in pairs(self.Characters) do
- v = Battle:GetCharacterFromID(i);
- v:SetPrimaryPartCFrame(CFrames[i]);
- end
- Part = Part and Part:Destroy();
- local Length = 0.25;
- Tween(ColorCorrection, TweenInfo.new(Length), {Brightness = 0}):Play()
- local Personas = {};
- local what = game:GetService('ReplicatedStorage'):WaitForChild('EffectStorage'):WaitForChild('DustPart'):Clone();
- local MiddleCF = self.EnemySpawns:GetChildren()[1].CFrame:Lerp(self.EnemySpawns:GetChildren()[#self.EnemySpawns:GetChildren()].CFrame, 0.5);
- local ChosenEffects = {};
- local ACF=0;
- local CompletedEffects = {};
- local Passed;
- -- spawn(function()
- -- repeat wait(.5) what.ParticleEmitter:Emit(1500) until Passed
- -- end)
- what.CFrame = MiddleCF;
- what.Parent = Instance.new('Model', workspace)
- what.Parent.PrimaryPart = what;
- local a = Instance.new('Humanoid', what.Parent);
- what.ParticleEmitter.Enabled = true;
- a.HipHeight = game.Players.LocalPlayer.Character.Humanoid.HipHeight
- for i, v in pairs(self.Characters) do
- local N = v;
- if (i ~= BattleInfo.SelectedMember) then
- v = Battle:GetCharacterFromID(i);
- for i, v in pairs(v:GetDescendants()) do
- if (v:IsA("BasePart") or v:IsA('Decal')) and (v.Name ~= 'HumanoidRootPart') then
- local Transparency = Instance.new'NumberValue';
- Transparency.Name = 'Opacity'
- Transparency.Value = v.Transparency;
- Transparency.Parent = v
- spawn(function(a)
- wait(0.5)
- for i = v.Transparency, 1, 0.1 do
- wait();
- v.Transparency = i;
- end
- end)
- end
- end
- end
- ChosenEffects[N.Persona.Name] = N.Persona.Attacks[math.random(1, #N.Persona.Attacks)]
- ACF=ACF+1;
- end
- for i, v in pairs(self.Characters) do --todo // change all _G.Characters to self.Characters unless in initialization function
- Personas[v.Persona.Name]=Battle:createPersona(nil, true, i)
- Personas[v.Persona.Name].Name = v.Name;
- end
- wait();
- for i, v in pairs(self.Characters) do
- local N = v;
- if (i ~= BattleInfo.SelectedMember) then
- v = Battle:GetCharacterFromID(i);
- v:WaitForChild('Humanoid'):MoveTo(MiddleCF.Position);
- end
- end
- wait(3.5);
- spawn(function()
- local Next = 0.1+math.random()/2
- while wait(Next) do
- if (Passed) then
- local HeavyHit = ReplicatedStorage.Music:WaitForChild('HeavyHit')
- HeavyHit = HeavyHit:Clone()
- HeavyHit.Parent = game.Players.LocalPlayer.PlayerGui;
- HeavyHit.PlayOnRemove = true;
- HeavyHit:Destroy();
- break;
- end;
- local HeavyHit = ReplicatedStorage.Music:WaitForChild('NormalHit')
- HeavyHit = HeavyHit:Clone()
- HeavyHit.Parent = game.Players.LocalPlayer.PlayerGui;
- HeavyHit.PlayOnRemove = true;
- HeavyHit:Destroy();
- Next = 0.1+math.random()/2
- end
- end)
- for i, v in pairs(ChosenEffects) do
- local Effect = Effects[getAttack(v).Effect] or function() end;
- coroutine.wrap(function()
- Effect({
- PrimaryPart = what;
- TargetPart = Personas[i].PrimaryPart;
- IgnoreAnimation = false;
- TargetFolder = self.EnemyContainer;
- });
- CompletedEffects[#CompletedEffects+1] = v;
- end)()
- end
- repeat wait() --[[impwarn(#CompletedEffects, ACF, ACF==#CompletedEffects)]] until #CompletedEffects == ACF
- Passed = true;
- for i, v in pairs(self.Characters) do
- v = Battle:GetCharacterFromID(i);
- v.Humanoid:MoveTo(v.PrimaryPart.Position);
- wait();
- v:SetPrimaryPartCFrame(CFrames[i]);
- for i, v in pairs(v:GetDescendants()) do
- spawn(function(a)
- if (v:IsA('BasePart') or v:IsA('Decal')) and (v:FindFirstChild'Opacity') then
- --impwarn(v.Transparency, v.Opacity.Value)
- for i = v.Transparency, v.Opacity.Value, -0.1 do
- wait();
- v.Transparency = i;
- end
- end
- end)
- end
- end
- -- Effects[attack.Effect]({PrimaryPart = Char.PrimaryPart, --enemy's part
- -- IgnoreAnimation = ia, --ignore animation?
- -- TargetPart = Me.PrimaryPart, --my primary part
- -- TargetFolder = self.EnemyContainer --enemy's folder? WHAT
- -- })
- what.ParticleEmitter.Enabled = false;
- local Damage = 0;
- for i, v in pairs(self.Characters) do
- local EquippedMelee = v.Equipped.Melee
- local Item = Items[EquippedMelee];
- if (Item) then
- Damage = Damage+(Item.Damage or 0);
- end
- end
- --[[
- attacks.Lunge = {
- Name = 'Lunge';
- Type = 'Physical',
- Damage = 35;
- HPRequired = 5;
- Description = 'Slight Physical damage to one foe.';
- JPDesc = '???????????????' --//??
- }
- --]]
- wait(1);
- Battle:AdorneeHealth();
- Battle:Damage(self.Characters[1], self.Enemies[1], {
- Name = "All Out Attack",
- Type = "Almighty",
- Damages = "All";
- Damage = Damage;
- HPRequired = 0;
- Description = "No time for apologies!";
- }, true)
- Battle:TweenHealth();
- for i, v in pairs(self.Enemies) do
- v.Debuffs = {};
- end
- RemoveAllPersonas(true)
- Input = true;
- elseif (Input.KeyCode == Enum.KeyCode.Left or Input.KeyCode == Enum.KeyCode.Right or Input.KeyCode == Enum.KeyCode.DPadLeft or lastInput == "Left" or lastInput == "Right") then
- --print(Input.Name:match('Left') or Input.Name:match('Right'));
- Input = lastInput and {Name = lastInput} or Input.KeyCode;
- Input = {Name = Input.Name:match('Left') or Input.Name:match('Right')};
- BattleInfo.SelectedEnemyGuy = self:GetEnemy(Input.Name:sub(1,1):lower(), BattleInfo.SelectedEnemyGuy)
- local Char = self:GetEnemyFromName(BattleInfo.SelectedEnemyGuy, true);
- Battle:CharacterPositionButWithPersona(1, Char.PrimaryPart, nil, 11, 3.5)
- Part = not (Part and Part:Destroy()) and Instance.new('Part')
- Part.Anchored = true;
- Part.Transparency = 1;
- Part.CFrame = Char:GetPrimaryPartCFrame() + Vector3.new(0,5,0);
- Part.CanCollide = false;
- Part.Parent = workspace;
- local PointLight = Instance.new('PointLight')
- PointLight.Color = Color3.fromRGB(206, 200, 131)
- PointLight.Range = 4;
- PointLight.Brightness = 32.25;
- PointLight.Parent = Part;
- lastInput = nil;
- lastInput = _G.ShowIntroSpeech(game:GetService('ReplicatedStorage').ModuleScripts.Dialogue.Timid, self.Enemies[SEG].Name, Battle, self.Enemies[SEG], BattleInfo.SelectedEnemyGuy);
- end
- until Input == true;
- self.Music:Resume();
- for i = 0, Vol, 0.075 do
- self.Music.Volume = i;
- Battle.OtherMusic.Volume = Battle.OtherMusic.Volume - i;
- wait();
- end
- Battle.OtherMusic:Stop();
- Battle.OtherMusic:Destroy();
- self.OneMore = false;
- end
- if (self.OneMore == 'W') then
- self.OneMore = true
- end
- --PlayerGui.Reticle.Enabled = false;
- local NoHealth = 0;
- for i, v in pairs(self.Enemies) do
- if (v.Health <= 0) then
- NoHealth = NoHealth + 1;
- end
- end
- local NHealth = 0
- for i, v in pairs(self.Characters) do
- if (v.Health <= 0) then
- NHealth = NHealth + 1;
- end;
- end
- RemoveAllPersonas(true)
- self:EndBattleProtocol(NoHealth, NHealth, false)
- -- if (NoHealth == #self.Enemies or NHealth == #self.Characters) then
- -- self:EndBattle();
- --
- -- for i, v in pairs(Character.Humanoid:GetPlayingAnimationTracks()) do
- -- v:Stop(); --stop all playing animations, the default animator will replay animations again so it doesn't matter'
- -- end
- -- local PLighting = ReplicatedStorage:FindFirstChild('Previous Lighting');
- -- if (PLighting) then
- -- for i, v in pairs(PLighting:GetChildren()) do
- -- pcall(function()
- -- game:GetService('Lighting')[v.Name] = v.Value;
- -- end)
- -- end
- -- end
- -- self.BattleArea:Destroy();
- -- for i, v in pairs(game:GetService'Lighting':GetChildren()) do
- -- if (v.ClassName:match('Effect') and v.Name ~= 'e') then
- -- v.Enabled = true
- -- end
- -- end
- -- Character:SetPrimaryPartCFrame(self.PositionBeforeBattle)
- -- Character:WaitForChild('HumanoidRootPart').Anchored = false;
- -- StopAnimation(nil, Character:WaitForChild('Humanoid'))
- -- _G.Music:Play();
- -- return true, script:Destroy(); --self destruct script just to be safe
- -- end
- BattleInfo.BattleStage = 'Main'; --reset BattleStage so the battle can basically refresh itself upon a new turn
- BattleInfo.SelectedEnemyGuy = 1 --workspace['Enemy Container']:GetChildren()[1] --set the selectedenemyguy to the first person
- if (BattleInfo.SelectedMember == 0) then
- --reset all tables in case a goof happened
- BattleInfo.EnemyTurns = {};
- BattleInfo.PlayerTurns = {};
- BattleInfo.MemberActions = {};
- elseif (BattleInfo.SelectedMember == 'Enemy') then
- BattleInfo.MemberActions = {}; --reset member actions if the player has already done stuff
- end
- local ChosenMember;
- if (not self.AvailableUsers) or (#self.AvailableUsers == 0) then
- impwarn("Refilling now.")
- ChosenMember = self:selectViableMember(true); --modify selectViableMember to provide enemy turns so debuffs wear off individually
- else
- impwarn("Not refilling, choosing a chracter now.")
- ChosenMember = self:selectViableMember() --true variable means that it just needs to choose a character and thats it, no reselecting
- end
- repeat game:GetService('RunService').RenderStepped:Wait();
- if not (typeof(ChosenMember) == "table") then
- if (not self.AvailableUsers) or (#self.AvailableUsers == 0) then
- impwarn("No chosen member. Refilling now.")
- ChosenMember = self:selectViableMember(true); --modify selectViableMember to provide enemy turns so debuffs wear off individually
- else
- impwarn("No chosen member. Not refilling.")
- ChosenMember = self:selectViableMember() --true variable means that it just needs to choose a character and thats it, no reselecting
- end
- end
- until (typeof(ChosenMember) == "table")
- impwarn("PASSED.")
- table.remove(self.AvailableUsers, 1)
- ChosenMember.Guard = false;
- BattleInfo.SelectedMember = ChosenMember;
- for x, v in pairs(self.Characters) do
- local n = v;
- BattleInfo.PlayerTurns[x] = BattleInfo.PlayerTurns[x] or 0;
- --warn('lope')
- if (v.Debuffs) then
- --warn('fat')
- for i, v in pairs(v.Debuffs) do
- --warn('worn')
- if (v.TurnAdded and v.Length and v.TurnAdded + v.Length <= BattleInfo.PlayerTurns[x]) then
- --warn('hi lol ecksdee')
- self:MoveCameraToCharacter(x)
- if (v.Name ~= 'Down') then
- local DebuffTitle = (v.Name or '???')..' has worn off!';
- DebuffTitle = v.WearOff or DebuffTitle;
- showLabel(DebuffTitle, 1.5);
- end
- if (v.Name == 'Down') then
- self.Characters[x].Debuffs.Down = nil;
- end
- spawn(function()
- print(n.Debuffs[i])
- end)
- impwarn('Debuff data:', v.Name, v.Length, v.TurnAdded, 'Turn:', BattleInfo.EnemyTurns[x], 'Holder:', n.Name)
- end
- end
- end
- if (v.Health == 0) then
- v.Debuffs = {};
- end
- end
- if (self.Characters[BattleInfo.SelectedMember] and self.Characters[BattleInfo.SelectedMember].Health > 0) then
- if (animationStatus(game.ReplicatedStorage.AnimationAssets.Death.Stay, Battle:GetCharacterFromID(BattleInfo.SelectedMember).Humanoid) and animationStatus(game.ReplicatedStorage.AnimationAssets.Death.Stay, Battle:GetCharacterFromID(BattleInfo.SelectedMember).Humanoid).IsPlaying) then
- impwarn('Character was alive but down! Recovering...')
- local Humanoid = Battle:GetCharacterFromID(BattleInfo.SelectedMember).Humanoid;
- --stop animation b
- self:InvisibleEnemies()
- StopAnimation(game.ReplicatedStorage.AnimationAssets.Death.Stay, Humanoid)
- StopAnimation(game.ReplicatedStorage.AnimationAssets.Death.Fall, Humanoid)
- self:MoveCameraToCharacter(BattleInfo.SelectedMember)
- local Anim = LoadAnimation(game.ReplicatedStorage.AnimationAssets.Rise.Rise, Humanoid)
- Anim:Play()
- Anim.Stopped:Wait()
- self:InvisibleEnemies()
- end
- end
- if (typeof(ChosenMember) ~= 'table') and not self.OneMore then
- BattleInfo.PlayerTurns[ChosenMember] = BattleInfo.PlayerTurns[ChosenMember] and BattleInfo.PlayerTurns[ChosenMember] + 1 or 1;
- warn(_G.Characters[ChosenMember].Name.."'s Turn:", BattleInfo.PlayerTurns[ChosenMember])
- if (checkIncapacitated(self.Characters[ChosenMember], nil)) then
- warn'incapazitated'
- return Battle:NewTurn()
- end
- end
- -- Battle:ResetCharacters()
- if (checkIncapacitated(self.Characters[ChosenMember])) then
- warn('Member is incapacitated! Skipping turn..')
- BattleInfo.MemberActions[ChosenMember] = "Incapacitated"
- return Battle:NewTurn();
- end
- for x, v in pairs(self.Enemies) do
- local n = v;
- --warn('lope2')
- if (v.Debuffs) then
- --warn('fat2')
- for i, v in pairs(v.Debuffs) do
- --warn('lorn2')
- BattleInfo.EnemyTurns[n.ID] = BattleInfo.EnemyTurns[n.ID] or 1;
- if (v.TurnAdded and v.Length and v.TurnAdded + v.Length <= BattleInfo.EnemyTurns[n.ID]) then
- --warn('enemy lolecksdee')
- Battle:MoveCameraToEnemy(n.ID)
- if (v.Name ~= 'Down') then
- showLabel((v.Name or '???')..' has worn off!', 1.5);
- end
- if (v.Name == 'Down') then
- n.Debuffs.Down = nil;
- warn("DOWN DATA:", n.Debuffs.Down)
- --stop animation a
- self:InvisibleParty()
- local Humanoid = Battle:GetEnemyFromID(n.ID, true).Humanoid;
- StopAnimation(game.ReplicatedStorage.AnimationAssets.Death.Stay, Humanoid)
- StopAnimation(game.ReplicatedStorage.AnimationAssets.Death.Fall, Humanoid)
- local Anim = LoadAnimation(game.ReplicatedStorage.AnimationAssets.Rise.Rise, Humanoid)
- Anim:Play()
- Anim.Stopped:Wait()
- self:InvisibleParty()
- end
- else
- warn('Debuff data:', v.Name, v.Length, v.TurnAdded, 'Turn:', BattleInfo.EnemyTurns[n.ID], 'Holder:', n.Name)
- end
- end
- end
- if (v.Health == 0) then
- v.Debuffs = {};
- end
- end
- if (not self.Ambush) and tonumber(ChosenMember) then
- Battle:CharacterPosition() --reset camera position to the player's back
- elseif (self.Ambush) then
- Battle:AmbushPosition()
- end
- if (typeof(ChosenMember) == 'table') then
- BattleInfo.EnemyTurns[ChosenMember.ID] = BattleInfo.EnemyTurns[ChosenMember.ID] and BattleInfo.EnemyTurns[ChosenMember.ID] + 1 or 1;
- PlayerGui.PersonaListR.Adornee = nil;
- PlayerGui.HealthBar.Adornee = nil;
- if (checkIncapacitated(ChosenMember)) then
- warn('Enemy is incapacitated! Skipping turn..')
- BattleInfo.EnemyActions[ChosenMember.ID] = "Incapacitated";
- return Battle:NewTurn();
- end
- --Battle:PointCameraToEnemy(ChosenMember.ID, true)
- if (ChosenMember.CTC and ChosenMember.TurnCount and ChosenMember.CTC >= ChosenMember.TurnCount) then
- --impwarn("First")
- BattleInfo.EnemyActions[ChosenMember.ID] = true;
- elseif (ChosenMember.CTC and ChosenMember.TurnCount and ChosenMember.CTC < ChosenMember.TurnCount) then
- --impwarn("Second")
- ChosenMember.CTC = ChosenMember.CTC+1;
- else
- --impwarn("Third");
- BattleInfo.EnemyActions[ChosenMember.ID] = true;
- end
- EnemyAPI:EnemyFunction(self.Characters[math.random(1, #self.Characters)], ChosenMember, Battle)
- wait(1.5)
- return Battle:NewTurn(); --make the function recursive
- end --enemy ai
- PlayerGui.PersonaListR.Adornee = ChosenMember == 1 and Character.PrimaryPart or workspace:WaitForChild('Party Container'):WaitForChild(self.Characters[ChosenMember].Name).PrimaryPart
- --^ set the adornee to the localplayer's primary part if the chosenmember is one otherwise it sets it to the other's primaryparts.
- --using a stage system to determine where we are at
- --connect to UserInputService for epicness
- local InputBegan; --define InputBegan as a dummy variable
- local KeyPressed;
- pcall(function()
- self.Characters[BattleInfo.SelectedEnemyGuy].Guard = false;
- end)
- InputBegan = UIS.InputBegan:Connect(function(Key, Process)
- if (KeyPressed or Process) then return nil end
- BattleInfo.MemberActions[BattleInfo.SelectedMember] = true; --remove this
- ReplicatedStorage.Music.Blip:Play();
- --redefine InputBegan as the signal so we can keep the signal local whilst being able to disconnect it in the signal
- Key = Key.KeyCode;
- local Stage = BattleInfo.BattleStage
- if (Stage == 'Main' or Stage == 'BatonPass') then
- if (Key == K.Z or Key == K.ButtonY) then
- local Humanoid = self:GetCharacterFromID(BattleInfo.SelectedMember):WaitForChild('Humanoid')
- BattleInfo.BattleStage = 'PersonaAttackList'
- PlayerGui['Persona Attacks List'].Enabled = true
- BattleInfo.MemberActions[BattleInfo.SelectedMember] = true;
- game:GetService('RunService').RenderStepped:Wait()
- -- for i, v in pairs(PlayerGui['Persona Attacks List'].Table:GetChildren()) do
- -- if (v:IsA('Frame')) then
- -- v.Button.Selected = true;
- -- game:GetService('GuiService').SelectedObject = v.Button;
- -- break;
- -- end
- -- end
- return true;
- elseif (Key == K.Q or Key == K.ButtonR2) and (self.OneMore) then
- BattleInfo.BattleStage = 'BatonPass'
- BattleInfo.SelectedEnemyGuy = BattleInfo.SelectedMember; --set btn pass to passer guy
- self:MoveCameraToCharacter(BattleInfo.SelectedMember)
- return true;
- end
- end
- if (Key == K.Backspace or Key == K.ButtonB) and Stage ~= 'Main' then
- Battle:RemoveHealthbars();
- if (Stage == 'AwaitGuard') then
- if (not self.Ambush) then
- Battle:CharacterPosition() --reset camera position to the player's back
- else
- Battle:AmbushPosition()
- end
- RemoveAllPersonas()
- PlayerGui['Guard'].Enabled = false;
- BattleInfo.BattleStage = 'Main'
- return nil;
- elseif (Stage == 'PersonaTarget' or Stage == 'PersonaChange') then
- BattleInfo.Waffle = "AnimAndSound";
- BattleInfo.BattleStage = 'PersonaAttackList'
- self.PersonaSelect = nil;
- return nil;
- elseif (Stage == 'Analysis') then
- BattleInfo.SelectedPersonaAttack = {Name = 'Analysis'}; --KOWALSKI
- BattleInfo.BattleStage = 'PersonaTarget'
- return nil;
- else
- if (not self.Ambush) then
- Battle:CharacterPosition() --reset camera position to the player's back
- else
- Battle:AmbushPosition()
- end
- RemoveAllPersonas()
- BattleInfo.BattleStage = 'Main'
- BattleInfo.SelectedPersonaAttack = {};
- return nil;
- end;
- elseif (Key == K.LeftBracket or Key == K.RightBracket or Key == K.ButtonL1 or Key == K.ButtonR1) and (Stage == 'PersonaChange' or Stage == 'PersonaAttackList') and (BattleInfo.SelectedMember == 1) then
- Key = (Key == K.LeftBracket or Key == K.ButtonL1) and 'Left' or 'Right'
- local OrigTable = {}
- local x = 0;
- local targetI = nil;
- for i, v in pairs(Personas) do
- if ((not self.PersonaSelect) and (v.Name == self.Characters[1].Persona.Name)) or self.PersonaSelect == x then
- --warn('Not Self.PersonaSelect, and v.Name is self.Characters[1].Persona.Name, or self.PersonaSelect is equal to X.')
- targetI = x;
- else
- --warn('?????')
- end
- if (not v.Unspawnable) and (v.Name) then
- x=x+1; --put the x in the Unspawnable area so it only increments if the persona is indeed spawnable, so we dont spawn a boss persona.
- OrigTable[x] = v
- end --so we don't use big boss personas by accident
- end
- self.CurrentPersona = nil
- --obtain player
- for i, v in pairs(OrigTable) do
- if (i == targetI) and (Stage ~= 'PersonaChange') then --v-1
- self.PersonaSelect = targetI;
- self.CurrentPersona = v[2] --set thing to the table so we can use it's first iterator value to determine what place we are in'
- elseif (i == self.PersonaSelect or i == 1) then
- if (Key == 'Left') then
- if (OrigTable[(self.PersonaSelect or 0)-1]) then
- self.PersonaSelect = self.PersonaSelect and self.PersonaSelect-1 or #OrigTable;
- else
- self.PersonaSelect = #OrigTable;
- end
- elseif (Key == 'Right') then
- if (OrigTable[(self.PersonaSelect or 0)+1]) then
- self.PersonaSelect = self.PersonaSelect and self.PersonaSelect+1 or 1;
- else
- self.PersonaSelect = 1;
- end
- end
- self.CurrentPersona = OrigTable[self.PersonaSelect];
- break;
- end
- end
- if (not self.CurrentPersona) then
- self.CurrentPersona = OrigTable[1];
- self.PersonaSelect = 1;
- end
- _G.RequestPersona(self.CurrentPersona or OrigTable[1]);
- BattleInfo.BattleStage = 'PersonaChange';
- elseif (Key == K.R or Key == K.ButtonL1) and (BattleInfo.BattleStage == 'Main') then
- BattleInfo.SelectedPersonaAttack = {Name = 'Analysis'}; --KOWALSKI
- BattleInfo.BattleStage = 'PersonaTarget'
- elseif (Key == K.Return or Key == K.ButtonA) then
- if (UIS:IsKeyDown(K.R)) then
- KeyPressed = true;
- return true;
- end
- if (BattleInfo.BattleStage == 'PersonaTarget' and BattleInfo.SelectedPersonaAttack and BattleInfo.SelectedPersonaAttack.Name == 'Analysis') then
- _G.RequestPersona(self.Enemies[BattleInfo.SelectedEnemyGuy] or self.Enemies[#self.Enemies], true)
- BattleInfo.BattleStage = 'Analysis'
- return true;
- end
- if (self.CurrentPersona and Stage == 'PersonaChange') then
- local Persona = self.CurrentPersona or Personas.Widgeon;
- local NeverSwappedPersona = self.CurrentPersona.Name == self.Characters[1].Persona.Name
- self.Characters[1].Persona = self.CurrentPersona or Personas.Widgeon;
- RefreshPersonaList(not NeverSwappedPersona)
- BattleInfo.BattleStage = 'PersonaAttackList'
- return true;
- end
- if (Stage == 'AwaitGuard') then
- self.Characters[BattleInfo.SelectedMember].Guard = true;
- KeyPressed = true;
- PlayerGui['Guard'].Enabled = false;
- BattleInfo.MemberActions[BattleInfo.SelectedMember] = true;
- wait(.25)
- return true;
- end
- if (Stage == 'BatonPass') then
- if (BattleInfo.SelectedEnemyGuy == BattleInfo.SelectedMember) then
- spawn(function(a) showLabel('Cannot baton pass to yourself.', 0.25) end)
- ReplicatedStorage.Music.Error:Play();
- return true;
- end
- if (self.Characters[BattleInfo.SelectedEnemyGuy].BatonPassed) then
- showLabel('Cannot baton pass to someone twice.', 0.25)
- return true;
- end
- self.Characters[BattleInfo.SelectedEnemyGuy].BatonPassed = true;
- self.BatonPass = BattleInfo.SelectedEnemyGuy;
- KeyPressed = true;
- return true;
- end
- if (Stage == 'PersonaAttackList') then
- KeyPressed = 'Waiting'
- if (not game:GetService('GuiService').SelectedObject) then KeyPressed = false; return nil end;
- local Attack = getAttack(game:GetService('GuiService').SelectedObject.Parent.AttackTitle.Text);
- if Attack.HPRequired and (modifyDamage(Attack.HPRequired, self.Characters[BattleInfo.SelectedMember].MaxHealth) > self.Characters[BattleInfo.SelectedMember].Health) then
- KeyPressed = false;
- ReplicatedStorage.Music['Error']:Play();
- return true, showLabel('Not enough HP!');
- elseif (Attack.SPRequired and self.Characters[BattleInfo.SelectedMember].SP < Attack.SPRequired) then
- KeyPressed = false;
- ReplicatedStorage.Music['Error']:Play();
- return true, showLabel('Not enough SP!');
- elseif Attack.Type == 'Buff' then
- if (Attack.Type2 == 'Revive') then
- local NobodyDead = true
- for i, v in pairs(self.Characters) do
- if (v.Health == 0) then
- NobodyDead = false
- end
- end
- if (NobodyDead) then
- KeyPressed = false;
- ReplicatedStorage.Music['Error']:Play();
- return true, showLabel('There are no fallen party members.');
- end
- elseif (Attack.Type2 == 'Cure') then
- local HasDebuff = false;
- for i, v in pairs(self.Characters) do
- for i, v in pairs(v.Debuffs) do
- if (Attack.Debuffs[v.Name]) then
- HasDebuff = true;
- end
- end
- end
- if (not HasDebuff) then
- KeyPressed = false;
- ReplicatedStorage.Music['Error']:Play();
- return true, showLabel('There are no party members with debuffs.');
- end
- else
- local FullHealth = 0;
- for i, v in pairs(self.Characters) do
- if (v.Health == v.MaxHealth) then
- FullHealth = FullHealth+1
- end
- end
- if (FullHealth == #self.Characters) then
- KeyPressed = false;
- ReplicatedStorage.Music['Error']:Play();
- return true, showLabel('All party members are fully healed.');
- end
- end
- end
- BattleInfo.BattleStage = 'PersonaTarget'
- BattleInfo.SelectedEnemyGuy = (not (Attack.Type == 'Buff' or (Attack.Type == 'Kaja' and Attack.Type2 ~= 'Debuff'))) and self:GetFirstLivingEnemy() or BattleInfo.SelectedMember;
- BattleInfo.SelectedPersonaAttack = Attack
- self:RemoveHealthbars()
- self:AdorneeHealth();
- KeyPressed = false;
- --local x = not self.Ambush and ((Attack.Type == 'Buff' or Attack.Type == 'Kaja') and
- --self:MoveCameraToCharacter(BattleInfo.SelectedMember) or self:MoveCameraToEnemy(self:GetEnemyFromID(BattleInfo.SelectedEnemyGuy)))
- --get attack from selected object name^
- if (self.Ambush) and ((Attack.Type == 'Kaja' and Attack.Type2 ~= 'Debuff') or Attack.Type == 'Buff') then
- --PlayerGui.Reticle.Enabled = true;
- PlayerGui.Reticle.Adornee = self:GetCharacterFromID(BattleInfo.SelectedMember)
- end
- local Char = self:GetEnemyFromName(BattleInfo.SelectedEnemyGuy, true);
- --move camera seamelessly
- local Factor = (Attack.Heals and "Heals") or (Attack.Damages and "Damages") or nil;
- if (Factor and not self.Ambush) then
- local y = (Factor == "Heals" and self.PartySpawns:GetChildren()) or (Factor == "Damages" and self.EnemySpawns:GetChildren());
- local First, Last;
- local LivingEnemies = 0;
- for i, v in pairs(self.Enemies) do
- if (v.Health > 0) then
- LivingEnemies=LivingEnemies+1;
- end
- end
- First = y[1]; --get the first spawn
- Last = y[LivingEnemies]; --get the last spawn
- local PositionToCirculateAround = First.CFrame:Lerp(Last.CFrame, 0.5) --get their distance from the leftmost cframe
- local thing = CFrame.new(PositionToCirculateAround.LookVector*(#(Factor == "Damages" and (function()local a={};for i=0,LivingEnemies do a[#a+1]=i return a end end)() or self.Characters)*3.5) + PositionToCirculateAround.Position);
- --local newThing = thing + Vector3.new(0,LivingEnemies*4,0)
- local EC = 0;
- local D
- for i, v in pairs(self.Enemies) do
- if (v.Health > 0) then
- EC = EC+1;
- D = not D and v.ID or D;
- end
- end
- workspace.CurrentCamera.CFrame = CFrame.new(workspace.CurrentCamera.CFrame.Position, (EC == 1 and self:GetCharacterFromID(D).PrimaryPart.CFrame.Position) or thing.Position+Vector3.new(0,(Character.Humanoid.HipHeight+2 or 6.5),0))
- return 0;
- end
- if (not self.Ambush) and (not Factor) then
- Battle:CharacterPositionButWithPersona(nil, Char.PrimaryPart.CFrame)
- else
- PlayerGui.Reticle.Adornee = Char.PrimaryPart;
- --PlayerGui.Reticle.Enabled = true;
- end
- if (self.Ambush) and not (Attack.Type == 'Kaja' or Attack.Type == 'Buff') then --woo spaghetti
- PlayerGui.Reticle.Adornee = Char.PrimaryPart;
- --PlayerGui.Reticle.Enabled = true;
- elseif (not self.Ambush) then
- --PlayerGui.Reticle.Enabled = false;
- end
- elseif (BattleInfo.BattleStage == 'PersonaTarget' and Battle.FinishedAttacking) then
- local Attack = BattleInfo.SelectedPersonaAttack;
- Battle.FinishedAttacking = false;
- if (Attack.Damage) then
- pcall(function()
- local SelectedShouts = Shouts.AttackShouts[tostring(BattleInfo.SelectedMember or 1)]
- local newShout = SelectedShouts:GetChildren()[math.random(1, #SelectedShouts:GetChildren())]:Clone();
- newShout.Parent = PlayerGui;
- newShout.PlayOnRemove = true;
- wait();
- newShout:Destroy();
- end)
- end
- Battle:Damage(self.Characters[BattleInfo.SelectedMember], (not Attack.Heals) and self.Enemies[BattleInfo.SelectedEnemyGuy] or self.Characters[1], Attack);
- KeyPressed = true;
- end
- elseif (Key == K.C or Key == K.ButtonB) then
- if (BattleInfo.BattleStage == 'Main') then
- BattleInfo.BattleStage = 'AwaitGuard'
- PlayerGui['Guard'].Enabled = true;
- return nil;
- elseif (BattleInfo.BattleStage == 'AwaitGuard') then
- PlayerGui['Guard'].Enabled = false;
- BattleInfo.BattleStage = 'Main'
- return nil;
- end
- elseif (Key == K.Left or Key == K.Right or Key == K.DPadLeft or Key == K.DPadRight) and (BattleInfo.SelectedPersonaAttack and (BattleInfo.BattleStage == 'PersonaTarget' or BattleInfo.BattleStage == 'BatonPass')) and (not BattleInfo.SelectedPersonaAttack.Damages) and not BattleInfo.SelectedPersonaAttack.Heals then
- local Attack = BattleInfo.SelectedPersonaAttack;
- Key = {Name = Key.Name:match('Left') or Key.Name:match('Right')};
- local Factor = (Attack.Heals and "Heals") or (Attack.Damages and "Damages") or nil;
- if (Attack.Type2 ~= "Debuff") and (BattleInfo.BattleStage == 'BatonPass' or Attack.Type == 'Kaja' or Attack.Type == 'Buff') then
- print(Attack.Name, Attack.Type, Attack.Type2, "Facing toward character.")
- BattleInfo.SelectedEnemyGuy = self:GetCharacter(Key.Name:sub(1,1):lower(), BattleInfo.SelectedEnemyGuy, (BattleInfo.SelectedPersonaAttack.Type2 == 'Revive' or nil)) or BattleInfo.SelectedEnemyGuy
- local Char = self:GetCharacterFromID(BattleInfo.SelectedEnemyGuy);
- Battle:MoveCameraToCharacter(BattleInfo.SelectedEnemyGuy);
- --PlayerGui.Reticle.Adornee = Char.PrimaryPart;
- ----PlayerGui.Reticle.Enabled = true;
- else
- print(Attack.Name, Attack.Type, Attack.Type2, "Facing toward enemy.")
- BattleInfo.SelectedEnemyGuy = self:GetEnemy(Key.Name:sub(1,1):lower(), BattleInfo.SelectedEnemyGuy)
- local Char = self:GetEnemyFromName(BattleInfo.SelectedEnemyGuy, true);
- if (not self.Ambush) then
- Battle:CharacterPositionButWithPersona(nil, Char.PrimaryPart.CFrame)
- else
- --PlayerGui.Reticle.Adornee = Char.PrimaryPart;
- ----PlayerGui.Reticle.Enabled = true;
- end
- end
- self:RemoveHealthbars()
- self:AdorneeHealth();
- end
- return true;
- end)
- repeat wait() until KeyPressed == true; --strict comparison because keypressed is also assigned to strings
- if (InputBegan) then
- InputBegan:Disconnect();
- end
- Battle.FinishedAttacking = true;
- if (self.OneMore == true) then
- self.OneMore = false;
- end
- return Battle:NewTurn();
- end
- function RefreshPersonaList(sound)
- --impwarn("Sound:", sound)
- for i,v in pairs(PlayerGui["Persona Attacks List"].List.Frame:GetChildren()) do
- if (v.Name ~= "Grid") then v:Destroy() end;
- end
- if (PlayerGui:WaitForChild("Persona Attacks List").Enabled) then
- local y = RichText:New(PlayerGui:WaitForChild('Persona Attacks List')['ID Background']:WaitForChild('PersonaName'), '<TextScale=1><TextScaled=true>'..personaIfy(Battle.Characters[BattleInfo.SelectedMember].Persona.Nickname or Battle.Characters[BattleInfo.SelectedMember].Persona.Name or '???'));
- y:Show()
- spawn(function()
- if (not sound) then
- pcall(function()
- if (BattleInfo.Waffle == 'AnimAndSound') then
- local SFX = ReplicatedStorage.SFX.SummonPersona:Clone();
- SFX.Parent = PlayerGui;
- SFX.PlayOnRemove = true;
- SFX:Destroy();
- elseif (not BattleInfo.Waffle) then
- local Humanoid = Battle:GetCharacterFromID(BattleInfo.SelectedMember):WaitForChild('Humanoid')
- BattleInfo.BattleStage = 'PersonaAttackList'
- LoadAnimation(ReplicatedStorage.AnimationAssets.Spin.Spin, Humanoid):Play();
- local SFX = ReplicatedStorage.SFX.SummonPersona:Clone();
- SFX.Parent = PlayerGui;
- SFX.PlayOnRemove = true;
- SFX:Destroy();
- if (math.random(1, 15) < 10) then
- local SelectedShouts = Shouts.PersonaShout[tostring(BattleInfo.SelectedMember or 1)]
- local newShout = SelectedShouts:GetChildren()[math.random(1, #SelectedShouts:GetChildren())]:Clone();
- newShout.Parent = PlayerGui;
- newShout.PlayOnRemove = true;
- newShout:Destroy();
- end
- end
- BattleInfo.Waffle = false;
- wait();
- end)
- end
- Battle:createPersona(BattleInfo.Waffle == true)
- end)
- ----
- for i, v in pairs(Battle.Characters[BattleInfo.SelectedMember].Persona.Attacks) do
- v = getAttack(v)
- if (v) then
- if (tostring(i):match('%a')) then
- --where the heck was I going with this?
- else
- local C = PlayerGui["Persona Attacks List"].ExampleObject:Clone();
- C.Name = i;
- C.BorderSizePixel = 0;
- if (C.Frame:FindFirstChild(v.Type)) then
- C.Frame[v.Type].Visible = true
- end
- C.AttackTitle.Text = v.Name;
- if (v.HPRequired) then
- C.HP.Visible = true;
- C.SP.Visible = false;
- C.HP.Text = tostring(modifyDamage(v.HPRequired, Battle.Characters[BattleInfo.SelectedMember].MaxHealth)).. 'HP'
- elseif (v.SPRequired) then
- C.HP.Visible = false;
- C.SP.Visible = true;
- C.SP.Text = tostring(v.SPRequired).. 'SP'
- end
- for i, x in pairs(Battle.Enemies) do
- if (x.Weak) and x.Weak[v.Type] and x.Health > 0 then
- C.WeakBack.Visible = true;
- C.WeakFront.Visible = true
- end
- end
- C.Parent = PlayerGui["Persona Attacks List"].List.Frame;
- C.Button.Text = ''
- C.Visible = true; end
- end
- end
- for i, v in pairs(PlayerGui['Persona Attacks List'].List.Frame:GetChildren()) do
- if (v:IsA('Frame')) then
- v.Button.Selected = true;
- game:GetService('GuiService').SelectedObject = v.Button;
- break;
- end
- end
- else
- end
- end
- --function Battle:EndBattle()
- -- self.Music:Stop();
- -- self.Music = ReplicatedStorage.Music['Persona 5 - Victory (Victory)'];
- -- self.Music.Looped = true;
- -- self.Music:Play();
- -- PlayerGui.YouWinAnimation.Enabled = true;
- -- local stuff = {};
- -- for i, v in pairs(PlayerGui.YouWinAnimation:GetChildren()) do
- -- stuff[v] = v.Position;
- -- end
- -- local e = 0;
- -- for i,v in pairs(self.Enemies) do
- -- e = e + v.Level;
- -- end
- -- e = math.ceil(e/#self.Enemies);
- -- local c = 1;
- ---- for i, v in pairs(self.Characters) do
- ---- c = c + v.Level;
- ---- end
- -- c = math.ceil(e/#self.Characters)
- -- local EXPGained = math.ceil((e/c)*3.5*((e+c)*math.random(2, 3)));--*math.clamp(math.random(), 1, 1.3)));
- -- EXPGained = EXPGained*DifficultyModifiers[self.Difficulty].Experience
- -- local SP = {}--script.Parent:WaitForChild('YouWinAnimation');
- -- local XYZ = PlayerGui.YouWinAnimation
- -- for i, v in pairs(PlayerGui.YouWinAnimation:GetChildren()) do
- -- SP[v.Name] = setmetatable({}, {__index = v;});
- -- local x = SP[v.Name]
- -- function x:TweenPosition(a,b,c,d, dir, style, num, override)
- -- return v:TweenPosition(UDim2.new(a,b,c,d), dir, style, num or 1, override)
- -- end
- -- SP[v.Name].__newindex = function(self, i, y) v[i] = y; end;
- -- end
- -- --[[
- -- Merciless={
- -- DamageRecieved=1.6;
- -- DamageDealt=0.8;
- -- Experience=0.4;
- -- Money=0.4;
- -- };
- -- --]]
- -- SP.XPLabel:TweenPosition(-0.09, 0, 0.114, -3, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true)
- -- SP.XPFrame:TweenPosition(-0.048, 0, 0.099, -0, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true)
- -- SP.XPNumber:TweenPosition(0.127,0,0.124,-8, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true);
- -- XYZ.XPNumber.Text = safetyZero(0, EXPGained)
- -- spawn(function(y)
- -- wait(1)
- -- for i = 0, EXPGained, EXPGained/10 do
- -- wait()
- -- XYZ.XPNumber.Text = safetyZero(math.ceil(i), EXPGained);
- -- end;
- -- end)
- --
- -- game:GetService('UserInputService').InputBegan:Wait();
- -- SP.MoneyFrame:TweenPosition(-0.012, 0, 0.297, 0, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true)
- -- SP.YenSign:TweenPosition(-0.848, 0, 0.279, -3, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true)
- -- SP.MoneyLabel:TweenPosition(0.058, 0, 0.334, 3, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true);
- -- SP.MoneyNumber:TweenPosition(0.303, 0, 0.307, -8, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true)
- -- --
- -- local Money = 0;
- -- Money = math.ceil(((EXPGained/math.random(3, 5))*DifficultyModifiers[self.Difficulty].Money)*math.clamp(math.random(), 0.5, 1)) + (Battle.MoneyNet or 0)
- -- --MoneyPlaceholder = MoneyPlaceholder + Money;
- --
- --
- -- XYZ.MoneyNumber.Text = safetyZero(0, Money)
- -- spawn(function(x)
- -- wait(1)
- -- for i = 0, Money, Money/10 do
- -- wait()
- -- XYZ.MoneyNumber.Text = safetyZero(math.ceil(i), Money);
- -- end;
- -- end)
- -- game:GetService('UserInputService').InputBegan:Wait();
- -- if (self.ItemsGained) then
- -- SP.ItemFrame:TweenPosition(-0.012, 0, 0.496, 0, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true)
- -- SP.ItemLabel:TweenPosition(0.092, 0, 0.507, -3, Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true)
- -- end
- -- local al = false;
- -- local level = false;
- -- for i, v in pairs(self.Characters) do
- -- local EXPToLevelUp = v.Level^2*3;
- -- local NowExperience = v.EXP + (EXPGained/#self.Characters);
- -- v.EXP = NowExperience;
- -- local levelUp = false;
- -- for i = v.Level, math.huge, 1 do
- -- game:GetService('RunService').RenderStepped:Wait();
- -- if (v.EXP >= EXPToLevelUp) then
- -- --
- -- level = true;
- -- levelUp = true;
- -- v.Level = v.Level+1;
- -- EXPToLevelUp = v.Level^2*5;
- -- local MXH = v.MaxHealth;
- -- local L = (v.Level^1.35)
- -- v.MaxHealth = math.ceil(100+L);
- -- v.MaxSP = math.ceil(v.Level*2.5 + 77.5 + 4)
- -- else
- -- v.EXP = v.EXP
- -- break;
- -- end
- -- end
- -- local newLevel = v.Level;
- -- if (levelUp) then
- -- if (level and not al) then
- -- al = true;
- -- PlayerGui.YouWinAnimation.RankUpFrame:TweenPosition(UDim2.new(0.665,0,0.115,0), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 1, true)
- -- end
- -- local ecks = PlayerGui.YouWinAnimation.RankUpFrame.ScrollingFrame.itemObjectThing:Clone();
- -- ecks.Parent = PlayerGui.YouWinAnimation.RankUpFrame.ScrollingFrame;
- -- ecks.Name = 'LevelUp'
- -- ecks.Visible = true;
- -- ecks.TextLabel.Text = (v.LastName or '')..' '..(v.Name or 'Akira')..' '..' ('..v.Level..')';
- -- game:GetService('UserInputService').InputBegan:Wait();
- -- end
- -- end
- --
- -- al = false;
- -- local y = PlayerGui.YouWinAnimation.RankUpFrame.ScrollingFrame.UIListLayout:Clone();
- -- wait();
- -- PlayerGui.YouWinAnimation.RankUpFrame.ScrollingFrame.CanvasPosition = Vector2.new(0,0)
- -- y.Parent = PlayerGui.YouWinAnimation.RankUpFrame.ScrollingFrame;
- --
- -- for i, v in pairs(PlayerGui.YouWinAnimation:GetChildren()) do
- -- if (v.Name ~= 'Background') then
- -- if (v.Name ~= 'RankUpFrame') then
- -- v.Position = UDim2.new(v.Position.X.Scale-1, v.Position.X.Offset, v.Position.Y.Scale, v.Position.Y.Offset)
- -- else
- -- v.Position = UDim2.new(v.Position.X.Scale+1, v.Position.X.Offset, v.Position.Y.Scale, v.Position.Y.Offset)
- -- end
- -- end
- -- end
- -- workspace["Enemy Container"]:Destroy();
- -- workspace["Party Container"]:Destroy();
- -- for i, v in pairs(stuff) do
- -- i.Position = v;
- -- end
- --
- -- for i, v in pairs(PlayerGui.YouWinAnimation.RankUpFrame.ScrollingFrame:GetChildren()) do
- -- if v:IsA('Frame') and v.Name ~= "itemObjectThing" then
- -- v:Destroy();
- -- end
- -- end
- --
- -- for i, v in pairs(PlayerGui.YouWinAnimation.ItemFrame.ScrollingFrame:GetChildren()) do
- -- if v:IsA('Frame') and v.Name ~= "itemObjectThing" then
- -- v:Destroy();
- -- end
- -- end
- --
- -- for i, v in pairs(game.Lighting:GetChildren()) do
- -- if v.ClassName:match('Effect') then
- -- v.Enabled = false
- -- end
- -- end
- --
- -- PlayerGui.YouWinAnimation.Enabled = false;
- --
- --
- -- --reset camerae by deleting it
- -- workspace.CurrentCamera:Destroy();
- -- wait(.1)
- -- workspace.CurrentCamera.CameraType = Enum.CameraType.Custom;
- -- workspace.CurrentCamera.CameraSubject = game.Players.LocalPlayer.Character.Humanoid;
- -- --
- -- workspace.CurrentCamera.CameraType = Enum.CameraType.Custom;
- -- self.Music:Stop();
- -- _G.Occupied = false;
- -- self.BattleFinished = true;
- -- BattleInfo.BattleStage = nil;
- -- _G.Stage = nil;
- -- local Sky = game:GetService('ReplicatedStorage'):FindFirstChild('TempSky');
- -- local OSky = game:GetService('Lighting'):FindFirstChildWhichIsA('Sky');
- --
- -- if (Sky) then
- -- if (OSky) then
- -- OSky:Destroy();
- -- end
- -- Sky.Name = 'Sky';
- -- Sky.Parent = game:GetService('Lighting');
- -- end
- -- for i, v in pairs(game:GetService('Lighting'):GetChildren()) do
- -- if (v.Name == 'Palace' and v:IsA('PostEffect')) then
- -- v.Enabled = true
- -- end
- -- end
- -- return true;
- --end
- function Battle:EndBattle()
- self.Music:Stop();
- self.Music = ReplicatedStorage.Music['Persona 5 - Victory (Victory)'];
- self.Music.Looped = true;
- self.Music:Play();
- local function Shorten(group)
- local Things = {};
- for i, v in pairs(group:GetChildren()) do
- if (tonumber(v.Name)) then
- Things[tonumber(v.Name)] = {v, v.Size};
- wait();
- v.Size = UDim2.new(0,0,v.Size.Y.Scale,v.Size.Y.Offset)
- end
- end
- return Things;
- end
- local newWinAnimationObject = PlayerGui:WaitForChild('YouWinAnimation')
- newWinAnimationObject = newWinAnimationObject:Clone();
- newWinAnimationObject.Parent = PlayerGui;
- local GuiOne = newWinAnimationObject:WaitForChild'PhaseOne';
- local GuiTwo = newWinAnimationObject:WaitForChild'PhaseTwo';
- local SetOne = Shorten(GuiOne);
- local SetTwo = Shorten(GuiTwo);
- for i, v in pairs(GuiOne:GetChildren()) do
- pcall(function()
- if (not tonumber(v.Name)) then
- v.Position = v.Position + UDim2.new(1)
- end
- end)
- end
- for i, v in pairs(GuiTwo:GetChildren()) do
- pcall(function()
- if (not tonumber(v.Name)) then
- v.Position = v.Position + UDim2.new(-1)
- end
- end)
- end
- newWinAnimationObject.Enabled = true;
- local UserInputService = game:GetService('UserInputService');
- local e = 0;
- for i,v in pairs(self.Enemies) do
- e = e + v.Level;
- end
- e = math.ceil(e/#self.Enemies);
- local c = 1;
- for i, v in pairs(self.Characters) do
- c = c + v.Level;
- end
- c = math.ceil(e/#self.Characters)
- local EXPGained = math.ceil((e/c)*3.5*((e+c)*math.random(2, 3)));--*math.clamp(math.random(), 1, 1.3)));
- EXPGained = EXPGained*DifficultyModifiers[self.Difficulty].Experience
- local Money = math.ceil(((EXPGained/math.random(3, 5))*DifficultyModifiers[self.Difficulty].Money)*math.clamp(math.random(), 0.5, 1)) + (Battle.MoneyNet or 0)
- local function numWithCommas(amount)
- local formatted = amount
- while true do
- game:GetService('RunService').RenderStepped:Wait();
- formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
- if (k==0) then
- break
- end
- k=nil;
- end
- return formatted
- end
- local function Odometize(stringObject, value, addend)
- local stringValue = tostring(stringObject.Text):gsub('%D', '');
- local oldValue = tonumber(stringValue) or 0;
- --stringObject = numWithCommas(tonumber(stringObject))
- local currentValue = oldValue;
- -- script.Parent.Money.Value = script.Parent.Money.Value + (math.sign(Difference) == 1 and math.ceil or math.floor)(math.sign(Difference) * (math.sign(Difference)*Difference/20))
- while game:GetService('RunService').RenderStepped:Wait() do
- local Difference = value - oldValue;
- oldValue = oldValue + (math.sign(Difference) == 1 and math.ceil or math.floor)(math.sign(Difference) * (math.sign(Difference)*Difference/10))--20
- if (math.floor(oldValue) == math.floor(value)) then
- print'Broken!';
- break;
- end
- stringObject.Text = (addend or '')..numWithCommas(oldValue);
- end
- end
- for i, v in pairs(SetOne) do
- v[1]:TweenSize(v[2], Enum.EasingDirection.InOut, Enum.EasingStyle.Linear, 0.05);
- wait(0.025)
- end
- for i, v in pairs(GuiOne:GetChildren()) do
- pcall(function()
- if (not tonumber(v.Name)) then
- v:TweenPosition(v.Position - UDim2.new(1), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.25)
- wait(0.15)
- end
- end)
- end
- GuiOne:TweenPosition(GuiOne.Position+UDim2.new(0.025,0,0,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 5, false)
- spawn(function()--{0.23, 0},{0, 0}
- Odometize(newWinAnimationObject.PhaseOne.ExpCount, EXPGained)
- end)
- repeat until UserInputService.InputBegan:Wait().KeyCode == Enum.KeyCode.Return;
- GuiTwo:TweenPosition(UDim2.new(0,0,0,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Linear, 1, false)
- GuiOne:TweenPosition(UDim2.new(1,0,0,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Linear, 1, true)
- wait(0.9)
- for i, v in pairs(SetTwo) do
- v[1]:TweenSize(v[2], Enum.EasingDirection.InOut, Enum.EasingStyle.Linear, 0.05);
- wait(0.025)
- end
- for i, v in pairs(GuiTwo:GetChildren()) do
- pcall(function()
- if (not tonumber(v.Name)) then
- v:TweenPosition(v.Position + UDim2.new(1), Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.25)
- wait(0.15);
- end
- end)--{0.018, 0},{0.003, 0}
- end
- GuiTwo:TweenPosition(GuiTwo.Position+UDim2.new(0.05,0,0,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 5, true)
- GuiOne:TweenPosition(GuiOne.Position+UDim2.new(0.05,0,0,0), Enum.EasingDirection.InOut, Enum.EasingStyle.Sine, 5, true)
- spawn(function()
- Odometize(GuiTwo.MoneyCounter, Money, '¥')
- end)
- repeat until UserInputService.InputBegan:Wait().KeyCode == Enum.KeyCode.Return;
- workspace["Enemy Container"]:Destroy();
- workspace["Party Container"]:Destroy();
- newWinAnimationObject:Destroy();
- --reset camerae by deleting it
- workspace.CurrentCamera:Destroy();
- wait(.1)
- workspace.CurrentCamera.CameraType = Enum.CameraType.Custom;
- workspace.CurrentCamera.CameraSubject = game.Players.LocalPlayer.Character.Humanoid;
- --
- workspace.CurrentCamera.CameraType = Enum.CameraType.Custom;
- self.Music:Stop();
- _G.Occupied = false;
- self.BattleFinished = true;
- BattleInfo.BattleStage = nil;
- _G.Stage = nil;
- self.OneMore = false;
- local Sky = game:GetService('ReplicatedStorage'):FindFirstChild('TempSky');
- local OSky = game:GetService('Lighting'):FindFirstChildWhichIsA('Sky');
- if (Sky) then
- if (OSky) then
- OSky:Destroy();
- end
- Sky.Name = 'Sky';
- Sky.Parent = game:GetService('Lighting');
- end
- for i, v in pairs(game:GetService('Lighting'):GetChildren()) do
- if (v.Name == 'Scene' and v:IsA('PostEffect')) then
- v.Enabled = true
- end
- if (v.Name == 'BattleEffect') then
- v:Destroy();
- end
- end
- --PlayerGui.Reticle.Enabled = false;
- PlayerGui.Reticle.Adornee = nil
- return true;
- end
- function showLabel(text, duration)
- text = text or '???'
- duration = duration or 1
- local Label = PlayerGui.Statuses.Frame:Clone();
- Label.Name = "CopiedStatusEffect"
- Label.Parent = PlayerGui.Statuses;
- Label.Frame.TextLabel.Text = text
- for i = 1, 0, -0.1 do
- Label.BackgroundTransparency = i;
- game:GetService('RunService').RenderStepped:Wait();
- end
- wait(duration)
- for i = 0, 1, 0.1 do
- Label.BackgroundTransparency = i;
- game:GetService('RunService').RenderStepped:Wait();
- end
- end
- function Battle:showLabel(text, duration)
- showLabel(text, duration)
- end
- function Battle.new(party, enemies, ambush, difficulty, ba, music, boss)
- _G.Occupied = true;
- CurrentCameraShake = CameraShaker.new(Enum.RenderPriority.Camera.Value+1, function(shakeOffset)
- workspace.CurrentCamera.CFrame = workspace.CurrentCamera.CFrame * shakeOffset;
- end)
- wait();
- coroutine.wrap(function()
- CurrentCameraShake:Start();
- CurrentCameraShake:ShakeSustain(CameraShaker.Presets.HandheldCamera);
- end)();
- _G.StartLoad(true)
- CMS:Disable()
- game.Players.LocalPlayer.Character.PrimaryPart.Anchored = true;
- EnemyAPI:Initialize() --start the enemy api
- for i, v in pairs(Battle) do
- print(i, v)
- end
- local battleArea = ba:Clone()
- battleArea.Name = "Arena";
- battleArea:SetPrimaryPartCFrame(CFrame.new(0,2500,0))
- for i, v in pairs(game:GetService('Lighting'):GetChildren()) do
- if (v.Name ~= 'e' and v:IsA('PostEffect')) then
- v.Enabled = false
- end
- end
- if (battleArea:FindFirstChild('Lighting')) then
- --preserve old lighting properties
- local PreLighting = Instance.new('Folder', game:GetService'ReplicatedStorage');
- PreLighting.Name = "Previous Lighting";
- for i, v in pairs(battleArea.Lighting:GetChildren()) do
- if (v:IsA('PostEffect') and v.Name ~= 'e') then
- v.Enabled = false;
- end
- local NewValue = Instance.new(v.ClassName, PreLighting);
- local success, info = pcall(function() --put it in a protected call so any invalid properties won't break the script
- NewValue.Name = v.Name;
- NewValue.Value = game:GetService('Lighting')[v.Name];
- end)
- if (not success) then --remove the lingering variable and continue
- NewValue:Destroy();
- else
- warn('Setting Lighting value of', v.Name, 'to', v.Value);
- game:GetService('Lighting')[v.Name] = v.Value;
- end
- end
- --begin tweening properties
- end
- battleArea.Parent = workspace;
- local self = Battle;
- self.OneMore = false;
- BattleInfo = { --Independant turns for every character.
- EnemyTurns = {}; --one for the enemies
- PlayerTurns = {}; --one for the player. this allows for rakukaja to turn on/off not when it's Akira's turn
- EnemyActions = {};
- MemberActions = {};
- MemberAnimations = {};
- SelectedPersonaAttack = nil;
- BattleStage = 'Main'; --using general identifiers for battlestage
- SelectedMember = 0; --Default to 0 so we can know this is the start of the battle.
- }
- self.BattleFinished = false;
- self.PositionBeforeBattle = Character:GetPrimaryPartCFrame();
- --set camera type to scriptable so we can manipulate the camera with ease
- workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable;
- --defining self properties for easier access
- self.Difficulty = difficulty;
- self.Characters = party;
- for i, v in pairs(self.Characters) do
- v.Debuffs = {};
- v.Guard = false;
- end
- Metatable(self.Characters) --give party memberds a metatable
- self.Ambush = ambush;
- self.Enemies = {};
- self.EnemiesString = enemies;
- local Keyword = ambush and 'Ambush Spawns' or 'Spawns'
- local Spawns = battleArea:WaitForChild(Keyword)
- for i, v in pairs(enemies) do
- if (not boss and i > #Spawns['Enemy Spawns']:GetChildren()) then
- break; --so overloading doesnt happen
- end
- self.Enemies[i] = getPersonaFromString(v) --convert all personas to actual tables so we can use them in battle
- self.Enemies[i].MaxHealth = v.Health; --set maxhealth property before they even spawn for ezpz work
- wait()
- end
- Metatable(self.Enemies) --give enemy members a metatable;
- for i, v in pairs(self.Characters) do
- v.Enemies = {};
- end
- self.BattleArea = battleArea;
- if (self.Ambush) then
- self:AmbushPosition();
- end
- if (self.BattleArea:FindFirstChild('Ambush Spawns')) then
- for i, v in next, self.BattleArea:FindFirstChild('Ambush Spawns'):GetDescendants() do
- if (v:IsA('BasePart')) then
- v.Transparency = 1;
- end
- end
- end
- if (self.BattleArea:FindFirstChild('Spawns')) then
- for i, v in next, self.BattleArea:FindFirstChild('Spawns'):GetDescendants() do
- if (v:IsA('BasePart')) then
- v.Transparency = 1;
- end
- end
- end
- if (self.BattleArea:FindFirstChildWhichIsA('Sky')) then
- local Sky = game:GetService('Lighting'):FindFirstChildWhichIsA("Sky");
- if (Sky) then
- Sky.Parent = game:GetService('ReplicatedStorage');
- Sky.Name = 'TempSky';
- end
- self.BattleArea:FindFirstChildWhichIsA('Sky'):Clone().Parent = game:GetService('Lighting');
- end
- self.BattleFolder = Spawns;
- self.PartySpawns = Spawns['Party Spawns']
- self.EnemySpawns = Spawns['Enemy Spawns']
- self.PartyContainer = workspace:FindFirstChild('Party Container') and workspace['Party Container']:ClearAllChildren() and workspace['Party Container'] or Instance.new('Folder')
- self.PartyContainer.Name = 'Party Container'
- self.PartyContainer.Parent = workspace;
- --Begin moving the entire party to the battle area
- for index, x in pairs(party) do
- for i, v in pairs(ReplicatedStorage["Party Members"]:GetChildren()) do
- if (v.Name:lower():match(x.Name:lower())) and (x.InParty or index == 1) then --Allow case-insensitivity just to make sure I can cover my mistakes.
- local PartyMemberClone = v:Clone()
- PartyMemberClone:WaitForChild('Humanoid').HipHeight = recalculateHipHeight(PartyMemberClone);
- local SpawnCFrame = Spawns:WaitForChild('Party Spawns'):WaitForChild('Spawn'..index).CFrame + Vector3.new(0, math.abs(PartyMemberClone:WaitForChild("Humanoid").HipHeight), 0)
- PartyMemberClone.Parent = self.PartyContainer;
- PartyMemberClone.Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
- PartyMemberClone.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
- PartyMemberClone.Humanoid.WalkSpeed = Character.Humanoid.WalkSpeed;
- PartyMemberClone.PrimaryPart.Anchored = false;
- if (v:FindFirstChild('Animations')) then
- -- for i, x in pairs(v.Animations:getChildren()) do
- -- LoadAnimation(x, PartyMemberClone:WaitForChild('Humanoid')):Play();
- -- end
- if v.Animations:FindFirstChild("Idle") then
- LoadAnimation(v.Animations.Idle, PartyMemberClone:WaitForChild("Humanoid")):Play();
- end
- end
- PartyMemberClone:SetPrimaryPartCFrame(SpawnCFrame)
- end
- end
- end
- game.Players.LocalPlayer.Character.PrimaryPart.Velocity = Vector3.new();
- game.Players.LocalPlayer.Character:SetPrimaryPartCFrame(Spawns:WaitForChild('Party Spawns')['Spawn1'].CFrame + Vector3.new(0,game.Players.LocalPlayer.Character.Humanoid.HipHeight+.5,0)) --teleport the character to the first spawn
- if _G.Music then _G.Music:Pause() end;
- if (not music) then
- if (Keyword == 'Ambush Spawns') then
- self.Music = ReplicatedStorage.Music['Persona 5 - Willpower (Awakening)']
- else
- self.Music = ReplicatedStorage.Music["Persona 5 - Last Surprise (Ambush)"]
- end
- else
- self.Music = music;
- end;
- --local sign = math.sign(self.Music.Volume - 0); local cond1 = (sign == 1 and 0 or self.Music.Volume); local cond2 = (sign == 1 and self.Music.Volume or 0); local cond3 = (sign == 1 and 0.1 or -0.1)
- local ms13 = 0.5;
- self.Music.Looped = true;
- self.Music.Volume = 0;
- self.Music:Play();
- coroutine.wrap(function()
- for i = 0, ms13, ms13/10 do
- wait();
- --game:GetService('RunService').RenderStepped:Wait();
- print(i);
- self.Music.Volume = i;
- end
- end)();
- for i, v in pairs(game:GetService'Lighting':GetChildren()) do
- if v.Name:lower():match('dungeon') or v.Name:match('ambush') then
- if (self.Ambush and v.Name:lower():match('ambush')) then
- v.Enabled = true;
- elseif (not self.Ambush) and (not v.Name:lower():match('ambush') and v.Name:lower():match('dungeon')) then
- v.Enabled = true;
- else
- v.Enabled = false;
- end
- end
- end
- Signal = PlayerGui:WaitForChild("Persona Attacks List"):GetPropertyChangedSignal('Enabled'):Connect(function()
- RefreshPersonaList();
- end)
- spawn(function()
- Battle:Failsafe()
- end)
- spawn(function(a)
- wait(2)
- game.Players.LocalPlayer.Character.PrimaryPart.Anchored = true;
- end)
- local EnemySpawns = Spawns:WaitForChild('Enemy Spawns')
- local EnemyContainer = workspace:FindFirstChild('Enemy Container') and workspace['Enemy Container']:ClearAllChildren() and workspace['Enemy Container'] or Instance.new('Folder')
- EnemyContainer.Name = 'Enemy Container'
- EnemyContainer.Parent = workspace;
- self.EnemyContainer = EnemyContainer;
- self.Boss = boss;
- local ChosenMember = Battle:selectViableMember(true);
- if (tonumber(ChosenMember)) then
- Battle:CharacterPosition(ChosenMember, nil, true);
- end
- for index, x in pairs(enemies) do
- if (not boss and index > #EnemySpawns:GetChildren()) then
- break; --prevent any infinite yields / errors
- end
- for i, v in pairs(ReplicatedStorage["Personas"]:GetChildren()) do
- if (v.Name:lower():match(x:lower())) then --enemies will be string values. their models will be taken from Persona List
- v = v:Clone();
- for i, v in pairs(v:GetDescendants()) do
- if v:IsA("BasePart") then
- local Trans = Instance.new('NumberValue', v);
- Trans.Value = v.Value;
- Trans.Name = 'OriginalTransparency';
- v.Transparency = 1;
- end
- end
- local n = self.Enemies[index] and self.Enemies[index].CustomSize or {};
- local H = v:WaitForChild('Humanoid')
- H.BodyDepthScale.Value = n.Depth or 1.25;
- H.BodyHeightScale.Value = n.Height or 1.35;
- H.BodyProportionScale.Value = n.Proportions or 1.2;
- H.BodyTypeScale.Value = n.Type or 1.75;
- H.BodyWidthScale.Value = n.Width or 1.2;
- H.HeadScale.Value = n.Head or 1.3;
- wait()
- H.HipHeight = recalculateHipHeight(H.Parent);
- spawn(function(a)
- wait(1.5)
- v.PrimaryPart.Anchored = true;
- end)
- local Indicator = Instance.new('StringValue', v)
- Indicator.Name = 'PersonaName'
- Indicator.Value = v.Name;
- v.Name = index
- v.Parent = EnemyContainer;
- --v:WaitForChild('Humanoid').HipHeight = 2.462;
- local Selector = not boss and Spawns:WaitForChild('Enemy Spawns'):WaitForChild('Spawn'..index) or battleArea:WaitForChild('BossSpawn')
- v:SetPrimaryPartCFrame(Selector.CFrame + Vector3.new(0,v.Humanoid.HipHeight + Selector.Size.Y/2, 0))
- spawn(function()
- local Sp = ReplicatedStorage.EffectStorage.Spawn:Clone();
- Sp.Parent = workspace;
- Sp:SetPrimaryPartCFrame(v:GetPrimaryPartCFrame() + Vector3.new(0,0,2.5));
- for i, v in pairs(Sp:GetDescendants()) do
- if (v:IsA('ParticleEmitter')) then
- v:Emit(150)
- end
- end
- ReplicatedStorage.EffectStorage.Sounds.EnemySpawn:Play();
- wait(.4);
- for i, v in pairs(v:GetDescendants()) do
- if v:IsA("BasePart") and v.Name:lower() ~= 'humanoidrootpart' then
- if v:findFirstChild('OriginalTransparency') then
- Tween(v, TweenInfo.new(.1), {Transparency = v.OriginalTransparency.Value}):Play();
- end
- end
- end
- end)
- game:GetService('RunService').RenderStepped:Wait() --prevent any bad things
- wait(1/#enemies)
- end
- end
- end
- _G.EndLoad()
- return Battle:NewTurn() --call the battle's new turn function
- end
- ospawn = spawn;
- spawn = function(f, ...)
- local a = {...};
- return ospawn(function()
- f(unpack(a))
- end)
- end
- function Effect(e, t, attack, targetIsEnemy, isEnemy, why, self, ia)
- --target, attack used, is target enemy?, (if t is enemy) target character's id, Battle (self), IgnoreAnimation
- --if (targetIsEnemy) then
- print(e, t)
- for i, v in pairs(attack) do
- print(i, v)
- end
- if (attack.Effect) then
- --badeffect
- if (isEnemy) then
- --local Char = self:GetCharacterFromID(BattleInfo.SelectedEnemyGuy);
- if (why) then
- local Char = self:GetCharacterFromID(why);
- if (typeof(attack.Effect) == 'function') then
- --Accepts a table with the following args: {PrimaryPart, IgnoreAnimation, TargetPart};
- Effects[attack.Effect]({PrimaryPart = Char.PrimaryPart,
- IgnoreAnimation = ia,
- TargetPart = Battle:GetEnemyFromName(e.ID).PrimaryPart,
- TargetFolder = self.PartyContainer,
- EnemySpawn = self.PartySpawns}, Battle)
- elseif Effects[attack.Effect] then
- Effects[attack.Effect]({PrimaryPart = Char.PrimaryPart,
- IgnoreAnimation = ia,
- TargetPart = Battle:GetEnemyFromName(e.ID).PrimaryPart,
- EnemySpawn = self.PartySpawns,
- TargetFolder = self.PartyContainer
- }, Battle)
- end
- end
- else
- local Char = self.EnemyContainer:FindFirstChild(t.ID)
- local Me = Battle:GetCharacterFromID(e.Name)
- if (Char and Me) then
- if (typeof(attack.Effect) == 'function') then
- Attacks[attack.Effect]({PrimaryPart = Char.PrimaryPart,
- IgnoreAnimation = ia,
- TargetPart = Me.PrimaryPart,
- EnemySpawn = self.EnemySpawns
- }, Battle)
- elseif Effects[attack.Effect] then
- Effects[attack.Effect]({PrimaryPart = Char.PrimaryPart, --enemy's part
- IgnoreAnimation = ia, --ignore animation?
- TargetPart = Me.PrimaryPart, --my primary part
- TargetFolder = self.EnemyContainer, --enemy's folder? WHAT
- EnemySpawn = self.EnemySpawns
- }, Battle)
- end
- else
- warn('Me: ', Me);
- end
- end
- elseif (Effects[attack.Type..'Effect']) then
- if (isEnemy) then
- if (why) then
- local Char = self:GetCharacterFromID(why);
- Effects[attack.Type..'Effect'](
- {PrimaryPart = Char.PrimaryPart,
- IgnoreAnimation = ia, TargetPart =
- Battle:GetEnemyFromName(e.ID).PrimaryPart,
- TargetFolder = self.PartyContainer,
- EnemySpawn = self.PartySpawns
- }, Battle)
- end
- else
- local Char = self.EnemyContainer:WaitForChild(t.ID)
- local Me = Battle:GetCharacterFromID(e.Name)
- if (Char and Me) then
- Effects[attack.Type..'Effect']({
- PrimaryPart = Char.PrimaryPart,
- IgnoreAnimation = ia,
- TargetPart = Me.PrimaryPart,
- TargetFolder = self.PartyContainer,
- EnemySpawn = self.EnemySpawns
- }, Battle)
- else
- warn('Char:', Char, 'Me:', Me)
- end
- end
- end
- --end
- end
- local BigAttackHappening = false;
- function Battle:Damage(attacker, target, attack, silent)
- local DownExclusionBecauseScrewThisStupidCodebase = nil;
- local Yield = attack.Yield
- local isEnemy = (not attacker.Persona and true) or false;
- local targetIsEnemy = (not target.Persona) or false
- local isHeal = attack.Type:lower() == "buff" or attack.Type:lower() == "kaja"
- local isMultiHit = attack.Damages or attack.Heals;
- local PositionOfCharacterAttacked;
- for i, v in pairs(self.Characters) do
- if (v.Name == (isEnemy and target.Name or attacker.Name)) then
- PositionOfCharacterAttacked = i;
- end
- end
- if (not silent) then
- coroutine.wrap(function()
- showLabel(attack.Name, 1.5)
- end)();
- end
- target.Debuffs = target.Debuffs or {};
- attacker.Debuffs = attacker.Debuffs or {};
- local AttackerDebuffTable = attacker and attacker.Debuffs;
- local TargetDebuffTable = target and target.Debuffs;
- if (attack.SPRequired) then
- attacker:SubtractSP(attack.SPRequired)
- elseif (attack.HPRequired) then
- attacker:SubtractHealth(modifyDamage(attack.HPRequired, attacker.MaxHealth))
- end
- local toggleOneMore;
- local HealingTarget = isEnemy and self.Enemies or self.Characters;
- if (isHeal) then
- if (attack.CustomMessage) then
- coroutine.wrap(showLabel)(attack.CustomMessage, 2.5);
- end
- if (isMultiHit) then
- for i, target in pairs(HealingTarget) do
- if (isEnemy) then
- Battle:MoveCameraToEnemy(i, {yield = true})
- else
- Battle:MoveCameraToCharacter(i, {yield = true})
- end
- -- for i, v in pairs(attack.Debuffs or {}) do
- -- local x = {};
- -- for i, v in pairs(v) do
- -- x[i] = v;
- -- end
- -- BattleInfo.PlayerTurns[PositionOfCharacterAttacked] = BattleInfo.PlayerTurns[PositionOfCharacterAttacked] or 1;
- -- x.TurnAdded = isEnemy and BattleInfo.PlayerTurns[PositionOfCharacterAttacked] or BattleInfo.EnemyTurns[target.ID];
- -- target:AddDebuff(x)
- -- end
- if (attack.Type2 == 'Revive' or target.Health > 0) then target:Heal(attack.Heal) end
- end
- else
- if (attack.CustomMessage) then
- coroutine.wrap(showLabel)(attack.CustomMessage, 2.5);
- end
- -- for i, v in pairs(attack.Debuffs or {}) do
- -- local x = {};
- -- for i, v in pairs(v) do
- -- x[i] = v;
- -- end
- -- BattleInfo.PlayerTurns[PositionOfCharacterAttacked] = BattleInfo.PlayerTurns[PositionOfCharacterAttacked] or 1;
- -- x.TurnAdded = isEnemy and BattleInfo.PlayerTurns[PositionOfCharacterAttacked] or BattleInfo.EnemyTurns[target.ID];
- -- target:AddDebuff(x)
- -- end
- if (isEnemy) then
- Battle:MoveCameraToEnemy(target.ID, {yield = true})
- if (attack.Type2 == 'Revive' or target.Health > 0) then target:Heal(attack.Heal) end
- else
- Battle:MoveCameraToCharacter(PositionOfCharacterAttacked, {yield = true})
- if (attack.Type2 == 'Revive' or target.Health > 0) then self.Characters[BattleInfo.SelectedEnemyGuy]:Heal(attack.Heal) end
- end
- end
- return 0; --finish the turn and healing.
- end
- if (attack.SelfHeal) then
- attacker:Heal(attack.SelfHeal);
- end
- if (attack.SPRecovered or attack.AddSP) then
- attacker:AddSP(attack.SPRecovered or attack.AddSP)
- end
- --Temporary Stats and Flags for Attacking
- local Evasion = 0;
- local Technical = false;
- local Hunger = false;
- local Def = 1;
- local Atk = 1;
- local a;
- --local d = (e.Equipped and not isEnemy) and (t.Equipped.Accessory.Defense or 0) or t.Defense or 85;
- local d = 0;
- if (target.Equipped and target.Equipped.Defense) then
- local EquippedDefense = Items[target.Equipped.Defense];
- d = EquippedDefense.Defense or 0;
- end
- d = d+ ((isEnemy and target.Persona.Stats.Endurance or target.EnemyStats.Endurance or 0)*1.25)
- d = d * Def
- local l = attacker.Level; --note: later down the line, we will be relying on persona stats and not level-based damage.
- if (not attack.Type:lower() == "physical") then
- if (isEnemy) then
- a = (attacker.EnemyStats or attacker.Stats).Magic+(attack.Damage)
- else
- a = attacker.Persona.Stats.Magic*1.25+attack.Damage*1.45
- a = a+(attack.Damage or 0)
- end
- else --if it IS physical
- --note: don't use a strict system, rely on strings so modifying data post-release will be easier (FINISHED)
- local AttackerEquipped = attacker.Equipped and Items[attacker.Equipped.Melee]
- if isEnemy == false and (AttackerEquipped and AttackerEquipped.Damage) then
- a = attacker.Persona.Stats.Strength*1.25+(AttackerEquipped.Damage)
- elseif (isEnemy) then
- a = (attacker.EnemyStats or attacker.Stats).Strength*1.25+(attacker.EnemyStats or attacker.Stats).Strength*1.45
- else
- a = attacker.Persona.Stats.Strength*1.25 + attack.Damage*1.25
- end
- end
- local Weak = target.Weak or (target.Persona and target.Persona.Weak or nil) or {}
- local Strong = target.Strong or (target.Persona and target.Persona.Strong or nil) or {}
- local WeakVar = Weak[attack.Type];
- local StrongVar = Strong[attack.Type];
- --
- if (target and target.Equipped and Items[target.Equipped.Defense]) then
- local ec = Items[target.Equipped.Defense]
- if ec.Evasion then
- Evasion = Evasion - ec.Evasion; --subtract the evasion from the thing --45
- end
- end
- if (attacker and attacker.Equipped and Items[attacker.Equipped.Defense]) then
- local ec = Items[attacker.Equipped.Defense] --incase brainwash is in effect
- if (ec.Evasion) then
- Evasion = Evasion + ec.Evasion
- end
- end
- if (attacker and attacker.Debuffs and attacker.Debuffs.EvasionUp) then
- Evasion = Evasion + 30;
- elseif (attacker and attacker.Debuffs and attacker.Debuffs.EvasionDown) then
- Evasion = Evasion - 30; --70
- end --get the attacker's evasion
- --add or subtract evasion points for attacker/defender benefit
- Evasion = Evasion - ((not target.Persona and target.EnemyStats) or target.Persona.Stats or {}).Agility or 0;
- Evasion = Evasion + ((not attacker.Persona and attacker.EnemyStats) or attacker.Persona.Stats or {}).Agility or 0;
- Evasion = math.abs(Evasion);
- local Divisor = 300; --divide the Evasion value by Divisor.
- local GroupToAttack, Type = (targetIsEnemy and self.Enemies) or self.Characters, (targetIsEnemy and "Enemies") or "Characters"
- --Stat Modification
- if (attacker and attacker.Debuffs and attacker.Debuffs.Hunger) then
- Hunger = true;
- --
- end
- if (target and target.Debuffs and target.Debuffs.DefenseDown) then
- Def = 0.7
- --
- end
- if (target and target.Debuffs and target.Debuffs.DefenseUp) then
- Def = 1.5
- --
- end
- if (attacker and attacker.Debuffs and attacker.Debuffs.AttackUp) then
- Atk = 1.2
- --
- end
- if (attacker and attacker.Debuffs and attacker.Debuffs.AttackDown) then
- Atk = 0.7
- --
- end
- -- if (attack.Type2 == 'Revive' or value.Health > 0) then
- -- value:Heal(attack.Heal)
- -- end
- -- if (attack.Debuffs) then
- -- for i, v in pairs(attack.Debuff) do
- -- value:AddDebuff(v)
- -- end
- -- end
- if (typeof(attack.Damage) == 'string') then
- target:SubtractHealth(target.Health / 2);
- return true;
- end
- local constant = .6969
- local dif = DifficultyModifiers[self.Difficulty];
- local DamageMod = 1;
- if (isEnemy) then
- DamageMod = dif.DamageRecieved
- else
- DamageMod = dif.DamageDealt
- end
- local Guard = target.Guard and 0.45 or 1;
- if Difficulty == 'Satanic' then
- Guard = Guard==0.45 and 0.1 or Guard;
- end
- local BTNCount = not isEnemy and (1 + (self.BatonCount and self.BatonCount/1.75 or 0)) or 1;
- print('BATON PASS!', BTNCount)
- a = a*Atk
- local AlreadyAttacked;
- local AlreadyCritNotif;
- local AlreadyAnimated;
- local CameraMoved;
- local CritStorage = {}; --Store criticals beforehand so we only show the animation once at the start of the animation;
- local CritCounter = 0;
- if (not isEnemy) then
- for i, v in pairs(self.Enemies) do
- if (attack.Damages) or v.ID == target.ID then
- local Luck = isEnemy and attacker.EnemyStats.Luck or attacker.Persona.Stats.Luck
- local Formula = math.clamp((Luck/100+(Luck and Luck/100 or 0)+(Luck/1000)+(attack.CritChance and attack.CritChance/1000 or 0/1000))/1.5, 0, 1000)/(math.pi);
- local crit = (tonumber(v.ID) == 2) or ((not v.Uncritable) and math.random() < Formula)
- if (v.Weak and v.Weak[attack.Type] or crit) and (not (v.Null and v.Null[attack.Type])) then
- CritCounter = CritCounter+1;
- CritStorage[tonumber(v.ID or i)] = {v.ID, i};
- --impwarn('CritStorage Length:', #CritStorage)
- end
- end
- end
- end
- if (not AlreadyAnimated) and (not isEnemy) and (CritCounter > 0) and (not self.OneMore) then
- AlreadyAnimated=true;
- local Audio = ReplicatedStorage:WaitForChild('SFX'):WaitForChild('Weak');
- Audio = Audio:Clone();
- Audio.Parent = PlayerGui;
- Audio.PlayOnRemove = true;
- Audio:Destroy();
- self:CharacterPosition(nil, true, true)
- local Animations = ReplicatedStorage:WaitForChild('AnimationAssets'):WaitForChild('CritAnim'):GetChildren()
- local Animation = LoadAnimation(Animations[math.random(1, #Animations)], Battle:GetCharacterFromID(BattleInfo.SelectedMember):FindFirstChild('Humanoid', true))
- Animation:AdjustWeight(1, 2)
- Animation:Play();
- wait(2);
- if (self.Ambush) then
- self:AmbushPosition()
- end
- end
- local attackFunction = function(target, attack, Iterator)
- local randomValue = math.random();
- if (not game:GetService'RunService':IsStudio()) and Evasion ~= 0 and (randomValue < math.abs(Evasion/Divisor)*0.9) and attack.Type ~= 'Buff' and attack.Type ~= 'Kaja' and attack.Type2 ~= 'Debuff' then
- impwarn('Missed! Raw Evasion Chance:', Evasion, 'Modified Evasion Change:', Evasion/Divisor, "Random value:", randomValue);
- ReplicatedStorage.Music:WaitForChild('Miss'):Play();
- else
- local crit;
- if (isEnemy) then
- local Luck = isEnemy and attacker.EnemyStats.Luck or attacker.Persona.Stats.Luck
- local Formula = math.clamp((Luck/100+(Luck and Luck/100 or 0)+(Luck/1000)+(attack.CritChance and attack.CritChance/1000 or 0/1000))/1.5, 0, 1000)/(math.pi);
- warn('Formula:', Formula)
- crit = ((not target.Uncritable) and math.random() < Formula)
- else
- crit = CritStorage[tonumber(target.ID)] ~= nil
- impwarn('Critical Status:', crit)
- end
- if (TargetDebuffTable) then
- for i, v in pairs(TargetDebuffTable) do
- local affinity = tostring(attack.Type):lower()
- if (Technicals[affinity] and Technicals[affinity][v.Name:lower()]) or (v.Name:lower() == 'dizzy' or v.Name:lower() == 'sleep') then
- Technical = true;
- if (v.Name ~= 'sleep' and v.Name ~= 'dizzy') then
- TargetDebuffTable[i] = nil;
- end
- end
- end
- end
- if (not CameraMoved) and (not silent) and (not isHeal) and (not self.Ambush) then
- CameraMoved=true;
- if (isEnemy) then
- if (isMultiHit and not isHeal) then
- Battle:PartyAttacked()
- else
- Battle:CharacterAttacked(PositionOfCharacterAttacked)
- end
- elseif (not isEnemy) then
- local Char = self.EnemyContainer:WaitForChild(target.ID)
- Battle:CharacterAttacking(BattleInfo.SelectedMember, Char.PrimaryPart, CritCounter>0, attack.Damages or attack.Heals)
- wait(0.25)
- end
- end
- if (target.Health > 0) then
- if (attack.Yield and not AlreadyAttacked) or (((not attack.Damages) and (not attack.Heals))) then
- AlreadyAttacked = true;
- Effect(attacker, target, attack, targetIsEnemy, isEnemy, PositionOfCharacterAttacked, Battle);
- elseif (not attack.Yield) then
- coroutine.wrap(Effect)(attacker, target, attack, targetIsEnemy, isEnemy, PositionOfCharacterAttacked, Battle);
- end
- end
- print('damage guy called', target)
- if (crit or WeakVar) and not (target.Null and target.Null[attack.Type]) then
- local HeavyHit = ReplicatedStorage.Music:WaitForChild('HeavyHit')
- HeavyHit = HeavyHit:Clone()
- HeavyHit.Parent = game.Players.LocalPlayer.PlayerGui;
- HeavyHit.PlayOnRemove = true;
- HeavyHit:Destroy();
- if (not AlreadyCritNotif) and (not target.Guard) then
- if ((WeakVar or crit) and not isEnemy) then --so morgana doesn't shout HAHA LOOKING COOL JOKER when i get murdered'
- if (target.Debuffs) then
- if (not target.Debuffs.Down) and (not self.OneMore) and (not target.Guard) then --check for self.onemore so i don't play the stupid sound over and over and over and over and over again'
- AlreadyCritNotif = true;
- local HeavyHit = ReplicatedStorage.Music:WaitForChild('Looking Cool Joker!') --what have i done
- HeavyHit = HeavyHit:Clone()
- HeavyHit.Parent = game.Players.LocalPlayer.PlayerGui;
- HeavyHit.PlayOnRemove = true;
- HeavyHit:Destroy();
- local Name = attacker.Name:lower();
- local RandomDownAwareness = {};
- if (Name == "ryuji") then
- RandomDownAwareness = {
- "Wow, Skull. You really showed me..",
- "Nice one, Skull!",
- "Wow, Skull! You're actually good at something for once!",
- "Great, Skull! Pass the baton and follow up!",
- "Awesome, Skull! You wiped a few enemies off their feet!"
- };
- elseif (Name == "Yuki") then
- RandomDownAwareness = {
- "Wow, Blizzard! You got them!",
- "Huh, for a shut-in chick, you have some skills! Good job, Blizzard!",
- "Great job, Blizzard! You knocked a few enemies off their feet!",
- "Nice exhibition of those \"magical powers\", Blizzard!",
- "Exemplary job, Blizzard! Pass the baton and follow up!"
- }
- elseif (Name == "akira") then
- RandomDownAwareness = {
- "Woah, Joker! You did it!",
- "Woaaah, looking cool Joker!",
- "For a quite uncharming messy-haired troublemaker, you're good at fighting! Good job, Joker!",
- "Nice job, Joker! You knocked a few enemies off their feet!",
- "Your powers are incredible, Joker!",
- }
- elseif (Name == "ann") then
- RandomDownAwareness = {
- "Panther knocked them down with style and grace!",
- "Great job, Panther! Keep it up!",
- "From one female to another, you're beautiful, Panther!",
- "Nice one, Panther! Pass the baton and follow up!",
- "A beautiful rose has thorns!",
- "Nice one, Panther!"
- }
- end
- local availableSpeakers = {}; --get a random list of the characters
- for i, v in pairs(self.Characters) do
- if (v.Name:lower() ~= Name) and i ~= 1 then --so 1. the downer can't congratulate themselves (downer lol)
- availableSpeakers[#availableSpeakers+1] = v.Name;
- else
- print(v.Name:lower(), Name, self.Characters[1].Name:lower(), #availableSpeakers);
- end
- end
- local Member = availableSpeakers[math.random(1, #availableSpeakers)];
- Member = Member:sub(1,1):upper()..Member:sub(2); --capitalize first letter of names
- Member = ReplicatedStorage:WaitForChild('Party Members'):WaitForChild(Member);
- local Chosen = RandomDownAwareness[math.random(1, #RandomDownAwareness)];
- warn'hrmm'
- toggleOneMore = "W"
- _G.BattleAnnouncement(Chosen, Member, true);
- end
- end
- elseif ((WeakVar or crit) and isEnemy) then --so morgana doesn't shout HAHA LOOKING COOL JOKER when i get murdered'
- if (target.Debuffs) then
- if (not target.Debuffs.Down) and (not self.knockedChar) and (not target.Guard) then --check for self.onemore so i don't play the stupid sound over and over and over and over and over again'
- self.knockedChar = true;
- local Name = target.Name:lower();
- local RandomDownAwareness = {};
- if (Name == "ryuji") then
- RandomDownAwareness = {
- "Skull, you're biting off more than what you can chew! Stay calm!",
- "Everyone, Skull is down! Be careful!",
- "One of the strongest in our team is knocked out! Watch out, everyone!",
- "If they can take down Skull, they can take down Joker! Protect them both at all costs!",
- "Come on, Skull! Get up!"
- }
- elseif (Name == "yuki") then
- RandomDownAwareness = {
- "Everyone, the most u- I mean, a party member is down! Take care of them!",
- "King's been knocked off their feet! Protect her at all costs!",
- "Guys, Ice-Girl has been knocked off her last leg! Watch out, everyone!",
- "They took down Ice-Girl! Everyone, be careful!",
- "King, get up! We need you!"
- }
- elseif (Name == "akira") then
- RandomDownAwareness = {
- "Joker? Hey, stop playing games! Get up!",
- "Joker! This isn't the time to be playing around!",
- "Everyone, Joker's been knocked off his feet! Take some time to tend to his wounds!",
- "Uh, guys! Joker's not doing too well!",
- "Joker, hurry and rise like a phoenix!",
- }
- elseif (Name == "ann") then
- RandomDownAwareness = {
- -- "Alright, Panther! Strike them down with style and grace!",
- -- "Alright, Panther! Time to start the counter-attack!"
- "Everyone, Panther has been downed! Watch her carefully!",
- "Discount K- I mean, Panther has been knocked off of her feet! Stay cautious, everyone!",
- "Guys, keep your guard up! Panther is down!",
- "Everyone, protect Panther until she gets up!",
- "Panther, now is definitely not the time! Get back up!",
- }
- end
- local Chosen = RandomDownAwareness[math.random(1, #RandomDownAwareness)] or "undefined";
- _G.BattleAnnouncement(Chosen, nil, true);
- end
- end
- end
- end
- --impwarn('Pass One:', target.Guard, target.Debuffs.Down, target.Health)
- elseif CritCounter < 1 then
- local HeavyHit = ReplicatedStorage.Music:WaitForChild('NormalHit')
- HeavyHit = HeavyHit:Clone()
- HeavyHit.Parent = game.Players.LocalPlayer.PlayerGui;
- HeavyHit.PlayOnRemove = true;
- HeavyHit:Destroy();
- toggleOneMore=false;
- self.OneMore = false;
- end
- local damage = math.floor(attack.Damage*constant^(d/a))
- --impwarn(damage, WeakVar, StrongVar, crit, d, a)
- damage = math.ceil(damage * (WeakVar and 1.35 or 1) * (StrongVar and 0.45 or 1) * (crit and 1.25 or 1))--l*math.floor(attack.Damage*constant^(d/a) * (WeakVar and 1.15 or 1) * (StrongVar and 0.55 or 1) * (crit and 1.15 or 1))
- local Formula = ((damage * DamageMod)*Atk)*(Hunger and 0.4 or 1)*(Technical and 1.25 or 1)*Guard*BTNCount;
- if (isEnemy) and (target.Persona.Drain and target.Persona.Drain[attack.Type]) then
- local SFX = ReplicatedStorage.SFX.Drain:Clone();
- SFX.Parent = PlayerGui;
- SFX.PlayOnRemove = true;
- SFX:Destroy();
- target:Heal(Formula, true)
- elseif (target.Drain and target.Drain[attack.Type]) then
- local SFX = ReplicatedStorage.SFX.Drain:Clone();
- SFX.Parent = PlayerGui;
- SFX.PlayOnRemove = true;
- SFX:Destroy();
- target:Heal(Formula, true)
- elseif (isEnemy) and (target.Null and target.Null[attack.Type]) then
- target:SubtractHealth(0)
- return 'NULL'
- elseif (target.Null and target.Null[attack.Type]) then
- target:SubtractHealth(0)
- return 'NULL'
- else
- target:SubtractHealth(Formula);--(object, shakeFactor, magnitude, dampeningFactor)
- if (target.Health <= 0) then
- target.Debuffs = {};
- local Humanoid = isEnemy and Battle:GetCharacterFromID(PositionOfCharacterAttacked).Humanoid or Battle:GetEnemyFromName(target.ID).Humanoid;
- local Anim = LoadAnimation(ReplicatedStorage.AnimationAssets.Death.Fall, Humanoid)
- local Anim2 = LoadAnimation(ReplicatedStorage.AnimationAssets.Death.Stay, Humanoid);
- spawn(function(a)
- Anim:Play();
- Anim.Stopped:Wait()
- Anim2:Play()
- end)
- else
- target.Debuffs = target.Debuffs or {};
- for i, v in pairs(attack.Debuffs or {}) do
- if (((not Strong) or ((not Weak[attack.Type]) and (not crit) and Strong and (not Strong[attack.Type]) and (not Strong[attack.Type:lower()])) and (not target.Guard) and (not target.Debuffs[v.Name])) and target.Health > 0) or game:GetService('RunService'):IsStudio() then --do thing
- if (v.Chance/100 >= math.random()) then
- local zyrf = v.Name == "Down" and impprint'downed... added'
- local x = {};
- for i, v in pairs(v) do
- x[i] = v;
- end
- if (target.ID) then
- BattleInfo.EnemyTurns[target.ID] = BattleInfo.EnemyTurns[target.ID] or 1
- end
- BattleInfo.PlayerTurns[PositionOfCharacterAttacked] = BattleInfo.PlayerTurns[PositionOfCharacterAttacked] or 1;
- x.TurnAdded = isEnemy and BattleInfo.PlayerTurns[PositionOfCharacterAttacked] or BattleInfo.EnemyTurns[target.ID];
- target:AddDebuff(x)
- coroutine.wrap(showLabel)(('%s has been inflicted with %s'):format(target.Name or '???', x.Name and x.Name..'!' or 'Unknown Debuff..?'), 2);
- end
- end
- end
- if not (DownExclusionBecauseScrewThisStupidCodebase == target) then
- impwarn("WTJASFJNASF??")
- if ((not target.Guard) and (not target.Debuffs.Down)) or (math.floor(target.Health) <= 0) then
- impwarn("WHAT????")
- if (( (not isEnemy) and ( not (target.Null and target.Null[attack.Type] ))) or ( (isEnemy) and not (target.Persona.Null and target.Persona.Null[attack.Type]))) then
- impwarn("WHY???")
- toggleOneMore = 'W';
- local Humanoid = isEnemy and Battle:GetCharacterFromID(PositionOfCharacterAttacked).Humanoid or Battle:GetEnemyFromName(target.ID).Humanoid;
- local Anim = LoadAnimation(ReplicatedStorage.AnimationAssets.Death.Fall, Humanoid)
- local Anim2 = LoadAnimation(ReplicatedStorage.AnimationAssets.Death.Stay, Humanoid);
- DownExclusionBecauseScrewThisStupidCodebase = target;
- spawn(function(a)
- Anim:Play();
- impwarn("Down.");
- Anim.Stopped:Wait()
- Anim2:Play()
- end)
- local x = math.floor(target.Health) > 0 and target:AddDebuff({Name = "Down", TurnAdded = (not isEnemy and BattleInfo.EnemyTurns[target.ID] or BattleInfo.PlayerTurns[PositionOfCharacterAttacked] or 1), Length = math.random(1, 2)+(target.TurnCount and target.TurnCount/2 or 0), Chance = 100});
- elseif CritCounter < 1 then
- toggleOneMore = false;
- self.OneMore=false;
- end
- elseif (target.Guard) then
- imppwarn("wat du hek", target.Name)
- end
- else
- impprint(DownExclusionBecauseScrewThisStupidCodebase, target, DownExclusionBecauseScrewThisStupidCodebase == target)
- end
- end
- if (PositionOfCharacterAttacked) then
- local newShake = Shake.new():setShake(PlayerGui:WaitForChild('Statuses').PartyIndicator:WaitForChild(tostring(PositionOfCharacterAttacked)), 0.5, 0):initShake(1);
- end
- end
- --print('Dealt', Formula,'damage.', target.Name.."'s health is now", tostring(target.Health)..'.')
- --print("Damage:", damage, "\nDamageMod:", DamageMod, "\nDamage*DamageMod:", damage*DamageMod, "\nAtk:", Atk, "\nDamage*DamageMod*Atk:", damage*DamageMod*Atk, "\nHunger:", Hunger, "\nGuard:", Guard, "\nBTNCount:", BTNCount, "\na:", a, "\nd:", d, "\nattack.Damage:", attack.Damage)
- Battle:TweenHealth(0.25)
- end
- end
- if (isMultiHit) then
- if (attack.AttackCount) then
- --impwarn('Has several hits.')
- local tab = typeof(attack.AttackCount) == "number" and {0, attack.AttackCount} or {attack.AttackCount[1], math.random(attack.AttackCount[1]+1, attack.AttackCount[2])};
- for i = tab[1], tab[2] do
- for i, v in pairs(GroupToAttack) do
- if (v.Health > 0) then
- if (attack.Yield and not AlreadyAttacked) then
- (attackFunction)(v, attack, nil)
- end
- coroutine.wrap(attackFunction)(v, attack, nil)
- wait(0.25)
- end
- end
- wait(0.175)
- end
- else
- for i, v in pairs(GroupToAttack) do
- if (v.Health > 0) then
- if (attack.Yield and not AlreadyAttacked) then
- (attackFunction)(v, attack, nil)
- end
- coroutine.wrap(attackFunction)(v, attack, nil)
- wait(0.25)
- end
- end
- end
- else
- if (attack.AttackCount) then
- --impwarn('Has several hits. (singular attack)')
- local tab = typeof(attack.AttackCount) == "number" and {0, attack.AttackCount[2]} or {attack.AttackCount[1], math.random(attack.AttackCount[1]+1, attack.AttackCount[2])};
- for i = tab[1], tab[2] do
- (attackFunction)(target, attack, PositionOfCharacterAttacked or target.ID)
- wait(0.175)
- end
- else
- (attackFunction)(target, attack, PositionOfCharacterAttacked or target.ID)
- end
- end
- self.OneMore = toggleOneMore;
- wait(1.25);
- end
- --battle input functionfd
- function Battle:Failsafe()
- Player.Chatted:Connect(function(c)
- c = c:match('giveattack:%s?(.*)');
- local C = _G.Characters[1].Persona.Attacks;
- for i, v in pairs(C) do
- if (v:lower() == c:lower()) then
- return false;
- end
- end
- for i, v in pairs(Attacks) do
- if (i:lower() == c:lower()) then
- C[#C+1] = i;
- print("Given attack:", i);
- return true;
- end
- end
- return false;
- end)
- print('Failsafe Started!')
- local DebugAndUi
- DebugAndUi = game:GetService('RunService').RenderStepped:Connect(function(DebugAndUI)
- --partyspawns, enemyspawns, partycontainer, enemycontainer
- --impwarn(self.Characters[1].Guard, self.Characters[2].Guard, self.Characters[3].Guard, self.Characters[4].Guard);
- pcall(function()
- PlayerGui:WaitForChild('Persona Attacks List').List.Description.Text = getAttack(game:GetService('GuiService').SelectedObject.Parent.AttackTitle.Text).Description
- end)
- --Used to make debug functions and for UI progression.
- if (self.BattleFinished) then
- if (Signal) then
- print'disconnected signal'
- Signal:Disconnect();
- Signal = nil;
- end
- DebugAndUi:Disconnect();
- DebugAndUi = nil;
- PlayerGui:WaitForChild('Persona Attacks List').Enabled = false;
- PlayerGui:WaitForChild('PersonaListR').Enabled = false;
- PlayerGui:WaitForChild('Change Persona').Enabled = false;
- BattleInfo.BattleStage = nil;
- _G.Stage = nil;
- CMS:Enable();
- script:Destroy();
- warn('Finished failsafe.')
- return nil;
- else
- _G.Occupied = true;
- _G.Stage = BattleInfo.BattleStage
- end
- _G.Occupied = true;
- if (tonumber(BattleInfo.SelectedMember) and not self.BattleFinished) then
- -- print(BattleInfo.BattleStage);
- PlayerGui:WaitForChild('Persona Attacks List').Enabled = BattleInfo.BattleStage == 'PersonaAttackList'
- PlayerGui:WaitForChild('PersonaListR').Enabled = BattleInfo.BattleStage == 'Main'
- PlayerGui.PersonaListR['BATON PASS'].Visible = self.OneMore
- PlayerGui:WaitForChild('Change Persona').Enabled = BattleInfo.BattleStage == 'PersonaChange' or BattleInfo.BattleStage == 'Analysis'
- pcall(function()
- PlayerGui.PersonaListR.StudsOffset = Vector3.new(
- self:
- GetCharacterFromID(BattleInfo.SelectedMember)
- .PrimaryPart.Size.X + 0.75,
- self:
- GetCharacterFromID(BattleInfo.SelectedMember)
- .PrimaryPart.Size.X/1.75,
- 0
- )
- end)
- local MovementStatus = (not self.BattleFinished) and CMS:Disable() or CMS:Enable()
- end
- end)
- if (self.Ambush) then
- while wait(2.5) do
- if (self.BattleFinished) then
- game:GetService('Lighting').ambusheffectpulse.Enabled = false;
- break;
- end
- --pulse if ambush
- Tween(game:GetService('Lighting').ambusheffectpulse, TweenInfo.new(0.35, Enum.EasingStyle.Sine, Enum.EasingDirection.InOut, 0, true, 0.5), {TintColor = Color3.fromRGB(255,114,114)}):Play()
- local CMFOV = workspace.CurrentCamera.FieldOfView;
- wait(0.65)
- Tween(workspace.CurrentCamera, TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out, 0, false, 0), {FieldOfView = CMFOV-15}):Play();
- wait()
- Tween(workspace.CurrentCamera, TweenInfo.new(0.5, Enum.EasingStyle.Sine, Enum.EasingDirection.Out, 0, false, 0), {FieldOfView = CMFOV}):Play();
- wait(0.5);
- end
- end
- end
- --debug
- local function getCharFromPartName(s)
- for i, v in pairs(Battle.Characters) do
- if (v.Name:lower():match(s:lower())) then
- return v;
- end
- end
- end
- local function getSonaFromPartName(s)
- for i, v in pairs(game:GetService'ReplicatedStorage':WaitForChild('Personas'):GetChildren()) do
- if (v.Name:lower():match(s:lower())) then
- return v;
- end
- end
- end
- return Battle;
Advertisement
Add Comment
Please, Sign In to add comment