Kitty Corp Meow Mix Forums

Super Smash Bros. Brawl Hacking => Attacks and Animations => Topic started by: KingJigglypuff on March 04, 2014, 08:08:45 PM



Title: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on March 04, 2014, 08:08:45 PM
Hey, Kittens, KJP here. I've decided to get cracking on what's possible to do in PSA and what's not (at the moment). But I need your help in gathering this information. If I'm wrong about something or I missed something, then post what I got wrong/missed, along with a link/post of a tutorial or an example.

What's Currently Possible.
-Counters. Various PSAs.
-Pseudo Gliding. Crusade Ridley PSA.
-Transformation. BrawlEx. Only between 2 characters at the moment.
-Pseudo Transformation. Various PSAs.
-Power Ups/Downs. Various PSAs.
-Adding new GFX. Various PSAs.
-Bone Index editing. Various PSAs.
-Adding new Visibility Bones. Various PSAs
-Adding a new character slot. BrawlEx
-Custom Attacks. All PSAs.
-Custom Special Attacks. Most PSAs.
-Custom Final Smashes. Most PSAs.
-Charge up Attacks. Various PSAs.
-Variable based Attacks. Various PSAs.
-"Stance Change". Various PSAs.
-Adding Action Overrides. Various PSAs.
-Custom Bones. Various PSAs.
-On hit cancel. Various PSAs.
-Healing/Self Damage. Various PSAs.
-Floating. Various PSAs.
-Attribute Editing. Various PSAs.
-Slot specific Attacks. Various PSAs.
-Adding a true Crawl. BrawlEx.
-Adding a true Glide. BrawlEx.
-Adding true Multijumps. BrawlEx.
-Adding new Sub Actions.
-Adding a new custom Sword Glow. Requires renaming the character's ef_char to something that has a Sword Glow.
-Item Attribute replacement.

What Might be Possible (requires further study).
-Adding new Actions.
-Creating Action Overrides on a character without them.
-Increasing maximum File Size.

What's Currently Impossible.
-Adding Articles.
-Transformation between 3 or 4 characters.
-Adding a Tether.

Let the PSA Discussion begin! \o0o/


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: ABloodyCanadian on March 04, 2014, 08:14:07 PM
This is a good read. Makes me want to try a few things.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: pikazz on March 05, 2014, 07:48:47 AM
Change "Adding a True Glide" to "What'S Currently Possible."

Add "Adding True Multijumps (like Kirby and Jigglypuff)" to "What Might be Possible (requires further study)."

and Add "Adding True Crawl" to "What's Currently Possible."

