`sets up initial program status
set display mode 1024,768,16
sync on
sync rate 60
hide mouse
autocam off
randomize timer()
set camera range 1,10000
color backdrop 0
 
`makes the ground texture
ink 0,0
box 0,0,64,64
ink rgb(25,25,25),0
box 1,1,63,63
ink rgb(50,50,50),0
box 2,2,62,62
ink rgb(75,75,75),0
box 3,3,61,61
ink rgb(100,100,100),0
box 4,4,60,60
ink rgb(125,125,125),0
box 5,5,59,59
ink rgb(150,150,150),0
box 6,6,58,58
ink rgb(175,175,175),0
box 7,7,57,57
get image 1,0,0,64,64
cls
 
`texture for box attack
ink rgb(100,80,0),0
box 0,0,64,64
ink rgb(130,120,0),0
box 5,5,59,59
 
ink rgb(80,70,0),0
box 15,15,49,49
 
get image 2,0,0,64,64
 
`makes level
make matrix 1,6000,6000,10,10
prepare matrix texture 1,1,1,1
 
`makes player
make object cone 3,40
xrotate object 3,90
fix object pivot 3
set object cull 3,0
 
`makes outside walls
make object cube 1,6000
texture object 1,1
scale object texture 1,10,10
set object 1,1,1,0,1,0
position object 1,3000,0,3000
 
`makes AI character
make object cone 2,40
xrotate object 2,90
fix object pivot 2
position object 2,3000,20,3000
color object 2,rgb(200,200,200)
set object cull 2,0
 
`players shadow
make object sphere 7,40
scale object 7,100,2,100
color object 7,rgb(0,0,0)
set object ambient 7,0
 
`players attack shadow
make object cube 8,50
scale object 8,100,2,100
color object 8,rgb(0,0,0)
hide object 8
 
`makes AI's shadow
make object sphere 5,40
scale object 5,100,2,100
color object 5,rgb(40,40,40)
set object ambient 5,0
 
`makes AI attack object
make object cube 4,5
scale object 4,40,200,300
color object 4,rgb(0,0,0)
 
`makes player's attack object
make object cube 6,50
scale object 6,100,50,100
texture object 6,2
 
`makes 5 randomly placed mp heals
mp1x#=rnd(5800)+100
mp1z#=rnd(5800)+100
mp2x#=rnd(5800)+100
mp2z#=rnd(5800)+100
mp3x#=rnd(5800)+100
mp3z#=rnd(5800)+100
mp4x#=rnd(5800)+100
mp4z#=rnd(5800)+100
mp5x#=rnd(5800)+100
mp5z#=rnd(5800)+100
 
for healer=10 to 14
   make object cone healer,150
   xrotate object healer,180
   set object cull healer,0
next healer
 
color object 10,rgb(255,100,100)
color object 11,rgb(255,100,100)
color object 12,rgb(255,100,100)
 
color object 13,rgb(100,255,100)
color object 14,rgb(100,255,100)
 
position object 10,mp1x#,get ground height(1,mp1x#,mp1z#),mp1z#
position object 11,mp2x#,get ground height(1,mp2x#,mp2z#),mp2z#
position object 12,mp3x#,get ground height(1,mp3x#,mp3z#),mp3z#
position object 13,mp4x#,get ground height(1,mp4x#,mp4z#),mp4z#
position object 14,mp5x#,get ground height(1,mp5x#,mp5z#),mp5z#
 
set ambient light 0
 
`AI ENEMY STATS
`health
enemy_hp=1200
enemy_maxhp=1200
`magic points
enemy_mp=120
enemy_maxmp=120
`damage dealt on normal attack
enemy_strength=10
 
`sets AI reaction and movement variables
aware=0
`the distance infront of the enemy used for his sight, same effects as hearing.
sight_distance#=750
`a distance around the enemy used for hearing. if you step within it, the enemy will become aware of your presence.
hearing_distance#=300
`the distance at which the enemy stops following you (gives up)
max_range#=1000
AI_attacktime=10
AI_weight=5
AI_walkingspeed=7
 
`AI healing ability
enemy_heal_effect=45
enemy_heal_mpuse=20
enemy_heal_speed=100
 
`PLAYER STATS
`health
hp=1000
maxhp=1000
`magic points
mp=150
maxmp=150
`damage dealt on normal attack
strength=15
 
