ID:2115356
 
(See the best response by MrStonedOne.)
Problem description: Hello, I am probably going about this the wrong way but I was wondering how do I position multiple projectiles in one direction. I am using Fireking's pixel projectile library.


Gyazo: What I want to accomplish is:



Gyazo: Current outcome:


Code: Projectile activation
ability/active/mage
roaringWaves
name = "Roaring Waves"
damage = list(130,140,150,160)
cooldown = 1//95
icon_state = "_gui_roaring_waves"
spiritCost = 1//22

perform(mob/a){
flick("Sword Slash1",a)
a.target = locate(a.x-5, a.y - 1, a.z)
new/pixel_projectile/mage/roaringWaves(a.loc)

a.target = locate(a.x, a.y - 1, a.z)
new/pixel_projectile/mage/roaringWaves(a.loc)

a.target = locate(a.x+5, a.y - 1, a.z)
new/pixel_projectile/mage/roaringWaves(a.loc)
}


Code: The actual projectile
pixel_projectile/mage/roaringWaves

icon = '_mage_effects.dmi'
layer = 4
icon_state = "_roaring_waves"
attackType = "spiritual"

moveLimit = 10
attackType = "spiritual"

collide(atom/a){

if(ismob(a)){
var/mob/attacker = owner
var/mob/defender = a

if(attacker.checkTeamate(defender)) return

var
damage = attacker.getDamage(defender = defender, attackType = src.attackType, guardIgnorant = src.guardIgnorant, damageAmount = src.damageAmount)
dmgShow = "<font color = #fff>[damage]"
image/aftermath/ia = new/image/aftermath/basicMageAttack

ia.aftermath(defender)

if(isnum(damage))

if(attacker.getProbability(attacker.getCriticalChance(defender)))
damage = attacker.getCriticalDamage(defender, damage)
dmgShow = "<font color = #ffa500><font size = 3>[damage]!"

defender.coreLoss(defender.health, damage, attacker)
//MAGE DOESN'T GET TO DEAL WOUND DAMAGE BUT INSTEAD DAMAGE IS INCREASED BY 1000% WOUND_DAMAGE
//Basic Attacks Generate 3% Spirit!
attacker.coreGain(attacker.spirit, attacker.spirit.maximum * 0.03)

//Roaring waves slows down enemies for 2 secs.
if(attacker.checkAbilitySpecial("RoaringWaves")) attacker.applyCondition(defender, "slow", 20)

attacker.showDamage(defender, "<b>[dmgShow]")
}

}


I just need help with the positions and fill in the blanks.

Thank you,
Luchasi
Best response
In general, when trying to translate something from your mind, into paper so that others can understand it, you want to ensure the reader has to infer the least amount of information.

in your "what I want" and "What I Get" pictures, you don't quite draw attention to what details in the pictures matter, and what is just background.

Like, i noticed your what i get picture has hud icons that your what i want picture lacks. did you mean you wanted help removing the hud icons? most likely not, but if you don't spell that out for us, how can we know for sure?

Maybe you were referring to the fact that one is landscape, and one is portrait. I could certainly help you convert your monitor into a portrait monitor if it's supported by your hardware, but i don't think that's what you were aiming for was it?

I'm assuming, that the issue between the two is two fold, the projectiles don't beam out, and their position should be parallel.

For the position one, the issue is in perform(mob/a)

target says where the beam ends, not where it starts. I don't know enough about the projectile library to know for sure how to solve this, but i think what you need to do is change the a.loc yo pass to the projectile to be the turfs next to the mob instead, and then rework the a.target math, because thats picking the wrong targets.
Yeah I should've been more clear when it came to describing the projectile itself. A brief description pointing it out should've done it.

The problem seemed to originate from the library itself. I noticed that no matter how many times I changed "a.loc", I had the same result. I looked into the library and found out that the location of the projectile was set to the mob's current location instead of the parameter itself.

I will probably come back from more assistance regarding this library but for now I have achieved what I was looking for.

Thank you.
Code: This is the new functioning code but as you can see, the design is horrid. How can I optimize this and I also want to add a trail for each projectile.

    roaringWaves
name = "Roaring Waves"
damage = list(130,140,150,160)
cooldown = 1//95
icon_state = "_gui_roaring_waves"
spiritCost = 1//22

