# This will controll characters. import os import bge from Scripts import Opt import math import json import time import mathutils import random from Scripts import Reuse from Scripts.Common import * from Scripts import Vehicle from Scripts import Multiplayer_Shared controls = { "forward" :keycodes["W"], "backward":keycodes["S"], "left" :keycodes["A"], "right" :keycodes["D"], "jump" :keycodes["LCtrl"], "getcar" :keycodes["E"], "swimdown":keycodes["LShift"], } if "chr_controls" not in bge.logic.globalDict: bge.logic.globalDict["chr_controls"] = controls controls = bge.logic.globalDict["chr_controls"] # Loading animation data. def LoadAnimations(): # Loading Json animation data files. folder = bge.logic.expandPath("//animdata/chr/") if "character-anim-data" not in bge.logic.globalDict: animations = {} for f in os.listdir(folder): if f.endswith(".json"): print("Reading", f, "...") with open(folder+f) as fl: data = json.load(fl) name = f.replace(".json", "") animations[name] = data bge.logic.globalDict["character-anim-data"] = animations return bge.logic.globalDict["character-anim-data"] animations = LoadAnimations() def DaniUpdate(): # This function is specifically meant for Dani. # Since he is the main character. But if you # want to modify the game, so somebody else is # the main character. Use this function on that # character. cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() dani = cont.owner keys = bge.logic.globalDict.get("keys", []) if not dani["driving"]: # Jump animation logic onground = OnGround(dani) if dani.get("not-onground", 0) > 20 and onground and "Water" not in str(onground): dani["landing"] = 13 if onground: dani["not-onground"] = 0 else: try: dani["not-onground"] += 1 except: pass if not onground or dani.get("grab"): GrabEdge(dani) dani["onground"] = onground if dani.get("landing"): ApplyAnimation(dani, "Land") WalkForward(dani) device = bge.logic.globalDict["SoundDevice"] sound = bge.logic.globalDict["sounds"]["dani_land"] if not sound["play"] or not sound["play"].status: sound["play"] = device.play(sound["sound"]) StopWalkSound(dani) dani["landing"] -= 1 elif not onground and not dani.get("underwater"): if not dani.get("grab"): ApplyAnimation(dani, "Fly") else: ApplyAnimation(dani, "Hang") StopWalkSound(dani) # Moving back and forth if controls["forward"] in keys: WalkForward(dani) elif controls["backward"] in keys: WalkBackward(dani) # Moving left to right if controls["left"] in keys: WalkLeft(dani) elif controls["right"] in keys: WalkRight(dani) # Jumping if controls["jump"] in keys: Jump(dani) else: dani["jumping"] = False # Swiming down if controls["swimdown"] in keys: GoDown(dani) if not dani.get("swimming_down"): WaterBoyancy(dani) # Standing still animation if not keys and not dani["walkingtowardcar"]: if not dani.get("underwater"): ApplyAnimation(dani, "Stand") else: ApplyAnimation(dani, "SwimIdle") StopWalkSound(dani) #AutoStand(dani) # If getting car if controls["getcar"] in keys and not dani.get("getcartimer"): getIntoCar(dani) dani["getcartimer"] = 10 elif dani["walkingtowardcar"]: walkTowardCar(dani) if any(controls[x] in keys for x in ["forward", "backward", "left", "right"]): getOutCar(dani) else: ApplyAnimation(dani, "Drive") # If getting out of car if controls["getcar"] in keys and not dani.get("getcartimer"): getOutCar(dani) dani["getcartimer"] = 10 if dani.get("getcartimer"): dani["getcartimer"] -= 1 collidewithwater = dani.collide(scene.objects["Water"]) if collidewithwater[1]: # Checking for collision points, first # boolean gives false positives. Bug? dani["underwater"] = True # Executing camera changes ExecuteChangeCameraTarget() CameraRuleOfThirds(dani) # Reverting swimming dani["swimming_down"] = False dani["jumping"] = False if dani.get("jump-timer"): dani["jump-timer"] -= 1 def OnGround(character): # Returns whether the car # in on the ground or not. # Getting the relative position of the ground down = Vehicle.RelativePoint(character, [0,0,-0.6]) center = Vehicle.RelativePoint(character, [0,0, 0.6]) # See if there is grown under the car ray = character.rayCast(down, center, poly=True) # If nothing is sensed, we return None if not ray[1]: return None # Else we return the material of the object underneith # Useful to see on what kind of ground the car is. else: try: return ray[3].material # If there is no material data it will game the name # of the object except: return ray[0].name def WalkForward(character): character.applyMovement([0,-0.02,0], True) character.localLinearVelocity.y = -5 # Facing correctly rig = getRig(character) rot = rig.localOrientation.to_euler() target = 0 rot[2] = rot[2] + (( target - rot[2] ) / 5 ) rig.localOrientation = rot if not character.get("underwater"): ApplyAnimation(character, "Walk") else: ApplyAnimation(character, "Swim") WalkSound(character) def WalkBackward(character): character.applyMovement([0,0.02,0], True) character.localLinearVelocity.y = 5 # Facing correctly rig = getRig(character) rot = rig.localOrientation.to_euler() target = math.pi if rot[2] < 0: target -= math.pi*2 rot[2] = rot[2] + (( target - rot[2] ) / 5 ) rig.localOrientation = rot if not character.get("underwater"): ApplyAnimation(character, "Walk") else: ApplyAnimation(character, "Swim") WalkSound(character) def WalkLeft(character): character.applyMovement([0.02,0,0], True) character.localLinearVelocity.x = 5 # Facing correctly if not character.get("grab"): rig = getRig(character) rot = rig.localOrientation.to_euler() target = math.pi/2 if rot[2] < -(math.pi/2): rot[2] += math.pi*2 rot[2] = rot[2] + (( target - rot[2] ) / 5 ) rig.localOrientation = rot if not character.get("underwater"): ApplyAnimation(character, "Walk") else: ApplyAnimation(character, "Swim") WalkSound(character) def WalkRight(character): character.applyMovement([-0.02,0,0], True) character.localLinearVelocity.x = -5 # Facing correctly if not character.get("grab"): rig = getRig(character) rot = rig.localOrientation.to_euler() target = -(math.pi/2) if rot[2] > math.pi/2: rot[2] -= math.pi*2 rot[2] = rot[2] + (( target - rot[2] ) / 5 ) rig.localOrientation = rot if not character.get("underwater"): ApplyAnimation(character, "Walk") else: ApplyAnimation(character, "Swim") WalkSound(character) def Jump(character): #if not OnGround(character) and not character.get("grab")\ # and not character.get("underwater"): # return character["jumping"] = True if ( character.localLinearVelocity.z > 0.5 \ or character.localLinearVelocity.z < -0.5 )\ and not character.get("grab")\ and not character.get("underwater")\ and not character.get("underwater"): return if character.get("jump-timer") and not character.get("grab")\ and not character.get("underwater"): return character["jump-timer"] = 20 #character.applyMovement([0, 0, 0.1], False) character.localLinearVelocity.z = 6 if "Dani" in character.name: device = bge.logic.globalDict["SoundDevice"] sound = bge.logic.globalDict["sounds"]["dani_jump"] if OnGround(character) and ( not sound["play"] or not sound["play"].status ) : sound["play"] = device.play(sound["sound"]) def GoDown(character): toFPS = Opt.ToFPS() character.applyMovement([0, 0, -0.1*toFPS], False) character["swimming_down"] = False def WaterBoyancy(character): # Creating water boyancy underwater toFPS = Opt.ToFPS() scene = bge.logic.getCurrentScene() if character.get("underwater") and character.position[2] < -10.5 and not character.get("driving"): #character.worldLinearVelocity.z /= 10 #if round(character.worldLinearVelocity.z, 1) == 0.0: if not character.get("jumping"): character.worldLinearVelocity.z = 0.5 character.worldLinearVelocity.x *= 0.9 character.worldLinearVelocity.y *= 0.9 #character.applyForce([0,0,character.mass*9.8*-min(0, character.worldLinearVelocity[2])]) #*min(1.1, (character.position[2]+9.5)*-10) #scene.objects["DanisRig"]["underwater"] = True elif character.position[2] > -9.5: character["underwater"] = False #scene.objects["DanisRig"]["underwater"] = False def getIntoCar(character, car=None, passanger=False, immediately=False, closest=10, avoidblown=False): # This function will run when any character wants to get into # any car # If character already in a car or walking to another car # we give this up. if character.get("driving") or character.get("walkingtowardcar"):# or character.get("last_change",0) > time.time()-1: return if not car: # If a car is not specified we are going to choose the # closest car within 10 meters away from Dani. car = None for trycar in bge.logic.globalDict["allcars"]: distance = trycar.getDistanceTo(character) if avoidblown and trycar.get("blown"): continue if distance < closest: car = trycar closest = distance if not car: # There is no car within this distance we give up return # Then we want to choose the closest car target. dani_stand_target = car.children["Dani_Stand_Target"] try: other_stand_target = car.children["Other_Stand_Target"] except: other_stand_target = dani_stand_target # Now we want to activate the movement. character["walkingtowardcar"] = car if not passanger: character["walkingtowardcartarget"] = dani_stand_target else: character["walkingtowardcartarget"] = other_stand_target character["becomepassanger"] = passanger if immediately: walkTowardCar(character, immediately=True) # Readjust the camera # if character.name == "Dani_Box": # car.children["CarCamTarget"].orientation = [0.2,0,0] # zoom = car["specs"].get("cameraZoom", 3) # ChangeCameraTarget(car.children["CarCamTarget"], 100, [zoom,zoom,zoom]) pass def walkToward(character, point, avoidObstacles=True): # Function used when character needs to walk somewhere if type(point) == bge.types.KX_GameObject: point = point.position.copy() rig = getRig(character) walkVector = character.getVectTo(point) # We want the character to walk only to the strongest # vector. So he will not end up flapping arround all # the time. fro = character.position.copy() fro.z += 1 if avoidObstacles: ray = Vehicle.BeautyRayCast(character, "walk", point, fro) else: ray = [None] if ray[0] and ray[0].position != point and ray[0] != point and ray[0].visible: distance = math.dist(ray[1], fro) if distance < 5: obstacleVector = character.getVectTo(ray[1]) # Instead of trying to walk toward the target we will instead walk # around the obstacle # WalkForward(character) # if obstacleVector[2][0] > 0: # character.alignAxisToVect(obstacleVector[1], 0, 0.5) # else: # character.alignAxisToVect(-obstacleVector[1], 0, 0.5) # character.alignAxisToVect( (0,0,1), 2, 1.0 ) if obstacleVector[2][0] < 0: rto = ray[2] else: rto = -ray[2] character.alignAxisToVect(rto, 0, 0.1) character.alignAxisToVect((0,0,1), 2, 1) rig.alignAxisToVect(rto, 0, 0.1) rig.alignAxisToVect((0,0,1), 2, 1) WalkForward(character) return walkVector # ELSE walkVectorIs = walkVector[2] if walkVectorIs[1] < 0: WalkForward(character) elif walkVectorIs[1] > 0: WalkBackward(character) if walkVectorIs[0] > 0: character.applyRotation([0,0,walkVectorIs[0]/5], False) #WalkLeft(character) elif walkVectorIs[0] < 0: #WalkRight(character) character.applyRotation([0,0,walkVectorIs[0]/5], False) if walkVectorIs[2] > 0.1: Jump(character) elif walkVectorIs[2] < -0.1: GoDown(character) return walkVector def ChangeCameraTarget(targetobject, delay, scaling=None, callable=None, rotate=True): # This function changes dani's camera target # useful for when getting into cars and the # mounting point of the camera is changed. # And because I can, it is also delayed. scene = bge.logic.getCurrentScene() bge.logic.globalDict["CameraTargetChange"] = {"delay":delay, "remaining":delay, "target":targetobject, "targetscale":scaling, "callable":callable, "rotate":rotate} cam_parent = scene.objects["DaniCam_Parent"] cam_parent.removeParent() cam_parent["startingPosition"] = cam_parent.position.copy() cam_parent["startingOrientation"] = mathutils.Vector(cam_parent.orientation.to_euler()) # This fixes the spins that are more than 360 degrees targetRotation = mathutils.Vector(targetobject.orientation.to_euler()) for i in range(3): d = targetRotation[i] - cam_parent["startingOrientation"][i] if d > math.pi: cam_parent["startingOrientation"][i] += 2 * math.pi elif d < -math.pi: cam_parent["startingOrientation"][i] -= 2 * math.pi cam_parent["startingScaling"] = cam_parent.scaling.copy() def CameraRuleOfThirds(dani): # This function implements the rule of thirds. # The rule of thirds is a technique to compose # pretty images. Where the main subject in the # frame is positioned on in the center of the # frame, but rather slightly to the side. # Imagine dividing the frame in 3. And putting # your subject on one of those division lines. # This is rule of thirds. # One more think to keep in mind. We want more empty # frame toward the direction where the main character # is looking. scene = bge.logic.getCurrentScene() cam = scene.objects["DaniCam"] # We do that only for the walking. if not dani["driving"]: # We want to get the z rotation of Dani's rig # which is determening where he is looking. # We are going to use local space orientation # since it is in relation to the parent, which # rotates in sinc with the camera. daniZrot = getRig(dani).localOrientation.to_euler()[2] # Finding the multiplication fraction of the effect # When dani points in the same direction as the camera # we want the effect to be 0. The same as if we look # directly at him from the front. But looking at him # from the side should give 100% effect. frac = math.cos(daniZrot * 2) - 1 # Limiting the effect to be between 0 and 1 frac = min(0, max(-1, frac)) # Multiplying the effectiveness of the effect frac = frac ** 0.6 if type(frac) == complex: frac = float(frac.real) # Flipping the effect when he looks right, versus left. if daniZrot > 0: frac *= -1 # Applying the math to the camera cam.localOrientation = [math.pi/2, # X - Move camera up, so it is not looking at the floor -frac/3, # Y - Add a dutch angle since it's cool and cool is cool math.pi+frac] # Z - Add the rule of thirds. else: # Applying the math to the camera cam.localOrientation = [math.pi/2, # X - Move camera up, so it is not looking at the floor 0, math.pi] def ExecuteChangeCameraTarget(): # This function will execute the actual camera movement itself. scene = bge.logic.getCurrentScene() if "CameraTargetChange" not in bge.logic.globalDict: return cam_parent = scene.objects["DaniCam_Parent"] targetObject = bge.logic.globalDict["CameraTargetChange"]["target"] delayFull = bge.logic.globalDict["CameraTargetChange"]["delay"] delayRemaining = bge.logic.globalDict["CameraTargetChange"]["remaining"] ToRotate = bge.logic.globalDict["CameraTargetChange"]["rotate"] # Counting down frames of the delay bge.logic.globalDict["CameraTargetChange"]["remaining"] -= 1 # Getting a fraction of how much from that other target the character walked try: camFactor = ( delayRemaining / delayFull ) ** 2 except: camFactor = 1 camFactor = camFactor * -1 + 1 camFactor = min(1, max(0, camFactor)) # Applying camera location and rotation based on this factor targetObject.orientation = [0.2,0,0] target_position = targetObject.position target_orientation = mathutils.Vector(targetObject.orientation.to_euler()) if bge.logic.globalDict["CameraTargetChange"]["targetscale"]: target_scale = mathutils.Vector(bge.logic.globalDict["CameraTargetChange"]["targetscale"]) if delayRemaining <= 0: if ToRotate: cam_parent.orientation = target_orientation else: vect = cam_parent.getVectTo(target_position) vect[1].z = min(-0.1, vect[1].z) cam_parent.alignAxisToVect(-vect[1], 1, 0.1) cam_parent.position = target_position if bge.logic.globalDict["CameraTargetChange"]["targetscale"]: cam_parent.scaling = target_scale cam_parent.setParent(targetObject, 0, 0) if bge.logic.globalDict["CameraTargetChange"]["callable"]: bge.logic.globalDict["CameraTargetChange"]["callable"]() del bge.logic.globalDict["CameraTargetChange"] return cam_parent.position = ( cam_parent["startingPosition"] + ( target_position - cam_parent["startingPosition"] ) * camFactor ) if ToRotate: cam_parent.orientation = ( cam_parent["startingOrientation"] + ( target_orientation - cam_parent["startingOrientation"] ) * camFactor ) if bge.logic.globalDict["CameraTargetChange"]["targetscale"]: cam_parent.scaling = ( cam_parent["startingScaling"] + ( target_scale - cam_parent["startingScaling"] ) * camFactor ) def walkTowardCar(character, immediately=False): # This function is running while the character is getting into car settings = bge.logic.globalDict["settings"] walkVector = walkToward(character, character["walkingtowardcartarget"]) scene = bge.logic.getCurrentScene() car = character["walkingtowardcar"] finaltarget = car.children["Dani_Stand_Target"] passanger = character["becomepassanger"] if passanger: try: finaltarget = car.children["Other_Stand_Target"] except: pass # Change to final target if walkVector[0] < 1 and character["walkingtowardcartarget"] != finaltarget: character["walkingtowardcartarget"] = finaltarget # Change to sitting inside of the car if immediately or walkVector[0] < 1 and character["walkingtowardcartarget"] == finaltarget: # Readjust the camera if character.name == "Dani_Box": car.children["CarCamTarget"].orientation = [0.2,0,0] zoom = car["specs"].get("cameraZoom", 3) ChangeCameraTarget(car.children["CarCamTarget"], 20, [zoom,zoom,zoom]) car["npc"] = "" car["enemy"] = "" car["shake"] = 0.0 character.position = finaltarget.position StopWalkSound(character) character["walkingtowardcar"] = False if character.name == "Dani_Box": car["active"] = True character["driving"] = car if not passanger: if car.get("driver"): driver = car["driver"] getOutCar(driver) driver["getbacktocar"] = car driver["getbacktimer"] = 60 car["driver"] = character else: if "passangers" not in car: car["passangers"] = [] car["passangers"].append(character) rig = getRig(character) rig["driving"] = True target = car.children["Dani_Sit_Target"] if passanger: try: target = car.children["Other_Sit_Target"] except: pass character.suspendPhysics(True) character.worldPosition = target.worldPosition character.worldOrientation = target.worldOrientation rig.worldOrientation = character.worldOrientation character.setParent(car, False, False) character["carTarget"] = finaltarget #car_rig = car.children[car.get("rig","RIG")] #car_rig.playAction(car.get("rigaction", "NeonspeedsterRIGAction"), 10,20) if character.name == "Dani_Box": scene.objects["Gage"].visible = True scene.objects["Gage_Arrow"].visible = True scene.objects["Gage_Health"].visible = True scene.objects["Gage_Nitro"].visible = True scene.objects["Gage_Tachometer"].visible = True scene.objects["Gage_Gear"].visible = True scene.objects["Gage_Redline"].visible = True if settings.get("veh_mouse"): if settings.get("veh_mouse_guides"): scene.objects["Mouse_Turn_UI_Piece"].visible = True scene.objects["Mouse_Turn_UI"].visible = True scene.objects["Mouse_Accelation_UI_Piece"].visible = True scene.objects["Mouse_Accelation_UI"].visible = True if settings.get("veh_mouse_cursor"): bge.render.showMouse(True) Vehicle.RemoveNetId(car) print(consoleForm(character), "in car:", consoleForm(car)) # Sound device for sounds. device = bge.logic.globalDict["SoundDevice"] sound = bge.logic.globalDict["sounds"]["door"] sound["play"] = device.play(sound["sound"]) sound["play"].location = car.worldPosition sound["play"].velocity = car.getLinearVelocity() sound["play"].relative = False sound["play"].distance_maximum = 200 sound["play"].distance_reference = 1 sound["play"].attenuation = 1 sound["play"].volume = 1.5 def getOutCar(character): # Fucntion to get out of car scene = bge.logic.getCurrentScene() # If character is not in the car if character["walkingtowardcar"]: car = character["walkingtowardcar"] soundDo = False elif character["driving"]: car = character["driving"] soundDo = True else: return rig = getRig(character) if character.name == "Dani_Box": car["active"] = False # Unfucking the camera cam = bge.logic.getCurrentScene().active_camera cam.shift_x = 0 cam.shift_y = 0 cam.lens = 20 if character == car.get("driver"): car["driver"] = None if character in car.get("passangers",[]): car["passangers"].remove(character) rig["driving"] = False character["last_change"] = int(time.time()) character.restorePhysics() character.removeParent() character.localLinearVelocity = [0,0,0] if -car.localLinearVelocity[1] > 10 and not character["walkingtowardcar"]: character["landing"] = 13 if not character.get("walkingtowardcar"): pos = car.worldOrientation.to_euler() character.orientation = [0,0,float(pos[2])] target = character.get("carTarget", car.children["Dani_Stand_Target"]) character.worldPosition = target.worldPosition character.position[2] += 1.5 character["driving"] = False # rig.removeParent() # pos = character.worldPosition # rig.position = [pos[0],pos[1],pos[2]] # pos = character.worldOrientation # rig.orientation = [pos[0],pos[1],pos[2]] # rig.setParent(character, False, False) # Readjust camera if character.name == "Dani_Box": character.children["Dani_cam_Target"].orientation = [0,0,0] ChangeCameraTarget(character.children["Dani_cam_Target"], 20, [1,1,1]) # if soundDo: # rig = car.children["RIG"] # rig.playAction(car.get("rigaction", "NeonspeedsterRIGAction"), 10,20) scene.objects["Gage"].visible = False scene.objects["Gage_Arrow"].visible = False scene.objects["Gage_Health"].visible = False scene.objects["Gage_Nitro"].visible = False scene.objects["Gage_Tachometer"].visible = False scene.objects["Gage_Gear"].visible = False scene.objects["Gage_Redline"].visible = False scene.objects["Mouse_Turn_UI_Piece"].visible = False scene.objects["Mouse_Turn_UI"].visible = False scene.objects["Mouse_Accelation_UI_Piece"].visible = False scene.objects["Mouse_Accelation_UI"].visible = False bge.render.showMouse(False) if not character.get("walkingtowardcar"): device = bge.logic.globalDict["SoundDevice"] sound = bge.logic.globalDict["sounds"]["door"] sound["play"] = device.play(sound["sound"]) sound["play"].location = car.worldPosition sound["play"].velocity = car.getLinearVelocity() sound["play"].relative = False sound["play"].distance_maximum = 200 sound["play"].distance_reference = 1 sound["play"].attenuation = 1 sound["play"].volume = 1.5 character["walkingtowardcar"] = False print(consoleForm(character), "got out of:", consoleForm(car)) def getRig(character): scene = bge.logic.getCurrentScene() if type(character.get("rig", "")) == str and character.get("rig", ""): rigname = character.get("rig", "") # if str(character) == "MoriaBox": # print() # print("character:", character) # print("rigname:", rigname) # print("Game Children") # for i in character.childrenRecursive: # print("child:", i) # print("Blender Children") # for i in character.blenderObject.children_recursive: # print("child:", i) rig = character.children[rigname] elif character.get("rig"): rig = character.get("rig") return rig def ApplyAnimation(character, animation, keep=False, **kwargs): # Optimization cam = bge.logic.getCurrentScene().active_camera if character in Reuse.reuse.get(character.name, [])\ or cam.getDistanceTo(character) > 150: return # Exctracting data request rig = getRig(character) action = rig.get("Action") startframe = animation[0] endframe = animation[1] # Failsafe if not action: return # If we are reading animation from the database if type(animation) == str and animation in animations.get(character.name, {}): data = animations[character.name][animation] action = data.get("Action", action) keep = data.get("Keep", keep) startframe = data["Frames"][0] endframe = data["Frames"][1] kwargs = data.get("kwargs", kwargs) elif type(animation) == str: startframe = 0 endframe = 0 # Sometimes we might want to keep the animation at it's # last frame when it ends. if keep and rig.getActionFrame(kwargs.get("layer", 0)) == endframe: startframe = endframe # Executing the animation rig.playAction(action, startframe, endframe, **kwargs) # To activate the stand animation we want to know if anything is playing if kwargs.get("layer", 0) == 0: # Recording the animation rig["animation"] = animation def AutoStand(character): # This function will automatically play the stand animation if # nothing else is playing. rig = getRig(character) if not rig.get("animation"): ApplyAnimation(character, "Stand") else: animation = rig.get("animation") startframe = animation[0] endframe = animation[1] # If we are reading animation from the database if type(animation) == str and animation in animations.get(character.name, {}): data = animations[character.name][animation] keep = data.get("Keep", None) startframe = data["Frames"][0] endframe = data["Frames"][1] kwargs = data.get("kwargs", {}) if rig.getActionFrame(0) == endframe: rig["animation"] = None def GrabEdge(character): rig = getRig(character) chest = Vehicle.RelativePoint(rig, [0,0,0.7]) fromchest = Vehicle.RelativePoint(rig, [0,-1,0.7]) chestray = Vehicle.BeautyRayCast(character, "chest", fromchest, chest) face = Vehicle.RelativePoint(rig, [0,0,1.5]) fromface = Vehicle.RelativePoint(rig, [0,-1,1.5]) faceray = Vehicle.BeautyRayCast(character, "face", fromface, face) try: facedist = math.dist(face, faceray[1]) except: facedist = 1 try: chestdist = math.dist(chest, chestray[1]) except: chestdist = 1 if chestdist < facedist: if not character.get("jumping"): dist = chestdist+0.01 toedge = Vehicle.RelativePoint(rig, [0,-dist,1.0]) fromedge = Vehicle.RelativePoint(rig, [0,-dist,1.5]) edgeray = Vehicle.BeautyRayCast(character, "edge", toedge, fromedge) if edgeray[1]: character["grab"] = float(edgeray[1].z-1.2) else: character["grab"] = float(character.position.z) character.position.z = character["grab"] character.worldLinearVelocity = [0,0,0] else: character["grab"] = character.position.z # Rotate character to face the point. #vect = character.getVectTo(chestray[2]) character.alignAxisToVect(chestray[2], 1, 1) character.alignAxisToVect((0,0,1), 2, 1) #vect = rig.getVectTo(chestray[2]) rig.alignAxisToVect(chestray[2], 1, 1) rig.alignAxisToVect((0,0,1), 2, 1) character.applyMovement((0,-0.01,0), True) else: character["grab"] = None ### NPC STUFF ### def GetBackCar(character): # First waiting in bevilderment if character.get("getbacktimer"): character["getbacktimer"] -= 1 return if not character.get("driving"): character["walkingtowardcar"] = None getIntoCar(character, closest=100, avoidblown=True) else: if character["driving"] == character["getbacktocar"]: character["driving"]["npc"] = "npc" else: character["driving"]["npc"] = "pursuit" character["driving"]["target"] = character["getbacktocar"] character["getbacktocar"] = None def WhenBlewUpCar(character): car = character["carblewup"] # Turning off this function if the # character got spawned. if character.get("driving"): if not character.get("target") or character.get("target") == character.get("driving"): character["driving"]["npc"] = "npc" else: character["driving"]["npc"] = "pursuit" character["driving"]["target"] = character.get("target") character["target"] = None character["carblewup"] = False return # Getting to any car getIntoCar(character, closest=1000, avoidblown=True) def NPCcar(character): car = character["NPCcar"] # Finishing the operation if character.get("driving"): if character["driving"] == car: car["npc"] = "npc" character["NPCcar"] = False return # If somebody is the targeted car if car.get("driver"): character["getbacktocar"] = car character["NPCcar"] = False return if not car.get("blown"): getIntoCar(character, car) else: getIntoCar(character, closest=100, avoidblown=True) ### SOUND STUFF #### def WalkSound(character): if "Dani" in character.name and character.get("onground") and not character.get("landing"): device = bge.logic.globalDict["SoundDevice"] sound = bge.logic.globalDict["sounds"]["dani_walk"] if not sound["play"] or not sound["play"].status: sound["play"] = device.play(sound["sound"]) def StopWalkSound(character): try: bge.logic.globalDict["sounds"]["dani_walk"]["play"].stop() except: pass ##### STORY RELATED FUNCTIONS #### def Update(character): # It may run from an actuator, so we want to make sure we get the object # and not the actuator. scene, character = Vehicle.GetSceneAndCar(character) if character.get("walkingtowardcar"): walkTowardCar(character) if not character.get("driving"): AutoStand(character) else: ApplyAnimation(character, "Drive") ReactionsToDaniDriving(character) if character.get("getbacktocar"): GetBackCar(character) if character.get("carblewup"): WhenBlewUpCar(character) if character.get("NPCcar"): NPCcar(character) collidewithwater = character.collide(scene.objects["Water"]) if collidewithwater[1]: # Checking for collision points, first # boolean gives false positives. Bug? character["underwater"] = True if not character.get("swimming_down"): WaterBoyancy(character) character["swimming_down"] = False character["jumping"] = False if character.get("jump-timer"): character["jump-timer"] -= 1 def ReactionsToDaniDriving(character): # This function will make characters react to dani's driving # when they are sitting in the same car. scene = bge.logic.getCurrentScene() dani = scene.objects["Dani_Box"] # First we need to make sure that the character is in the # car as dani. if not character.get("driving") == dani.get("driving") or not character.get("driving"): return # Then we want to get data about what if going on with the car. car = character.get("driving") crash = car.get("crash", 0.0) near = car.get("near", 0.0) speed = -car.localLinearVelocity[1] car["crash"] = 0.0 car["near"] = 0.0 react = None if crash > 0.1: react = "crash" if speed > 50: react = "speed" if near >= 0.4: react = "near" device = bge.logic.globalDict["SoundDevice"] try: voices = bge.logic.globalDict[character.name+"Voices"] except: return if ( not character.get("saying") or not character.get("saying").status ) and react: sound = random.choice(voices[react]) while character.get("lastsaid") == sound: sound = random.choice(voices[react]) character["lastsaid"] = sound sound["play"] = device.play(sound["sound"]) character["saying"] = sound["play"] sound["play"].volume = 2 ApplyAnimation(character, "Talk") ##### NETWORK RELATE FUNCTIONS #### def Encode(character): data = { "ID" :id(character), "type" :"chr", "name" :character.name, "netId" :character.get("netId"), "position" :list(character.position), "orientation" :list(character.orientation.to_euler()) } character["netId"] = data["netId"] netObjects = bge.logic.globalDict["netObjects"] if data["ID"] not in netObjects["pythonId"]: netObjects["pythonId"][data["ID"]] = character return data def Decode(data, network=False): # Decoding character data netObjects = bge.logic.globalDict["netObjects"] if data.get("netId") not in netObjects["netId"]: # Making the character try: character = Reuse.Create(data.get("name")) except: character = Reuse.Create("MoriaBox") netObjects["netId"][data.get("netId")] = character character = netObjects["netId"][data.get("netId")] character["netId"] = data.get("netId") character.position = data.get("position", (0,0,0)) character.orientation = data.get("orientation", (0,0,0))