`character variables
`how fast the player walks
player_walkingspeed=10
weight=5
`how high player jumps
player_jumpforce=23
`how fast the players attack is
player_attacktime=20
 
`player healing ability
`how many points to heal
heal_effect=50
`how much mp used
heal_mpuse=20
`how long it takes
heal_speed=60
 
 
`action shortcuts
stand=0
jump=1
walk=2
heal=3
attack=4
limit=5
 
 
`sets gravity
gravity=-5
lcount=-100
 
`text color
ink rgb(200,50,50),0
 
position object 3,0,0,0
 
 
 
 
do
gosub player_movement
gosub AI_player
gosub healers
gosub debug_info
gosub rules
`gets distance between player and AI player
distance#=sqrt((object position x(3)-object position x(2))^2+(object position y(3)-object position y(2))^2+(object position z(3)-object position z(2))^2)
sync
loop
 
 
 
debug_info:
ink 0,0
box 3,1,152,187
box 893,1,1007,72
 
ink rgb(100,100,100),0
box 5,3,150,185
box 895,3,1005,70
 
ink rgb(255,255,255),0
text 10,5,"-Player Stats-"
text 10,20,"Hp:"+str$(hp)+"/"+str$(maxhp)
text 10,35,"Mp:"+str$(mp)+"/"+str$(maxmp)
 
if action=0 then text 10,50,"Action:Standing"
if action=1 then text 10,50,"Action:Jumping"
if action=2 then text 10,50,"Action:Walking"
if action=3 then text 10,50,"Action:Healing"
if action=4 then text 10,50,"Action:Attacking"
 
text 900,2,"-Enemy Stats-"
text 900,20,"Hp:"+str$(enemy_hp)+"/"+str$(enemy_maxhp)
text 900,35,"Mp:"+str$(enemy_mp)+"/"+str$(enemy_maxmp)
 
if goal=0
   if eaction=0 then text 900,50,"Action:Standing"
   if eaction=1 then text 900,50,"Action:Jumping"
   if eaction=2 and emovement_action=1 then text 900,50,"Action:Following"
   if eaction=2 and emovement_action=0 then text 900,50,"Action:Escaping"
   if eaction=3 then text 900,50,"Action:Healing"
   if eaction=4 then text 900,50,"Action:Attacking"
else
   text 900,50,"Action:Patrol"
endif
 
 
text 10,80,"-Player Controls-"
text 10,95,"Mouse:Turn"
text 10,110,"Mousebuttons:Move"
text 10,125,"Spacebar:Jump"
text 10,140,"Enter:Attack"
text 10,155,"Control:Heal"
text 10,170,"Shift:Limit"
return
 
 
 
player_movement:
 
`gets players old values
oldx#=x#
oldy#=y#
oldz#=z#
 
`movement and rotation
if action=stand or action=walk or action=jump
   if upkey()=1
      move object 3,player_walkingspeed
      if action=0 then action=2
   endif
 
   if downkey()=1
      move object 3,-1*player_walkingspeed
      if action=0 then action=2
   endif
   if upkey()=0 and downkey()=0 and action=2 then action=0
endif
 
`turning player
if action<>attack
   if leftkey()=1 then yrotate object 3,wrapvalue(object angle y(3)-5)
   if rightkey()=1 then yrotate object 3,wrapvalue(object angle y(3)+5)
endif
 
`gets camera variables
x#=object position x(3)
y#=object position y(3)
z#=object position z(3)
yr#=object angle y(3)
 
camyr#=wrapvalue(curveangle(yr#,camera angle y(),12.0))
camx#=newxvalue(x#,wrapvalue(camyr#+180),300)
camz#=newzvalue(z#,wrapvalue(camyr#+180),300)
 
camy#=get ground height(1,camx#,camz#)+200
 
if camx#>5900 then camx#=5900
if camx#<100 then camx#=100
if camz#>5900 then camz#=5900
if camz#<100 then camz#=100
if camy#>2800 then camy#=2800
 