perform(mob/a){
flick("Sword Slash1",a)

for(var/i = 0, i < 6, i++){
var/tempLoc
var/tempTarget

switch(i){
if(1){//left
tempLoc = get_step(a, turn(a.dir, -45))
switch(a.dir){
if(1) tempTarget = locate(a.x + 1, a.y + 2, a.z)
if(2) tempTarget = locate(a.x - 1, a.y - 2, a.z)
if(4) tempTarget = locate(a.x + 2, a.y - 1, a.z)
if(8) tempTarget = locate(a.x - 2, a.y + 1, a.z)
}
}

if(2){ //middle
tempLoc = get_step(a, a.dir)
switch(a.dir){
if(1) tempTarget = locate(a.x, a.y + 2, a.z)
if(2) tempTarget = locate(a.x, a.y - 2, a.z)
if(4) tempTarget = locate(a.x + 2, a.y, a.z)
if(8) tempTarget = locate(a.x - 2, a.y, a.z)
}
}

if(3){//right
tempLoc = get_step(a, turn(a.dir, 45))
switch(a.dir){
if(1) tempTarget = locate(a.x - 1, a.y + 2, a.z)
if(2) tempTarget = locate(a.x + 1, a.y - 2, a.z)
if(4) tempTarget = locate(a.x + 2, a.y + 1, a.z)
if(8) tempTarget = locate(a.x - 2, a.y - 1, a.z)
}
}
if(4){//outer right
switch(a.dir){
if(1)
tempLoc = locate(a.x + 2, a.y + 1, a.z)
tempTarget = locate(a.x + 2, a.y + 2, a.z)
if(2)
tempLoc = locate(a.x + 2, a.y - 1, a.z)
tempTarget = locate(a.x + 2, a.y - 2, a.z)
if(4)
tempLoc = locate(a.x + 1, a.y + 2, a.z)
tempTarget = locate(a.x + 2, a.y + 2, a.z)
if(8)
tempLoc = locate(a.x - 1, a.y - 2, a.z)
tempTarget = locate(a.x - 2, a.y - 2, a.z)
}
}

if(5){//outer left
switch(a.dir){
if(1)
tempLoc = locate(a.x - 2, a.y + 1, a.z)
tempTarget = locate(a.x - 2, a.y + 2, a.z)
if(2)
tempLoc = locate(a.x - 2, a.y - 1, a.z)
tempTarget = locate(a.x - 2, a.y - 2, a.z)
if(4)
tempLoc = locate(a.x + 1, a.y - 2, a.z)
tempTarget = locate(a.x + 2, a.y - 2, a.z)
if(8)
tempLoc = locate(a.x - 1, a.y + 2, a.z)
tempTarget = locate(a.x - 2, a.y + 2, a.z)
}
}
}

a.target = tempTarget
new/pixel_projectile/mage/roaringWaves(tempLoc)
}

}


Gyazo: Current outcome



Gyazo: Desired outcome


Thanks,
Luchasi
bump