why?
True Crawl (http://www.youtube.com/watch?v=wdcnQZX1bmk#ws)

playing with "Misc Crawl", "Misc MultiJump" and "Misc Glide" inside FitFighter.pac. successfully added Misc Crawl to jigglypuff! will try Multijump on someone who cant double jump or Misc Glide on someone with working action override

best use with BrawlEx Engine, letting you set the flag to make them useable

EDIT: True Glide (http://www.youtube.com/watch?v=HB7Vi6xqcU8#ws)
Fully working true glide on Yoshi!


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: TheShyGuy on May 21, 2014, 03:43:45 AM
How far have you guys gotten on new Actions?  I stopped working on a brawl-like game recently but I based the moveset system off PSA actions/subactions from the PSA docs.

Here's what I learned and implemented that might be useful to others:

Actions
- run every game step
- nothing special, more like an animation  finite state machine
- those "ChangeAction" events are the transitions between states/actions
- in Unity, it's represented similarly.
-->the animation system has a bag of variables that are used to decide when wand what to transition to if a requirement succeeds (--> ChangeActions)
- Early on, I noticed that Actions never(?) contain any timer events (Asynchronous, Synchronous timers), but made plenty use of infinite loops + loop rests.
-->this backs up the idea that Actions are ran once per game step,
-->anyone who uses timers in there are probably misusing the event and are pausing the action for an entire animation frame instead of a single game step (loop rest)
-Since actions are just FSMs, you can create an entire alternative moveset if you can add actions.  --within memory limits ofc.
-gives control of an Action at the per game step

Subaction
- run once per animation step, sets an animation
- really, just gives control of an Action/animation code on a per animation frame step. (very useful as everyone who PSA's should know by now)
- I used to have an "AllowInterrupt" "event" in my game too.  Straight to the point, "AllowInterrupt" (do you guys still name it that?) is just a fancy word for "specific change actions".
--All current ChangeActions on my side are cached and checked at the end of a game step.
--when an Action changes, any currently existing ChangeActions events are thrown away
-Again, Actions are nothing special but a FSM -but at the PSA-like level, they're very easy to use (for those who program, a FSM doesn't scale well in code. However, the way Brawl does it for Actions, they scale fine.)
-Subactions also aren't anything special but a small script

uhh if I think of anything else that might be useful, I'll be sure to add to this.  These are just things I learned about when I was using PSA docs for guidance on how to setup a PSA-like system.  AFAIK, both systems turned out similar.

This is pretty much advertising a game I don't work on anymore... but I dunno it might be useful to see how my side turned out?

*Note*, anywhere you see coroutine.yield(runStatus.Running) within an infinite loop, it's similar to a LoopRest in PSA
*WARNING* raw and uneditted.  This is a debug/test moveset using Lua
Actions
Code:
local mitActions = function(_events)
local events = _events

events.lightPunchKeyPress = function()
return events:isKeyPress(keys.X)
end
events.jumpKeyPressed = function()
return events:isKeyPressed(keys.Z)
end
events.crouchKeyPressed = function()
return events:isKeyPressed(keys.Down)
end
events.upKeyPressed = function()
return events:isKeyPressed(keys.Up)
end

events.heavy_UpKeyPressed = function()
return events:isKeyPressed(keys.Up) and events:isKeyPressed(keys.C)
end
events.horizontalKeysPressed = function()
return events:areKeysPressed(events.horizontalKeys)
end
events.keyPressedTowardsWall = function()
local wallSide = events:getWallSide()

return (events:isKeyPressed(keys.Left) and wallSide == -1) or
  (events:isKeyPressed(keys.Right) and wallSide == 1)
end

--add change actions for: attack11,jumpBegin,crouch,walk,heavyUpAttackBegin
events.changeActions_Ground0 = function()

events:changeAction(events.actions.walk,events.horizontalKeysPressed)
events:addRequirement(events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.jumpBegin,events.jumpkeyPressed)
events:addRequirement(events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.crouch,events.crouchKeyPressed)
events:addRequirement(events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.attack11,events.lightPunchKeyPress)
events:addRequirement(events.onGround)
events:addRequirement(events.shouldBeOnGround)

end

--add change actions for: airN,airF,wallSlide,hammerUp
events.changeActions_Air0 = function()
events:changeAction(events.actions.walk,events.horizontalKeysPressed)
events:changeAction(events.actions.walk,events.horizontalKeysPressed)
events:changeAction(events.actions.walk,events.horizontalKeysPressed)
events:changeAction(events.actions.walk,events.horizontalKeysPressed)

end
--empty func for now,replace with specifics later.
events.allowInterrupt = function()end
events.actions =
{
idle = action(
{
id = 0,
method = function()
--yield once to stay in sync with how game handles coroutines internally
coroutine.yield()

events:changeAction(events.actions.walk,events.horizontalKeysPressed)
events:addRequirement(events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.jumpBegin,events.jumpKeyPressed)
events:addRequirement(events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.attack11,events.lightPunchKeyPress)
events:addRequirement(events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.heavyAttack_Up_Begin,events.heavy_UpKeyPressed)

events:changeAction(events.actions.fall,events.isFalling)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)


events:setSubaction(events.subactions.idle)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
walk = action(
{
id = 1,
method = function()
coroutine.yield()
events:changeAction(events.actions.idle,events.horizontalKeysPressed,true)

events:changeAction(events.actions.fall,events.isFalling)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

events:changeAction(events.actions.jumpBegin,events.jumpKeyPressed)
events:addRequirement(events.onGround)

events:changeAction(events.actions.attack11,events.lightPunchKeyPress)
events:addRequirement(events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.heavyAttack_Up_Begin,events.heavy_UpKeyPressed)

events:setSubaction(events.subactions.walk)

while true do
events:moveRelative()
coroutine.yield(runStatus.Running)
end
end
}),
jumpBegin = action(
{
id = 5,
method = function()
coroutine.yield()

   events:offsetRelative(vector2(0,-3))
events:applyJumpImpulse()
events:setGroundAirTime(0)
--events:ignoreGroundCollisions()
--events:playSound(3,0.5)

events:setSubaction(events.subactions.jumpBegin)

coroutine.yield(runStatus.Running)
events:setShouldBeInAir(true)
events:setInAir(true)

events:changeAction(events.actions.fall,events.isFalling)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

events:changeAction(events.actions.rise,events.isRising)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
rise = action(
{
id = 6,
method = function()
coroutine.yield()

events:changeAction(events.actions.idle,events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.fall,events.isFalling)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)


events:changeAction(events.actions.airN,events.lightPunchKeyPress)
events:addRequirement(events.horizontalKeysPressed,true)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

events:changeAction(events.actions.airF,events.lightPunchKeyPress)
events:addRequirement(events.isKeyPressed_Forward)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

events:changeAction(events.actions.heavyAttack_Up_Begin,events.heavy_UpKeyPressed)

events:setSubaction(events.subactions.jumpLoop)

while true do
events:move()

--try to rise
if(events:isRiseTimeLessThanAllowed() and
events:isKeyPressed(events.jumpKeys)) then
events:setVelocityY(-150)
end

coroutine.yield(runStatus.Running)
end
end
}),
fall = action(
{
id = 7,
method = function()
coroutine.yield()

events:changeAction(events.actions.idle,events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.rise,events.isRising)
events:addRequirement(events.inAir)

events:changeAction(events.actions.wallSlide,events.isFalling)
events:addRequirement(events.isTouchingWall)
events:addRequirement(events.keyPressedTowardsWall)

events:changeAction(events.actions.airN,events.lightPunchKeyPress)
events:addRequirement(events.horizontalKeysPressed,true)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

events:changeAction(events.actions.airF,events.lightPunchKeyPress)
events:addRequirement(events.isKeyPressed_Forward)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

events:changeAction(events.actions.heavyAttack_Up_Begin,events.heavy_UpKeyPressed)

events:setSubaction(events.subactions.fall)

while true do
events:move()
coroutine.yield(runStatus.Running)
end
end
}),
attack11 = action(
{
id = 10,
method = function()
coroutine.yield()

events:changeAction(events.actions.idle,events.isSubactionNull)
events:setSubaction(events.subactions.attack11)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
attack12 = action(
{
id = 11,
method = function()
coroutine.yield()
events:setSubaction(events.subactions.attack12)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
attack13 = action(
{
id = 12,
method = function()
coroutine.yield()
events:setSubaction(events.subactions.attack13)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
heavyAttack_Idle = action(
{
id = 13,
method = function()
coroutine.yield()
events:setSubaction(events.subactions.heavyAttack_Idle)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
heavyAttack_Up_Begin = action(
{
id = 14,
method = function()
coroutine.yield()

events:setSubaction(events.subactions.heavyAttack_Up_Begin)
events:changeAction(events.actions.heavyAttack_Up_Loop,events.isSubactionNull)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
heavyAttack_Up_Loop = action(
{
id = 15,
method = function()
coroutine.yield()

 events:setSubaction(events.subactions.heavyAttack_Up_Loop)
 events:changeAction(events.actions.heavyAttack_Up_End,events.upKeyPressed,true)

while true do
events:moveRelative()

coroutine.yield(runStatus.Running)
end
end
}),
heavyAttack_Up_End = action(
{
id = 16,
method = function()
coroutine.yield()

events:setSubaction(events.subactions.heavyAttack_Up_End)
events:changeAction(events.actions.idle,events.isSubactionNull)


while true do
events:moveRelative()
coroutine.yield(runStatus.Running)
end
end
}),
heavyAttack_AirN = action(
{
id = 20,
method = function()
coroutine.yield()
events:setSubaction(events.subactions.heavyAttack_AirN)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
airN = action(
{
id = 21,
method = function()
coroutine.yield()

events:changeAction(events.actions.airNFall,events.isSubactionNull)

events:setSubaction(events.subactions.airN)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
airNFall = action(
{
id = 22,
method = function()
coroutine.yield()

events:changeAction(events.actions.idle,events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.rise,events.isRising)
events:addRequirement(events.inAir)

events:changeAction(events.actions.wallSlide,events.isFalling)
events:addRequirement(events.isTouchingWall)
events:addRequirement(events.keyPressedTowardsWall)

events:changeAction(events.actions.airN,events.lightPunchKeyPress)
events:addRequirement(events.horizontalKeysPressed,true)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

events:changeAction(events.actions.airF,events.lightPunchKeyPress)
events:addRequirement(events.isKeyPressed_Forward)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

events:setSubaction(events.subactions.airNFall)

while true do
events:move()
coroutine.yield(runStatus.Running)
end
end
}),
airF = action(
{
id = 23,
method = function()
coroutine.yield()
events:changeAction(events.actions.fall,events.isSubactionNull)
events:setSubaction(events.subactions.airF)

while true do
coroutine.yield(runStatus.Running)
end
end
}),
wallSlide = action(
{
id = 30,
method = function()
coroutine.yield()

events:changeAction(events.actions.idle,events.onGround)
events:addRequirement(events.shouldBeOnGround)

events:changeAction(events.actions.fall,events.isFalling)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)
events:addRequirement(events.keyPressedTowardsWall,true)

events:changeAction(events.actions.wallJump,events.jumpKeyPressed)

events:setSubaction(events.subactions.wallSlide)

while true do
events:setVelocity(vector2(0,15))
coroutine.yield(runStatus.Running)
end
end
}),
wallJump = action(
{
id = 31,
method = function()
coroutine.yield()

events:setSubaction(events.subactions.wallJump)

coroutine.yield(runStatus.Running)

events:changeAction(events.actions.fall,events.isFalling)
events:addRequirement(events.inAir)
events:addRequirement(events.shouldBeInAir)

while true do
--events:move()

--try to rise
--if(events:isRiseTimeLessThanAllowed() and
-- events:isKeyPressed(events.jumpKeys)) then
-- events:setVelocityY(-150)
--end

coroutine.yield(runStatus.Running)
end
end
}),
}

end

mitActions(...)

Subactions
Code:
local create =  function(_events)
local events = _events

--to prevent creating strings everytime used
local bones =
{
HandL = 'HandL',
HandR = 'HandR',
FootL = 'FootL',
FootR = 'FootR',
Hammer = 'Hammer'
}
events.subactions =
{
idle = subaction(
{
id = 0,
animationID = 0,
looped = true,
functions =
{
main = function()
-- first yield gets consumed by coroutine start
coroutine.yield()
end
}
}),
walk = subaction(
{
id = 1,
animationID = 1,
looped = true,
functions =
{
main = function()
coroutine.yield()

events:allowInterrupt()

events:playSound(0,0.1)
events:synchronous(12)
events:playSound(0,0.1)
events:synchronous(11)
end
}
}),
jumpBegin = subaction(
{
id = 5,
animationID = 2,
looped = false,
functions =
{
main = function()
coroutine.yield()

events:addParticleRelative(particle(13,1,color.White,vector2(0,10),vector2(-20,0),false,true))
events:addParticleRelative(particle(13,1,color.White,vector2(0,10),vector2(20,0),false, true))
    
events:allowInterrupt()
end
}
}),
jumpLoop = subaction(
{
id = 6,
animationID = 2,
looped = true,
functions =
{
main = function()
coroutine.yield()
events:allowInterrupt()
end
}
}),
fall = subaction(
{
id = 7,
animationID = 3,
looped = true,
functions =
{
main = function()
coroutine.yield()
events:allowInterrupt()
end
}
}),
attack11 =subaction(
{
id = 10,
animationID = 9,
looped = false,
functions =
{
main = function()
coroutine.yield()

events:synchronous(4)
events:playSound(5,1)

events:offensiveCollision(0, true, bones.HandL, 1, 2, 180,0, 3, 4, vector2(-1, 0), 3, 1,0,5)
events:offensiveCollision(1, true, bones.HandL, 1, 2, 135,0, 4, 4, vector2(-1, 0), 8, .2,0,5)
events:offensiveCollision(2, true, bones.HandL, 1, 2, 0,0, 1, 1, vector2(-1, 0), 10, 0,0,5)

events:asynchronous(5)

for i=0,10 do
events:synchronous(1)
if(events:isKeyPress(events.punchKeys)) then
events:terminateAllCollisions()
events:setSubaction(events.subactions.attack12)
end
end

events:asynchronous(16)
events:terminateAllCollisions()
end
}
}),
attack12 =subaction(
{
id = 11,
animationID = 10,
looped = false,
functions =
{
main = function()

coroutine.yield()

events:asynchronous(4)
   events:playSound(6,1)
  
events:synchronous(1)
events:offensiveCollision( 0, true, bones.HandR, 1, 2, 270,0, 5, 5,vector2(-1, 0), 10, 1)
    
for i = 0,10 do
events:synchronous(1)
if(events:isKeyPress(events.punchKeys)) then
events:terminateAllCollisions()
events:setSubaction(events.subactions.attack13)
return coroutine.yield(runStatus.Success)
end
end

events:asynchronous(16)
events:terminateAllCollisions()
end
}
}),
attack13 =subaction(
{
id = 12,
animationID = 11,
looped = false,
functions =
{
main =function()

coroutine.yield()

events:asynchronous(4)
   events:playSound(7)
events:offensiveCollision(0, true, bones.FootR, 1, 2, 45,0, 4, 10,vector2(-1, 0), 10, 2)
    
events:asynchronous(16)
events:terminateAllCollisions()                
end
}
}),
heavyAttack_Idle =subaction(
{
id = 13,
animationID = 4,
looped = false,
functions =
{
main = function()
coroutine.yield()
events:playSound(3,1)
end
}
}),
heavyAttack_Up_Begin =subaction(
{
id = 14,
animationID = 13,
looped = false,
functions =
{
main = function()

coroutine.yield()

events:playSound(28,.1)
events:asynchronous(15)


if(events:inAir()) then
events:playSound(15,.2)
events:setVelocityY(-200)
end
end,
gfx = function()
coroutine.yield()

--BIFF
local _particle =particle(32,.5,color.White)
_particle:SetInitialMatrix(-15,-25,0,.5,.5,0,0)
_particle:SetPosition(0,10,0,-100)
_particle:SetRotation(3.14/-2,3.14)
_particle:SetScale(1.5,1,0,0)
_particle.FadeOut=true

events:addParticleRelative(_particle)
events:asynchronous(15)

--MARTY
_particle.AnimationIndex = 34
_particle:SetInitialMatrix(15,-25,0,.5,.5,0,0)
_particle:SetRotation(3.14 / 2,-3.14)

events:addParticleRelative(_particle)


if(events:inAir()) then

--smoke puff
_particle.AnimationIndex = 11
_particle:SetInitialMatrix(0,5,0,.5,.5,0,0)
_particle:SetPosition(0,20,0,-60)
_particle:SetRotation(0,0)
_particle:SetScale(3,3,-10,-10)

events:addParticleRelative(_particle);
_particle.LifeTime = 1

--leaves
for i=1,4 do
_particle.AnimationIndex = i
_particle:SetInitialMatrix(0,5,0,1,1,0,0)
_particle:SetPosition(random.NextDouble(-30,30),random.NextDouble(-10,30),0,50)
_particle:SetRotation(6.14,-6.14)
_particle:SetScale(0,0,0,0)

events:addParticleRelative(_particle)
end
end
end
}
}),
heavyAttack_Up_Loop =subaction(
{
id = 15,
animationID = 14,
looped = true,
functions =
{
main = function()

coroutine.yield()

local offset = vector2(0,-1)

events:offensiveCollision(0, true, bones.Hammer, 0, 0, 135,0, 0, 10, offset, 9, 1)
events:offensiveCollision(1, true, nil, 0, 0, 135,0, 0, 10,vector2.Zero,10,1)-- vector2(0,-5), 6, 1)
events:synchronous(15)
events:terminateAllCollisions()
end,
gfx = function()

coroutine.yield()

local _particle = particle(0,.5,color.White)
_particle.LifeTime = .5
for i=0,2 do
if(events:onGround()) then
--smoke trail
_particle.AnimationIndex = 12
_particle:SetInitialMatrix(0,5,0,.5,.5,0,0)
_particle:SetScale(-.5,-.5,0,0)

events:addParticleRelative(_particle)

--V particles
_particle.AnimationIndex = 4
_particle:SetInitialMatrix(0,10,0,.5,.5,0,0)
_particle:SetPosition(-60,-60,0,0)
_particle:SetScale(5,5,0,0)

events:addParticleRelative(_particle)

_particle:SetPosition(60,-60,0,0)

events:addParticleRelative(_particle)
end
events:synchronous(5)
end
end
,sfx = function()

coroutine.yield()

events:playSound(27,.1)

if(events:onGround()) then
events:playSound(20,.01)
end
end
}
}),
heavyAttack_Up_End = subaction(
{
id = 16,
animationID = 15,
looped = false,
functions =
{
main = function()

coroutine.yield()

end
}
}),
heavyAttack_AirN =  subaction(
{
id = 20,
animationID = 22,
looped = false,
functions =
{
main = function()
coroutine.yield()

events:playSound(10,1)
for i = 0,18 do
if(events:shouldBeOnGround()) then
events:setSubactionPassTime(events.subactions.heavyAttack_Idle,events:getCurrentAnimationFrameTime())
return coroutine.yield(runStatus.Success)
end
events:synchronous(1)
end
end
}
}),
airN = subaction(
{
id = 21,
animationID = 18,
looped = false,
functions =
{
main = function()

coroutine.yield()

local offset = vector2(0,0)

events:synchronous(4)
--events:playSound(4,1)
events:enableConstantMomentum()
events:setConstantMomentum(vector2.Zero)
  
events:asynchronous(9)
events:offensiveCollision(0, true, bones.HandL, 0, 0, 135,0, 0, 10, offset, 10, 1)
events:offensiveCollision(1, true, bones.HandR, 0, 0, 45,0, 0, 10, offset, 10, 1)
events:offensiveCollision(2, true, bones.FootL, 0, 0, 225,0, 0, 10, offset, 10, 1)
events:offensiveCollision(3, true, bones.FootR, 0, 0, 315,0, 0, 10, offset, 10, 1)
events:synchronous(3)
events:terminateAllCollisions()
  
events:offensiveCollision(0, true, bones.HandL, 0, 0, 135,0, 0, 8, offset, 8, 1)
events:offensiveCollision(1, true, bones.HandR, 0, 0, 45 ,0, 0, 8, offset, 8, 1)
events:offensiveCollision(2, true, bones.FootL, 0, 0, 225,0, 0, 8, offset, 8, 1)
events:offensiveCollision(3, true, bones.FootR, 0, 0, 315,0, 0, 8, offset, 8, 1)
events:synchronous(15)
events:terminateAllCollisions()
  
events:synchronous(5)
events:disableConstantMomentum()
events:allowInterrupt()
end
}
}),
airNFall = subaction(
{
id = 22,
animationID = 19,
looped = false,
functions =
{
main = function()
coroutine.yield()
end
}
}),
airF =subaction(
{
id = 23,
animationID = 17,
looped = false,
functions =
{
main = function()

coroutine.yield()

events:asynchronous(4)
events:applyImpulse(vector2(0,-50))
events:offensiveCollision( 0,true, bones.HandL, 1, 1, 0,0, 50, 8,vector2(0, -4), 10, 3)
--events:playSound(5)
events:asynchronous(13)
events:terminateAllCollisions()
events:allowInterrupt()
end
}
}),
wallSlide =subaction(
{
id = 30,
animationID = 16,
looped = true,
functions =
{
main = function()
coroutine.yield()

  
--I don't want this subaction being called every frame because it plays sound
local rnd = random.NextDouble(0,10)

local _particle = nil
if(rnd >= 5) then
local life = random.NextDouble(.3,2)
   _particle = particle(11,life,color.White)
_particle:SetInitialMatrix(10,0,0,.7,.7,0,0)
_particle:SetPosition(0,-5,0,0)
_particle:SetRotation(random.NextDouble(0,6),0)
_particle:SetScale(-1/life,-1/life,0,0)
_particle.DeathOnAnimationEnd = true
_particle.FadeOut = true
events:addParticleRelative(_particle)
end

rnd = random.NextDouble(0,10)
if(rnd >= 8) then
local life = random.NextDouble(.3,2)
   _particle = particle(11,life,color.White)
_particle:SetInitialMatrix(10,10,0,.7,.7,0,0)
_particle:SetPosition(0,-10,0,0)
_particle:SetRotation(random.NextDouble(0,6),0)
_particle:SetScale(-1/life,-1/life,0,0)
_particle.DeathOnAnimationEnd = true
_particle.FadeOut = true

events:addParticleRelative(_particle)
end

events:allowInterrupt()
                            
end
}
}),
wallJump =subaction(
{
id = 31,
animationID = 2,
looped = false,
functions =
{
main = function()
coroutine.yield()

--events:playSound(13,1)
events:addParticleRelative(particle(11,1,color.White,vector2(10, 0),vector2(0,-20),true, true))
events:addParticleRelative(particle(11,1,color.White,vector2(10, 0),vector2(0, 20),true, true))

local wallNormal = events.context.PlacementData.BodySensorNormalCollection.AverageNormal
local jumpDirection = vector2.Transform(wallNormal,matrix.CreateRotationZ(-mathHelper.PiOver4))

jumpDirection.X = jumpDirection.X * 300
jumpDirection.Y = jumpDirection.Y * 300

if(jumpDirection.Y > 0) then
jumpDirection.Y = jumpDirection.Y * -1.0
end

local levelMask = events.context.BasicPhysicsData.LevelCollisionMask

if(events:waitForPermission()) then
events:offsetRelative( wallNormal)
levelMask:ApplyLinearImpulse(jumpDirection)
end

events:setFacingDirection(events:getWallSide() * -1)
end
}
}),
}
end

return create(...)

You can check my dead devlog for gifs what this code actually does  (http://www.vg-resource.com/thread-24417.html).  If this is against the rules, I have no problem if this post is deleted or editted.

___

Oh yea, I never got to fully implementing articles.  The way I would've done articles was to have articles also have it's own "Moveset" data (actions/subactions).  Then the owner (Mario->fireball) controls the visibility/active/enabled of an article as well as set Actions directly.  To me (who hasn't PSA-ed in years), it sounds like how brawl might also do it.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: SonicBrawler on May 21, 2014, 05:43:10 AM
I really want to look into adding articles


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on May 21, 2014, 08:02:15 AM
Your post is fine, ShyGuy. It was just really big, so I put it into a Spoiler.

As for Actions and Sub Actions, Pikazz managed to perfectly add new Sub Actions, and is progressing on adding new Actions (there's various bugs with adding new Actions).

I really want to look into adding articles
Adding and/or porting Articles would be a breakthrough on the same grounds as BrawlEx.

I believe Pikazz, PhantomWings(?), and SammiHusky(?) are looking into it.

So ask those three about what you can do to look into adding/porting articles.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Akeno/Archer on May 21, 2014, 08:41:49 AM
This is a list that would be useful to people who starts PSAing.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Allbait on June 05, 2014, 07:29:28 AM
Adding articles isn't possible currently but it is possible to port some assist trophy articles onto characters' items: http://forums.kc-mm.com/index.php?topic=43789.msg892895#msg892895 (http://forums.kc-mm.com/index.php?topic=43789.msg892895#msg892895)

But this only truly works over characters that have item spawning capabilities like Link, Toon Link, Peach, Snake and anything whatever else I'm forgetting. Although you can make any PSA summon these items if you wanted. IMO the best way to add articles one day will be through adding new items since it's the closest I've seen.

Not everything works but one of the things that does almost always work is Jeff's Pencil rocket which homes in on enemies and is the closest thing to a auto-homing article ported.
 
So add on character item replacement onto that list xD Or whatever anyone would call them.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on June 05, 2014, 08:06:16 AM
Adding articles isn't possible but it is possible to port some assist trophy articles onto characters' items: [url]http://forums.kc-mm.com/index.php?topic=43789.msg892895#msg892895[/url] ([url]http://forums.kc-mm.com/index.php?topic=43789.msg892895#msg892895[/url])

But this only truly works over characters that have item spawning capabilities like Link, Toon Link, Peach, Snake and anything whatever else I'm forgetting. Although you can make any PSA summon these items if you wanted. IMO the best way to add articles one day will be through adding new items since it's the closest I've seen.

Not everything works but one of the things that does almost always work is Jeff's Pencil rocket which homes in on enemies and is the closest thing to a auto-homing article ported.
 
So add on character item replacement onto that list xD Or whatever anyone would call them.
Alright. Will do.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: pikazz on June 05, 2014, 09:51:26 AM
Alses: Adding articles WILL be possible in the future, we just need to find a way to rebuild the module files completely!

but there is one thing I wonder if its possible, that would be "Merging Subactions" together! perfect example is from the game Kirbys Return to dreamland, there example there is a animation for a drill arm thats its animation is "loop" while it plays durning the other animations aswell! and the arm isnt a article, its on the body itself

I have seen it to Damagefaces, they "Merges" into the damage subactions like "throwN" animations without any problem


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Large Leader on June 05, 2014, 09:54:02 AM
Alses: Adding articles WILL be possible in the future, we just need to find a way to rebuild the module files completely!

Now this is great to hear!


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: pikazz on June 05, 2014, 09:59:27 AM
Now this is great to hear!
but sadly, it will not be easy cause it will require huge programming and PowerPC/Asm knowledge. even if it just "copypaste" if you want someones elses article on that character


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Archer(AkenoS3) on June 05, 2014, 10:01:33 AM
Alses: Adding articles WILL be possible in the future, we just need to find a way to rebuild the module files completely!
This would be... so great... :srs:
There would be alot of PSAs to update, though... lol



Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Allbait on June 05, 2014, 10:05:58 AM
Alses: Adding articles WILL be possible in the future, we just need to find a way to rebuild the module files completely!

but there is one thing I wonder if its possible, that would be "Merging Subactions" together! perfect example is from the game Kirbys Return to dreamland, there example there is a animation for a drill arm thats its animation is "loop" while it plays durning the other animations aswell! and the arm isnt a article, its on the body itself

I have seen it to Damagefaces, they "Merges" into the damage subactions like "throwN" animations without any problem

Ah, I meant as in right now xD Fixed the post =) And brand new modules sounds awesome but I don't even know how to see what's coded in the sora module. =P Good luck on learning what it all means and hope to see progress!


but sadly, it will not be easy cause it will require huge programming and PowerPC/Asm knowledge. even if it just "copypaste" if you want someones elses article on that character

Hopefully with enough look into it adding articles will be just as easy as adding special grabs!


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: namq on June 13, 2014, 11:18:20 AM
I need to ask a question.

Is it possible to inject a special from one character to another?

Example:

Porting the animations is cake, brawlbox does that for us.  Also porting the PSA stuff is cake aswell, just copy paste specials from one character to another, but here is the hard part...

Character doesn't not have enough specials
- How to add new specials with hex edit?

and here is the other thing:
- How to edit Floating points so that the injected specials work as the Owner of that special


Example:

Fox has Ike's Side B and all it's attributes (Floating Points, charge frames, etc

Or even the Cypher stats and all, so he would not be able to have button input to get momentum like fore fox, and just go upwards like snake.

Thanks in advance!


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on June 13, 2014, 11:24:14 AM
Is it possible to inject a special from one character to another?
It depends on the Special.

Character doesn't not have enough specials
- How to add new specials with hex edit?
Adding Special Actions isn't entirely possible yet. Pikazz managed to do it, but it's very buggy.

and here is the other thing:
- How to edit Floating points so that the injected specials work as the Owner of that special
That is not possible at the moment.

Fox has Ike's Side B and all it's attributes (Floating Points, charge frames, etc
You can use various PSA commands and Float Variables for a pseudo Ike Side Special.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: namq on June 13, 2014, 12:34:34 PM
Thanks for the quick reply, I will look into the Side B stuff.  I saw some posts around here for teleports, Which I need to also make a teleport way for my character.

TYVM KoC!


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Sage Lotus on June 24, 2014, 11:11:27 PM
Might be a noob question but what is a "tether"?


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: pikazz on June 25, 2014, 04:03:54 AM
Might be a noob question but what is a "tether"?

a tether is that when you "Z Attacking" in air with some character, example Link using his clawshot, Samus using her grapple beam

but the real tether is when you using it at a ledge! the article will attach to the ledge and you can easy wind up yourself to it!

I have taken a look at it  myself, but it appears you need a proper article for it to work! :/ without article, you will fall down and die!


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: MegaGEN50 on July 07, 2014, 12:46:43 PM
How is it that Articles are so impossible to make?


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Rosetta-Hime on July 07, 2014, 07:14:25 PM
How is it that Articles are so impossible to make?
I don't know if this is correct or not, but I'm pretty sure Articles are hard coded in sora_melee.rel, and from what I've heard, it's pretty difficult to edit that in any way. Aticles are also coded in the the character's .rel too, I believe.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: armyguy110 on September 26, 2014, 08:07:15 PM
has shiek ever had a tether? I have a psa that has a tether...


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on September 26, 2014, 08:09:03 PM
has shiek ever had a tether? I have a psa that has a tether...
Yes. Sheik's always had a tether in Brawl.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Carnage on September 28, 2014, 09:00:55 AM
so the subactions added trough bb psa acutally work? or you need to do some rel editing? just wondering.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on September 28, 2014, 09:04:14 AM
so the subactions added trough bb psa acutally work? or you need to do some rel editing? just wondering.
Yes. You need to do rel editing.

http://forums.kc-mm.com/index.php?topic=66811.0 (http://forums.kc-mm.com/index.php?topic=66811.0)


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: super1234 on December 02, 2015, 10:51:57 PM
i need help here i tried editing king dedede with PSA but it keeps on telling me "cannot locate file data" then it says "could not open file"
is there any way to edit FitDedede.pac?
is there another version of psa that works with dedede or which other program
i just want to increase his damage


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on December 03, 2015, 06:27:25 AM
This isn't the place for that, but you should be able to open the FitDedede.pac file with this version of PSA.

https://www.dropbox.com/s/2msd86co64ujdfb/PSA%20v1.3%20%28Sammi%20Husky%29.zip?dl=0 (https://www.dropbox.com/s/2msd86co64ujdfb/PSA%20v1.3%20%28Sammi%20Husky%29.zip?dl=0)


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: super1234 on December 03, 2015, 03:05:53 PM
This isn't the place for that, but you should be able to open the FitDedede.pac file with this version of PSA.

https://www.dropbox.com/s/2msd86co64ujdfb/PSA%20v1.3%20%28Sammi%20Husky%29.zip?dl=0 (https://www.dropbox.com/s/2msd86co64ujdfb/PSA%20v1.3%20%28Sammi%20Husky%29.zip?dl=0)
thanks


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Alexarah2014 on December 12, 2015, 09:03:24 PM
Hey KingJigglyPuff do know the methods or have a hint on how to make a counterattack for a character? I'm trying to give Ganondorf a counterattack in Project M. Oh by the way sorry if this isn't the right place to ask but I've been searching through the web for a solution but have found nothing. It's quite frustrating. :-[


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Direact_N1 on December 12, 2015, 09:13:33 PM
Sorry if this isn't the type of place to be asking this, but has anything close to Pac-Man's Smash 4 moveset been proven to be possible or not? At least Bonus Fruit, Power Pellet, Fire Hydrant, and how he spawns the ghosts in his Smash attacks?

Also, I checked the list over again, and, is it possible to add Super Armor to an attack? I heard you also couldn't make reflectors, either.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on December 13, 2015, 08:53:55 AM
Hey KingJigglyPuff do know the methods or have a hint on how to make a counterattack for a character? I'm trying to give Ganondorf a counterattack in Project M. Oh by the way sorry if this isn't the right place to ask but I've been searching through the web for a solution but have found nothing. It's quite frustrating. :-[
A Counter? That's certainly possible.

So things aren't cluttered, I can make a basic tutorial on it.

Sorry if this isn't the type of place to be asking this, but has anything close to Pac-Man's Smash 4 moveset been proven to be possible or not? At least Bonus Fruit, Power Pellet, Fire Hydrant, and how he spawns the ghosts in his Smash attacks?

Also, I checked the list over again, and, is it possible to add Super Armor to an attack? I heard you also couldn't make reflectors, either.
Pac Man's Fruit and Hydrant aren't currently possible, as those are Articles, but Super Armor and the Ghost effects are possible. Power Pellet would possibly be a mix between the two. Though it would likely require advanced coding.

Super Armor is applied via command while the Ghost effects would be applied by either GFX, Model Changer, or VIS0.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Alexarah2014 on December 13, 2015, 09:17:02 PM
A Counter? That's certainly possible.

So things aren't cluttered, I can make a basic tutorial on it.
Pac Man's Fruit and Hydrant aren't currently possible, as those are Articles, but Super Armor and the Ghost effects are possible. Power Pellet would possibly be a mix between the two. Though it would likely require advanced coding.

Super Armor is applied via command while the Ghost effects would be applied by either GFX, Model Changer, or VIS0.
Awesome bro when can you find time to make a tutorial on making a counterattack?


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Large Leader on December 13, 2015, 10:26:05 PM
He already made one. Check out the A/A Tutorial section.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: masamune on December 17, 2015, 08:24:33 PM
Moves which depend on the distance between your character and its opponent, can we implement them?
I'll take Link as an example for what I mean:
If you press A when the opponent is far, he will fire an arrow.  
When the opponent is close, however,he will execute the spin attack.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on December 17, 2015, 08:31:09 PM
You technically can by having a rapidly moving flinchless hitbox, setting/clearing a Bit based on the hitbox, then changing the Action, based on which Bit is set.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: masamune on December 17, 2015, 09:07:40 PM
I see!
Thank you for answering!


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Direact_N1 on December 21, 2015, 05:32:29 PM
Is it possible to spawn items? I mean to have the character do some motion, and spawn any of the game items right in their hand to use/absorb. Even food items, which are instantly used when spawned, and badges, which are instantly applied when spawned, and even other things like trophies, stickers, and CDs. Finally, even to spawn Sandbags with this attack? Weapons would be spawned, then you can use/throw them like normal. Is any of this do-able?


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on December 21, 2015, 05:42:36 PM
Yes, it's possible to spawn items. I believe every item can be spawned with the Generate Item command. Items like food and badges cannot be changed to not auto use, as that will cause glitches (unable to pick up other items until KO'd).


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Direact_N1 on December 21, 2015, 05:57:45 PM
You can even get the bonus stuff like that, too? (Stickers and CDs?)


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on December 21, 2015, 06:02:15 PM
Yes. Use this page to figure out the Item IDs. http://tinyurl.com/ovj4a49 (http://tinyurl.com/ovj4a49)


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Tabuu Forte Akugun on December 21, 2015, 06:57:24 PM
Nice, you can PSA a fighter to spawn CD's? cool.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on December 21, 2015, 07:06:32 PM
Yes. I did it with my Cheat-a-Chu PSA back when I was newer at PSA.
http://forums.kc-mm.com/Gallery/BrawlView.php?Number=14499 (http://forums.kc-mm.com/Gallery/BrawlView.php?Number=14499)


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Direact_N1 on December 21, 2015, 07:36:48 PM
Oh, wow. Thanks, I was thinking of a moveset idea and wanted the Standard-B to spawn just about every possible item type thing in the game, I never even thought about the side stuff like Wario's bike pieces, ROB's gyroscope, Link's bombs or Peach's peaches.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on December 21, 2015, 08:01:53 PM
Just note that Link's and Toon Link's bombs won't have their GFX unless Link/Toon Link is in the match, due to characters not loading other GFX IDs.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Nebulon on December 22, 2015, 10:13:15 AM
Hello.

I'm messing with Pokemon Trainer and wanted to know if there was a way for me to edit the Fitpoketrainer.pac in order to have it so that when a Pokemon is KOd, it doesn't switch out during the respawn. Is that something I can edit?


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on December 22, 2015, 12:22:57 PM
Hello.

I'm messing with Pokemon Trainer and wanted to know if there was a way for me to edit the Fitpoketrainer.pac in order to have it so that when a Pokemon is KOd, it doesn't switch out during the respawn. Is that something I can edit?
There's no way to do that with PSA, unfortunately.

You have to use this code.

Code:
P.Trainer No Swap: (11 Lines) [Y.S. & Phantom Wings]
C2816AF4 0000000A
3E408062 3A523320
3A60FFFF 3E730001
7E732038 1E730244
7E529A14 80120000
2C00001D 41800024
2C000022 4181001C
2C170115 41820014
38A5FFFF 2C050000
40800008 38A00002
7C0802A6 00000000


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Nebulon on December 22, 2015, 01:11:29 PM
That'll work. Thanks!!!


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Dinoverlord on May 03, 2016, 08:26:04 AM
I want to do a dry bowser PSA, I want to change his smash attack and running to that like smash 4 bowser. Also I'd like to make his down b stronger and faster, but when he hits the ground he falls apart, there forth making to longer to get up.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on May 03, 2016, 01:01:23 PM
That's very easy to do. Just increase the damage and speed, then make a longer animation in which he falls apart and has to get up.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Patzipatzpatz on May 07, 2016, 08:17:33 AM
Is adding a tether really impossible? In BrawlEx the FighterX.dat (opened with BrawlEx Config Utility v1.3) has a CanZAir boolean field..
A Yoshi with a tongue tether would be awesome ^^


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on May 07, 2016, 08:20:09 AM
A tether requires an Article, and articles aren't possible to be added at the moment, thus making adding a tether currently impossible.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: highonphazon on July 26, 2016, 01:25:32 PM
Do the modding gods foresee adding an AI teammate to a character other than IC's ever possible?


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: teh-myuutsu on August 27, 2016, 07:45:25 AM
How do you add Crawling in? I tried extracting the .rel file from the config editor, but it doesn't seem to be extracting anything. I am trying to add crawling to Mr.Game&Watch. And I don't want a download link for it because I want to learn how to do it myself.


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: KingJigglypuff on August 27, 2016, 07:48:14 AM
-snip
Follow this tutorial to learn how to do so.

http://forums.kc-mm.com/index.php?topic=66724.0 (http://forums.kc-mm.com/index.php?topic=66724.0)


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Rooftop Sword Master on April 27, 2018, 07:07:23 AM
Dos anyone know how to lengthen sword trails in BrawlBox or project smash attack?


Title: Re: PSA Tips: What's possible and what's not possible.
Post by: Coolmanland on July 27, 2018, 12:55:07 AM
Can somebody teach me how to delete Ness' and Lucas' special double jump data and Grab data? I want Ness and Lucas to have normal jumps and for lucas to do a normal grab.