As a gesture of gratitude to the general community I want to share my AI code for the attack system
It's far from finished but I figure maybe it'll make sense to someone and help another project. It's
purely a battle system and I am using a virtually exact version for 'friends' as the 'enemies'... anyway, here it is:
function update_enemy()
for e=1 to 50
if object exist(e)
sc_updateobject e
t=enemy(e).targ
m=enemy(e).mode
select m
case 1
`attack
if t<>0
if object exist(t)
`random rolling
roll=enemy(e).roll
rolling=enemy(e).rolling
if time>rolling
if roll=0
r=rnd(2)+1
select r
case 1:roll=-1:endcase
case 2:roll=0:endcase
case 3:roll=1:endcase
endselect
rolling=time+1000+rnd(5000)
else
roll=0
rolling=time+10000+rnd(5000)
endif
endif
enemy(e).roll=roll
enemy(e).rolling=rolling
roll object right e,roll*2*TM
`ship data
ex#=object position x(e)
ey#=object position y(e)
ez#=object position z(e)
tx#=object position x(t)
ty#=object position y(t)
tz#=object position z(t)
`turn to target
EZro_SetupFromObject e
EZro_RotateTo 2,tx#,ty#,tz#,2*TM
EZro_PitchTo tx#,ty#,tz#,2*TM
EZro_FindEuler
frx#=EZro_GetEulerX()
fry#=EZro_GetEulerY()
frz#=EZro_GetEulerZ()
rotate object e,frx#,fry#,frz#
`move
move object e,10*TM
`check attack distance
d#=sqrt((ex#-tx#)^2+(ey#-ty#)^2+(ez#-tz#)^2)
if d#<300
m=2
rx#=object angle x(e)
ry#=object angle y(e)
rz#=object angle z(e)
a#=rnd(359)
roll object right e,a#
move object up e,1200
enemy(e).tx=object position x(e)
enemy(e).ty=object position y(e)
enemy(e).tz=object position z(e)
move object down e,1200
rotate object e,rx#,ry#,rz#
endif
`avoid
m=avoid(e,m,ex#,ey#,ez#)
if m=3
enemy(e).tx=targX
enemy(e).ty=targY
enemy(e).tz=targZ
endif
`fire
fire=enemy(e).fire
if time>fire
ex#=object position x(e)
ey#=object position y(e)
ez#=object position z(e)
move object e,1200
vx#=object position x(e)
vy#=object position y(e)
vz#=object position z(e)
move object e,-1200
aim=sc_raycast(t,ex#,ey#,ez#,vx#,vy#,vz#,e)
if aim>0
enemy(e).fire=time+500+rnd(500)
b=find free object(1000,500)
bullet(b-1000).life=time+5000
make object sphere b,10,2,3
scale object b,100,100,500
color object b,rgb(255,0,0)
position object b,ex#,ey#,ez#
set object to object orientation b,e
move object b,100
endif
endif
else
enemy(e).targ=0
endif
else
`find new target
cnt=0
t=rnd(50)+100
while object exist(t)=0 and t<>99999
t=rnd(50)+100
inc cnt
if cnt>2000
t=99999
endif
endwhile
if t<>99999
enemy(e).targ=t
else
gosub delete_ships:
gosub load_ships:
endif
endif
endcase
case 2
`turn to target
tx#=enemy(e).tx
ty#=enemy(e).ty
tz#=enemy(e).tz
`turn to target
EZro_SetupFromObject e
EZro_RotateTo 2,tx#,ty#,tz#,2*TM
EZro_PitchTo tx#,ty#,tz#,2*TM
EZro_FindEuler
frx#=EZro_GetEulerX()
fry#=EZro_GetEulerY()
frz#=EZro_GetEulerZ()
rotate object e,frx#,fry#,frz#
`move
move object e,10*TM
d#=sqrt((object position x(e)-tx#)^2+(object position y(e)-ty#)^2+(object position z(e)-tz#)^2)
if d#<200
m=1
endif
`avoid
m=avoid(e,m,object position x(e),object position y(e),object position z(e))
if m=3
enemy(e).tx=targX
enemy(e).ty=targY
enemy(e).tz=targZ
endif
endcase
case 3
`random rolling
roll=enemy(e).roll
rolling=enemy(e).rolling
if time>rolling
rolling=time+5000+rnd(5000)
if roll=0
r=rnd(2)+1
select r
case 1:roll=-1:endcase
case 2:roll=0:endcase
case 3:roll=1:endcase
endselect
else
roll=0
endif
endif
enemy(e).roll=roll
enemy(e).rolling=rolling
roll object right e,roll*TM
`avoid collision
tx#=enemy(e).tx
ty#=enemy(e).ty
tz#=enemy(e).tz
EZro_SetupFromObject e
EZro_RotateTo 2,tx#,ty#,tz#,2*TM
EZro_PitchTo tx#,ty#,tz#,2*TM
EZro_FindEuler
frx#=EZro_GetEulerX()
fry#=EZro_GetEulerY()
frz#=EZro_GetEulerZ()
rotate object e,frx#,fry#,frz#
`move
move object e,10*TM
m=1
`avoid
m=avoid(e,m,object position x(e),object position y(e),object position z(e))
if m=3
enemy(e).tx=targX
enemy(e).ty=targY
enemy(e).tz=targZ
endif
endcase
endselect
enemy(e).mode=m
`check for ship collision
col=sc_groupcollision(e,2)
if col<>0
spawn_explosion(object position x(e),object position y(e),object position z(e),1+rnd(8),100)
delete object e
else
col=sc_groupcollision(e,3)
if col<>0
spawn_explosion(object position x(e),object position y(e),object position z(e),1+rnd(8),100)
delete object e
endif
endif
endif
next
endfunction
function avoid(obj,m,sx#,sy#,sz#)
move object obj,300
nx#=object position x(obj)
ny#=object position y(obj)
nz#=object position z(obj)
move object obj,-300
clr=sc_spherecastgroup(2,sx#,sy#,sz#,nx#,ny#,nz#,100,obj)
if clr<>0
m=3
targX=sc_getstaticcollisionx()+sc_getcollisionnormalx()*110
targY=sc_getstaticcollisiony()+sc_getcollisionnormaly()*110
targZ=sc_getstaticcollisionz()+sc_getcollisionnormalz()*110
else
clr=sc_spherecastgroup(3,sx#,sy#,sz#,nx#,ny#,nz#,100,obj)
if clr<>0
m=3
targX=sc_getstaticcollisionx()+sc_getcollisionnormalx()*110
targY=sc_getstaticcollisiony()+sc_getcollisionnormaly()*110
targZ=sc_getstaticcollisionz()+sc_getcollisionnormalz()*110
endif
endif
endfunction m
Currently
everything is in collision group 2 for simplicity and I have a few arrays set up like this:
type aitype
targ as integer
tx as float
ty as float
tz as float
mode as integer
health as float
fire as integer
roll as integer
rolling as integer
endtype
dim enemy(50) as aitype
dim friend(50) as aitype
gosub load_ships:
type bull
life as integer
endtype
dim bullet(1000) as bull
I'm updating bullets using this code:
function update_bullets()
for b=1000 to 1999
if object exist(b)
sx#=object position x(b)
sy#=object position y(b)
sz#=object position z(b)
move object b,75*TM
fx#=object position x(b)
fy#=object position y(b)
fz#=object position z(b)
`check for enemy hit
hit=sc_raycastgroup(2,sx#,sy#,sz#,fx#,fy#,fz#,0)
if hit<>0
delete object b
if hit<51
h#=enemy(hit).health
h#=h#=10
if h#<=0
delete object hit
spawn_explosion(sx#,sy#,sz#,1+rnd(8),100)
else
enemy(hit).health=h#
endif
else
spawn_explosion(sx#,sy#,sz#,1+rnd(8),20)
endif
else
hit=sc_raycastgroup(3,sx#,sy#,sz#,fx#,fy#,fz#,0)
if hit<>0
delete object b
if hit>99
if hit<>p1
h#=friend(hit-99).health
h#=h#=10
if h#<=0
delete object hit
spawn_explosion(sx#,sy#,sz#,1+rnd(8),100)
else
friend(hit-99).health=h#
endif
else
spawn_explosion(sx#,sy#,sz#,1+rnd(8),20)
endif
else
spawn_explosion(sx#,sy#,sz#,1+rnd(8),20)
endif
endif
endif
if object exist(b)
if time>bullet(b-1000).life then delete object b
endif
endif
next
endfunction
Now there are all kinds of variables not explained and I'm using a float variable called "TM" for timer based movement so if anyone wants to use this code and needs help then let me know!