DanisRace/Scripts/Main_update.py
2025-03-16 04:47:56 +02:00

618 lines
19 KiB
Python

import bge
import bpy
import json
import os
import aud
import time
import datetime
import threading
import random
import numpy
import math
import mathutils
from Scripts import Reuse
from Scripts import Destruction
from Scripts import Opt
from Scripts.Common import *
from Scripts import Map
from Scripts import UI
from Scripts import Script
from Scripts import Vehicle
from Scripts import Settings
from Scripts import Tools
from Scripts import Money
from Scripts import Garage
from Scripts import Racing
from Scripts import Mouse
from Scripts import Music
from Scripts import Hints
from Scripts import Cinema
from Scripts import GameTime
from Scripts import Doors
from Scripts import Elevators
from Scripts import Input
from Scripts import Character
from Scripts import Multiplayer_Client
def main():
# Resolution for optimization
spawnAtDistance = 250
maxCars = 6
bge.logic.globalDict["spawnAtDistance"] = spawnAtDistance
bge.logic.globalDict["maxCars"] = maxCars
# Often referenced objects
scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()
dani = scene.objects["Dani_Box"]
cam = scene.active_camera
# Inputs
Input.UpdateKeys()
Input.UpdateMouse()
keys = bge.logic.globalDict["keys"]
Mouse.DeactivateToggler()
Input.UnpressSimulatedPresses()
firsteverupdatetime = False
if UI.StartLoadingScreen(): return # Loading screen
UI.UpdateFPSCounter()
Opt.ExecuteScheduled()
# Calculating the camera surround position.
camSurroundCars = Opt.Surround(cam.position, spawnAtDistance, cam.orientation.to_euler())
# Getting if Dani is in Cinema.
inCinema = Cinema.InCinema()
# Destroy those needing destroying
Reuse.SelfDestructDo()
# Initialization
if not Opt.chunks:
Init()
# Delaying Danis physics for a few frames after Init()
# so that the physics of the house could load in properly.
if bge.logic.globalDict["restore-physics-timer"]:
bge.logic.globalDict["restore-physics-timer"] -= 2
Mouse.CenterCursor()
return
elif bge.logic.globalDict["restore-physics"]:
bge.logic.globalDict["restore-physics"] = False
dani.restorePhysics()
Mouse.CenterCursor()
UI.RemoveLoadingScreen()
# Getting settings
settings = bge.logic.globalDict["settings"]
# Updating chunks
Opt.ScheduleTask("Scene Chunk Updates", 0.85, Opt.UpdateScene,
cam, spawnAtDistance, cam.orientation.to_euler())
# Running the story of the game
Script.Run(scene, dani)
# Multiplayer scene updates
if settings.get("multiplayer"):
Multiplayer_Client.SecondaryLoop()
# SPAWNING CARS
if not settings.get("multiplayer"):
Opt.ScheduleTask("Car Updates", 0.80, Vehicle.SpawnLogic,
camSurroundCars)
Vehicle.UnspawnLogic()
# Logic reducing hints rendered on the screens.
Hints.UnshowLogic()
# Updating elevators
Elevators.MainLoop()
# Updating doors
Doors.MainLoop()
# 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
Input.CheatCodes()
# RACES
Racing.MainLoop(spawnAtDistance)
# Messages
if "done-prints" not in bge.logic.globalDict:
bge.logic.globalDict["done-prints"] = []
if bge.logic.globalDict.get("print") and bge.logic.globalDict.get("last_print") != bge.logic.globalDict["print"]:
print()
for line in bge.logic.globalDict["print"].split("\n"):
print(" "+clr["bold"]+clr["tdyl"]+line+clr["norm"])
print()
#scene.objects["Messages"]["Text"] = str(bge.logic.globalDict.get("print"))
scene.objects["Messages"].blenderObject.data.body = str(bge.logic.globalDict.get("print"))
scene.objects["Messages"].stopAction()
scene.objects["Messages"].playAction("MessagesAction", 0, 100)
bge.logic.globalDict["print-change-size"] = True
bge.logic.globalDict["last_print"] = bge.logic.globalDict["print"]
if bge.logic.globalDict["print"] not in bge.logic.globalDict["done-prints"]:
bge.logic.globalDict["done-prints"].append(bge.logic.globalDict["print"])
bge.logic.globalDict["print"] = ""
elif bge.logic.globalDict.get("print-change-size"):
# Changing the size of the element under the text
# This is done in a different frame, because we need
# to let it update the depsgraph with the text dimensions.
camscale = scene.objects["DaniCam_Parent"].scaling[0]
textSize = scene.objects["Messages"].blenderObject.dimensions
thingSize = scene.objects["Message_Background"].blenderObject.dimensions
thingScale = scene.objects["Message_Background"].worldScale
textSize = mathutils.Vector((
textSize.x + ( 0.04 * camscale ),
textSize.y + ( 0.02 * camscale ),
textSize.z
))
thingSize = mathutils.Vector((
thingSize.x / thingScale.x,
thingSize.y / thingScale.y,
thingSize.z / thingScale.z
))
thingScale = mathutils.Vector((
textSize.x / thingSize.x,
textSize.y / thingSize.y,
1.0 # It doesn't matter, and making it 0 collapes the object
))
scene.objects["Message_Background"].worldScale = thingScale
point = Vehicle.RelativePoint(scene.objects["Messages"],
(-0.007 * camscale,
(-0.010 * camscale) + (textSize.y / 2),
-0.001))
scene.objects["Message_Background"].worldPosition = point
bge.logic.globalDict["print-change-size"] = False
# 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}
bge.logic.globalDict["sounds"]["dani_jump"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/voices/dani/jump.ogg")),
"play":None}
bge.logic.globalDict["sounds"]["dani_land"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/voices/dani/land.ogg")),
"play":None}
bge.logic.globalDict["sounds"]["dani_walk"] = {"sound":aud.Sound(bge.logic.expandPath("//sfx/voices/dani/walk.ogg")),
"play":None}
# Jack voices
bge.logic.globalDict["JackBoxVoices"] = {"crash":[],
"near" :[],
"speed":[]}
JV = bge.logic.globalDict["JackBoxVoices"]
JF = bge.logic.expandPath("//sfx/voices/jack/")
for t in ["crash", "near", "speed"]:
for f in os.listdir(JF):
if f.startswith(t) and f.endswith(".ogg"):
name = f.replace(".ogg", "")
bge.logic.globalDict["sounds"]["jack_"+name] = {"sound":aud.Sound(JF+f),
"play":None}
JV[t].append(bge.logic.globalDict["sounds"]["jack_"+name])
# 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)
# Music subsystem
if settings.get("music"):
Music.Loop()
else:
Music.CoolDown()
Music.ShakyCam()
# LODs of buildings
Opt.BuildingsLOD()
############ Camera UI ###########
Map.UpdateMapUI()
#Map.Show([0,0,0], icon="Map_Circle")
############ GARAGE ##########
# The idea is that all cars inside of the garage will
# stay in the garage.
garage = scene.objects["GarageColider"]
garageDistance = 70
if dani.getDistanceTo(garage) > garageDistance:
Garage.Encode()
elif dani.getDistanceTo(garage) < garageDistance - 10:
Garage.Decode()
# Crates
# There are crates in the house, in the garage. They are rigid body objects.
# the problem is that when you go far enough away, the ground beneath them
# stops being solid, so we need to deactiave their physics.
crates = bge.logic.globalDict["garage-crates"]
for crate in crates:
if dani.getDistanceTo(crate) > 100:
crate.suspendPhysics()
elif dani.getDistanceTo(crate) < 90:
crate.restorePhysics()
# Tools
Tools.MainLoop()
Garage.Computer()
################ DAY NIGHT CYCLE ################
GameTime.UpdateClock()
if firsteverupdatetime or Opt.GoodFPS("clock-scene-updates"):
GameTime.UpdateScene()
timecontroller = scene.objects["TimeController"]
# Background racetrack / city backdrop calcualtion
city_at = 137
racetrack_at = 630
now_at = float(cam.worldPosition.y)
if now_at > racetrack_at: crFactor = 1.0
elif now_at < city_at: crFactor = 0.0
else:
crFactor = (now_at - city_at) / ( racetrack_at - city_at )
timecontroller.position.y = ( crFactor * 100 ) - 100
# Moving the background up and down depending on the position of
# the camera.
max_z = 39
min_z = -12
now_z = float(cam.worldPosition.z)
move_z = 14
if now_z > max_z: mzFactor = 0.0
elif now_z < min_z: mzFactor = 1.0
else:
mzFactor = 1- ((now_z - min_z) / ( max_z - min_z ))
timecontroller.position.z = ( mzFactor * move_z )
# Now to position the racetrack properly we want to rotate it
p1 = [7.39, -805.686]
p2 = [30 , 95.5932]
cur_x = float(cam.worldPosition.x)
rotFactor = (cur_x - p1[1]) / (p2[1] - p1[1]) * ( p2[0] - p1[0] ) + p1[0]
rotationcontroller = scene.objects["Racetrack_rotaion"]
rotationcontroller.position.x = rotFactor
# Now the same object at Z will control the level of the volumetric
# Water effect. ( Important when below water level, but not in the
# water ).
waterleveler = scene.objects["WaterLevel"]
if dani.position.y < 0:
waterleveler.position.z = -1000
else:
waterleveler.position.z = 0
# Police related stuff
# Updating cops rate
chasing = Vehicle.IsChased(dani.get("driving"))
if chasing:
# 5 chasing cars and you are having 100% police spawning.
a = len(chasing)
p = max(0.1, min(1.0, a / 5.5 + 0.1))
bge.logic.globalDict["policeSpawnFactor"] = p
else:
bge.logic.globalDict["policeSpawnFactor"] = 0.2
# hiding UI
# for i in cam.childrenRecursive:
# if i.visible:
# i.visible = False
def Init():
spawnAtDistance = bge.logic.globalDict["spawnAtDistance"]
maxCars = bge.logic.globalDict["spawnAtDistance"]
# Often referenced objects
scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()
dani = scene.objects["Dani_Box"]
cam = scene.active_camera
dani.suspendPhysics()
Mouse.CenterCursor()
# Making settings executed
Settings.Execute()
settings = Settings.load_settings()
bge.logic.globalDict["settings"] = settings
Settings.LoadGame()
Script.StatusText(" ")
GameTime.InitiateClock()
firsteverupdatetime = True
# Stuff
bge.logic.globalDict["netObjects"] = {
"pythonId":{},
"netId":{}
}
bge.logic.globalDict["elevators"] = {}
bge.logic.globalDict["sound-ambiances"] = []
bge.logic.globalDict["doors"] = {}
bge.logic.globalDict["garage-crates"] = []
# Cars related
bge.logic.globalDict["spawns"] = {}
bge.logic.globalDict["allcars"] = []
bge.logic.globalDict["cars"] = []
bge.logic.globalDict["policeCars"] = []
bge.logic.globalDict["policeSpawnFactor"] = 0.1
bge.logic.globalDict["spawnedCarModels"] = []
# Cheat code modes
bge.logic.globalDict["pursuit-cheat"] = False
bge.logic.globalDict["derby-cheat"] = False
bge.logic.globalDict["gravity"] = True
# Navigation for NPCs
bge.logic.globalDict["Navigation"] = {"road" :[],
"parking":[]}
Navigation = bge.logic.globalDict["Navigation"]
for navtag in bpy.data.collections["Navigation"].objects:
tagdata = {"position":navtag.location,
"orientation":navtag.rotation_euler,
"radius":navtag.scale[0],
"connected":[]}
if navtag.get("parking"):
Navigation["parking"].append(tagdata)
else:
Navigation["road"].append(tagdata)
# Races
Racing.Precalculate()
# Characters
Reuse.Delete(scene.objects["PapsBox"])
#Reuse.Delete(scene.objects["MoriaBox"])
Reuse.Delete(scene.objects["JackBox"])
# Objects
for object in scene.objects:
if "spawn" in object:
Vehicle.RegisterSpawnPoint(object)
if str(object.name).startswith("Crate"):
crates = bge.logic.globalDict["garage-crates"]
crates.append(object)
if "LightSpawn" in object:
Opt.RegisterObjects(object, spawnAtDistance, "LightSpawn")
elif type(object.blenderObject.data) == bpy.types.AreaLight:
Opt.RegisterObjects(object, spawnAtDistance, "AreaLamp")
elif "Tree" in object.name:
Opt.RegisterObjects(object, spawnAtDistance, "Tree")
elif "Palm" in object.name:
Opt.RegisterObjects(object, spawnAtDistance, "Palm")
elif "Elevator" in object:
Elevators.RegisterElevator(object)
elif "Door" in object:
Doors.RegisterDoor(object)
elif "ambiance-sound" in object:
bge.logic.globalDict["sound-ambiances"].append(object)
# Precalculating objects for smoothness
Opt.Precalculate()
# Setting Exit Function
scene.onRemove.append(OnExit)
# Dani's Delay for proper loading.
bge.logic.globalDict["restore-physics-timer"] = 100
bge.logic.globalDict["restore-physics"] = True
# Running multiplayer daemon
if settings.get("multiplayer"):
multiplayer = threading.Thread(target=Multiplayer_Client.MainLoop)
multiplayer.setDaemon(True)
multiplayer.start()
def OnExit():
# Function running on the exit.
preData = bge.logic.globalDict["preData"]
print("\nScene Spawn Totals:\n")
for obj in Reuse.amounts:
precached = preData.get(obj, 0)
cached = Reuse.amounts[obj]
d = cached - precached
if d > 0:
dc = clr["tdrd"]
d = "+"+str(d)
elif d <= 0:
dc = clr["tdgr"]
print(" "+clr["bold"]+obj+clr["norm"]+" Exited with"+clr["bold"], cached, clr["norm"]+", Started with"+clr["bold"], precached, clr["norm"]+", Difference"+dc, d , clr["norm"] )
print()
Settings.SaveGame()
print()