Thanks,
Luchasi
To optimize it you can change
for(var/i = 0, i < 6, i++){
var/tempLoc
var/tempTarget
so that the vars are created before the if so you don't keep recreating them.
// (all of this goes under your roaringWaves type; indent appropriately)

// how many tiles out from the center to extend the projectile wall
var radius = 2

// type of projectile to use
var projectileType = /pixel_projectile/mage/roaringWaves

// icon state to flick when performing this skill
var flickState = "Sword Slash1"

// launch a projectile from `a` in the direction of `a` starting at `startLoc`
proc/launchProjectile(mob/a, atom/startLoc)
a.target = get_step(startLoc, a.dir)
new projectileType (startLoc)

perform(mob/a)
flick(flickState, a)

// launch a projectile directly in front of `a`
var turf/frontTurf = get_step(a, a.dir)
launchProjectile(a, frontTurf)

var turf/leftTurf = frontTurf
var turf/rightTurf = frontTurf
var leftDir = turn(a.dir, 90)
var rightDir = turn(a.dir, -90)

// step outward from the front turf, launching a projectile each step
for(var/n in 1 to radius)
leftTurf = get_step(leftTurf, leftDir)
rightTurf = get_step(rightTurf, rightDir)
launchProjectile(a, rightTurf)
launchProjectile(a, leftTurf)

I highly advise against using FIREking's pixel_projectile library. It abuses usr in ways I've never seen before.

Incidentally, this code is written so that if you ever decide to use a different projectile system, you'd only really have to change projectileType and how launchProjectile() works.
In response to Kaiochao
Thanks for replying everyone. This is probably off topic but what about FIREKing's Pixel Movement? The reason why I begun using his Pixel Projectile library it's because I leveraged his Movement library and that conflicted with my current projectile system.

My original projectile and movement system ate a lot of CPU and I played around with it to reduced the lag but I wasn't successful. The weird thing is, I never lagged but the players logged into my game had lag spikes here and there.

I will do some more research and reattempt both systems and come back with some result. Or if you can check out what I currently have that would be even better maybe? Not really sure. It would be really appreciated if you can point in the right direction.

Thank you,
Luchasi
In response to Luchasi
FIREking doesn't have a Pixel Movement library...
In response to Kaiochao
My apologies, I meant his smooth tile movement. I need to cater the projectile system I am using to his movement library.


Code: There is probably a better way to go about this but this how I am handling projectiles.

obj/projectile
layer = 4;
var/tmp
grade
speed = 1
duration = 50
breakable = TRUE
mob/owner
targets[0]
mob/target
standStill
attackType
woundDamage
damageAmount
guardIgnorant = FALSE
movementLimit = FALSE


proc
projectileSet(loc, dir, mob/owner, mob/target, grade)
src.dir = dir
src.loc = loc
src.grade = grade
src.owner = owner
src.target = target

if(!standStill) src.projectileFire(target)
else projectileSummon()
..()


projectileFire(var/targetLock = FALSE)

if(targetLock && owner.target) walk_towards(src,owner.target, src.speed)

else walk(src, src.dir, src.speed)

if(src) spawn(duration) del(src)


projectileSummon()

if(src) spawn(duration) del(src)


Code: This is how I am handling movement. I picked up most of it from Ter13

mob/var
run = null
move = TRUE
rundelay = null


mob
player
Move(turf/NewLoc,Dir=0,step_x=0,step_y=0)
if(checkCondition("stun")) return
var
turf/OldLoc = src.loc
oDir = src.dir
osx = step_x
osy = step_y

. = ..(NewLoc, Dir, step_x, step_y)

if(strafeDir) dir = strafeDir

if(.)
//if the move was successful, call Moved()

rundelay = 1

if(checkCondition("slow")) rundelay += 2

rundelay += world.time

Moved(OldLoc,oDir,osx,osy)

proc
Moved(turf/OldLoc,oDir=0,osx,osy)
//for(var/mob/Enemies/ai in range(MAX_AGGRO_RANGE, src)) ai.foundTarget(src)

Enemies
Move(turf/NewLoc,Dir=0,step_x=0,step_y=0)
//prevent diagonal movement
var/d = Dir & Dir-1
if(d)
Dir = rand(1) ? d : Dir^d
NewLoc = get_step(src,Dir)
. = ..(NewLoc,Dir,step_x,step_y)



client
Move()
if(mob.rundelay < world.time) return ..()


North()
if(mob.checkCondition("confuse")) mob.dir = pick(2,4,8)
return ..()


Gyzao: This is the profile without calculating the averages.



Code: This is FIREKing's movement library

//get_speed_delay(n) takes an argument speed "n" and returns how long it would take to travel 1 tile at this speed in 10ths of a second
proc/get_speed_delay(n)
return (world.icon_size * world.tick_lag) / (!n ? 1 : n)

//get_glide_size(n, dir) takes an argument speed "n", and direction "dir", and returns the smoothest possible glide_size setting
proc/get_glide_size(n, dir)
return (dir & (dir - 1)) ? n + (n >> 1) : n

atom/movable
var/speed = 12
var/tmp/move_time = 0
var/tmp/transferring = 0

Move()
//if(!src.loc) return ..()

if(world.time < src.move_time || usr.checkCondition("stun")) return 0

if(transferring) return 0

. = ..()

if(.)
src.move_time = world.time + get_speed_delay(src.speed)
src.glide_size = get_glide_size(src.speed, src.dir)

return .

proc/Transfer(atom/location)
if(!location) return

src.transferring = 1

spawn(get_speed_delay(src.speed) - world.tick_lag)
src.x = location.x
src.y = location.y
src.z = location.z

spawn(world.tick_lag)
src.transferring = 0


Gyzao: A runtime error I am experiencing when using his library and I think this has to with not specifying what "atom/movable" is under the Move().

bump :)
=)
You're using usr.checkCondition() instead of src
In response to Kozuma3
Thank you for replying.

It comes back as an undefined proc with "src" and I think it's because "checkCondition()" is a mob proc instead of an atom. That's just an assumption though.

EDIT: I am really looking for efficiency here. Is this the best way to check for movement impairing effects?
Would changing /atom/movable to /mob break anything? -shrug-
Conditions that prevent player movement should happen before mob.Move() is called, e.g. in client/Move().
Conditions that prevent player movement should happen before mob.Move() is called, e.g. in client/Move().

Strongly disagree. Conditions tied to the mob's behavior should occur before Move()'s default action is called.

client/Move() has no business involving itself at all in the result of the input. It should only notify the connected object that the input has occurred. This is to preserve interoperability or a control scheme that is object-agnostic.
In response to Kozuma3
Kozuma3 wrote:
Would changing /atom/movable to /mob break anything? -shrug-

It didn't break anything. I was able to test it but I see high cpu consumption from mob/Move(). However I am not looking at average. I'm starting to think my lag spikes are coming from else where. Like the "abilityCooldown()."

This is my latest profile.



EDIT: Is it in my best interest to create a separate movement system for projectiles?
bump :)
Bump ^_^
Page: 1 2