2024-02-26 00:17:10 +05:30
# ba_meta require api 6
2024-04-07 05:16:55 +05:30
# Server restart issue solved by SARA
2024-02-26 00:17:10 +05:30
from __future__ import annotations
from typing import TYPE_CHECKING
2024-04-07 05:16:24 +05:30
import ba , _ba
import random
import math
2024-02-26 00:17:10 +05:30
from bastd . gameutils import SharedObjects
from bastd . actor . bomb import Bomb
from ba . _generated . enums import InputType
2024-04-07 05:16:24 +05:30
2024-02-26 00:17:10 +05:30
if TYPE_CHECKING :
from typing import Optional
class Floater ( ba . Actor ) :
2024-04-07 05:16:24 +05:30
def __init__ ( self , bounds : tuple ) :
2024-02-26 00:17:10 +05:30
super ( ) . __init__ ( )
shared = SharedObjects . get ( )
self . controlled = False
self . source_player = None
2024-04-07 05:16:24 +05:30
self . floater_material = ba . Material ( )
self . floater_material . add_actions (
2024-02-26 00:17:10 +05:30
conditions = ( ' they_have_material ' ,
shared . player_material ) ,
actions = ( ( ' modify_node_collision ' , ' collide ' , True ) ,
( ' modify_part_collision ' , ' physical ' , True ) ) )
2024-04-07 05:16:24 +05:30
self . floater_material . add_actions (
2024-02-26 00:17:10 +05:30
conditions = ( ( ' they_have_material ' ,
shared . object_material ) , ' or ' ,
( ' they_have_material ' ,
shared . footing_material ) , ' or ' ,
( ' they_have_material ' ,
2024-04-07 05:16:24 +05:30
self . floater_material ) ) ,
2024-02-26 00:17:10 +05:30
actions = ( ' modify_part_collision ' , ' physical ' , False ) )
self . pos = bounds
2024-04-07 05:16:24 +05:30
self . px = random . uniform ( self . pos [ 0 ] , self . pos [ 3 ] )
self . py = random . uniform ( self . pos [ 1 ] , self . pos [ 4 ] )
self . pz = random . uniform ( self . pos [ 2 ] , self . pos [ 5 ] )
2024-02-26 00:17:10 +05:30
self . node = ba . newnode (
' prop ' ,
delegate = self ,
owner = None ,
attrs = {
2024-04-07 05:16:24 +05:30
' position ' : ( self . px , self . py , self . pz ) ,
' model ' : ba . getmodel ( ' landMine ' ) ,
' light_model ' : ba . getmodel ( ' landMine ' ) ,
' body ' : ' landMine ' ,
' body_scale ' : 3 ,
' model_scale ' : 3.1 ,
' shadow_size ' : 0.25 ,
' density ' : 999999 ,
' gravity_scale ' : 0.0 ,
' color_texture ' : ba . gettexture ( ' achievementFlawlessVictory ' ) ,
' reflection ' : ' soft ' ,
2024-02-26 00:17:10 +05:30
' reflection_scale ' : [ 0.25 ] ,
2024-04-07 05:16:24 +05:30
' materials ' : [ shared . footing_material , self . floater_material ]
2024-02-26 00:17:10 +05:30
} )
self . node2 = ba . newnode (
' prop ' ,
owner = self . node ,
attrs = {
' position ' : ( 0 , 0 , 0 ) ,
2024-04-07 05:16:24 +05:30
' body ' : ' sphere ' ,
' model ' : None ,
' color_texture ' : None ,
' body_scale ' : 1.0 ,
' reflection ' : ' powerup ' ,
' density ' : 999999 ,
2024-02-26 00:17:10 +05:30
' reflection_scale ' : [ 1.0 ] ,
2024-04-07 05:16:24 +05:30
' model_scale ' : 1.0 ,
' gravity_scale ' : 0 ,
' shadow_size ' : 0.1 ,
' is_area_of_interest ' : True ,
' materials ' : [ shared . object_material , self . floater_material ]
2024-02-26 00:17:10 +05:30
} )
self . node . connectattr ( ' position ' , self . node2 , ' position ' )
2024-04-07 05:16:24 +05:30
def check_can_control ( self ) - > bool :
2024-02-26 00:17:10 +05:30
if not self . node . exists ( ) :
return False
if not self . source_player . is_alive ( ) :
self . dis ( )
return False
return True
2024-04-07 05:16:24 +05:30
def con ( self ) - > None :
2024-02-26 00:17:10 +05:30
self . controlled = True
2024-04-07 05:16:24 +05:30
self . check_player_die ( )
2024-02-26 00:17:10 +05:30
2024-04-07 05:16:24 +05:30
def up ( self ) - > None :
if not self . check_can_control ( ) :
2024-02-26 00:17:10 +05:30
return
v = self . node . velocity
self . node . velocity = ( v [ 0 ] , 5 , v [ 2 ] )
2024-04-07 05:16:24 +05:30
def upR ( self ) - > None :
if not self . check_can_control ( ) :
2024-02-26 00:17:10 +05:30
return
v = self . node . velocity
self . node . velocity = ( v [ 0 ] , 0 , v [ 2 ] )
2024-04-07 05:16:24 +05:30
def down ( self ) - > None :
if not self . check_can_control ( ) :
2024-02-26 00:17:10 +05:30
return
v = self . node . velocity
self . node . velocity = ( v [ 0 ] , - 5 , v [ 2 ] )
2024-04-07 05:16:24 +05:30
def downR ( self ) - > None :
if not self . check_can_control ( ) :
2024-02-26 00:17:10 +05:30
return
v = self . node . velocity
self . node . velocity = ( v [ 0 ] , 0 , v [ 2 ] )
2024-04-07 05:16:24 +05:30
def leftright ( self , value : float ) - > None :
if not self . check_can_control ( ) :
2024-02-26 00:17:10 +05:30
return
v = self . node . velocity
self . node . velocity = ( 5 * value , v [ 1 ] , v [ 2 ] )
2024-04-07 05:16:24 +05:30
def updown ( self , value : float ) - > None :
if not self . check_can_control ( ) :
2024-02-26 00:17:10 +05:30
return
v = self . node . velocity
self . node . velocity = ( v [ 0 ] , v [ 1 ] , - 5 * value )
2024-04-07 05:16:24 +05:30
def dis ( self ) - > None :
2024-02-26 00:17:10 +05:30
if self . node . exists ( ) :
self . controlled = False
self . node . velocity = ( 0 , 0 , 0 )
self . move ( )
2024-04-07 05:16:24 +05:30
def check_player_die ( self ) - > None :
2024-02-26 00:17:10 +05:30
if not self . controlled :
return
if self . source_player is None :
return
if self . source_player . is_alive ( ) :
2024-04-07 05:16:24 +05:30
ba . timer ( 1 , self . check_player_die )
2024-02-26 00:17:10 +05:30
return
else :
self . dis ( )
2024-04-07 05:16:24 +05:30
def distance ( self , x1 : float , y1 : float , z1 : float , x2 : float , y2 : float , z2 : float ) - > float :
2024-02-26 00:17:10 +05:30
d = math . sqrt ( math . pow ( x2 - x1 , 2 ) + math . pow ( y2 - y1 , 2 ) + math . pow ( z2 - z1 , 2 ) )
return d
2024-04-07 05:16:24 +05:30
def drop ( self ) - > None :
2024-02-26 00:17:10 +05:30
try :
np = self . node . position
except :
np = ( 0 , 0 , 0 )
2024-04-07 05:16:24 +05:30
self . b = Bomb ( bomb_type = random . choice ( [ ' normal ' , ' ice ' , ' sticky ' , ' impact ' , ' land_mine ' , ' tnt ' ] ) ,
source_player = self . source_player , position = ( np [ 0 ] , np [ 1 ] - 1 , np [ 2 ] ) , velocity = ( 0 , - 1 , 0 ) ) . autoretain ( )
2024-02-26 00:17:10 +05:30
if self . b . bomb_type in [ ' impact ' , ' land_mine ' ] :
self . b . arm ( )
2024-04-07 05:16:24 +05:30
def move ( self ) - > None :
px = self . px
py = self . py
pz = self . pz
2024-02-26 00:17:10 +05:30
if self . node . exists ( ) and not self . controlled :
pn = self . node . position
dist = self . distance ( pn [ 0 ] , pn [ 1 ] , pn [ 2 ] , px , py , pz )
self . node . velocity = ( ( px - pn [ 0 ] ) / dist , ( py - pn [ 1 ] ) / dist , ( pz - pn [ 2 ] ) / dist )
t = dist - 1 if dist - 1 > = 0 else 0.1
ba . timer ( t , ba . WeakCall ( self . move ) , suppress_format_warning = True )
2024-04-07 05:16:24 +05:30
def handlemessage ( self , msg ) - > None :
2024-02-26 00:17:10 +05:30
if isinstance ( msg , ba . DieMessage ) :
self . node . delete ( )
self . node2 . delete ( )
self . controlled = False
elif isinstance ( msg , ba . OutOfBoundsMessage ) :
self . handlemessage ( ba . DieMessage ( ) )
else :
super ( ) . handlemessage ( msg )
2024-04-07 05:16:24 +05:30
def assign_flo_inputs ( client_id : int ) - > None :
2024-02-26 00:17:10 +05:30
with ba . Context ( _ba . get_foreground_host_activity ( ) ) :
activity = ba . getactivity ( )
2024-04-07 05:16:24 +05:30
# Check if the activity is a type that has a 'map' attribute
2024-02-26 00:17:10 +05:30
if not hasattr ( activity , ' flo ' ) or not activity . flo . node . exists ( ) :
2024-04-07 05:16:24 +05:30
try :
activity . flo = Floater ( activity . map . get_def_bound_box ( ' map_bounds ' ) )
except Exception as e :
print ( f " An error occurred while creating Floater: { e } " )
return # Perhaps using in main-menu/score-screen
else :
# Reset the controlled flag to allow control again
activity . flo . controlled = False
2024-02-26 00:17:10 +05:30
floater = activity . flo
if floater . controlled :
2024-04-07 05:16:24 +05:30
ba . screenmessage ( ' Floater is already being controlled ' , color = ( 1 , 0 , 0 ) , transient = True , clients = [ client_id ] )
2024-02-26 00:17:10 +05:30
return
2024-04-07 05:16:24 +05:30
ba . screenmessage ( ' You Gained Control Over The Floater! \n Press Bomb to Throw Bombs and Punch to leave! ' , clients = [ client_id ] , transient = True , color = ( 0 , 1 , 1 ) )
2024-02-26 00:17:10 +05:30
for i in _ba . get_foreground_host_activity ( ) . players :
2024-04-07 05:16:24 +05:30
if i . sessionplayer . inputdevice . client_id == client_id :
2024-02-26 00:17:10 +05:30
def dis ( i , floater ) :
i . actor . node . invincible = False
i . resetinput ( )
i . actor . connect_controls_to_player ( )
floater . dis ( )
ps = i . actor . node . position
i . actor . node . invincible = True
floater . node . position = ( ps [ 0 ] , ps [ 1 ] + 1.0 , ps [ 2 ] )
i . actor . node . hold_node = ba . Node ( None )
i . actor . node . hold_node = floater . node2
i . actor . connect_controls_to_player ( )
i . actor . disconnect_controls_from_player ( )
i . resetinput ( )
floater . source_player = i
floater . con ( )
i . assigninput ( InputType . PICK_UP_PRESS , floater . up )
i . assigninput ( InputType . PICK_UP_RELEASE , floater . upR )
i . assigninput ( InputType . JUMP_PRESS , floater . down )
i . assigninput ( InputType . BOMB_PRESS , floater . drop )
i . assigninput ( InputType . PUNCH_PRESS , ba . Call ( dis , i , floater ) )
i . assigninput ( InputType . UP_DOWN , floater . updown )
i . assigninput ( InputType . LEFT_RIGHT , floater . leftright )