position camera camx#,camy#,camz#
point camera x#,y#,z#
yrotate camera wrapvalue(camyr#)
 
 
 
`calculates standing and jumping
if action=stand or action=walk then y#=get ground height(1,x#,z#)+20
`jump with out flying
if action=jump then y#=oldy#:gravity_force=gravity_force+(gravity/10):y#=y#+gravity_force+vertforce
 
`starting an attack
if returnkey()=1
   if action=stand or action=walk then action=attack
endif
 
`starting a heal
if controlkey()=1 and mp=>heal_mpuse
   if action=stand or action=walk then action=heal
endif
 
`starting a limit break
if shiftkey()=1 and mp>20
   if action=stand or action=walk then action=limit
endif
 
`going to various abilities
gosub attack
gosub heal
gosub limit
 
`sliding collision with walls and roof
if x#>5900 then x#=5900
if x#<100 then x#=100
if z#>5900 then z#=5900
if z#<100 then z#=100
if y#>2800 then y#=2800
 
`jumping, gravity and staying on the ground
if vertforce>0 then dec vertforce
if y#<get ground height(1,x#,z#)+20 then action=stand
 
`starting a jump
if spacekey()=1
   if action=stand or action=walk
      vertforce=player_jumpforce
      action=jump
      gravity_force=gravity
   endif
endif
 
`sliding collision with AI player
dx#=object position x(3)-object position x(2)
dz#=object position z(3)-object position z(2)
`moving player away
if dx#<25 and dx#>0 and dy#>-25 and dy#<20 and z#>az#-25 and z#<az#+25 then x#=ax#+25
if dx#>-25 and dx#<0 and dy#>-25 and dy#<20 and z#>az#-25 and z#<az#+25 then x#=ax#-25
if dz#<25 and dz#>0 and dy#>-25 and dy#<20 and x#>ax#-25 and x#<ax#+25 then z#=az#+25
if dz#>-25 and dz#<0 and dy#>-25 and dy#<20 and x#>ax#-25 and x#<ax#+25 then z#=az#-25
 
`positioning camera in final position
position object 3,x#,y#,z#
 
`positions players shadow
position object 7,x#,get ground height(1,x#,z#)+1,z#
 
return
 
 
 
 
 
 
AI_player:
`gets the AI player's current position into variables.
ax#=object position x(2)
ay#=object position y(2)
az#=object position z(2)
ary#=object angle y(2)
 
`stores old AI positions
oldax#=ax#
olday#=ay#
oldaz#=az#
 
`makes enemy patrol if it is unaware that you are around, and if its hp is less than 50% it will heal.
if aware=0
   if enemy_hp>enemy_maxhp/2
      gosub enemy_patrol
   else
      if enemy_mp=>enemy_heal_mpuse
         eaction=heal
      gosub enemy_heal
      else
         gosub enemy_patrol
      endif
   endif
endif
 
 
`things to do if the AI player is aware that the main player exists.
if aware=1
   `points and AI object towards player if it is aware, and moves it if it's not in attack range.
   point object 2,x#,y#,z#
   goal=0
   if eaction=walk or eaction=stand
      `enemy will run away if it's hp is less than 25%, if not it will keep chasing you
      if enemy_hp>enemy_maxhp*0.30
         if range=0 then emovement_action=1:eaction=walk
      else
         emovement_action=0:eaction=walk
      endif
      gosub enemy_follow
      gosub enemy_escape
   endif
 
   if range=1
   `attacks player if it is aware, in range, and facing the right angle
   if eaction=stand or eaction=walk
      if enemy_hp>enemy_maxhp*0.30 then eaction=attack
   endif
   endif
   `makes enemy unaware when it is past it's max range, so it won't chase you forever.
   if distance#>max_range# then aware=0
endif
 
`enemy heals itself
if enemy_hp<enemy_maxhp*0.3
   if distance#>500
      if eaction<>jump and enemy_mp=>enemy_heal_mpuse then eaction=heal
   endif
endif
 
`goes to ability code and checks the eaction
gosub enemy_attack
gosub enemy_heal
 
`if Ai player hears the main player then it is aware
if distance#<hearing_distance# then aware=1:text 200,30,"You are in AI player's hearing range!"
 
`if AI player sees the main player then it is aware.
if distance#<sight_distance#
   position camera ax#,ay#,az#
   yrotate camera ary#
   if object in screen(3)=1 then aware=1:text 200,45,"You are in AI player's seeing range!"
   position camera camx#,camy#,camz#
   yrotate camera camyr#
endif
 
`checks to see if player and enemy are in range
if distance#<=50
   range=1
else
   range=0
endif
 
`sliding collision with walls and roof
if ax#>5900 then ax#=5900
if ax#<100 then ax#=100
if az#>5900 then az#=5900
if az#<100 then az#=100
if ay#>2800 then ay#=2800
 
`poisitons and rotates enemy and it's shadow
position object 2,ax#,ay#,az#
yrotate object 2,ary#
position object 5,ax#,get ground height(1,ax#,az#)+1,az#
 
return
 
 
`a healing ability that takes mp - used by the enemy
enemy_heal:
if enemy_mp+enemy_heal_mpuse=>enemy_heal_mpuse
   if eaction=heal and ehealcount=0 then dec enemy_mp,enemy_heal_mpuse:ehealcount=enemy_heal_speed
   if ehealcount>0
      color object 2,rgb(rnd(100)+100,rnd(100)+100,rnd(100)+100)
      eaction=heal
      scale object 2,100,ehealcount*3+100,100
      dec ehealcount
      if ehealcount=0
         inc enemy_hp,enemy_heal_effect
         if enemy_hp>enemy_maxhp then enemy_hp=enemy_maxhp
         color object 2,rgb(100,100,100)
         eaction=stand
      endif
   endif
else
   scale object 2,100,100,100
endif
return
 
 
`a healing ability that takes mp - used by player
heal:
if mp+heal_mpuse=>heal_mpuse
   if action=heal and healcount=0 then dec mp,heal_mpuse:healcount=heal_speed
   if healcount>0
      color object 3,rgb(rnd(100)+100,rnd(100)+100,rnd(100)+100)
      scale object 3,healcount*2+100,healcount*2+100,healcount*2+100
      action=heal
      dec healcount
      if healcount=0
         scale object 3,100,100,100
         color object 3,rgb(200,200,200)
         inc hp,heal_effect
         if hp>maxhp then hp=maxhp
         action=stand
      endif
   endif
endif
return
 
 
`a normal attack by the enemy
enemy_attack:
if eaction=attack and eattackcount=0 then eattackcount=AI_attacktime
if eattackcount>0
   eaction=attack
   `dealing damage
   if eattackcount=1 and distance#<55 then dec hp,enemy_strength
   show object 4
   position object 4,ax#,ay#+eattackcount*4-15,az#
   yrotate object 4,ary#
   move object 4,20
   color object 2,rgb(255,100,100)
   dec eattackcount
   if eattackcount=0 then eaction=stand:color object 2,rgb(100,100,100)
else
   hide object 4
endif
return
 
 
`a normal attack by the player
attack:
if action=attack and attackcount=0 then attackcount=player_attacktime
if attackcount>0
   action=attack
   show object 6
   show object 8
   position object 6,x#,y#+(attackcount*5),z#
   position object 8,x#,get ground height(1,x#,z#)+1,z#
   yrotate object 6,yr#
   yrotate object 8,yr#
   move object 6,50
   move object 8,50
   dec attackcount
   `dealing damage and ending attack
   if attackcount=0
      if distance#<70 and object in screen(2)=1 then dec enemy_hp,strength
      action=stand
   endif
else
   hide object 6
   hide object 8
endif
return
 
 
enemy_patrol:
if goal=0
goalx#=rnd(5800)+100
goalz#=rnd(5800)+100
goal=1
endif
if goal=1
   point object 2,goalx#,get ground height(1,goalx#,goalz#),goalz#
   move object 2,AI_walkingspeed
   ax#=object position x(2)
   ay#=get ground height(1,ax#,az#)+20
   az#=object position z(2)
   ary#=object angle y(2)
 
for check=10 to 14
   if object exist(check)=1
      if goalx#=object position x(check)
         if goalz#=object position x(check) then goto noheal
      endif
   endif
next check
 
for check=10 to 14
   if object exist(check)=1
   if ax#>object position x(check)-1000 and ax#<object position x(check)+1000 and az#>object position z(check)-1000 and az#<object position z(check)+1000
      if check<13 and check>9
         if enemy_hp<enemy_maxhp/2
            goalx#=object position x(check)
            goalz#=object position z(check)
         endif
      else
         if enemy_mp<enemy_maxmp/2
            goalx#=object position x(check)
            goalz#=object position z(check)
         endif
      endif
   endif
   endif
next check
noheal:
   `it gets to its goal
   if ax#>goalx#-10 and ax#<goalx#+10 and az#>goalz#-10 and az#<goalz#+10
      goal=0
   endif
endif
return
 
 
 
`the enemy's movement to follow you
enemy_follow:
if emovement_action=1 and eaction=walk
   move object 2,AI_walkingspeed
   ax#=object position x(2)
   ay#=get ground height(1,ax#,az#)+20
   az#=object position z(2)
   ary#=object angle y(2)
endif
return
 
 
`the enemy's movement to run away from you
enemy_escape:
if emovement_action=0 and eaction=walk
   yrotate object 2,wrapvalue(object angle y(2)-180)
   move object 2,AI_walkingspeed
   ax#=object position x(2)
   ay#=get ground height(1,ax#,az#)+20
   az#=object position z(2)
   ary#=object angle y(2)
   if distance#>max_range#-100 then aware=0:
   if needheal=1 and distance#>400 then eaction=heal
endif
return
 
 
healers:
for healer=10 to 14
if object exist(healer)=0 then goto nexthealplayer
if object position x(3)>object position x(healer)-40 and object position x(3)<object position x(healer)+40
if object position z(3)>object position z(healer)-40 and object position z(3)<object position z(healer)+40
if healer<13 then inc hp,maxhp/4 else inc mp,maxmp/4
delete object healer
endif
endif
nexthealplayer:
next healer
for healer=10 to 14
if object exist(healer)=0 then goto nexthealenemy
if object position x(2)>object position x(healer)-40 and object position x(2)<object position x(healer)+40
if object position z(2)>object position z(healer)-40 and object position z(2)<object position z(healer)+40
if healer<13 then inc enemy_hp,enemy_maxhp/4 else inc enemy_mp,enemy_maxmp/4
delete object healer
endif
endif
nexthealenemy:
next healer
return
 
 
rules:
if enemy_hp>enemy_maxhp then enemyhp=enemy_maxhp
if enemy_mp>enemy_maxmp then enemy_mp=enemy_maxmp
 
if hp>maxhp then hp=maxhp
if mp>maxmp then mp=maxmp
 
if enemy_hp<1 then goto victory
if hp<1 then goto gameover
return
 
 
victory:
text object screen x(2),object screen y(2),"You win!!"
ghost object on 2
sync
wait 500
for explosion=1 to 30
   make object sphere explosion+20,50
   position object explosion+20,ax#,ay#,az#
   yrotate object explosion+20,wrapvalue(explosion*36)
next explosion
delete object 2
delete object 4
delete object 5
delete object 6
a=100
do
a=a+2
for move_explosion=1 to 30
   move object move_explosion+20,1
   color object move_explosion+20,rgb(rnd(100)+100,rnd(100)+100,rnd(100)+100)
next move_explosion
set gamma a,a,a
if a=500 then exit
sync
loop
goto ending
 
 
limit:
if action=limit and lcount=-100
for crates=1 to 10
   make object cube crates+100,rnd(15)+40
   texture object crates+100,2
next crates
make object cylinder 111,150
color object 111,rgb(255,255,180)
ghost object on 111
scale object 111,100,500,100
oldmp=mp
lcount=200
endif
if lcount>-100
   action=limit
   if lcount<50 and mp>0 then dec mp:dec enemy_hp,6
 
   if lcount>0
      for position=1 to 10
         position object position+100,ax#+rnd(4)-2,ay+(lcount*3)-position*50,az#+rnd(4)-2
      next position
      position object 111,ax#,ay#,az#
      position camera camera position x()+rnd(10),camera position y()+rnd(10),camera position z()+rnd(10)
   endif
   dec lcount
   if lcount<0
      scale object 111,lcount+100,500,lcount+100
   endif
   `dealing damage and ending attack
   if lcount=-100
      for decrates=1 to 11
         delete object decrates+100
      next decrates
      dec enemy_hp,mp
      action=stand
   endif
endif
return
 
gameover:
a=255
do
move camera rnd(5)-2.5
rotate camera wrapvalue(camera angle x()+rnd(5)-2.5),wrapvalue(camera angle y()+rnd(5)-2.5),wrapvalue(camera angle z()+rnd(5)-2.5)
if camera position x()<100 then position camera 100,camera position y(),camera position z()
if camera position x()>900 then position camera 900,camera position y(),camera position z()
if camera position z()<100 then position camera camera position x(),camera position y(),100
if camera position z()>900 then position camera camera position x(),camera position y(),900
if camera position y()<get ground height(1,camera position x(),camera position z() )+10 then position camera camera position x(),get ground height(1,camera position x(),camera position z() )+10,camera position z()
set gamma a,a,a
dec a,2
if a<=5 then exit
sync
loop
wait 500
set gamma 255,255,255
 
ending: