Exemple #1
0
 def testInvalidInput(self):
     fsm = FiniteStateMachine("0,1",  "EVEN:pass,ODD:fail,BAD:fail",  "EVEN:ODD:1,ODD:EVEN:1,ODD:BAD:0")
     didFail = False
     try:
         fsm.execute("00a10")
     except Exception:
         didFail = True
         pass
     assert didFail
Exemple #2
0
 def testBaseCase(self):
     fsm = FiniteStateMachine("0,1",  "EVEN:pass,ODD:fail,BAD:fail",  "EVEN:ODD:1,ODD:EVEN:1,ODD:BAD:0")
     assert fsm.execute("00110") == 'pass'
     fsm.reset() # put it back into initial state
     assert "fail" == fsm.execute("00111")
     fsm.reset()
     assert "fail" == fsm.execute("001110000110011")
     pass
    def __init__(self, packet=None):
        super().__init__(packet)

        self.interact_label = 'Talk'
        self.health = 80
        self.faction = -841
        #self.localScale = self.localScale * (1+random.random*.3)
        self.update_time = time.time() + random.random()
        self.ticker = 1.0
        self.ai_state = None
        self.alert_radius = 80
        self.target_enemy = None
        self.alerted = False

        self.path = 0.0
        self.speed = 5

        # Animations
        self.animations = {
            'walk': 0,
            'run': 0,
            'attack': 0,
            'reload': 0,
            'idle': 1,
            'cround': 0
        }

        # FSM States
        self.movement_state_machine = FiniteStateMachine(self)
        self.movement_state_machine.add_state('idle', self.handle_idle_state)
        self.movement_state_machine.add_state('walk', self.handle_walk_state)
        self.movement_state_machine.add_state('attack',
                                              self.handle_attack_state)
        self.movement_state_machine.add_state('dead', self.handle_dead_state)
        self.movement_state_machine.current_state = "idle"

        # FSM Transitions
        self.movement_state_machine.add_transition('idle', 'walk',
                                                   self.is_alerted)
        self.movement_state_machine.add_transition_c('attack', 'walk',
                                                     self.is_close)
        self.movement_state_machine.add_transition_u('dead', self.is_dead)

        #
        self.interact_label = "Morgoar"
        self.interact_icon = None
    def _wrap(self, object):
        entities.EntityBase._wrap(self, object)

        # Spread
        self.ryn = random.randrange(-5, 5)
        self.rxn = random.randrange(-5, 5)

        # Children
        self.armature = [
            child for child in self.childrenRecursive if 'Armature' in child
        ][0]
        self.aimer = [
            child for child in self.childrenRecursive if 'aimer' in child
        ][0]
        self.bullet_spread = [
            child for child in self.childrenRecursive if 'spread' in child
        ][0]
        self.weapon_pos = [
            child for child in self.childrenRecursive if 'weapon_pos' in child
        ][0]
        self.head_track = [
            child for child in self.childrenRecursive if 'head_track' in child
        ][0]

        # Inventory
        self.inventory = Inventory()
        self.inventory.replace_weapon("F2000")  # Starting weapon
        self.inventory.primary_weapon.equip(self, weapon_type="3rd")

        # FSM
        self.ai_state_machine = FiniteStateMachine(self)

        self.ai_state_machine.add_state('idle', self.handle_idle)
        self.ai_state_machine.add_state('dead', self.handle_dead)
        self.ai_state_machine.add_state('attack', self.handle_attack)
        self.ai_state_machine.add_state('talk', self.handle_talk)
        #self.ai_state_machine.add_state('move', self.handle_move)

        #self.movement_state_machine.add_transition('attack', self.transition_to_attack)

        self.ai_state_machine.current_state = "idle"

        ###
        self._data['entity_base'] = self
