forked from BlenderDumbass/DanisRace
1327 lines
49 KiB
Python
1327 lines
49 KiB
Python
|
import bge
|
||
|
import bpy
|
||
|
import aud
|
||
|
import time
|
||
|
import datetime
|
||
|
import threading
|
||
|
import random
|
||
|
import numpy
|
||
|
import math
|
||
|
import mathutils
|
||
|
|
||
|
import Reuse
|
||
|
import Distraction
|
||
|
import Opt
|
||
|
|
||
|
|
||
|
# SPAWNING ASSETS AND STUFF
|
||
|
|
||
|
spawnAtDistance = 300
|
||
|
maxCars = 6
|
||
|
|
||
|
scene = bge.logic.getCurrentScene()
|
||
|
cont = bge.logic.getCurrentController()
|
||
|
dani = scene.objects["Dani_Box"]
|
||
|
cam = scene.active_camera
|
||
|
|
||
|
FPS = bge.logic.getAverageFrameRate()
|
||
|
goodFPS = FPS >= 30
|
||
|
|
||
|
camSurround = Opt.Surround(cam.position, spawnAtDistance/2)#, cam.orientation.to_euler())
|
||
|
camSurroundCars = Opt.Surround(cam.position, spawnAtDistance)#, cam.orientation.to_euler())
|
||
|
|
||
|
inCinema = scene.objects["CinemaColider"]["InCinema"]
|
||
|
|
||
|
#print(bge.logic.globalDict.get("reuse"))
|
||
|
|
||
|
# Destroy those needing destroying
|
||
|
Reuse.SelfDestructDo()
|
||
|
|
||
|
# Dani water boyancy
|
||
|
if dani["underwater"] and dani.position[2] < -9.5 and not dani["driving"]:
|
||
|
dani.applyForce([0,0,min(0.6, -0.5*(dani.position[2]+9.5))])
|
||
|
scene.objects["DanisRig"]["underwater"] = True
|
||
|
elif dani.position[2] > -9.5:
|
||
|
dani["underwater"] = False
|
||
|
scene.objects["DanisRig"]["underwater"] = False
|
||
|
|
||
|
|
||
|
|
||
|
# Available car to spawn
|
||
|
NPC_cars = ["NeonSpeedsterBox",
|
||
|
"RedKissBox",
|
||
|
"DarkShadowBox",
|
||
|
"HatchBack01-white",
|
||
|
"HatchBack01-orange",
|
||
|
"HatchBack01-blue",
|
||
|
"HatchBack01-black"]
|
||
|
|
||
|
npccp = [1,
|
||
|
1,
|
||
|
1,
|
||
|
10,
|
||
|
8,
|
||
|
5,
|
||
|
3]
|
||
|
|
||
|
NPC_cars_probability = []
|
||
|
for i in npccp:
|
||
|
NPC_cars_probability.append( 1 / sum(npccp) * i)
|
||
|
#print(sum(NPC_cars_probability), NPC_cars_probability)
|
||
|
|
||
|
# Storing some values to the globalDict
|
||
|
bge.logic.globalDict["NPC_cars"] = NPC_cars
|
||
|
bge.logic.globalDict["spawnAtDistance"] = spawnAtDistance
|
||
|
bge.logic.globalDict["maxCars"] = maxCars
|
||
|
|
||
|
|
||
|
def GenerateDoorObject(i):
|
||
|
# Location doesn't matter when you dealing with rotation
|
||
|
doorObject = {"ClosedRotX":i.get("ClosedRotX", i.orientation.to_euler()[0]),
|
||
|
"ClosedRotY":i.get("ClosedRotY", i.orientation.to_euler()[1]),
|
||
|
"ClosedRotZ":i.get("ClosedRotZ", i.orientation.to_euler()[2]),
|
||
|
|
||
|
"OpenRotX":i.get("OpenRotX", i.orientation.to_euler()[0]),
|
||
|
"OpenRotY":i.get("OpenRotY", i.orientation.to_euler()[1]),
|
||
|
"OpenRotZ":i.get("OpenRotZ", i.orientation.to_euler()[2]),
|
||
|
|
||
|
"ClosedLocX":i.get("ClosedLocX", i.position[0]),
|
||
|
"ClosedLocY":i.get("ClosedLocY", i.position[1]),
|
||
|
"ClosedLocZ":i.get("ClosedLocZ", i.position[2]),
|
||
|
|
||
|
"door": i
|
||
|
}
|
||
|
# But rotation and location both matter when you dealing with location
|
||
|
move = [0,0,0]
|
||
|
moveback = [0,0,0]
|
||
|
|
||
|
for naxis, axis in enumerate(["X", "Y", "Z"]):
|
||
|
code = "OpenLoc"+axis
|
||
|
move[naxis] = i.get(code, 0)
|
||
|
moveback[naxis] = -i.get(code, 0)
|
||
|
|
||
|
i.applyMovement(move, True)
|
||
|
for naxis, axis in enumerate(["X", "Y", "Z"]):
|
||
|
code = "OpenLoc"+axis
|
||
|
doorObject[code] = i.position[naxis]
|
||
|
i.applyMovement(moveback, True)
|
||
|
|
||
|
return doorObject
|
||
|
|
||
|
def OpenCloseDoor(door, openClose):
|
||
|
|
||
|
onTarget = []
|
||
|
|
||
|
for n, axis in enumerate(["X", "Y", "Z"]):
|
||
|
|
||
|
targetRot = door[openClose+"Rot"+axis]
|
||
|
targetLoc = door[openClose+"Loc"+axis]
|
||
|
|
||
|
dRot = door["door"].orientation.to_euler()
|
||
|
|
||
|
onRotTarget = round(targetRot, 2) == round(dRot[n], 2)
|
||
|
onLocTraget = round(targetLoc, 1) == round(door["door"].position[n], 1)
|
||
|
|
||
|
if not onRotTarget:
|
||
|
dRot[n] += (targetRot - dRot[n])/15
|
||
|
|
||
|
|
||
|
else:
|
||
|
dRot[n] = targetRot
|
||
|
|
||
|
door["door"].orientation = dRot
|
||
|
|
||
|
if not onLocTraget:
|
||
|
|
||
|
door["door"].position[n] += (targetLoc - door["door"].position[n])/15
|
||
|
|
||
|
|
||
|
else:
|
||
|
door["door"].position[n] = targetLoc
|
||
|
|
||
|
onTarget.append( onRotTarget and onLocTraget )
|
||
|
|
||
|
return all( onTarget )
|
||
|
|
||
|
# INITIALIZING
|
||
|
|
||
|
# This runs only on the first frame
|
||
|
|
||
|
if "spawns" not in bge.logic.globalDict:
|
||
|
bge.logic.globalDict["spawns"] = {} # Spawn points for cars
|
||
|
bge.logic.globalDict["light-spawns"] = {} # Spawn points for destructables ( such as lights )
|
||
|
bge.logic.globalDict["allcars"] = [] # List of all spawned cars
|
||
|
bge.logic.globalDict["spawnedCarModels"] = [] # List of models of cars that were spawned already.
|
||
|
bge.logic.globalDict["all-lights"] = [] # List with all spawned lights
|
||
|
bge.logic.globalDict["sound-ambiances"] = [] # Points generating ambiant sounds
|
||
|
bge.logic.globalDict["elevators"] = {} # Handles Elevators
|
||
|
bge.logic.globalDict["doors"] = {} # Handles Doors
|
||
|
bge.logic.globalDict["trees"] = {"spawned":[],
|
||
|
"cu":1000 } # Handles Trees
|
||
|
|
||
|
# Adding spawn points to the lists
|
||
|
for i in scene.objects:
|
||
|
if "spawn" in i:
|
||
|
|
||
|
|
||
|
lightSpawns = bge.logic.globalDict["light-spawns"]
|
||
|
objectData = {"position": i.worldPosition.copy(),
|
||
|
"orientation": i.worldOrientation.copy(),
|
||
|
"spawn": i.get("spawn"),
|
||
|
"to_spawn": i["to_spawn"],
|
||
|
"race":i.get("race"),
|
||
|
"npc":i.get("npc")}
|
||
|
|
||
|
addr = Opt.Address(objectData["position"], spawnAtDistance)
|
||
|
if addr not in bge.logic.globalDict["spawns"]:
|
||
|
bge.logic.globalDict["spawns"][addr] = []
|
||
|
|
||
|
bge.logic.globalDict["spawns"][addr].append(objectData)
|
||
|
i.endObject()
|
||
|
|
||
|
|
||
|
|
||
|
elif "Elevator" in i:
|
||
|
elevator = {"elevator":i,
|
||
|
"radius":i.get("Radius", 5),
|
||
|
"levels":[],
|
||
|
"doors":{}}
|
||
|
for level in range(10):
|
||
|
if "Level"+str(level) in i:
|
||
|
elevator["levels"].append(i["Level"+str(level)])
|
||
|
|
||
|
|
||
|
for door in scene.objects:
|
||
|
if door.get("ElevatorDoor") == i["Elevator"]:
|
||
|
|
||
|
|
||
|
# Door's motion matrix
|
||
|
doorObject = GenerateDoorObject(door)
|
||
|
elevator["doors"][door["Level"]] = doorObject
|
||
|
|
||
|
bge.logic.globalDict["elevators"][i["Elevator"]] = elevator
|
||
|
|
||
|
elif "Door" in i:
|
||
|
|
||
|
doorObject = GenerateDoorObject(i)
|
||
|
if i["Door"] not in bge.logic.globalDict["doors"]:
|
||
|
bge.logic.globalDict["doors"][i["Door"]] = {"doors":[],
|
||
|
"radius":3}
|
||
|
bge.logic.globalDict["doors"][i["Door"]]["doors"].append(doorObject)
|
||
|
if "Radius" in i:
|
||
|
bge.logic.globalDict["doors"][i["Door"]]["radius"] = i["Radius"]
|
||
|
bge.logic.globalDict["doors"][i["Door"]]["position"] = i.position.copy()
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
elif "LightSpawn" in i:
|
||
|
|
||
|
lightSpawns = bge.logic.globalDict["light-spawns"]
|
||
|
objectData = {"position": i.worldPosition.copy(),
|
||
|
"orientation": i.worldOrientation.copy(),
|
||
|
"movez": i.get("movez", 0),
|
||
|
"to_spawn": i["to_spawn"],
|
||
|
"broken":False,
|
||
|
"spawned_object": i.get("spawned_object"),
|
||
|
"good": i.get("good"),
|
||
|
"LightSpawn": i["LightSpawn"]}
|
||
|
|
||
|
addr = Opt.Address(objectData["position"], spawnAtDistance/2)
|
||
|
if addr not in lightSpawns:
|
||
|
lightSpawns[addr] = []
|
||
|
|
||
|
lightSpawns[addr].append(objectData)
|
||
|
i.endObject()
|
||
|
|
||
|
elif "ambiance-sound" in i:
|
||
|
bge.logic.globalDict["sound-ambiances"].append(i)
|
||
|
|
||
|
|
||
|
######## TREES #######
|
||
|
|
||
|
elif "Tree" in i.name:
|
||
|
tree_object = {"position":i.position.copy(),
|
||
|
"orientation":i.orientation.copy(),
|
||
|
"scaling":i.scaling.copy(),
|
||
|
"tree":"NormalTreeTrunk",
|
||
|
"treelow":"TreeLowres",
|
||
|
"treeverylow":"TreeBillboard",
|
||
|
"to_spawn":True}
|
||
|
i.endObject()
|
||
|
addr = Opt.Address(tree_object["position"], spawnAtDistance)
|
||
|
if addr not in bge.logic.globalDict["trees"]:
|
||
|
bge.logic.globalDict["trees"][addr] = []
|
||
|
bge.logic.globalDict["trees"][addr].append(tree_object)
|
||
|
|
||
|
|
||
|
# Cheat code modes
|
||
|
|
||
|
bge.logic.globalDict["pursuit-cheat"] = False
|
||
|
bge.logic.globalDict["derby-cheat"] = False
|
||
|
bge.logic.globalDict["gravity"] = True
|
||
|
|
||
|
# Making races
|
||
|
|
||
|
bge.logic.globalDict["races"] = {} # Object containing infor about races
|
||
|
|
||
|
# Yes i'm using BPY, shut up!
|
||
|
for collection in bpy.data.collections['Races'].children:
|
||
|
|
||
|
race = {"starters":[],
|
||
|
"checkpoints":[],
|
||
|
"racers":[],
|
||
|
"racer_spawns": [],
|
||
|
"started":False }
|
||
|
|
||
|
for object in collection.objects:
|
||
|
tag = {"location":object.location,
|
||
|
"rotation":object.rotation_euler,
|
||
|
"radius":object.scale[0],
|
||
|
"OnLoop":object.get("OnLoop"),
|
||
|
"Uturn":object.get("Uturn"),
|
||
|
"cylinder":None}
|
||
|
|
||
|
# Race starters ( the blue cylinder )
|
||
|
|
||
|
if object.name.startswith("Starter"):
|
||
|
race["starters"].append(tag)
|
||
|
race["laps"] = object["laps"]
|
||
|
|
||
|
# Race checkpoints ( the yellow cylinder )
|
||
|
|
||
|
else:
|
||
|
race["checkpoints"].append(tag)
|
||
|
|
||
|
bge.logic.globalDict["races"][collection.name] = race
|
||
|
|
||
|
# Precalculating objects for smoothness
|
||
|
preData = {"MetalGate_good":50,
|
||
|
"GatePart":50,
|
||
|
"LightStand": 20,
|
||
|
"NormalTreeTrunk":20,
|
||
|
#"TreeLowres":8,
|
||
|
"TreeBillboard":30,
|
||
|
"House_Shelf":4,
|
||
|
"Moria's Bed":1,
|
||
|
"Moria's Bed.001":1,
|
||
|
"Sparkle": 100,
|
||
|
"Smoke": 20,
|
||
|
"LightStand.Borked.Head": 5,
|
||
|
"LightStand.Borked.Tail": 5,
|
||
|
"GatePart.Level0": 50,
|
||
|
"GatePart.Level1": 50,
|
||
|
"Fire": 200,
|
||
|
"Road Blocker": 12
|
||
|
}
|
||
|
|
||
|
print("Precalculating... ")
|
||
|
for n, object in enumerate(preData):
|
||
|
for i in range( preData[object] ):
|
||
|
Reuse.Create(object, selfDestructFrames = 1, selfDestructInactive = False )
|
||
|
|
||
|
# This is a good idea in theory ( so I'm keeping this code ). But...
|
||
|
# For some reason cars become way faster when I do this. Weird.
|
||
|
|
||
|
# for carModel in NPC_cars:
|
||
|
#
|
||
|
# car = Reuse.Create(carModel, selfDestructFrames = 1 )
|
||
|
# car["underwater"] = False
|
||
|
# rig = car.children[car.get("rig","RIG")]
|
||
|
# body = rig.children["Car_body"]
|
||
|
# body["good"] = body.meshes[0].name
|
||
|
# bge.logic.globalDict["spawnedCarModels"].append(carModel)
|
||
|
|
||
|
|
||
|
# SPAWNING CARS
|
||
|
|
||
|
spawnedCarModels = bge.logic.globalDict["spawnedCarModels"]
|
||
|
spawnedCars = len( bge.logic.globalDict["allcars"] )
|
||
|
|
||
|
SpawnsCloseEnough = []
|
||
|
for i in camSurroundCars:
|
||
|
SpawnsCloseEnough += bge.logic.globalDict["spawns"].get(i, [])
|
||
|
|
||
|
|
||
|
for spawnPoint in SpawnsCloseEnough:
|
||
|
|
||
|
inview = cam.pointInsideFrustum(spawnPoint["position"]) == cam.INSIDE
|
||
|
distance = cam.getDistanceTo(spawnPoint["position"])
|
||
|
|
||
|
# Car information
|
||
|
carModel = spawnPoint["spawn"]
|
||
|
carBehaviour = spawnPoint.get("npc")
|
||
|
carRace = spawnPoint.get("race")
|
||
|
|
||
|
# If this is a road npc, we want to choose a random car model
|
||
|
if carBehaviour == "npc":
|
||
|
|
||
|
carModel = numpy.random.choice(NPC_cars, p=NPC_cars_probability)
|
||
|
toSpawn = spawnPoint["to_spawn"] and inview and spawnAtDistance / 2 < distance < spawnAtDistance and spawnedCars < maxCars
|
||
|
|
||
|
else:
|
||
|
toSpawn = spawnPoint["to_spawn"] and inview and distance < spawnAtDistance
|
||
|
|
||
|
# Trying not to add any more cars than nessesary
|
||
|
if toSpawn and carModel in Reuse.amounts and not Reuse.reuse.get(carModel):
|
||
|
|
||
|
force_add = False
|
||
|
|
||
|
# Making sure that the race still works
|
||
|
if carRace and not dani.get("race"):
|
||
|
for car in bge.logic.globalDict["allcars"]:
|
||
|
if car.name == carModel:
|
||
|
if not car.get("active"):
|
||
|
Reuse.Delete(car, inactive=True)
|
||
|
else:
|
||
|
force_add = True
|
||
|
break
|
||
|
if carRace:
|
||
|
force_add = True
|
||
|
|
||
|
if not force_add:
|
||
|
continue
|
||
|
|
||
|
|
||
|
# Spawning a car
|
||
|
if goodFPS and toSpawn:
|
||
|
|
||
|
# Making car
|
||
|
car, new = Reuse.Create(carModel, declarenew=True)
|
||
|
|
||
|
# If you claimed the car, one more car!
|
||
|
if car["active"]:
|
||
|
car, new = Reuse.Create(carModel, declarenew=True)
|
||
|
|
||
|
car.position = spawnPoint["position"]
|
||
|
car.orientation = spawnPoint["orientation"]
|
||
|
|
||
|
if carBehaviour == "npc":
|
||
|
car.setLinearVelocity([0,-15,0], True)
|
||
|
else:
|
||
|
car["spawnPoint"] = spawnPoint
|
||
|
|
||
|
car["npc"] = carBehaviour
|
||
|
car["enemy"] = ""
|
||
|
car["chased"] = False
|
||
|
car["launchtime"] = 300
|
||
|
|
||
|
if carRace:
|
||
|
|
||
|
car["race"] = carRace
|
||
|
car["racing"] = False
|
||
|
car["checkpoint"] = 0
|
||
|
car["rescue"] = bge.logic.globalDict["races"][carRace]["starters"][0]["location"]
|
||
|
car["lap"] = 0
|
||
|
car["blown"] = False
|
||
|
bge.logic.globalDict["races"][carRace]["racers"].append(car)
|
||
|
bge.logic.globalDict["races"][carRace]["racer_spawns"].append(spawnPoint)
|
||
|
|
||
|
# Cars are deformable during game, so we will need to restore them
|
||
|
rig = car.children[car.get("rig","RIG")]
|
||
|
body = rig.children["Car_body"]
|
||
|
|
||
|
# Doors ( some cars have them falling )
|
||
|
try:
|
||
|
rig.children["Door_Pease.001"].visible = True
|
||
|
rig.children["Door_Pease"].visible = True
|
||
|
except:
|
||
|
pass
|
||
|
|
||
|
# If it's a fresh car
|
||
|
if new:
|
||
|
body["good"] = body.meshes[0].name
|
||
|
|
||
|
# Making sure not to spawn too many cars.
|
||
|
spawnedCarModels.append(carModel)
|
||
|
|
||
|
else:
|
||
|
|
||
|
# Restoring car
|
||
|
body.replaceMesh( body["good"] )
|
||
|
vehicle = bge.constraints.getVehicleConstraint(car["cid"])
|
||
|
|
||
|
# Restoring wheels
|
||
|
for i in range(4):
|
||
|
vehicle.setSuspensionStiffness(car.get("suspension", 200), i)
|
||
|
vehicle.setTyreFriction(car.get("friction", 1), i)
|
||
|
vehicle.setRollInfluence(car.get("roll", 0), i)
|
||
|
bge.logic.globalDict[car["cid"]]["wheels"][i].setVisible(True)
|
||
|
for i in ["Front_Right", "Front_Left", "Back_Left", "Back_Right"]:
|
||
|
car[i] = 1
|
||
|
|
||
|
|
||
|
bge.logic.globalDict["allcars"].append(car)
|
||
|
|
||
|
spawnPoint["to_spawn"] = False
|
||
|
spawnPoint["to_spawn_timer"] = 1000
|
||
|
break
|
||
|
|
||
|
# If player is standing still keep spawning cars near by
|
||
|
if not spawnPoint["to_spawn"] and spawnPoint["to_spawn_timer"]:
|
||
|
spawnPoint["to_spawn_timer"] -= 1
|
||
|
elif not spawnPoint["to_spawn"] and carBehaviour == "npc":
|
||
|
spawnPoint["to_spawn"] = True
|
||
|
|
||
|
|
||
|
# LIGHTS AND OTHER DISTRACTABLES
|
||
|
|
||
|
# Getting all the spawns within a certain distance
|
||
|
SpawnsCloseEnough = []
|
||
|
for i in camSurround:
|
||
|
SpawnsCloseEnough += bge.logic.globalDict["light-spawns"].get(i, [])
|
||
|
|
||
|
# Sorting them by distance
|
||
|
byDistance = []
|
||
|
for n, i in enumerate(SpawnsCloseEnough):
|
||
|
distance = cam.getDistanceTo(i["position"])
|
||
|
byDistance.append([distance, n, i])
|
||
|
byDistance = sorted(byDistance)
|
||
|
|
||
|
# Spawning the objects
|
||
|
for i in byDistance:
|
||
|
distance, n, i = i
|
||
|
|
||
|
inmemory = Reuse.reuse.get(i["LightSpawn"])
|
||
|
inview = cam.pointInsideFrustum(i["position"]) == cam.INSIDE
|
||
|
if goodFPS and inview and inmemory and i["to_spawn"] and not i["broken"]:
|
||
|
obj = Reuse.Create(i["LightSpawn"])
|
||
|
obj.suspendDynamics(True)
|
||
|
obj.position = i["position"]
|
||
|
obj.position[2] += obj.get("movez", 0)
|
||
|
obj.orientation = i["orientation"]
|
||
|
obj["spawned_by"] = i
|
||
|
obj["despawn_damping"] = random.randint(100,200)
|
||
|
|
||
|
bge.logic.globalDict["all-lights"].append(obj)
|
||
|
|
||
|
if obj.get("good"):
|
||
|
obj.replaceMesh(obj["good"])
|
||
|
|
||
|
i["to_spawn"] = False
|
||
|
|
||
|
|
||
|
# Deleting them when they are far away
|
||
|
for obj in bge.logic.globalDict["all-lights"]:
|
||
|
|
||
|
objAddress = Opt.Address(obj.position, spawnAtDistance/2)
|
||
|
inview = obj.getDistanceTo(cam) < 20 or cam.pointInsideFrustum(obj.position) == cam.INSIDE
|
||
|
|
||
|
if objAddress not in camSurround or not inview:
|
||
|
|
||
|
if not obj in Reuse.reuse.get(obj.name, []):
|
||
|
Reuse.Delete(obj)
|
||
|
|
||
|
obj["spawned_by"]["to_spawn"] = True
|
||
|
bge.logic.globalDict["all-lights"].remove(obj)
|
||
|
break
|
||
|
|
||
|
# Fixing broken ones when out of frame
|
||
|
lookingAt = random.choice(list(bge.logic.globalDict["light-spawns"].keys()))
|
||
|
if lookingAt not in camSurround:
|
||
|
listOfLights = bge.logic.globalDict["light-spawns"][lookingAt]
|
||
|
theLightToFix = random.choice(listOfLights)
|
||
|
if theLightToFix.get("broken"):
|
||
|
theLightToFix["broken"] = False
|
||
|
print("Fixed", theLightToFix["LightSpawn"], "at:", lookingAt)
|
||
|
|
||
|
|
||
|
##### TREES ######
|
||
|
|
||
|
# Making two pulls of points.
|
||
|
# One for where to spawn Trees.
|
||
|
# Other for where to take trees from.
|
||
|
|
||
|
# Where to put trees
|
||
|
trees = bge.logic.globalDict["trees"]
|
||
|
PutTreesAt = []
|
||
|
n = 0
|
||
|
for addr in camSurroundCars:
|
||
|
for spawnPoint in bge.logic.globalDict["trees"].get(addr, []):
|
||
|
n += 1
|
||
|
distance = cam.getDistanceTo(spawnPoint["position"])
|
||
|
PutTreesAt.append([distance, n, spawnPoint])
|
||
|
PutTreesAt = sorted(PutTreesAt)
|
||
|
|
||
|
# Where to take trees
|
||
|
GetTreesFrom = []
|
||
|
for n, tree in enumerate(bge.logic.globalDict["trees"]["spawned"]):
|
||
|
distance = cam.getDistanceTo(tree)
|
||
|
GetTreesFrom.append([distance, n, tree])
|
||
|
GetTreesFrom = reversed(sorted(GetTreesFrom))
|
||
|
|
||
|
# Lets actually populate the trees
|
||
|
for spawnPoint in PutTreesAt:
|
||
|
|
||
|
distance, n, spawnPoint = spawnPoint
|
||
|
|
||
|
if not spawnPoint["to_spawn"]:
|
||
|
continue
|
||
|
inview = cam.pointInsideFrustum(spawnPoint["position"]) == cam.INSIDE
|
||
|
|
||
|
tree = None
|
||
|
|
||
|
if goodFPS and inview and Reuse.reuse.get(spawnPoint["treeverylow"]):
|
||
|
tree = Reuse.Create(spawnPoint["treeverylow"])
|
||
|
tree.position = spawnPoint["position"]
|
||
|
tree.orientation = spawnPoint["orientation"]
|
||
|
tree.scaling = spawnPoint["scaling"] / 1.603
|
||
|
|
||
|
spawnPoint["to_spawn"] = False
|
||
|
tree["spawned_by"] = spawnPoint
|
||
|
tree["lod"] = 0
|
||
|
bge.logic.globalDict["trees"]["spawned"].append(tree)
|
||
|
break
|
||
|
|
||
|
elif goodFPS and inview:
|
||
|
for tree in GetTreesFrom:
|
||
|
treeDistance, treeN, tree = tree
|
||
|
treeInview = cam.pointInsideFrustum(tree.position) == cam.INSIDE or treeDistance > 100
|
||
|
if ( treeDistance > distance or not treeInview ) and tree["spawned_by"]["treeverylow"] == spawnPoint["treeverylow"]:
|
||
|
|
||
|
|
||
|
bge.logic.globalDict["trees"]["spawned"].remove(tree)
|
||
|
tree["spawned_by"]["to_spawn"] = True
|
||
|
Reuse.Delete(tree, inactive=True)
|
||
|
tree = None
|
||
|
break
|
||
|
|
||
|
# And low let's implement the lod system for trees.
|
||
|
|
||
|
for tree in GetTreesFrom:
|
||
|
treeDistance, treeN, tree = tree
|
||
|
|
||
|
inview = cam.pointInsideFrustum(tree.position) == cam.INSIDE
|
||
|
newtree = None
|
||
|
|
||
|
# Hires
|
||
|
if goodFPS and treeDistance <= 50 and Reuse.reuse.get(tree["spawned_by"]["tree"]) and not tree["lod"] == 2 and inview:
|
||
|
newtree = Reuse.Create(tree["spawned_by"]["tree"])
|
||
|
newtree["lod"] = 2
|
||
|
|
||
|
# Lowres
|
||
|
elif goodFPS and treeDistance > 50 and Reuse.reuse.get(tree["spawned_by"]["treeverylow"]) and not tree["lod"] == 0:
|
||
|
newtree = Reuse.Create(tree["spawned_by"]["treeverylow"])
|
||
|
newtree["lod"] = 2
|
||
|
|
||
|
if goodFPS and newtree:
|
||
|
|
||
|
newtree.position = tree.position
|
||
|
newtree.orientation = tree.orientation
|
||
|
newtree.scaling = tree.scaling
|
||
|
newtree["spawned_by"] = tree["spawned_by"]
|
||
|
#trees["keep"] = random.randint(0,20)
|
||
|
|
||
|
Reuse.Delete(tree)
|
||
|
bge.logic.globalDict["trees"]["spawned"].append(newtree)
|
||
|
bge.logic.globalDict["trees"]["spawned"].remove(tree)
|
||
|
break
|
||
|
|
||
|
#SpawnsCloseEnough = []
|
||
|
#for i in camSurroundCars:
|
||
|
# SpawnsCloseEnough += bge.logic.globalDict["trees"].get(i, [])
|
||
|
#
|
||
|
#byDistance = []
|
||
|
#for n, i in enumerate(SpawnsCloseEnough):
|
||
|
# distance = cam.getDistanceTo(i["position"])
|
||
|
# byDistance.append([distance, n, i])
|
||
|
#byDistance = sorted(byDistance)
|
||
|
|
||
|
#bge.logic.globalDict["trees"]["cu"] = byDistance[-1][0]
|
||
|
|
||
|
#for i in byDistance:
|
||
|
#
|
||
|
# distance, n, i = i
|
||
|
|
||
|
# #addr = Opt.Address(i["position"], spawnAtDistance)
|
||
|
# inmemory = Reuse.reuse.get(i["treeverylow"])
|
||
|
#
|
||
|
# inview = True#cam.pointInsideFrustum(i["position"]) == cam.INSIDE
|
||
|
# tree = None
|
||
|
#
|
||
|
# if inmemory and inview and i["to_spawn"]:
|
||
|
#
|
||
|
## if i.get("keep"):
|
||
|
## i["keep"] -= 1
|
||
|
## continue
|
||
|
#
|
||
|
# tree = Reuse.Create(i["treeverylow"])
|
||
|
#
|
||
|
# tree.position = i["position"]
|
||
|
# tree.orientation = i["orientation"]
|
||
|
# tree.scaling = i["scaling"] / 1.603
|
||
|
#
|
||
|
# i["to_spawn"] = False
|
||
|
#
|
||
|
# tree["spawned_by"] = i
|
||
|
# tree["lod"] = 0
|
||
|
# tree["keep"] = 20
|
||
|
#
|
||
|
# bge.logic.globalDict["trees"]["spawned"].append(tree)
|
||
|
#
|
||
|
# elif not inmemory and distance < bge.logic.globalDict["trees"]["cu"]:
|
||
|
# bge.logic.globalDict["trees"]["cu"] = distance
|
||
|
|
||
|
#byDistance = []
|
||
|
#for n, tree in enumerate(bge.logic.globalDict["trees"]["spawned"]):
|
||
|
#
|
||
|
# distance = cam.getDistanceTo(tree.position)
|
||
|
# byDistance.append([distance, n, tree])
|
||
|
|
||
|
#byDistance = sorted(byDistance)
|
||
|
|
||
|
#for tree in reversed(byDistance):
|
||
|
#
|
||
|
#
|
||
|
# distance, n, tree = tree
|
||
|
#
|
||
|
# addr = Opt.Address(tree.position, spawnAtDistance)
|
||
|
# inview = addr in camSurroundCars# and cam.pointInsideFrustum(i["position"]) == cam.INSIDE
|
||
|
#
|
||
|
# if not inview or distance > bge.logic.globalDict["trees"]["cu"]:
|
||
|
#
|
||
|
# if tree["keep"]:
|
||
|
# tree["keep"] -= 1
|
||
|
# continue
|
||
|
#
|
||
|
# bge.logic.globalDict["trees"]["spawned"].remove(tree)
|
||
|
# Reuse.Delete(tree, inactive=True)
|
||
|
# tree["spawned_by"]["to_spawn"] = True
|
||
|
# tree["spawned_by"]["keep"] = 20
|
||
|
# break
|
||
|
#
|
||
|
#for tree in byDistance:
|
||
|
#
|
||
|
# distance, n, tree = tree
|
||
|
# inview = cam.pointInsideFrustum(i["position"]) == cam.INSIDE
|
||
|
#
|
||
|
# if inview:
|
||
|
#
|
||
|
# tree["keep"] = 20
|
||
|
#
|
||
|
# newtree = None
|
||
|
#
|
||
|
# if distance <= 70 and Reuse.reuse.get(tree["spawned_by"]["tree"]) and tree["lod"] != 2:
|
||
|
#
|
||
|
# newtree = Reuse.Create(tree["spawned_by"]["tree"])
|
||
|
# newtree["lod"] = 2
|
||
|
#
|
||
|
#
|
||
|
# elif distance > 70 and Reuse.reuse.get(tree["spawned_by"]["treeverylow"]) and tree["lod"] != 0:
|
||
|
#
|
||
|
# newtree = Reuse.Create(tree["spawned_by"]["treeverylow"])
|
||
|
# newtree["lod"] = 0
|
||
|
#
|
||
|
#
|
||
|
# if newtree:
|
||
|
#
|
||
|
# newtree.position = tree.position
|
||
|
# newtree.orientation = tree.orientation
|
||
|
# newtree.scaling = tree.scaling
|
||
|
# newtree["spawned_by"] = tree["spawned_by"]
|
||
|
# newtree["keep"] = 20
|
||
|
#
|
||
|
# Reuse.Delete(tree)
|
||
|
# bge.logic.globalDict["trees"]["spawned"].append(newtree)
|
||
|
# bge.logic.globalDict["trees"]["spawned"].remove(tree)
|
||
|
# break
|
||
|
#
|
||
|
|
||
|
|
||
|
# ELEVATORS
|
||
|
|
||
|
# Seeing on what level dani is.
|
||
|
def atLevel(object):
|
||
|
levelis = 0
|
||
|
closest = 1000
|
||
|
for n, i in enumerate(elevator["levels"]):
|
||
|
dist = object.position[2] - i
|
||
|
if dist < 0: dist *= -1
|
||
|
|
||
|
if dist < closest:
|
||
|
closest = dist
|
||
|
levelis = n
|
||
|
return levelis
|
||
|
|
||
|
for elevatorname in bge.logic.globalDict["elevators"]:
|
||
|
|
||
|
elevator = bge.logic.globalDict["elevators"][elevatorname]
|
||
|
|
||
|
# Seeing if Dani is anywhere near an elevator
|
||
|
eloc = elevator["elevator"].position.copy()
|
||
|
eloc[2] = dani.position[2]
|
||
|
|
||
|
if dani.getDistanceTo(eloc) < elevator["radius"]:
|
||
|
|
||
|
|
||
|
|
||
|
# If dani not at the same level as the elevator
|
||
|
if atLevel(dani) != atLevel(elevator["elevator"]):
|
||
|
bge.logic.globalDict["print"] = "Press E to call Elevator."
|
||
|
|
||
|
# Pressing E to call it
|
||
|
if 27 in bge.logic.globalDict["keys"]:
|
||
|
elevator["going_to"] = atLevel(dani)
|
||
|
elevator["closing_doors"] = True
|
||
|
|
||
|
else:
|
||
|
bge.logic.globalDict["print"] = "Press 0-"+str(len(elevator["levels"])-1)+" activate the elevator."
|
||
|
|
||
|
numbers = [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]
|
||
|
for num in numbers:
|
||
|
if num in bge.logic.globalDict["keys"] and numbers.index(num) < len(elevator["levels"]):
|
||
|
elevator["going_to"] = numbers.index(num)
|
||
|
elevator["closing_doors"] = True
|
||
|
|
||
|
# Elevator coming
|
||
|
if elevator.get("going_to") != None and not elevator.get("closing_doors"):
|
||
|
destination = elevator["levels"][elevator["going_to"]]
|
||
|
position = elevator["elevator"].position[2]
|
||
|
|
||
|
if destination < position:
|
||
|
elevator["elevator"].position[2] -= 0.1
|
||
|
else:
|
||
|
elevator["elevator"].position[2] += 0.1
|
||
|
|
||
|
if round(destination, 1) == round(position, 1):
|
||
|
elevator["going_to"] = None
|
||
|
elevator["closing_doors"] = True
|
||
|
|
||
|
# Doors
|
||
|
if elevator.get("closing_doors"):
|
||
|
|
||
|
cancelBucket = []
|
||
|
|
||
|
# If elevator is moving, all doors should be closed.
|
||
|
if elevator.get("going_to") != None:
|
||
|
openLevel = -1
|
||
|
else:
|
||
|
openLevel = atLevel(elevator["elevator"])
|
||
|
|
||
|
for level in elevator["doors"]:
|
||
|
|
||
|
door = elevator["doors"][level]
|
||
|
|
||
|
# The elevator is at the current door's level,
|
||
|
# the door should be open.
|
||
|
if level == openLevel:
|
||
|
openClose = "Open"
|
||
|
else:
|
||
|
openClose = "Closed"
|
||
|
|
||
|
onTarget = OpenCloseDoor(door, openClose)
|
||
|
|
||
|
cancelBucket.append(onTarget)
|
||
|
|
||
|
if all(cancelBucket):
|
||
|
elevator["closing_doors"] = False
|
||
|
|
||
|
# DOOR ( in general )
|
||
|
|
||
|
for doorname in bge.logic.globalDict["doors"]:
|
||
|
|
||
|
doors = bge.logic.globalDict["doors"][doorname]
|
||
|
|
||
|
if doors.get("doOpenClose"):
|
||
|
cancelBucket = []
|
||
|
for door in doors["doors"]:
|
||
|
onTarget = OpenCloseDoor(door, doors["OpenClosed"])
|
||
|
cancelBucket.append(onTarget)
|
||
|
if all(cancelBucket):
|
||
|
doors["doOpenClose"] = False
|
||
|
|
||
|
else:
|
||
|
|
||
|
|
||
|
|
||
|
if doors.get("OpenClosed", "Closed") == "Closed" and dani.getDistanceTo(doors["position"]) < doors["radius"]:
|
||
|
|
||
|
doors["OpenClosed"] = "Open"
|
||
|
doors["doOpenClose"] = True
|
||
|
|
||
|
elif doors.get("OpenClosed") == "Open" and dani.getDistanceTo(doors["position"]) > doors["radius"]:
|
||
|
|
||
|
doors["OpenClosed"] = "Closed"
|
||
|
doors["doOpenClose"] = True
|
||
|
|
||
|
# Sound
|
||
|
if doors.get("doOpenClose"):
|
||
|
|
||
|
device = bge.logic.globalDict["SoundDevice"]
|
||
|
|
||
|
for n, door in enumerate(doors["doors"]):
|
||
|
|
||
|
s = "//sfx/home_door.ogg"
|
||
|
code = str(n)+s
|
||
|
if code not in bge.logic.globalDict["sounds"]:
|
||
|
bge.logic.globalDict["sounds"][code] = {"sound":aud.Sound(bge.logic.expandPath(s)),
|
||
|
"play":None}
|
||
|
|
||
|
sound = bge.logic.globalDict["sounds"][code]
|
||
|
sound["play"] = device.play(sound["sound"])
|
||
|
sound["play"].location = door["door"].position
|
||
|
sound["play"].velocity = door["door"].getLinearVelocity()
|
||
|
sound["play"].relative = False
|
||
|
sound["play"].distance_maximum = 100
|
||
|
sound["play"].distance_reference = 1
|
||
|
sound["play"].attenuation = 1
|
||
|
sound["play"].pitch = random.uniform(1, 2)
|
||
|
sound["play"].volume = 0.3
|
||
|
|
||
|
|
||
|
# WHEEL UP DOWN
|
||
|
|
||
|
cam_parent = scene.objects["DaniCam_Parent"]
|
||
|
|
||
|
wheelup = cont.sensors["wheel_up"]
|
||
|
wheeldown = cont.sensors["wheel_down"]
|
||
|
if wheelup.status:
|
||
|
cam_parent.scaling /= 1.1
|
||
|
elif wheeldown.status and cam_parent.scaling[0] < 20:
|
||
|
cam_parent.scaling *= 1.1
|
||
|
|
||
|
# CHEAT CODES
|
||
|
|
||
|
cheat_spawn = scene.objects["Dani_Cheater"]
|
||
|
keys = cheat_spawn.sensors["Keyboard"]
|
||
|
bge.logic.globalDict["keys"] = []
|
||
|
for key in keys.events:
|
||
|
bge.logic.globalDict["keys"].append(key[0])
|
||
|
|
||
|
if keys.events:
|
||
|
|
||
|
#print("Key pressed code:",keys.events)
|
||
|
|
||
|
if "cheat" not in bge.logic.globalDict:
|
||
|
bge.logic.globalDict["cheat"] = [0]
|
||
|
|
||
|
for i in keys.events:
|
||
|
if i[0] != bge.logic.globalDict["cheat"][-1]:
|
||
|
bge.logic.globalDict["cheat"].append(i[0])
|
||
|
|
||
|
# SPAWN CHEATS
|
||
|
|
||
|
cheats = {
|
||
|
"NeonSpeedsterBox":[36, 27, 37, 36, 41, 38, 27, 26, 41, 42, 27, 40],
|
||
|
"RedKissBox":[40, 27, 26, 33, 31, 41],
|
||
|
"DarkShadowBox":[26, 23, 40, 33, 41, 30, 23, 26, 37, 45]
|
||
|
}
|
||
|
|
||
|
for i in cheats:
|
||
|
code = bge.logic.globalDict["cheat"][-(len(cheats[i])):]
|
||
|
|
||
|
if code == cheats[i]:
|
||
|
print("Spawning:", i)
|
||
|
|
||
|
car = Reuse.Create(i)
|
||
|
car["npc"] = ""
|
||
|
car["race"] = ""
|
||
|
bge.logic.globalDict["allcars"].append(car)
|
||
|
car.position = cheat_spawn.position
|
||
|
car.orientation = cheat_spawn.orientation
|
||
|
car["underwater"] = False
|
||
|
rig = car.children[car.get("rig","RIG")]
|
||
|
body = rig.children["Car_body"]
|
||
|
body["good"] = body.meshes[0].name
|
||
|
bge.logic.globalDict["spawnedCarModels"].append(i)
|
||
|
|
||
|
bge.logic.globalDict["cheat"] = [0]
|
||
|
|
||
|
|
||
|
bge.logic.globalDict["print"] = "A Vehicle Is Waiting For You, Sir."
|
||
|
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"]) # Play a Ding
|
||
|
|
||
|
teleportations = [
|
||
|
[[-17.86, 899.2, 4.738], [40,23,25,27,42,40,23,25,33]], # Racetrack
|
||
|
[[-752.78, -937.4, 411.08], [30, 37, 43, 41, 27]], # House
|
||
|
[[-937.3, -277.1, 257.7], [35, 23, 36, 41, 31, 37, 36]],# Mansion
|
||
|
[[-2.122, 1322, 99.85],[42, 37, 45, 27, 40, 13]], # Tower0
|
||
|
[[-172.4, 1147, 99.68],[42, 37, 45, 27, 40, 14]], # Tower1
|
||
|
[[200, 1204, 100],[42, 37, 45, 27, 40, 15]], # Tower2
|
||
|
[[12.19, 1127, 139.3],[42, 37, 45, 27, 40, 16]], # Tower3
|
||
|
[[148.4, 941.7, 98.83],[42, 37, 45, 27, 40, 17]], # Tower4
|
||
|
[[-725, -984.6, 409.2],[25, 31, 36, 27, 35, 23]] # Cinema
|
||
|
]
|
||
|
|
||
|
for i in teleportations:
|
||
|
code = bge.logic.globalDict["cheat"][-(len(i[1])):]
|
||
|
|
||
|
if code == i[1]:
|
||
|
dani.position = i[0]
|
||
|
bge.logic.globalDict["cheat"] = [0]
|
||
|
|
||
|
bge.logic.globalDict["print"] = "Teleportation Finished, Sir."
|
||
|
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"]) # Play a Ding
|
||
|
|
||
|
# Puruit code
|
||
|
code = bge.logic.globalDict["cheat"][-(len("pursuit")):]
|
||
|
if code == [38, 43, 40, 41, 43, 31, 42]:
|
||
|
bge.logic.globalDict["pursuit-cheat"] = not bge.logic.globalDict["pursuit-cheat"]
|
||
|
bge.logic.globalDict["cheat"] = [0]
|
||
|
|
||
|
if bge.logic.globalDict["pursuit-cheat"]:
|
||
|
bge.logic.globalDict["print"] = "Everybody Hates You, Sir. At Your Request, Sir."
|
||
|
else:
|
||
|
bge.logic.globalDict["print"] = "Everybody Stopped Hating You, Sir."
|
||
|
|
||
|
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"]) # Play a Ding
|
||
|
|
||
|
# Derby code
|
||
|
code = bge.logic.globalDict["cheat"][-(len("derby")):]
|
||
|
if code == [26, 27, 40, 24, 47]:
|
||
|
bge.logic.globalDict["derby-cheat"] = not bge.logic.globalDict["derby-cheat"]
|
||
|
bge.logic.globalDict["cheat"] = [0]
|
||
|
|
||
|
if bge.logic.globalDict["derby-cheat"]:
|
||
|
bge.logic.globalDict["print"] = "Everybody Is Crazy, Sir."
|
||
|
else:
|
||
|
bge.logic.globalDict["print"] = "Everybody Stopped Being Crazy, Sir."
|
||
|
|
||
|
|
||
|
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"]) # Play a Ding
|
||
|
|
||
|
|
||
|
|
||
|
# Gravity code
|
||
|
code = bge.logic.globalDict["cheat"][-(len("gravity")):]
|
||
|
if code == [29, 40, 23, 44, 31, 42, 47]:
|
||
|
bge.logic.globalDict["gravity"] = not bge.logic.globalDict["gravity"]
|
||
|
if bge.logic.globalDict["gravity"]:
|
||
|
bge.constraints.setGravity(0, 0, -9.8)
|
||
|
else:
|
||
|
bge.constraints.setGravity(0, 0, 0)
|
||
|
|
||
|
bge.logic.globalDict["cheat"] = [0]
|
||
|
|
||
|
if bge.logic.globalDict["gravity"]:
|
||
|
bge.logic.globalDict["print"] = "We're Back To Earth, Sir."
|
||
|
else:
|
||
|
bge.logic.globalDict["print"] = "We're Up In Space, Sir."
|
||
|
|
||
|
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"]) # Play a Ding
|
||
|
|
||
|
# Explosion code
|
||
|
code = bge.logic.globalDict["cheat"][-(len("bom")):]
|
||
|
if code == [24,37,35]:
|
||
|
expos = cheat_spawn.position.copy()
|
||
|
expos[2] = dani.position[2]
|
||
|
Distraction.Explosion(expos, mass=1, size=2)
|
||
|
|
||
|
bge.logic.globalDict["print"] = "Boom! , Sir."
|
||
|
bge.logic.globalDict["cheat"] = [0]
|
||
|
|
||
|
# no ding here, the boom is enough
|
||
|
|
||
|
# RACES
|
||
|
for racename in bge.logic.globalDict["races"]:
|
||
|
race = bge.logic.globalDict["races"][racename]
|
||
|
|
||
|
pointer = scene.objects["PointingArrow"]
|
||
|
posindicator = scene.objects["Dani_Pos_Indicator"]
|
||
|
timeindicator = scene.objects["Dani_Time_Indicator"]
|
||
|
lapindicator = scene.objects["Dani_Lap_Indicator"]
|
||
|
|
||
|
if not race["started"] and not dani.get("race") and race["racers"]:
|
||
|
|
||
|
for starter in race["starters"]:
|
||
|
|
||
|
if not starter["cylinder"] and dani.getDistanceTo(starter["location"]) < spawnAtDistance:
|
||
|
starter["cylinder"] = Reuse.Create("Starter.Cylinder")
|
||
|
starter["cylinder"].position = starter["location"]
|
||
|
starter["cylinder"].orientation = starter["rotation"]
|
||
|
starter["cylinder"].scaling[0] = starter["radius"]
|
||
|
starter["cylinder"].scaling[1] = starter["radius"]
|
||
|
|
||
|
if dani.getDistanceTo(starter["location"]) < starter["radius"]:
|
||
|
if dani["driving"]:
|
||
|
bge.logic.globalDict["print"] = "Press R to start the race."
|
||
|
|
||
|
if keys.events and 40 in keys.events[0]:
|
||
|
|
||
|
race["started"] = True
|
||
|
Reuse.Delete(starter["cylinder"])
|
||
|
starter["cylinder"] = None
|
||
|
|
||
|
race["start-time"] = bge.logic.getRealTime()
|
||
|
|
||
|
for racer in race["racers"]:
|
||
|
racer["racing"] = True
|
||
|
racer["launchtime"] = 100
|
||
|
|
||
|
# Testing
|
||
|
racer["npc"] = "racer"
|
||
|
#racer["active"] = False
|
||
|
|
||
|
# Beam of energy
|
||
|
racer["beam"] = scene.addObject("Racer.Indicator", "Racer.Indicator")
|
||
|
|
||
|
dani["race"] = racename
|
||
|
dani["checkpoint"] = 0
|
||
|
dani["lap"] = 0
|
||
|
|
||
|
|
||
|
posindicator.visible = True
|
||
|
pointer.visible = True
|
||
|
timeindicator.visible = True
|
||
|
lapindicator.visible = True
|
||
|
|
||
|
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"]) # Play a Ding
|
||
|
|
||
|
else:
|
||
|
bge.logic.globalDict["print"] = "Come here with a car to race."
|
||
|
|
||
|
|
||
|
# If this race is going
|
||
|
elif dani.get("race") == racename:
|
||
|
nextcheck = race["checkpoints"][dani["checkpoint"]]
|
||
|
|
||
|
# Alight the arrow to the checkpoint
|
||
|
tocheck = pointer.getVectTo(nextcheck["location"])
|
||
|
pointer.alignAxisToVect(tocheck[1], 1, 0.1)
|
||
|
|
||
|
# Alighn the arrow to the next checkpoint if close enough to it.
|
||
|
if cam.pointInsideFrustum(nextcheck["location"]) == cam.INSIDE:
|
||
|
nextcheckpoint = race["checkpoints"][ ( dani.get("checkpoint") + 1 ) % len(race["checkpoints"]) ]
|
||
|
tonextcheck = pointer.getVectTo(nextcheckpoint["location"])
|
||
|
pointer.alignAxisToVect(tonextcheck[1], 1, min(1, max(0, 1-(tocheck[0]/500))) ** 5 )
|
||
|
|
||
|
# Align the arrow vertically
|
||
|
pointer.alignAxisToVect( (0,0,1), 2, 1.0 )
|
||
|
|
||
|
# Time of the race
|
||
|
currentRaceTime = bge.logic.getRealTime() - race["start-time"]
|
||
|
formattedTime = str(datetime.timedelta(seconds=currentRaceTime))[:-4]
|
||
|
while formattedTime.startswith("0") or formattedTime.startswith(":"):
|
||
|
formattedTime = formattedTime[1:]
|
||
|
if formattedTime.startswith("."):
|
||
|
formattedTime = "0"+formattedTime
|
||
|
|
||
|
timeindicator["Text"] = formattedTime
|
||
|
lapindicator["Text"] = str(dani["lap"]+1)+"/"+str(race["laps"])
|
||
|
|
||
|
if not nextcheck["cylinder"] and dani.getDistanceTo(nextcheck["location"]) < spawnAtDistance:
|
||
|
nextcheck["cylinder"] = Reuse.Create("Tag.Cylinder")
|
||
|
nextcheck["cylinder"].position = nextcheck["location"]
|
||
|
nextcheck["cylinder"].orientation = nextcheck["rotation"]
|
||
|
nextcheck["cylinder"].scaling[0] = nextcheck["radius"] * 0.8
|
||
|
nextcheck["cylinder"].scaling[1] = nextcheck["radius"] * 0.8
|
||
|
|
||
|
if dani.getDistanceTo(nextcheck["location"]) < nextcheck["radius"]:
|
||
|
|
||
|
if not nextcheck.get("OnLoop"):
|
||
|
dani["prevrescue"] = dani.get("rescue")
|
||
|
dani["rescue"] = nextcheck["location"]
|
||
|
dani["rescueTo"] = dani["checkpoint"]
|
||
|
|
||
|
Reuse.Delete(nextcheck["cylinder"])
|
||
|
nextcheck["cylinder"] = None
|
||
|
|
||
|
dani["checkpoint"] += 1
|
||
|
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["checkpoint"]["sound"]) # Play a Ding
|
||
|
|
||
|
if dani["checkpoint"] == len(race["checkpoints"]):
|
||
|
dani["checkpoint"] = 0
|
||
|
dani["lap"] += 1
|
||
|
|
||
|
# If finished race
|
||
|
if dani["lap"] == race["laps"]:# or not dani["driving"]:
|
||
|
dani["race"] = None
|
||
|
race["started"] = False
|
||
|
|
||
|
posindicator.visible = False
|
||
|
timeindicator.visible = False
|
||
|
pointer.visible = False
|
||
|
lapindicator.visible = False
|
||
|
|
||
|
|
||
|
race["racer_spawns"] = []
|
||
|
|
||
|
for racer in race["racers"]:
|
||
|
racer["npc"] = "npc"
|
||
|
racer["beam"].endObject()
|
||
|
|
||
|
race["racers"] = []
|
||
|
|
||
|
if nextcheck["cylinder"]:
|
||
|
Reuse.Delete(nextcheck["cylinder"])
|
||
|
nextcheck["cylinder"] = None
|
||
|
|
||
|
# If won
|
||
|
if race["positions"].index(dani) == 0:
|
||
|
bge.logic.globalDict["print"] = "You've Won This Race! Time: "+formattedTime
|
||
|
# If finished
|
||
|
else:
|
||
|
bge.logic.globalDict["print"] = "You finished number "+str(race["positions"].index(dani)+1) + " Time: "+formattedTime
|
||
|
|
||
|
|
||
|
positions = []
|
||
|
for racer in race["racers"]:
|
||
|
racer["into_race"] = [race["laps"] - racer["lap"], len(race["checkpoints"]) - racer["checkpoint"], racer.getDistanceTo(race["checkpoints"][racer["checkpoint"]]["location"])]
|
||
|
positions.append([racer["into_race"], racer])
|
||
|
|
||
|
dani["into_race"] = [race["laps"] - dani["lap"], len(race["checkpoints"]) - dani["checkpoint"], dani.getDistanceTo(race["checkpoints"][dani["checkpoint"]]["location"])]
|
||
|
positions.append([dani["into_race"], dani])
|
||
|
|
||
|
positions = sorted(positions)
|
||
|
race["positions"] = []
|
||
|
for position, racer in positions:
|
||
|
race["positions"].append(racer)
|
||
|
|
||
|
posindicator["Text"] = str(race["positions"].index(dani)+1)
|
||
|
|
||
|
|
||
|
|
||
|
# Messages
|
||
|
|
||
|
if bge.logic.globalDict.get("print") and bge.logic.globalDict.get("last_print") != bge.logic.globalDict["print"]:
|
||
|
print("Message:", bge.logic.globalDict["print"])
|
||
|
scene.objects["Messages"]["Text"] = str(bge.logic.globalDict.get("print"))
|
||
|
scene.objects["Messages"].playAction("MessagesAction", 0, 100)
|
||
|
bge.logic.globalDict["last_print"] = bge.logic.globalDict["print"]
|
||
|
bge.logic.globalDict["print"] = ""
|
||
|
|
||
|
|
||
|
# SOUND
|
||
|
|
||
|
#print(dir(aud))
|
||
|
|
||
|
if "SoundDevice" not in bge.logic.globalDict:
|
||
|
bge.logic.globalDict["SoundDevice"] = aud.Device()
|
||
|
bge.logic.globalDict["SoundDevice"].distance_model = aud.DISTANCE_MODEL_INVERSE_CLAMPED
|
||
|
bge.logic.globalDict["sounds"] = {}
|
||
|
|
||
|
bge.logic.globalDict["sounds"]["active"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/active.ogg")),
|
||
|
"play":None}
|
||
|
|
||
|
# Angry pursuit sounds
|
||
|
|
||
|
bge.logic.globalDict["sounds_angry_start"] = []
|
||
|
|
||
|
for i in range(8):
|
||
|
i += 1
|
||
|
i = str(i)
|
||
|
if len(i) < 2:
|
||
|
i = "0"+i
|
||
|
i = "//sfx/voices/angry_pursuit/start_"+i+".ogg"
|
||
|
bge.logic.globalDict["sounds"][i] = {"sound":aud.Sound(bge.logic.expandPath(i)),
|
||
|
"play":None}
|
||
|
bge.logic.globalDict["sounds_angry_start"].append(i)
|
||
|
|
||
|
|
||
|
bge.logic.globalDict["sounds_angry_hit"] = []
|
||
|
|
||
|
for i in range(5):
|
||
|
i += 1
|
||
|
i = str(i)
|
||
|
if len(i) < 2:
|
||
|
i = "0"+i
|
||
|
i = "//sfx/voices/angry_pursuit/hit_"+i+".ogg"
|
||
|
bge.logic.globalDict["sounds"][i] = {"sound":aud.Sound(bge.logic.expandPath(i)),
|
||
|
"play":None}
|
||
|
bge.logic.globalDict["sounds_angry_hit"].append(i)
|
||
|
|
||
|
# Dani voices
|
||
|
|
||
|
bge.logic.globalDict["sounds"]["dani_yelling"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/voices/dani/yelling.ogg")),
|
||
|
"play":None}
|
||
|
bge.logic.globalDict["sounds"]["dani_entering"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/voices/dani/entering.ogg")),
|
||
|
"play":None}
|
||
|
bge.logic.globalDict["sounds"]["dani_ohno"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/voices/dani/ohno.ogg")),
|
||
|
"play":None}
|
||
|
bge.logic.globalDict["sounds"]["dani_ohnoindeed"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/voices/dani/ohnoindeed.ogg")),
|
||
|
"play":None}
|
||
|
bge.logic.globalDict["sounds"]["dani_wearesinking"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/voices/dani/wearesinking.ogg")),
|
||
|
"play":None}
|
||
|
bge.logic.globalDict["sounds"]["dani_ohgod"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/voices/dani/ohgod.ogg")),
|
||
|
"play":None}
|
||
|
|
||
|
|
||
|
# Car Sounds
|
||
|
|
||
|
bge.logic.globalDict["sounds"]["door"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/door.ogg")),
|
||
|
"play":None}
|
||
|
bge.logic.globalDict["sounds"]["tire_pop"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/tire_pop.ogg")),
|
||
|
"play":None}
|
||
|
|
||
|
# Race sounds
|
||
|
|
||
|
bge.logic.globalDict["sounds"]["checkpoint"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/checkpoint.ogg")),
|
||
|
"play":None}
|
||
|
|
||
|
|
||
|
device = bge.logic.globalDict["SoundDevice"]
|
||
|
device.listener_location = scene.active_camera.worldPosition
|
||
|
device.listener_orientation = scene.active_camera.worldOrientation.to_quaternion()
|
||
|
device.listener_velocity = scene.active_camera.getLinearVelocity()
|
||
|
|
||
|
for i in bge.logic.globalDict["sound-ambiances"]:
|
||
|
s = i["ambiance-sound"]
|
||
|
#s = "//sfx/ambiance/forest.ogg"
|
||
|
if s not in bge.logic.globalDict["sounds"]:
|
||
|
bge.logic.globalDict["sounds"][s] = {"sound":aud.Sound(bge.logic.expandPath(s)),
|
||
|
"play":None}
|
||
|
|
||
|
sound = bge.logic.globalDict["sounds"][s]
|
||
|
|
||
|
if not sound["play"] or not sound["play"].status:
|
||
|
sound["play"] = device.play(sound["sound"])
|
||
|
|
||
|
scale = i.scaling[0]
|
||
|
distance = i.getDistanceTo(dani)
|
||
|
|
||
|
if inCinema:
|
||
|
sound["inCinema"] = sound.get("inCinema", 1) * 0.95
|
||
|
elif sound.get("inCinema", 1) < 1:
|
||
|
if sound["inCinema"] < 0.1:
|
||
|
sound["inCinema"] = 0.1
|
||
|
sound["inCinema"] = sound.get("inCinema", 1) * 1.05
|
||
|
sound["play"].volume = max(0, min(1, (1-(distance / scale ))*5))*i.get("volume", 1) * sound.get("inCinema", 1)
|
||
|
|
||
|
########## LODS FOR CHUNKS OF THE ROAD #############
|
||
|
if "LODchunks" not in bge.logic.globalDict:
|
||
|
bge.logic.globalDict["LODchunks"] = {"TheRacetrack":{
|
||
|
"object":scene.objects["TheRacetrack"],
|
||
|
"high":"TheRacetrackHigh",
|
||
|
"low":"TheRacetrackLow",
|
||
|
"radius":1000,
|
||
|
"now":"high"
|
||
|
},
|
||
|
|
||
|
"TheCity":{
|
||
|
"object":scene.objects["TheCity"],
|
||
|
"high":"TheCityHigh",
|
||
|
"low":"TheCityLow",
|
||
|
"radius":1500,
|
||
|
"now":"high"
|
||
|
},
|
||
|
|
||
|
"TheHouse":{
|
||
|
"object":scene.objects["TheHouse"],
|
||
|
"high":"TheHouseGood",
|
||
|
"low":"TheHouseBorked",
|
||
|
"radius":200,
|
||
|
"now":"high"
|
||
|
},
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
chunks = bge.logic.globalDict["LODchunks"]
|
||
|
|
||
|
for chunkname in chunks:
|
||
|
chunk = chunks[chunkname]
|
||
|
|
||
|
if chunk["now"] == "low" and cam.getDistanceTo(chunk["object"]) < chunk["radius"]:
|
||
|
print("Making", chunkname, "high")
|
||
|
chunk["object"].replaceMesh(chunk["high"])
|
||
|
chunk["object"].restorePhysics()
|
||
|
chunk["now"] = "high"
|
||
|
|
||
|
elif chunk["now"] == "high" and cam.getDistanceTo(chunk["object"]) > chunk["radius"]:
|
||
|
print("Making", chunkname, "low")
|
||
|
chunk["object"].replaceMesh(chunk["low"])
|
||
|
if not dani.get("race"):
|
||
|
chunk["object"].suspendPhysics()
|
||
|
chunk["now"] = "low"
|
||
|
|