-- LUA Script - melee attacker script for classic characters -- APOCALYPSE Animframes: -- 8,28 - RUN -- 38,98 - IDLE 1 -- 105,164 - IDLE 2 -- 172,231 - IDLE 3 -- 239,298 - IDLE 4 -- 304,392 - DOUBLE ARM SLASH (330) (350) -- 407,459 - SINGLE ARM SLASH (434) -- 473,536 - OVERHEAD SLASH LEFT (503) -- 551,615 - OVERHEAD SLASH RIGHT (581) -- 629,687 - RAGE 1 -- 701,760 - RAGE 2 -- 740,751 - HURT -- 773,849 - BOUNCE FALL -- 869,932 - FACEPLANT -- 946,1001 - FALLBACK -- 1030,1101 - FALLSIDE -- 1107,1137 - WALK -- 1158,1188 - WALK LEAN BACK -- 1208,1238 - WALK ARMS OUT -- 1259,1306 - MARCH -- 1334,1355 - RUN 1 -- 1362,1383 - RUN 2 -- 1394,1464 - BODY HIT 1 -- 1504,1595 - BODY HIT 2 -- 1610,1658 - BODY HIT 3 -- 1685,1757 - HEADSHOT 1 -- 1780,1883 - HEADSHOT 2 -- 1900,2011 - HEADSHOT 3 -- 2020,2148 - LEFT ARM HIT 1 -- 2215,2291 - LEFT ARM HIT 2 -- 2350,2415 - LEFT LEG DIE 1 -- 2500,2669 - LEFT LEG DIE 2 -- 2780,2870 - RIGHT ARM HIT 1 -- 2980,3087 - RIGHT ARM HIT 2 -- 3140,3205 - RIGHT LEG DIE 1 -- 3300,3469 - RIGHT LEG DIE 2 -- 3578,3647 - LEFT LEG HIT TO PRONE -- 3709,3779 - RIGHT LEG HIT TO PRONE -- 3818,3818 - PRONE -- 3819,3864 - UP FROM PRONE -- 3865,3912 - PRONE ATTACK -- 3913,3967 - PRONE DIE -- 3973,3993 - CRAWL REACH -- 3994,4013 - CRAWL PULL local random = math.random local lower = string.lower local len = string.len local find = string.find math.randomseed(os.time()) random(); random(); random() --ai_soldier_state = ai_soldier_state or {} --ai_old_health = ai_old_health or {} local ai_old_health = {} local ai_soldier_state = {} local attackdistance = 85 local roarstart = 629 local roarend = 687 local hurtstart = 740 local hurtend = 751 local attackstart = {} local attackend = {} local damageframestart = {} local damageframeend = {} local viewrange = {} local lastroar = {} local lastswipe = {} function ai_classiccharacter_apocalypse_new_init( e ) CharacterControlLimbo( e ) ai_soldier_state[ e ] = "patrol" ai_old_health[ e ] = -1 SetAnimationFrames( 2, 79 ) LoopAnimation( e ) ModulateSpeed( e, 1.0 ) SetAnimationSpeed( e, 1.0 ) lastroar[ e ] = 0 lastswipe[ e ] = 0 attackstart[ e ] = 304 damageframestart[ e ] = 330 damageframeend[ e ] = 334 SetCharacterSoundSet( e ) end local function getPatrolPoint( e, Ent ) CharacterControlUnarmed( e ) local PathIndex = -1 local PathPointIndex = -1 local pClosest = math.huge for pa = 1, AIGetTotalPaths() do for po = 1, AIGetPathCountPoints( pa ) do local pDX = Ent.x - AIPathGetPointX( pa, po ) local pDZ = Ent.z - AIPathGetPointZ( pa, po ) local pDist = pDX*pDX + pDZ * pDZ if pDist < pClosest and pDist < 200 * 200 then pClosest = pDist PathIndex = pa PathPointIndex = po end end -- po end -- pa if PathIndex > -1 then ai_soldier_pathindex[ e ] = PathIndex ai_path_point_index[ e ] = PathPointIndex ModulateSpeed( e, 1.0 ) SetCharacterToWalk( e ) ai_path_point_direction[ e ] = 1 ai_path_point_max[ e ] = AIGetPathCountPoints( ai_soldier_pathindex[ e ] ) else ai_soldier_state[ e ] = 'idle' SetAnimationFrames( 2, 79 ) LoopAnimation( e ) end end local function followPath( e, Ent ) local ai_patrol_x = AIPathGetPointX( ai_soldier_pathindex[ e ], ai_path_point_index[ e ] ) local ai_patrol_z = AIPathGetPointZ( ai_soldier_pathindex[ e ], ai_path_point_index[ e ] ) AIEntityGoToPosition( Ent.obj, ai_patrol_x, ai_patrol_z ) local tDistX = Ent.x - ai_patrol_x local tDistZ = Ent.z - ai_patrol_z if tDistX * tDistX + tDistZ*tDistZ < 50 * 50 then if ai_path_point_direction[ e ] == 1 then ai_path_point_index[ e ] = ai_path_point_index[ e ] + 1 if ai_path_point_index[ e ] > ai_path_point_max[ e ] then ai_path_point_index[ e ] = ai_path_point_max[ e ] - 1 ai_path_point_direction[ e ] = 0 end else ai_path_point_index[ e ] = ai_path_point_index[ e ] - 1 if ai_path_point_index[ e ] < 1 then ai_path_point_index[ e ] = 2 ai_path_point_direction[ e ] = 1 end end end end local hitList = { "head", -- 1 "spine", -- 2 "l_thigh", -- 3 "l_calf", -- 4 "l_foot", -- 5 "r_thigh", -- 6 "r_calf", -- 7 "r_foot", -- 8 "l_upperarm", -- 9 "l_forearm", -- 10 "l_hand", -- 11 "l_finger", -- 12 "r_upperarm", -- 13 "r_forearm", -- 14 "r_hand", -- 15 "r_finger" } -- 16 local hitMap = { 1, 99, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5 } local function getHitArea( e, Ent ) lwrlimb = lower( Ent.limbhit ) ResetLimbHit( e ) if len( lwrlimb ) > 3 then for k, v in ipairs( hitList ) do if find( lwrlimb, v ) then return hitMap[ k ] end end end return 99 end local function ai_classiccharacter_apocalypse_dying( e, Ent ) local hitarea = getHitArea( e, Ent ) PlayCharacterSound( e, "onDeath" ) StartTimer( e ) CharacterControlLimbo( e ) local animStart, animEnd = 0, 0 --PromptDuration( hitarea, 3000 ) if hitarea == 1 then local randHit = random( 1, 3 ) if randHit == 1 then animStart, animEnd = 1685, 1757 elseif randHit == 2 then animStart, animEnd = 1780, 1883 else animStart, animEnd = 1900, 2011 end elseif hitarea == 2 then if random( 1, 2 ) == 1 then animStart, animEnd = 2350, 2415 else animStart, animEnd = 2500, 2669 end elseif hitarea == 3 then if random( 1, 2 ) == 1 then animStart, animEnd = 3140, 3205 else animStart, animEnd = 3300, 3469 end elseif hitarea == 4 then if random( 1, 2 ) == 1 then animStart, animEnd = 2020, 2148 else animStart, animEnd = 2215, 2291 end elseif hitarea == 5 then if random( 1, 2 ) == 1 then animStart, animEnd = 2780, 2870 else animStart, animEnd = 2980, 3087 end else local randHit = random( 1, 4 ) if randHit == 1 then animStart, animEnd = 1394, 1464 elseif randHit == 2 then animStart, animEnd = 1504, 1595 elseif randHit == 3 then animStart, animEnd = 1610, 1658 else animStart, animEnd = 773, 849 end end SetAnimationFrame( e, animStart ) SetAnimationFrames( animStart, animEnd ) PlayAnimation( e ) ModulateSpeed( e, 1.0 ) SetAnimationSpeed( e, 1.0 ) ai_soldier_state[ e ] = 'deathanim' end --function ai_classiccharacter_apocalypse_preexit( e ) -- SetPreExitValue( e, 1 ) -- tFrame = frame -- if dyingstart[ e ] > 0 and dyingend[ e ] > 0 then -- if ai_bot_state[ e ] ~= ai_state_preexit then -- ai_bot_state[ e ] = ai_state_preexit -- ai_classiccharacter_apocalypse_dying( e ) -- end -- else -- SetPreExitValue( e, 2 ) -- end -- if tFrame >= dyingend[ e ] - 2 then -- SetPreExitValue( e, 2 ) -- end --end function ai_classiccharacter_apocalypse_new_main( e ) local Ent = g_Entity[ e ] -- Death Animation if ai_soldier_state[ e ] ~= 'deathanim' then PlayerDist = GetPlayerDistance( e ) if viewrange[ e ] == nil then viewrange[ e ] = AIGetEntityViewRange(Ent.obj) end if ai_soldier_state[ e ] == 'patrol' then if ai_soldier_pathindex[ e ] == nil then getPatrolPoint( e, Ent ) else followPath( e, Ent ) end end local frame = GetAnimationFrame( e ) if PlayerDist < viewrange[ e ] then if PlayerDist < attackdistance and g_PlayerHealth > 0 then if ai_soldier_state[ e ] ~= 'attack' then AIEntityStop( Ent.obj ) ai_soldier_state[ e ] = 'attack' CharacterControlLimbo( e ) local attackType = random( 1, 5 ) if attackType == 1 then attackstart[ e ] = 304 attackend[ e ] = 392 damageframestart[ e ] = 330 damageframeend[ e ] = 334 elseif attackType == 2 then attackstart[ e ] = 304 attackend[ e ] = 392 damageframestart[ e ] = 350 damageframeend[ e ] = 354 elseif attackType == 3 then attackstart[ e ] = 407 attackend[ e ] = 459 damageframestart[ e ] = 434 damageframeend[ e ] = 437 elseif attackType == 4 then attackstart[ e ] = 473 attackend[ e ] = 536 damageframestart[ e ] = 503 damageframeend[ e ] = 507 elseif attackType == 5 then attackstart[ e] = 551 attackend[ e] = 615 damageframestart[ e ] = 581 damageframeend[ e ] = 585 end SetAnimationSpeed( e, 1.5 ) SetAnimationFrames( attackstart[ e ], attackend[ e ] ) PlayAnimation( e ) lastswipe[ e ] = 0 else if lastswipe[ e ] == 0 and frame < attackend[ e ] -1 then lastswipe[ e ] = 1 end if lastswipe[ e ] == 1 and frame >= attackend[ e ] -1 then ai_soldier_state[ e ] = 'patrol' SetAnimationSpeed( e, 1.0 ) StopAnimation( e ) lastswipe[ e ] = 2 end end else if ai_soldier_state[e] == 'attack' then if frame < attackstart[ e ] or frame >= attackend[ e ] - 1 then ai_soldier_state[ e ] = 'patrol' SetAnimationSpeed( e, 1.0 ) StopAnimation( e ) end else if ai_soldier_state[ e ] ~= 'charge' then if lastroar[ e ] == 0 or lastroar[ e ] > g_Time then if lastroar[ e ] == 0 then lastroar[ e ] = g_Time + 1000 end AIEntityGoToPosition( Ent.obj, g_PlayerPosX, g_PlayerPosZ ) else if ai_soldier_state[ e ] == 'hurtanim' then if frame > hurtend - 2 then ai_soldier_state[e] = 'charge' end else if ( frame > roarend - 2 and frame < roarend + 20 ) or lastroar[ e ] == -2 then ai_soldier_state[e] = 'charge' CharacterControlUnarmed( e ) if random( 1, 2 ) == 1 then SetCharacterToWalk(e) else SetCharacterToRun(e) end ModulateSpeed( e, 1.0 ) lastroar[ e ] = -2 end end if lastroar[ e ] > 0 then AIEntityStop( Ent.obj ) ai_soldier_state[ e ] = 'roar' CharacterControlLimbo( e ) SetAnimationFrames( roarstart, roarend ) PlayAnimation( e ) RotateToPlayer( e ) PlaySound( e, 1 ) lastroar[ e ] = -1 end end end end end if ai_soldier_state[ e ] == 'charge' then CharacterControlUnarmed( e ) RotateToPlayer( e ) AIEntityGoToPosition( Ent.obj, g_PlayerPosX, g_PlayerPosZ ) end if ai_soldier_state[ e ] == 'attack' then RotateToPlayer( e ) if frame > damageframestart[ e ] and frame < damageframeend[ e ] then if PlayerDist < attackdistance + 40 then HurtPlayer( e, 1 ) end end end elseif ai_soldier_state[ e ] == 'hurtanim' and frame >= hurtend then ai_soldier_state[ e ] = 'patrol' CharacterControlUnarmed( e ) SetCharacterToWalk( e ) ModulateSpeed( e, 1.0 ) end --PromptLocal( e, ai_old_health[ e ] .. ", " .. Ent.health .. ", " .. ai_soldier_state[ e ] ) if ai_old_health[ e ] == -1 then ai_old_health[ e ] = 1000000 + Ent.health SetEntityHealth( e, 1000000 + Ent.health ) elseif Ent.health < ai_old_health[ e ] then -- AI is hurt ai_old_health[ e ] = Ent.health AIEntityStop( Ent.obj ) if Ent.health < 1000000 then ai_classiccharacter_apocalypse_dying( e, Ent ) else ai_soldier_state[ e ] = 'hurtanim' CharacterControlLimbo( e ) SetAnimationFrames( hurtstart, hurtend ) PlayAnimation( e ) PlayCharacterSound( e, 'onHurt' ) end end else --DeathAnim Else -- wait until death anim over if GetTimer( e ) > 2000 then SetEntityHealth( e, 0 ) end end --DeathAnim Endif end function ai_classiccharacter_apocalypse_new_exit( e ) CollisionOff( e ) end