Exemple #5
0
class MachineRunner(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.machine = FiniteStateMachine()
        self._start_keyboard_listener()

    def run(self):
        self.machine.set_current_state(MachineCommand.START)
        data = self.machine.collect_data(size=SQUARE_ARRAY_LENGTH)
        print('Data collected!')
        processed_data = self.machine.process_data(data)
        print(processed_data)

    def _on_press(self, key):
        if key == keyboard.Key.enter: print(self.machine.get_current_state())

    def _start_keyboard_listener(self):
        print('Press ENTER to get machine state')
        listener = keyboard.Listener(on_press=self._on_press)
        listener.daemon = True
        listener.start()
    def _wrap(self, object1):
        entities.EntityBase._wrap(self, object1)

        ###
        self.ray_pos = [
            child for child in self.childrenRecursive if 'ray' in child
        ][0]
        self.rotation_speed = 0.0
        self.last_rotation = 0.0
        self.rotation_difference = 0.0

        ### Activate Vehicle Controls
        self.vehicle_on = False

        # HACK
        self._data['entity_base'] = self
        self.camera = [
            child for child in self.childrenRecursive if 'vcam' in child
        ][0]

        for child in self.childrenRecursive:
            if 'remove' in child:
                child.removeParent()
                #pass

        ### FSM
        self.FSM = FiniteStateMachine(self)
        self.FSM.add_state('on', self.handle_on)
        self.FSM.add_state('off', self.handle_off)
        self.FSM.add_transition('off', 'on', self.is_active)

        self.FSM.current_state = 'off'

        ### BUILD VEHICLE
        self.assembleVehicle(self._data)
        self._data['build'] = True
class Player(entities.Actor):
    def __init__(self):
        print("player.__init__()")

        super().__init__()

        # Player Stats
        self.health = 100
        self.faction = 0  # Default Faction = Player faction
        #self.name = 'player'

        self.hunger = 0.0
        self.fatigue = 0.0
        self.alert = 0
        self.last_shot = 0.0
        self.reloading = False
        self.reload_start_time = 0.0
        self.roll = 0.0

        self.walk_speed = 5.0
        self.run_speed = 25.0
        self.walk_temp = 0.0
        self.last_move = 0.0
        self.jump_speed = 10.0

        # Stops mouse events from triggering for a frame
        # Used for when a UI screen is exited
        self.hold_mouse_update = False

        self.init_1 = False
        self.animations = {
            'walk': 0,
            'run': 0,
            'attack': 0,
            'reload': 0,
            'idle': 1,
            'cround': 0
        }

        self.recoil_time = None
        self.recoiled = False

        self.bullets_auto = 10
        self.bullets_shotgun = 10
        self.bullets_pistol = 10

        # Smooth Camera
        self.oldX = None

        #
        self.impants = []
        self.stats = {'temp': 'temp'}

        #
        self.current_weapon = None  # TODO - outdated reference, has this been moved to inventory?
        self.current_animations = {
            'walk': None,
            'run': None,
            'reload': None,
            'attack': None,
            'switch': None,
            'aim': None,
        }

        self.talking = False
        self.is_in_combat = False
        self.stored_state = None
        self.camera_on = True

        # Inventory
        self.inventory = Inventory()
        self.inventory.id = 'Player'

        # adding some items for testing: # TODO - remove
        self.inventory.add_item('cube', item_amount=9)
        self.inventory.add_item('wrench', item_amount=9)
        self.inventory.add_item('p90')

        # calculating this once for mouse move
        w = bge.render.getWindowWidth()
        h = bge.render.getWindowHeight()
        self.window_middle = [
            int((w - int(w) % 2) / 2),
            int((h - int(h) % 2) / 2)
        ]

    def _wrap(self, object):
        entities.EntityBase._wrap(self, object)

        # Vehicle
        self.current_vehicle = None
        self.in_vehicle = False

        self.camera = [
            child for child in self.children if 'camera_temp' in child
        ][0]
        self.lens = self.camera.lens

        self.armature = [
            child for child in self.childrenRecursive if 'Armature' in child
        ][0]
        self.bullet_spread = [
            child for child in self.childrenRecursive if 'spread' in child
        ][0]
        self.weapon_pos = [
            child for child in self.childrenRecursive if 'weapon_pos' in child
        ][0]
        self.climb_ray = [
            child for child in self.childrenRecursive if 'climb_ray' in child
        ][0]
        self.c_r_t = [
            child for child in self.childrenRecursive if 'c_r_t' in child
        ][0]
        self.c_r_b = [
            child for child in self.childrenRecursive if 'c_r_b' in child
        ][0]

        self.c_r_top = [
            child for child in self.childrenRecursive if 'c_r_top' in child
        ][0]

        self.squad_position_R = [
            child for child in self.childrenRecursive if 'squad_R' in child
        ][0]
        self.squad_position_L = [
            child for child in self.childrenRecursive if 'squad_L' in child
        ][0]

        self.blood_effect = [
            child for child in self.childrenRecursive
            if 'blood_effect' in child
        ][0]

        # FSM States
        self.movement_state_machine = FiniteStateMachine(self)
        self.movement_state_machine.add_state('walk', self.handle_walk_state)
        self.movement_state_machine.add_state('fall', self.handle_fall_state)
        self.movement_state_machine.add_state('vehicle',
                                              self.handle_vehicle_state)
        self.movement_state_machine.add_state('none', self.handle_none_state)

        # FSM Transitions
        self.movement_state_machine.add_transition('fall', 'walk',
                                                   self.is_grounded)
        self.movement_state_machine.add_transition('walk', 'vehicle',
                                                   self.is_in_vehicle)

        # HACKS
        self.temp_pos = 1
        self.set_loc = [
            child for child in self.childrenRecursive if 'set_loc' in child
        ][0]
        self.lev = None
        self.saved_armature_localPosition = self.armature.localPosition.copy()

        # WEAPON STARTING
        self.inventory.replace_weapon("F2000")
        self.inventory.primary_weapon.equip(self)

        #
        self._data['entity_base'] = self

    def _unwrap(self):
        entities.EntityBase._unwrap(self)

    def damage(self, amount, object=None):
        self.health += amount
        bge.logic.getCurrentScene().objects['FX']['hurt'] = 2.0
        bge.logic.getCurrentScene().objects['FX']['hurt_s'] += 0.3
        self.blood_effect['blood_effect'] = 1.0
        print("HURT")

    def is_in_vehicle(self, FSM):
        return bool(self.in_vehicle)

    def handle_walk_state(self, FSM):
        keyboard = bge.logic.keyboard.events
        vel = self.getLinearVelocity()
        move = [0, 0, 0]

        ### Keys
        if keyboard[bge.events.LEFTSHIFTKEY]:  # and self.fatigue < 10:
            self.fatigue += 0.2
            speed = self.run_speed
        else:
            if self.fatigue > 0.0:
                self.fatigue += -0.2
            speed = self.walk_speed

        if keyboard[bge.events.WKEY]:
            move[0] += speed
        if keyboard[bge.events.SKEY]:
            move[0] -= speed
        if keyboard[bge.events.AKEY]:
            move[1] -= speed
        if keyboard[bge.events.DKEY]:
            move[1] += speed

        ### Jump
        if keyboard[bge.events.SPACEKEY] == bge.logic.KX_INPUT_JUST_ACTIVATED:
            pos1 = [self.position[0], self.position[1], self.position[2] - 10]
            ray = self.rayCast(pos1, self.position, 2, '', 0, 0, 0)

            if ray[0] != None:
                move[2] = self.jump_speed
                self.walk_temp = 19

        ###
        com = vel[2] + move[2]
        self.localLinearVelocity = Vector([move[1], move[0], com])

        ###
        if move[0] != 0 or move[1] != 0:
            if speed == self.walk_speed:
                sudo.game.sound_manager.play_sound_on_frame(
                    [5, 15],
                    layer=2,
                    armature=self.armature,
                    sound_name=[
                        'walk_grass_s_1.ogg', 'walk_grass_s_2.ogg',
                        'walk_grass_s_3.ogg', 'walk_grass_s_4.ogg'
                    ],
                    sound_object=None,
                    play_type='play',
                    use_3d=False,
                    lowpass=False,
                    obstructed_lowpass=True,
                    alert_entities=True,
                    volume=1.0)
                self.roll += 0.5
                self.camera.applyRotation([
                    0,
                    math.sin(self.roll * 0.5) * 0.002,
                    math.sin(self.roll * 0.5) * 0.003
                ], 1)  # Y
                self.camera.localPosition[2] += math.sin(self.roll) * 0.03
                self.play_animation('walk')
                self.walk_temp += 1

            elif speed == self.run_speed:
                self.roll += 0.75
                self.camera.applyRotation([math.sin(self.roll) * 0.004, 0, 0],
                                          1)  # Y
                self.play_animation('run')
                self.walk_temp += 2
        else:
            self.play_animation('idle')
            #pass

        if self.walk_temp > 20:
            self.walk_temp = 0
            print("Play Sound")
            #session.game.sound_manager.play_sound('walk_grass_1.ogg', self)

    def update_path_follow(self):
        """ """
        super().update_path_follow()
        self.play_animation('walk')

    ### ANIMATIONS ###
    def play_animation(self, name):
        self.animations[name] = 1

    def stop_animation(self, layer):
        for n in range(0, 7):
            if n != layer:
                self.armature.stopAction(n)

    def handle_animations(self):
        weapon = self.inventory.primary_weapon

        if self.animations['reload'] == 1:
            self.armature.playAction(str(weapon.name) + "_reload",
                                     1,
                                     200,
                                     layer=4,
                                     priority=2,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_PLAY,
                                     speed=1.0)
            self.stop_animation(4)

        elif self.animations['attack'] == 1:
            if self.recoiled == False:
                x = random.uniform(
                    self.inventory.primary_weapon.recoil_min_x,
                    self.inventory.primary_weapon.recoil_max_x
                )  #random.randrange(self.inventory.primary_weapon.recoil_min_x,self.inventory.primary_weapon.recoil_max_x)
                y = random.uniform(
                    self.inventory.primary_weapon.recoil_min_y,
                    self.inventory.primary_weapon.recoil_max_y
                )  #random.randrange(self.inventory.primary_weapon.recoil_min_y,self.inventory.primary_weapon.recoil_max_y)
                z = 0

                self.armature.localPosition = self.armature.localPosition + Vector(
                    [y, x, z])
                #self.camera.applyRotation([abs(y*3.0), 0, 0], 1)
                self.recoiled = True

            elif sudo.world.world_time - self.recoil_time < 5.0:
                print("Here!----------")
                self.armature.localPosition = self.armature.localPosition.lerp(
                    self.saved_armature_localPosition, 0.25)

            else:
                print("Now here!!!!")
                self.armature.localPosition = self.saved_armature_localPosition
                self.animations['attack'] = 0

            #self.armature.localPosition[1] += math.sin(sudo.world.world_time)*0.03
            #self.armature.playAction("F2000_shoot", 4, 10, layer=3, priority=2, blendin=2, play_mode=bge.logic.KX_ACTION_MODE_LOOP, speed=1.0)
            #self.stop_animation(3)
            #print("OH!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
            #frame = self.armature.getActionFrame(3)

            #if frame > 5:
            #	self.animations['shoot'] = 0

        elif self.animations['walk'] == 1:
            self.armature.playAction(str(weapon.name) + "_walk",
                                     1,
                                     21,
                                     layer=2,
                                     priority=2,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_LOOP,
                                     speed=1.0)
            self.stop_animation(2)

        elif self.animations['run'] == 1:
            self.armature.playAction(str(weapon.name) + "_run",
                                     1,
                                     17,
                                     layer=1,
                                     priority=3,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_LOOP,
                                     speed=1.0)
            self.stop_animation(1)

        else:
            self.stop_animation(0)
            self.armature.playAction(str(weapon.name) + "_idle",
                                     1,
                                     101,
                                     layer=0,
                                     priority=5,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_LOOP,
                                     speed=1.0)

        for name in self.animations:
            if name != "attack":
                self.animations[name] = 0

    def handle_fall_state(self, FSM):
        pass

    def handle_vehicle_state(self, FSM):
        keyboard = bge.logic.keyboard

        bge.logic.getCurrentScene().active_camera = self.current_vehicle.camera

        # HACK
        self.camera_on = False  # Turn off player camera
        self.position = [
            self.current_vehicle.position[0], self.current_vehicle.position[1],
            self.current_vehicle.position[2] + 10
        ]

        # Get out of vehicle
        if keyboard.events[bge.events.EKEY] == 1:
            self.camera_on = True
            self.position = [
                self.current_vehicle.position[0],
                self.current_vehicle.position[1],
                self.current_vehicle.position[2] + 10
            ]  # add player above the vehicle

            self.current_vehicle.vehicle_on = False
            self.in_vehicle = False
            self.movement_state_machine.current_state = 'walk'
            self.current_vehicle.FSM.current_state = 'off'
            self.current_vehicle = None

    def is_grounded(self, FSM):
        pos2 = [self.position[0], self.position[1], self.position[2] - 5]
        ray2 = self.rayCast(pos2, self._data, 0, '', 0, 0, 0)
        return bool(ray2[0])

    def is_falling(self, FSM):
        pos2 = [self.position[0], self.position[1], self.position[2] - 5]
        ray2 = self.rayCast(pos2, self._data, 0, '', 0, 0, 0)
        return not bool(ray2[0])

    def has_entered_vehicle(self, FSM):
        return bool(self.vehicle)

    def has_exited_vehicle(self, FSM):
        return bool(self.vehicle)

    def handle_none_state(self, FSM):
        pass

    """def reload(self):
		print("Reloading...")


		if self.inventory.ammo['Assault'] > 0:
			if self.reload_start_time == 0.0:
				self.reload_start_time = sudo.game.game_time
				self.entity.play_animation('reload')
				self.reloading = True

			elif self.reload_start_time + self.reload_time < sudo.game.game_time:
				self.reload_start_time = 0.0
				self.in_clip = self.clip_size
				self.reloading = False

				if self.inventory.ammo['Assault'] < self.inventory.weapon_slot_1.clip_size:
					self.inventory.weapon_slot_1.clip = self.inventory.ammo['Assault']
					self.inventory.ammo['Assault'] = 0
				else:
					self.inventory.weapon_slot_1.clip = self.inventory.weapon_slot_1.clip_size
					self.inventory.ammo['Assault'] += -self.inventory.weapon_slot_1.clip_size

				self.reload_start_time = 0.0

			else:
				self.play_animation('reload')
		else:
			print("Out Of Ammo!!")
			"""

    def handle_weapon(self):
        if self.hold_mouse_update != 0:
            # Don't fire the gun after exiting a screen
            return

        weapon = self.inventory.primary_weapon  # TODO - add secondary weapon

        if weapon is not None:
            weapon.main()

    def handle_interactions(self):
        ray = self.camera.controllers[0].sensors['interact_ray']
        hit = ray.hitObject
        keyboard = bge.logic.keyboard

        if hit != None and 'entity_base' in hit:
            sudo.ui_manager.screens['hud'].set_interact_text(
                hit['entity_base'].interact_label,
                hit['entity_base'].interact_icon)
            if type(hit['entity_base']) is str:
                temp = __import__("weapon_pickup")
                temp = temp.WeaponPickup(hit, hit['info'],
                                         hit['name'])  # ex hack
                hit['entity_base'] = temp
            else:
                if keyboard.events[bge.events.EKEY] == 1:
                    hit['entity_base'].on_interact(self)
        else:
            sudo.ui_manager.screens['hud'].set_interact_text('')
            pass

    def fast_travel(self, location):
        self.position = location_id.position
        # handle world cells

    def handle_camera(self):
        bge.logic.getCurrentScene(
        ).active_camera = self.camera  # set active_camera
        """
		w = R.getWindowWidth()//2
		h = R.getWindowHeight()//2
		screen_center = (w, h)

		Mouse = bge.logic.mouse
		speed = 0.08				# walk speed
		sensitivity = 0.002		# mouse sensitivity
		smooth = 0.7			# mouse smoothing (0.0 - 0.99)

		if self.oldX == None:

			R.setMousePosition(w + 1, h + 1)
			
			self.oldX = 0.0
			self.oldY = 0.0

		else:
			
			scrc = Vector(screen_center)
			mpos = Vector(Mouse.position)
			
			x = scrc.x-mpos.x
			y = scrc.y-mpos.y

			# Smooth movement
			self.oldX = (self.oldX*smooth + x*(1.0-smooth))
			self.oldY = (self.oldY*smooth + y*(1.0-smooth))
			
			x = self.oldX* sensitivity
			y = self.oldY* sensitivity
			 
			# set the values
			self.applyRotation([0, 0, x], False)
			self.applyRotation([y, 0, 0], False)
			
			# Center mouse in game window
			R.setMousePosition(*screen_center)
			

		"""
        smooth = 0.5
        sensitivity = 1.5
        mpos = bge.logic.mouse.position[:]
        mouse = bge.logic.mouse

        if self.oldX == None:
            self.oldX = [0.0, 0.0]

        if self.hold_mouse_update != 0:
            self.hold_mouse_update -= 1
            mpos = [0.5, 0.5]

        if mouse.events[bge.events.RIGHTMOUSE]:
            #self.camera.lens = self.inventory.primary_weapon.zoom_lens
            self.camera.lens += (self.inventory.primary_weapon.zoom_lens -
                                 self.camera.lens) * 0.1
            bge.logic.getCurrentScene().objects['FX']['autofocus'] = True
        else:
            bge.logic.getCurrentScene().objects['FX']['autofocus'] = False
            self.camera.lens = self.lens

        bge.render.setMousePosition(self.window_middle[0],
                                    self.window_middle[1])

        if not 'ml_rotx' in self.camera:
            self.camera['ml_rotx'] = -(
                self.camera.localOrientation.to_euler().x - (math.pi * 0.5))

        else:
            #mouse_mx = (self.oldX[0]*smooth)+((mpos[0] - 0.5) * 3)*(1.0-smooth)#bge.logic.globalDict['game'].control_options[1]#MOUSE_SENSITIVITY # bge.logic.globalDict['game'].control_options[Game.MOUSE_SENSITIVITY]
            #mouse_my = (self.oldX[1]*smooth)+((mpos[1] - 0.5) * 3)*(1.0-smooth)#bge.logic.globalDict['game'].control_options[1]#MOUSE_SENSITIVITY
            self.oldX[0] = (self.oldX[0] * smooth) + (
                (mpos[0] - 0.5) * 3) * (1.0 - smooth)
            self.oldX[1] = (self.oldX[1] * smooth) + (
                (mpos[1] - 0.5) * 3) * (1.0 - smooth)

            mouse_mx = self.oldX[0] * sensitivity
            mouse_my = self.oldX[1] * sensitivity

            self.armature.localPosition = self.armature.localPosition + Vector(
                [mouse_mx * 0.1, mouse_my * 0.1, 0.0])

            cap = 1.5

            if -(self.camera['ml_rotx'] + mouse_my) < cap and -(
                    self.camera['ml_rotx'] + mouse_my) > -cap:
                if abs(mouse_mx) > 0.0025 or abs(mouse_my) > 0.0025:
                    self.camera.parent.applyRotation([0, 0, -mouse_mx], 0)  # X
                    self.camera.applyRotation([-mouse_my, 0, 0], 1)  # Y
                    self.camera['ml_rotx'] += mouse_my

        self.armature.localPosition = self.armature.localPosition.lerp(
            self.saved_armature_localPosition, 0.25)

    def remove_controls(self):
        self.stored_state = self.movement_state_machine.current_state

    def restore_controls(self):
        self.movement_state_machine.current_state = self.stored_state

    ###
    def update(self):
        if bge.logic.globalDict['pause'] == 0 and self._data:
            if not self.frozen:
                self.movement_state_machine.main()

                if self.in_vehicle == False:
                    self.handle_camera()
                    self.handle_interactions()

                    if self.inventory.primary_weapon:
                        self.handle_animations()
                        self.handle_weapon()
    def _wrap(self, object):
        entities.EntityBase._wrap(self, object)

        # Vehicle
        self.current_vehicle = None
        self.in_vehicle = False

        self.camera = [
            child for child in self.children if 'camera_temp' in child
        ][0]
        self.lens = self.camera.lens

        self.armature = [
            child for child in self.childrenRecursive if 'Armature' in child
        ][0]
        self.bullet_spread = [
            child for child in self.childrenRecursive if 'spread' in child
        ][0]
        self.weapon_pos = [
            child for child in self.childrenRecursive if 'weapon_pos' in child
        ][0]
        self.climb_ray = [
            child for child in self.childrenRecursive if 'climb_ray' in child
        ][0]
        self.c_r_t = [
            child for child in self.childrenRecursive if 'c_r_t' in child
        ][0]
        self.c_r_b = [
            child for child in self.childrenRecursive if 'c_r_b' in child
        ][0]

        self.c_r_top = [
            child for child in self.childrenRecursive if 'c_r_top' in child
        ][0]

        self.squad_position_R = [
            child for child in self.childrenRecursive if 'squad_R' in child
        ][0]
        self.squad_position_L = [
            child for child in self.childrenRecursive if 'squad_L' in child
        ][0]

        self.blood_effect = [
            child for child in self.childrenRecursive
            if 'blood_effect' in child
        ][0]

        # FSM States
        self.movement_state_machine = FiniteStateMachine(self)
        self.movement_state_machine.add_state('walk', self.handle_walk_state)
        self.movement_state_machine.add_state('fall', self.handle_fall_state)
        self.movement_state_machine.add_state('vehicle',
                                              self.handle_vehicle_state)
        self.movement_state_machine.add_state('none', self.handle_none_state)

        # FSM Transitions
        self.movement_state_machine.add_transition('fall', 'walk',
                                                   self.is_grounded)
        self.movement_state_machine.add_transition('walk', 'vehicle',
                                                   self.is_in_vehicle)

        # HACKS
        self.temp_pos = 1
        self.set_loc = [
            child for child in self.childrenRecursive if 'set_loc' in child
        ][0]
        self.lev = None
        self.saved_armature_localPosition = self.armature.localPosition.copy()

        # WEAPON STARTING
        self.inventory.replace_weapon("F2000")
        self.inventory.primary_weapon.equip(self)

        #
        self._data['entity_base'] = self
class NPC2(entities.AIBase):
    def __init__(self, packet, name="AI_Default"):
        super().__init__(packet)

        self.factions = {
            "Enemies": [2],
            "Allies": [0, 1, 3]
        }  # Player faction = 0, Human faction = 1, Rebel Faction = 2, Kree Faction = 3

        # UI
        self.interact_label = "NPC"
        self.interact_icon = None

    def _wrap(self, object):
        entities.EntityBase._wrap(self, object)

        # Spread
        self.ryn = random.randrange(-5, 5)
        self.rxn = random.randrange(-5, 5)

        # Children
        self.armature = [
            child for child in self.childrenRecursive if 'Armature' in child
        ][0]
        self.aimer = [
            child for child in self.childrenRecursive if 'aimer' in child
        ][0]
        self.bullet_spread = [
            child for child in self.childrenRecursive if 'spread' in child
        ][0]
        self.weapon_pos = [
            child for child in self.childrenRecursive if 'weapon_pos' in child
        ][0]
        self.head_track = [
            child for child in self.childrenRecursive if 'head_track' in child
        ][0]

        # Inventory
        self.inventory = Inventory()
        self.inventory.replace_weapon("F2000")  # Starting weapon
        self.inventory.primary_weapon.equip(self, weapon_type="3rd")

        # FSM
        self.ai_state_machine = FiniteStateMachine(self)

        self.ai_state_machine.add_state('idle', self.handle_idle)
        self.ai_state_machine.add_state('dead', self.handle_dead)
        self.ai_state_machine.add_state('attack', self.handle_attack)
        self.ai_state_machine.add_state('talk', self.handle_talk)
        #self.ai_state_machine.add_state('move', self.handle_move)

        #self.movement_state_machine.add_transition('attack', self.transition_to_attack)

        self.ai_state_machine.current_state = "idle"

        ###
        self._data['entity_base'] = self

    def _unwrap(self):
        EntityBase._unwrap(self)

    def on_interact(self, player):
        #self.ai_state_machine.current_state = "talk" # Disabled
        sudo.world.dialogue_manager.display_dialogue('./data/dialogue/' +
                                                     'test' + '.xml')

    """ FSM Transitions """

    def transition_to_attack(self, FSM):
        return self.target_in_sight

    def is_dead(self, FSM):
        if self['Health'] < 0:
            return True
        else:
            return False

    def is_fleeing(self, FSM):
        moral = 0
        moral += -len(self.enemies)
        moral += len(self.allies)
        moral += -(self.health - 100) * 0.25
        return False

    """ FSM States """

    def handle_idle(self, FSM):
        self['Steer'] = 0
        self.play_animation("idle")

        # Head tracking
        self.track(sudo.player.position,
                   tracker=self.head_track,
                   speed=0.8,
                   track_3d=True)

    def handle_talk(self, FSM):
        self['Steer'] = 0
        self.play_animation("idle")
        sudo.world.dialogue_manager.display_dialogue('./data/dialogue/' +
                                                     'test' + '.xml')

    def handle_flee(self, FSM):
        self.move_to(self.target.position)

    def handle_attack(self, FSM):
        # If Target Found
        if self.target:
            self.track(self.target.position,
                       tracker=self.head_track,
                       speed=0.8,
                       track_3d=True)
            dist = self.getDistanceTo(self.target.position)

            # Check if target is in sight
            if self.is_in_sight(self.target.name):
                self.target_last_pos = self.target._data.position.copy()
                self.target_in_sight = True
            else:
                self.target_in_sight = False

            # If everything is Vaild
            if self.target and self.target_last_pos:

                # Far away -> move closer
                if dist > 60:
                    self.move_to(self.target_last_pos)

                # Close enough to attack
                else:
                    self.localLinearVelocity = [0.0, 0.0, 0.0]  # Stop moving

                    if self.is_in_sight(self.target.name):
                        self.track(self.target.position, speed=0.25)
                        self.track(self.target.position,
                                   tracker=self.aimer,
                                   speed=0.85,
                                   track_3d=True)
                        self.inventory.primary_weapon.ai_fire(self)
                        self.target_in_sight = True
                        print("FIRE!!!")

                    else:
                        self.move_to(self.target_last_pos)

    def handle_dead(self, FSM):
        print("Dead")
        self['Steer'] = 0
        self.remove()

    def find_target(self):
        if self.enemies:
            self.target = self.enemies[0][1]
        else:
            self.target = None

    def alert_entities(self):
        for temp in game.Game.singleton.world.entity_list:
            temp.alerted = 1
            temp.alert_position = self.position.copy()

    def damage(self, damage_amount=1, object=None):
        print("HIT")
        self.target = object
        self.target_last_pos = self.target.position.copy()
        self.health += -damage_amount

        if object.faction in self.factions['Allies']:
            index = self.factions['Allies'].index(object.faction)
            self.factions['Allies'].remove(index)

        if not object.faction in self.factions['Enemies']:
            self.factions["Enemies"].append(object.faction)

        # IF dead
        if self.health < 0:
            self.ai_state_machine.current_state = 'dead'

        self.ai_state_machine.current_state = 'attack'

    def alert_entity(self, object):
        self.target = object
        self.target_last_pos = self.target.position.copy()
        self.track(self.target_last_pos)
        self.ai_state_machine.current_state = 'handle_no_cover'

    """ 'Checks' """

    def is_scared():
        return False

    def is_in_cover(self, FSM):
        return bool(self.in_cover)

    def is_enemy_near(self, FSM):
        enemies = self.detect_enemies()
        return bool(enemies != None)

    def is_in_sight(self, target):
        sight = False
        radar = self.aimer.controllers[0].sensors['Radar']

        for hit_obj in radar.hitObjectList:
            if hit_obj.name == target:
                ray = self.rayCast(hit_obj.position, self.aimer.position, 0,
                                   '', 0, 0, 0)
                if (ray[0]) and ray[0].name == target:
                    sight = True

        return sight

    """ ANIMATIONS """

    def play_animation(self, name):
        self.animations[name] = 1

    def stop_animation(self, layer):
        for n in range(0, 7):
            if n != layer:
                self.armature.stopAction(n)

    def handle_animations(self):
        weapon = self.inventory.primary_weapon

        if self.animations['reload'] == 1:
            self.armature.playAction(weapon.name + "_reload_3rd",
                                     1,
                                     64,
                                     layer=4,
                                     priority=2,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_PLAY,
                                     speed=1.0)
            self.stop_animation(4)

        elif self.animations['attack'] == 1:
            self.armature.playAction(weapon.name + "_attack_3rd",
                                     1,
                                     5,
                                     layer=3,
                                     priority=3,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_PLAY,
                                     speed=1.0)
            self.stop_animation(3)

        elif self.animations['walk'] == 1:
            self.armature.playAction(weapon.name + "_walk_3rd",
                                     1,
                                     32,
                                     layer=2,
                                     priority=2,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_LOOP,
                                     speed=1.0)
            self.stop_animation(2)

        elif self.animations['run'] == 1:
            self.armature.playAction(weapon.name + "_run_3rd",
                                     1,
                                     20,
                                     layer=1,
                                     priority=3,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_LOOP,
                                     speed=1.0)
            self.stop_animation(1)

        else:
            self.stop_animation(0)
            self.armature.playAction(weapon.name + "_idle_3rd",
                                     1,
                                     64,
                                     layer=0,
                                     priority=5,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_LOOP,
                                     speed=1.0)

        for name in self.animations:
            self.animations[name] = 0

    """ 'Main' """

    def update(self):

        if self._data:
            self.handle_animations()

            # Update target
            if self.target == None:
                self.update_enitity_list()  # Update Enemy/Ally list
                self.find_target(
                )  # Update Target with the enemy with the highest threat level

            self.ai_state_machine.main()

        else:
            print("NO DATA")
class Morgoar(entities.EntityBase):
    """ A simple entity for talking to """
    def __init__(self, packet=None):
        super().__init__(packet)

        self.interact_label = 'Talk'
        self.health = 80
        self.faction = -841
        #self.localScale = self.localScale * (1+random.random*.3)
        self.update_time = time.time() + random.random()
        self.ticker = 1.0
        self.ai_state = None
        self.alert_radius = 80
        self.target_enemy = None
        self.alerted = False

        self.path = 0.0
        self.speed = 5

        # Animations
        self.animations = {
            'walk': 0,
            'run': 0,
            'attack': 0,
            'reload': 0,
            'idle': 1,
            'cround': 0
        }

        # FSM States
        self.movement_state_machine = FiniteStateMachine(self)
        self.movement_state_machine.add_state('idle', self.handle_idle_state)
        self.movement_state_machine.add_state('walk', self.handle_walk_state)
        self.movement_state_machine.add_state('attack',
                                              self.handle_attack_state)
        self.movement_state_machine.add_state('dead', self.handle_dead_state)
        self.movement_state_machine.current_state = "idle"

        # FSM Transitions
        self.movement_state_machine.add_transition('idle', 'walk',
                                                   self.is_alerted)
        self.movement_state_machine.add_transition_c('attack', 'walk',
                                                     self.is_close)
        self.movement_state_machine.add_transition_u('dead', self.is_dead)

        #
        self.interact_label = "Morgoar"
        self.interact_icon = None

    def _wrap(self, object1):
        entities.EntityBase._wrap(self, object1)
        self.armature = [
            child for child in self._data.childrenRecursive
            if 'Armature' in child
        ][0]
        self.ray_b = [
            child for child in self._data.childrenRecursive
            if 'ray_bottom' in child
        ][0]
        self.ray_top = [
            child for child in self._data.childrenRecursive
            if 'ray_top' in child
        ][0]

        self._data['entity_base'] = self
        sudo.world.entity_list.append(self)
        print('ghost init')

    def is_alerted(self, FSM):
        if self.target_enemy != None:
            return True
        else:
            return False

    def is_close(self, FSM):
        dist = self._data.getDistanceTo(self.target_enemy.position)
        if dist < 2.0:
            return True
        else:
            return False

    def is_dead(self, FSM):
        if self.health < 0.0:
            return True
        else:
            return False

    def alert_entity(self, object1):
        self.target_enemy = object1

    def on_interact(self, player):
        pass

    ### ANIMATIONS ###
    def play_animation(self, name):
        self.animations[name] = 1

    def stop_animation(self, layer):
        for n in range(0, 7):
            if n != layer:
                self.armature.stopAction(n)

    def handle_animations(self):
        if self.animations['attack'] == 1:
            self.armature.playAction("m_attack",
                                     1,
                                     32,
                                     layer=2,
                                     priority=2,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_LOOP,
                                     speed=1.0)
            self.stop_animation(2)

        elif self.animations['walk'] == 1:
            self.armature.playAction("m_walk",
                                     1,
                                     30,
                                     layer=1,
                                     priority=2,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_LOOP,
                                     speed=1.0)
            self.stop_animation(1)

        else:
            self.armature.playAction("m_idle",
                                     1,
                                     30,
                                     layer=0,
                                     priority=2,
                                     blendin=5,
                                     play_mode=bge.logic.KX_ACTION_MODE_LOOP,
                                     speed=1.0)
            self.stop_animation(0)

        for name in self.animations:
            self.animations[name] = 0

    def handle_dead_state(self, FSM):
        pass

    def handle_attack_state(self, FSM):
        st = self.controllers[0].actuators['Steering']
        st.velocity = 0.0
        target = self.target_enemy
        self.track(target.position)
        target.damage(10)
        self.play_animation("attack")

    def handle_walk_state(self, FSM, behavior=3, offset=0, speed='walk'):
        if speed == 'walk':
            speed = self.speed
        elif speed == 'run':
            speed = self.speed * 2

        self.navmesh = bge.logic.getCurrentScene().objects['Navmesh_box']
        self.path = self.navmesh.findPath(self.position,
                                          self.target_enemy.position)
        self.path_index = 0

        if len(self.path) > 0:
            current_node = self.path[self.path_index]
            dist = self._data.getDistanceTo(current_node)

            if dist < 1.0:
                self.path_index += 1

            self.track(self.path[self.path_index])
            self.localLinearVelocity = [0.0, speed, 0.0]
            self.play_animation("walk")

    def handle_idle_state(self, FSM):
        self.play_animation("idle")
        entities = sudo.world.entity_list

        enemy_list = []
        """

		for entity in entities:
			try:
				faction = entity.faction
			except:
				faction = self.faction
			
			if faction != self.faction:
				dist = self._data.getDistanceTo(entity._data)

				if dist < 35:
					ray = self._data.rayCast(entity.position, self.position, 0,'',0,0,0)

					if ray[0] == entity._data:
						enemy_list.append([dist, entity])

		enemy_list.sort()

		if len(enemy_list) > 0:
			self.target_enemy = enemy_list[0][1]
		else:
			self.target_enemy = None
			"""

        self.target_enemy = sudo.player

    def track(self, target, speed=1.0):
        vec = self.getVectTo(target)
        self.alignAxisToVect(vec[1], 1, speed)
        self.alignAxisToVect([0, 0, 1], 2, speed)

    def damage(self, amount, obj):
        self.health = self.health - amount

        ### Mist
        #new = bge.logic.getCurrentScene().addObject("blood_mist",'CELL_MANAGER_HOOK',5)
        #new.position = self._data.position

        ### Splatter
        ray = self._data.rayCast(self.ray_b, self.ray_top, 0, 'Ground', 0, 1,
                                 0)
        #index = random.randrange(0,len(blood_textures))

        #if ray[0] != None:
        #	blood_textures = ["Blood", "Blood_2"]
        #	index = random.randrange(0,len(blood_textures))
        """
			new = bge.logic.getCurrentScene().addObject(blood_textures[index],'CELL_MANAGER_HOOK',2500)
			new.position = ray[1]+Vector([0.0,0.0,0.05])

			ran = random.randrange(0.0,10.0)
			new.orientation = new.orientation*Vector([0.0,0.0,ran])
			"""

        if self.health < 0.0:
            chunks = [
                "morgoar_chunk", "morgoar_chunk.001", "morgoar_chunk.002",
                "morgoar_chunk.003", "morgoar_chunk.004", "morgoar_chunk.005",
                "morgoar_chunk.006", "morgoar_chunk.007", "morgoar_chunk.008",
                "morgoar_chunk.009"
            ]

            md = bge.logic.getCurrentScene().addObject("morgaor_death",
                                                       'CELL_MANAGER_HOOK', 50)
            md.position = self._data.position

            for chunk in chunks:
                c = bge.logic.getCurrentScene().addObject(
                    chunk, 'CELL_MANAGER_HOOK', 2500)
                c.position = self._data.position

                for child in md.children:
                    if "prop" in child:
                        if child['prop'] == chunks[chunks.index(chunk)]:
                            c.position = child.position
                            c.orientation = child.orientation

            if ray[0] != None:
                new = bge.logic.getCurrentScene().addObject(
                    "Blood_floor", 'CELL_MANAGER_HOOK')
                new.position = ray[1] + Vector([0.0, 0.0, 0.05])

                ran = random.randrange(0.0, 100.0)
                new.orientation = new.orientation * Vector([0.0, 0.0, ran])

            self.remove()

    def update(self):
        self.movement_state_machine.main()
        self.handle_animations()
    def __init__(self, object_name):

        print("-- VehicleBase.__init__() --")
        entities.EntityBase.__init__(self, None)
        entities.EntityBase._wrap(self, object_name)
        self.vehicle_wheels = None

        ### Vehicle Properties
        self.speed = 15
        self.acceleration = 1.0
        self.brake_amount = 0.5
        self.steer_amount = 0.5
        self.car_susp = 0.70  # suspension factor for the car

        self.gear = 1
        self.engine_sound = 0.0

        ### Wheel properties
        self.wheel_radius = 1.0
        self.wheel_suspension = 1.0
        self.wheel_roll = 0.1
        self.wheel_friction = 1.0
        self.wheel_compression = 2.0
        self.wheel_damping = 1.5
        self.wheel_stiffness = 6.0
        self.wheel_susp_angle = [0.0, 0.0, -1.0]
        self.wheel_axis = [-1.0, 0.0, 0.0]

        ### DONT MESS WITH THESE
        self.wheel_max_drive = 1.0
        self.wheel_max_reverse_drive = 1.0
        self.wheel_max_brake = 0.1
        self.wheel_max_left_steer = 0.0
        self.wheel_max_right_steer = 0.0

        ###
        self.car_drive = 0.0
        self.car_steer = 0.0
        self.car_brake = 0.0
        self.current_steer = 0

        ###
        self.ray_pos = [
            child for child in self.childrenRecursive if 'ray' in child
        ][0]
        self.rotation_speed = 0.0
        self.last_rotation = 0.0
        self.rotation_difference = 0.0

        ### Activate Vehicle Controls
        self.vehicle_on = False

        # HACK
        self._data['entity_base'] = self
        self.camera = [
            child for child in self.childrenRecursive if 'vcam' in child
        ][0]

        for child in self.childrenRecursive:
            if 'remove' in child:
                child.removeParent()
                #pass

        self.camera.removeParent()

        ### FSM
        self.FSM = FiniteStateMachine(self)
        self.FSM.add_state('on', self.handle_on)
        self.FSM.add_state('off', self.handle_off)
        self.FSM.add_transition('off', 'on', self.is_active)

        self.FSM.current_state = 'off'

        ### BUILD VEHICLE
        self.assembleVehicle(self._data)
        self._data['build'] = True
class VehicleBase(EntityBase):

    ### INIT
    def __init__(self, object_name):

        print("-- VehicleBase.__init__() --")
        entities.EntityBase.__init__(self, None)
        entities.EntityBase._wrap(self, object_name)
        self.vehicle_wheels = None

        ### Vehicle Properties
        self.speed = 15
        self.acceleration = 1.0
        self.brake_amount = 0.5
        self.steer_amount = 0.5
        self.car_susp = 0.70  # suspension factor for the car

        self.gear = 1
        self.engine_sound = 0.0

        ### Wheel properties
        self.wheel_radius = 1.0
        self.wheel_suspension = 1.0
        self.wheel_roll = 0.1
        self.wheel_friction = 1.0
        self.wheel_compression = 2.0
        self.wheel_damping = 1.5
        self.wheel_stiffness = 6.0
        self.wheel_susp_angle = [0.0, 0.0, -1.0]
        self.wheel_axis = [-1.0, 0.0, 0.0]

        ### DONT MESS WITH THESE
        self.wheel_max_drive = 1.0
        self.wheel_max_reverse_drive = 1.0
        self.wheel_max_brake = 0.1
        self.wheel_max_left_steer = 0.0
        self.wheel_max_right_steer = 0.0

        ###
        self.car_drive = 0.0
        self.car_steer = 0.0
        self.car_brake = 0.0
        self.current_steer = 0

        ###
        self.ray_pos = [
            child for child in self.childrenRecursive if 'ray' in child
        ][0]
        self.rotation_speed = 0.0
        self.last_rotation = 0.0
        self.rotation_difference = 0.0

        ### Activate Vehicle Controls
        self.vehicle_on = False

        # HACK
        self._data['entity_base'] = self
        self.camera = [
            child for child in self.childrenRecursive if 'vcam' in child
        ][0]

        for child in self.childrenRecursive:
            if 'remove' in child:
                child.removeParent()
                #pass

        self.camera.removeParent()

        ### FSM
        self.FSM = FiniteStateMachine(self)
        self.FSM.add_state('on', self.handle_on)
        self.FSM.add_state('off', self.handle_off)
        self.FSM.add_transition('off', 'on', self.is_active)

        self.FSM.current_state = 'off'

        ### BUILD VEHICLE
        self.assembleVehicle(self._data)
        self._data['build'] = True

    def _unwrap(self):
        EntityBase._unwrap(self)

    ### Functions
    def findWheels(self, vehicle):
        wheels = []
        children = list(vehicle.children)

        for child in children:
            if "wheel" in child:
                wheels.append(child)
        return wheels

    def convertToFloatList(self, aList):
        if type(aList) == type(''):
            aList = eval(aList)
        newList = []
        for entry in aList:
            newList.append(float(entry))

        return newList

    ### Build Vehicle
    def assembleVehicle(self, vehicle):
        vehicleWrapper = self.createConstraint(vehicle)
        self.vehicle_wheels = self.findWheels(vehicle)
        self.assembleWheels(vehicle, vehicleWrapper)

    def createConstraint(self, carObj):
        car_PhysicsID = carObj.getPhysicsId()
        vehicle_constraint = PhysicsConstraints.createConstraint(
            car_PhysicsID, 0, 11)
        self.vehicle_constraint = vehicle_constraint

        constraint_ID = vehicle_constraint.getConstraintId()
        vehicleWrapper = PhysicsConstraints.getVehicleConstraint(constraint_ID)

        self.wrapper = vehicleWrapper

        return vehicleWrapper

    def assembleWheels(self, vehicle, vehicleWrapper):
        #wheels = self.vehicle_wheels
        wheelId = 0

        ###
        for wheel in self.vehicle_wheels:
            #pos = wheel.localPosition
            pos = Mathutils.Vector(wheel.localPosition)
            #pos = Mathutils.Vector(wheel.localPosition)#wheel.position - wheel.parent.position

            #print (pos)
            #print (wheel.localPosition)
            #print (Mathutils.Vector(wheel.localPosition))

            wheel.removeParent()

            vehicleWrapper.addWheel(
                wheel, pos, self.convertToFloatList(self.wheel_susp_angle),
                self.convertToFloatList(self.wheel_axis),
                self.wheel_suspension, wheel['radius'], True)
            vehicleWrapper.setRollInfluence(self.wheel_roll, wheelId)
            vehicleWrapper.setTyreFriction(wheel['friction'], wheelId)
            vehicleWrapper.setSuspensionCompression(self.wheel_compression,
                                                    wheelId)
            vehicleWrapper.setSuspensionDamping(self.wheel_damping, wheelId)
            vehicleWrapper.setSuspensionStiffness(self.wheel_stiffness,
                                                  wheelId)

            wheel["wheelId"] = wheelId
            wheel["vehicle"] = vehicle
            wheelId += 1

        print("STARTED")

    ### Drive
    def handle_drive(self, vehicle_wrapper):

        ###
        keyboard = bge.logic.keyboard.events
        speed = 0

        ###
        if keyboard[bge.events.WKEY]:
            speed = self.speed * self.acceleration

            if self.acceleration < 1.0:
                self.acceleration += 0.005

        elif keyboard[bge.events.SKEY]:
            speed = -self.speed * 0.5

        else:
            if self.acceleration > 0.0:
                self.acceleration += -0.01

        for wheel in self.vehicle_wheels:
            id = self.vehicle_wheels.index(wheel)
            vehicle_wrapper.applyEngineForce(speed * wheel['maxDrive'], id)

    ### Brake
    def handle_brake(self, vehicle_wrapper):

        ###
        keyboard = bge.logic.keyboard.events
        brake = 0

        ###
        if keyboard[bge.events.SPACEKEY]:
            brake = self.brake_amount

        for wheel in self.vehicle_wheels:
            id = self.vehicle_wheels.index(wheel)
            vehicle_wrapper.applyBraking(brake, id)

    ### Steering
    def handle_steering(self, vehicle_wrapper):

        ###
        keyboard = bge.logic.keyboard.events

        ###
        if keyboard[bge.events.AKEY]:
            if self.current_steer < self.steer_amount:
                self.current_steer += 0.075  #self.steer_amount

        elif keyboard[bge.events.DKEY]:
            if self.current_steer > -self.steer_amount:
                self.current_steer += -0.075  #-self.steer_amount

        else:
            if self.current_steer > 0.1:
                self.current_steer += -0.075
            elif self.current_steer < -0.1:
                self.current_steer += 0.075
            else:
                self.current_steer = 0

        vehicle_wrapper.setSteeringValue(self.current_steer, 2)
        vehicle_wrapper.setSteeringValue(self.current_steer, 3)

    def handle_stablization(self):
        #ray_pos = [own.position[0],own.position[1],own.position[1]-10]
        ray = self.rayCast(self.ray_pos, self._data, 0, '', 0, 0, 0)

        if ray[0] == None:
            self.alignAxisToVect([0.0, 0.0, 1.0], 2, 0.03)
        else:
            self.alignAxisToVect([0.0, 0.0, 1.0], 2, 0.01)

    ### FSM
    def handle_on(self, FSM):
        print("ON")
        vehicle_wrapper = self.wrapper  #_data[self.vehicle_wrapper]

        ###
        self.handle_drive(vehicle_wrapper)
        self.handle_brake(vehicle_wrapper)
        self.handle_steering(vehicle_wrapper)
        self.handle_stablization()

        ###
        self.last_rotation = self.rotation_speed
        self.rotation_speed = (vehicle_wrapper.getWheelRotation(0) +
                               vehicle_wrapper.getWheelRotation(1)) / 2

        self.rotation_difference = self.last_rotation - self.rotation_speed

        ### Gears
        if self.rotation_difference > 1.0:
            self.gear = 3
        elif self.rotation_difference > 0.75:
            self.gear = 2
        elif self.rotation_difference > 0.5:
            self.gear = 1

        #self.engine_sound = self.rotation_difference*self.gear

        ### TO fix reload crash
        #bge.constraints.removeConstraint(vehicle_wrapper.getConstraintId())

    def handle_off(self, FSM):
        vehicle_wrapper = self.wrapper  #_data[self.vehicle_wrapper]
        print("OFF")

        # Brake amount
        brake = 0.25

        # Brake
        for wheel in self.vehicle_wheels:
            id = self.vehicle_wheels.index(wheel)
            vehicle_wrapper.applyBraking(brake, id)

    def is_active(self, FSM):
        return bool(self.vehicle_on)

    ### Interact
    def on_interact(self, entity):
        if self.vehicle_on == False:
            print("TURNING ON ---")
            self.vehicle_on = True
            entity.current_vehicle = self
            entity.in_vehicle = True

    ### MAIN
    def main(self):
        EntityBase.main(self)
        self.FSM.main()
Exemple #13
0
 def __init__(self):
     threading.Thread.__init__(self)
     self.machine = FiniteStateMachine()
     self._start_keyboard_listener()
class VehicleBase(entities.EntityBase):
    """ A simple entity for talking to """
    def __init__(self, packet=None):
        super().__init__(packet)
        #def __init__(self, object_name):

        print("-- VehicleBase.__init__() --")
        #entities.EntityBase.__init__(self, None)
        #entities.EntityBase._wrap(self, object_name)
        self.vehicle_wheels = None

        ### Vehicle Properties
        self.speed = 15
        self.acceleration = 1.0
        self.brake_amount = 0.5
        self.steer_amount = 0.5
        self.car_susp = 0.70  # suspension factor for the car

        self.gear = 1
        self.engine_sound = 0.0

        ### Wheel properties
        self.wheel_radius = 1.0
        self.wheel_suspension = 1.0
        self.wheel_roll = 0.1
        self.wheel_friction = 1.0
        self.wheel_compression = 2.0
        self.wheel_damping = 1.5
        self.wheel_stiffness = 6.0
        self.wheel_susp_angle = [0.0, 0.0, -1.0]
        self.wheel_axis = [-1.0, 0.0, 0.0]
        self.last_dust_created = {}

        ### DONT MESS WITH THESE
        self.wheel_max_drive = 1.0
        self.wheel_max_reverse_drive = 1.0
        self.wheel_max_brake = 0.1
        self.wheel_max_left_steer = 0.0
        self.wheel_max_right_steer = 0.0

        ###
        self.car_drive = 0.0
        self.car_steer = 0.0
        self.car_brake = 0.0
        self.current_steer = 0

        #
        self.interact_label = "Morgoar"
        self.interact_icon = None

    def _wrap(self, object1):
        entities.EntityBase._wrap(self, object1)

        ###
        self.ray_pos = [
            child for child in self.childrenRecursive if 'ray' in child
        ][0]
        self.rotation_speed = 0.0
        self.last_rotation = 0.0
        self.rotation_difference = 0.0

        ### Activate Vehicle Controls
        self.vehicle_on = False

        # HACK
        self._data['entity_base'] = self
        self.camera = [
            child for child in self.childrenRecursive if 'vcam' in child
        ][0]

        for child in self.childrenRecursive:
            if 'remove' in child:
                child.removeParent()
                #pass

        ### FSM
        self.FSM = FiniteStateMachine(self)
        self.FSM.add_state('on', self.handle_on)
        self.FSM.add_state('off', self.handle_off)
        self.FSM.add_transition('off', 'on', self.is_active)

        self.FSM.current_state = 'off'

        ### BUILD VEHICLE
        self.assembleVehicle(self._data)
        self._data['build'] = True
        #self.sound_actuator = self._data.controllers[0].actuators['Sound']

    #def _unwrap(self):
    #	entities.EntityBase._unwrap(self)

    ### Functions
    def findWheels(self, vehicle):
        wheels = []
        children = list(vehicle.children)

        for child in children:
            if "wheel" in child:
                wheels.append(child)
        return wheels

    def convertToFloatList(self, aList):
        if type(aList) == type(''):
            aList = eval(aList)
        newList = []
        for entry in aList:
            newList.append(float(entry))

        return newList

    ### Build Vehicle
    def assembleVehicle(self, vehicle):
        vehicleWrapper = self.createConstraint(vehicle)
        self.vehicle_wheels = self.findWheels(vehicle)
        self.assembleWheels(vehicle, vehicleWrapper)

    def createConstraint(self, carObj):
        car_PhysicsID = carObj.getPhysicsId()
        vehicle_constraint = PhysicsConstraints.createConstraint(
            car_PhysicsID, 0, 11)
        self.vehicle_constraint = vehicle_constraint

        constraint_ID = vehicle_constraint.getConstraintId()
        vehicleWrapper = PhysicsConstraints.getVehicleConstraint(constraint_ID)

        self.wrapper = vehicleWrapper

        return vehicleWrapper

    def assembleWheels(self, vehicle, vehicleWrapper):
        #wheels = self.vehicle_wheels
        wheelId = 0

        ###
        for wheel in self.vehicle_wheels:
            pos = wheel.localPosition.copy()

            wheel.removeParent()

            vehicleWrapper.addWheel(
                wheel, pos, self.convertToFloatList(self.wheel_susp_angle),
                self.convertToFloatList(self.wheel_axis),
                self.wheel_suspension, wheel['radius'], True)
            vehicleWrapper.setRollInfluence(self.wheel_roll, wheelId)
            vehicleWrapper.setTyreFriction(wheel['friction'], wheelId)
            vehicleWrapper.setSuspensionCompression(self.wheel_compression,
                                                    wheelId)
            vehicleWrapper.setSuspensionDamping(self.wheel_damping, wheelId)
            vehicleWrapper.setSuspensionStiffness(self.wheel_stiffness,
                                                  wheelId)

            wheel["wheelId"] = wheelId
            wheel["vehicle"] = vehicle
            wheelId += 1

            self.last_dust_created[wheel] = sudo.world.world_time

        print("STARTED **********")

    ### Drive
    def handle_drive(self, vehicle_wrapper):

        ###
        keyboard = bge.logic.keyboard.events
        speed = 0

        ###
        if keyboard[bge.events.WKEY]:

            if self.engine_sound < 1.0:
                self.engine_sound += 0.01

            speed = self.speed * self.acceleration

            if self.acceleration < 1.0:
                self.acceleration += 0.005

        elif keyboard[bge.events.SKEY]:
            speed = -self.speed * 0.5

        else:
            if self.engine_sound > 0.0:
                self.engine_sound += -0.005

            if self.acceleration > 0.0:
                self.acceleration += -0.01

        print(dir(self.vehicle_wheels[0]))

        for wheel in self.vehicle_wheels:
            id = self.vehicle_wheels.index(wheel)
            vehicle_wrapper.applyEngineForce(speed * wheel['maxDrive'], id)

            if keyboard[bge.events.WKEY]:
                ray = self.rayCast(self.ray_pos, self._data, 0, '', 0, 0, 0)

                if ray[0]:
                    self.spawn_dust(wheel)

    ### Brake
    def handle_brake(self, vehicle_wrapper):

        ###
        keyboard = bge.logic.keyboard.events
        brake = 0

        ###
        if keyboard[bge.events.SPACEKEY]:
            brake = self.brake_amount

        for wheel in self.vehicle_wheels:
            id = self.vehicle_wheels.index(wheel)
            vehicle_wrapper.applyBraking(brake, id)

    ### Steering
    def handle_steering(self, vehicle_wrapper):

        ###
        keyboard = bge.logic.keyboard.events

        ###
        if keyboard[bge.events.AKEY]:
            if self.current_steer < self.steer_amount:
                self.current_steer += 0.075  #self.steer_amount

        elif keyboard[bge.events.DKEY]:
            if self.current_steer > -self.steer_amount:
                self.current_steer += -0.075  #-self.steer_amount

        else:
            if self.current_steer > 0.1:
                self.current_steer += -0.075
            elif self.current_steer < -0.1:
                self.current_steer += 0.075
            else:
                self.current_steer = 0

        vehicle_wrapper.setSteeringValue(self.current_steer, 0)
        vehicle_wrapper.setSteeringValue(self.current_steer, 1)

    def handle_stablization(self):
        #ray_pos = [own.position[0],own.position[1],own.position[1]-10]

        ray = self.rayCast(self.ray_pos, self._data, 0, '', 0, 0, 0)

        if ray[0] == None:
            self.alignAxisToVect([0.0, 0.0, 1.0], 2, 0.05)
        else:
            self.alignAxisToVect([0.0, 0.0, 1.0], 2, 0.03)

    ### FSM
    def handle_on(self, FSM):
        print("ON")
        vehicle_wrapper = self.wrapper  #_data[self.vehicle_wrapper]

        ### Camera
        self.camera.controllers[0].actuators['Edit Object'].object = self._data

        ###
        self.handle_drive(vehicle_wrapper)
        self.handle_brake(vehicle_wrapper)
        self.handle_steering(vehicle_wrapper)
        self.handle_stablization()

        ###
        self.last_rotation = self.rotation_speed
        self.rotation_speed = (vehicle_wrapper.getWheelRotation(0) +
                               vehicle_wrapper.getWheelRotation(1)) / 2

        self.rotation_difference += -(self.last_rotation - self.rotation_speed)

        ### Gears
        if self.rotation_difference > 1.0:
            self.gear = 3
        elif self.rotation_difference > 0.75:
            self.gear = 2
        elif self.rotation_difference > 0.5:
            self.gear = 1

        #self.engine_sound = self.rotation_difference#*self.gear
        #self.sound_actuator.pitch = 1.0 + (self.engine_sound*2.0)

        #print (self.sound_actuator)

        ### TO fix reload crash
        #bge.constraints.removeConstraint(vehicle_wrapper.getConstraintId())

    def handle_off(self, FSM):
        vehicle_wrapper = self.wrapper  #_data[self.vehicle_wrapper]

        # Brake amount
        brake = 0.25

        # Brake
        for wheel in self.vehicle_wheels:
            id = self.vehicle_wheels.index(wheel)
            vehicle_wrapper.applyBraking(brake, id)

        print("OFF")

    def is_active(self, FSM):
        return bool(self.vehicle_on)

    ### Interact
    def on_interact(self, entity):
        if self.vehicle_on == False:
            print("TURNING ON ---")
            self.vehicle_on = True
            entity.current_vehicle = self
            entity.in_vehicle = True

    ###
    def spawn_dust(self, wheel):

        if (sudo.world.world_time - self.last_dust_created[wheel] > 0.1):
            dust = bge.logic.getCurrentScene().addObject(
                "Dust", "CELL_MANAGER_HOOK", 20)
            dust.position = wheel.position - Vector(
                [0.0, 0.0, 1.0])  #Landscape height at position
            dust.localScale = [3.0, 3.0, 3.0]
            self.last_dust_created[wheel] = sudo.world.world_time

    ### MAIN
    def main(self):
        entities.EntityBase.main(self)
        self.FSM.main()
Exemple #15
0
class FiniteStateMachineTests(unittest.TestCase):

	def setUp(self):
		self.finite_state_machine = FiniteStateMachine()

	def test_createNewMachine_withoutParameters_initialStateMustBeStopped(self):
		actual_state = self.finite_state_machine.get_current_state() 
		assert_that(actual_state).is_equal_to(MachineState.STOPPED)

	def test_setCurrentState_withInvalidCommand_exceptionMustBeRaised(self):
		with self.assertRaises(ValueError):
			self.finite_state_machine.set_current_state('foo')

	def test_setCurrentState_withValidCommand_stateMustBeSetted(self):
		self.finite_state_machine.set_current_state(MachineCommand.START)
		actual_state = self.finite_state_machine.get_current_state()

		assert_that(actual_state).is_equal_to(MachineState.STARTED)

	def test_setCollectInStartedMachine_thenGetPreviousState_previousStateMustBeStarted(self):
		self.finite_state_machine.set_current_state(MachineCommand.START)
		self.finite_state_machine.set_current_state(MachineCommand.COLLECT)

		previous_state = self.finite_state_machine.get_previous_state()
		assert_that(previous_state).is_equal_to(MachineState.STARTED)

	def test_collectData_mustReturnMultidimensionalArray(self):
		expected_array_rows = 3
		expected_array_columns = 3

		expected_min_value = 0
		expected_max_value = 9

		self.finite_state_machine.set_current_state(MachineCommand.START)
		actual = self.finite_state_machine.collect_data()

		assert_that(actual).is_not_empty()
		assert_that(actual).is_length(expected_array_rows)

		for row in actual:
			assert_that(row).is_length(expected_array_columns)

			for column in row:
				assert_that(column).is_less_than_or_equal_to(expected_max_value)
				assert_that(column).is_greater_than_or_equal_to(expected_min_value)


	def test_processData_mustReturnScalar5TransposedArray(self):
		target_array = numpy.array(
						[[1, 2, 3],
						[4, 5, 6],
						[7, 8, 9]])

		expected_array = numpy.array([[5, 20, 35],
						  [10, 25, 40],
						  [15, 30, 45]])

		self.finite_state_machine.set_current_state(MachineCommand.START)
		self.finite_state_machine.set_current_state(MachineCommand.COLLECT)
		actual_array = self.finite_state_machine.process_data(target_array)

		for actual_row, expected_row in zip(actual_array.tolist(), expected_array.tolist()):
			assert_that(actual_row).is_equal_to(expected_row)
Exemple #16
0
	def setUp(self):
		self.finite_state_machine = FiniteStateMachine()