Version 2024-09-25
This commit is contained in:
parent
db92590087
commit
4b5dac1d91
87 changed files with 834 additions and 13462 deletions
4
LICENSE~
4
LICENSE~
|
@ -1,4 +0,0 @@
|
|||
Because the game is done in UPBGE which is a fork of Blender it is all together
|
||||
technically GPLv3-or-later.
|
||||
|
||||
This package though, at this point in time is CC-BY-SA.
|
|
@ -1,45 +0,0 @@
|
|||
MADEULOOK_Soundfont - CC-BY - https://musical-artifacts.com/artifacts/2385
|
||||
|
||||
Ambience, Night Wildlife, A.wav - CC-BY by InspectorJ (www.jshaw.co.uk) of Freesound.org https://freesound.org/people/InspectorJ/sounds/352514/
|
||||
|
||||
Leather Bow Stretch - CC-BY by EminYILDIRIM from Freesound .org https://freesound.org/people/EminYILDIRIM/sounds/536085/
|
||||
|
||||
Eurofighter Typhoon Flyby 004 – Close Proximity - CC-BY by TimoSchmied https://freesound.org/people/TimoSchmied/sounds/640498/
|
||||
|
||||
jet engine start, CRJ 900 - CC-BY by alex36917 https://freesound.org/people/alex36917/sounds/582249/
|
||||
|
||||
Jet Engine 1 - CC-BY by InSintesi https://freesound.org/people/InSintesi/sounds/346034/
|
||||
|
||||
motor_drill01 - CC-BY by Taira Komori https://freesound.org/people/Taira%20Komori/sounds/212397/
|
||||
|
||||
ELECTRIC_MOTOR - CC-BY by jacobsteel https://freesound.org/people/jacobsteel/sounds/336665/
|
||||
|
||||
Dental_chair_servo_switch - CC-BY by beerbelly38 https://freesound.org/people/beerbelly38/sounds/160432/
|
||||
|
||||
steps_sneakers - CC-BY by neohylanmay https://freesound.org/people/neohylanmay/sounds/333201/
|
||||
|
||||
|
||||
Pipe_Drag_01 - CC-BY by dheming https://freesound.org/people/dheming/sounds/177782/
|
||||
|
||||
robot step short medium-heavy - CC-BY by keemocore https://freesound.org/people/keemocore/sounds/148309/
|
||||
|
||||
Swoosh_EminYILDIRIM CC-BY by EminYILDIRIM https://freesound.org/people/EminYILDIRIM/sounds/555057/
|
||||
|
||||
bunch_of_swooshes CC-BY by berglindsi https://freesound.org/people/berglindsi/sounds/402977/
|
||||
|
||||
Horn Honk CC-BY by mkoenig https://freesound.org/people/mkoenig/sounds/81173/
|
||||
|
||||
underwater_ambience CC-BY by akemov https://freesound.org/people/akemov/sounds/255597/
|
||||
|
||||
Water_Swirl_Small_3 CC-BY by InspectorJ https://freesound.org/people/InspectorJ/sounds/398723/
|
||||
|
||||
aprox-5000 CC-BY by lonemonk https://freesound.org/people/lonemonk/sounds/100840/
|
||||
|
||||
|
||||
unfa's-swoosh CC-0 by unfa https://freesound.org/people/unfa/sounds/584188/
|
||||
|
||||
tire_puncture CC-BY by WaveAdventurer
|
||||
https://freesound.org/people/WaveAdventurer/sounds/702718/
|
||||
|
||||
Big Explosion CC-BY by Lamoot
|
||||
https://opengameart.org/content/big-explosion
|
|
@ -1,106 +0,0 @@
|
|||
[01_Bring_Neonspeedster_To_Racetrack]
|
||||
|
||||
Dani wakes up in the room. Nobody is home. Telephone rings after 10 seconds.
|
||||
|
||||
Dani: Yes?
|
||||
Paps Voice: Dani, I can't believe that I'm telling this. Jack just brought
|
||||
the truck over without the car. Moria has to start practicing. And there is no
|
||||
car. Dani. Bring here the Neonspeedster. It should be in the garage. You have
|
||||
3 minutes. Not a single scratch. You hear me! Not a single scratch.
|
||||
|
||||
Message: Bring Neonspeedster to Paps onto the Racetrack.
|
||||
|
||||
A directional arrow appears and it points to Neonspeedster in the garage. As
|
||||
soon as the player takes the car. The arrow will point at the racetrack. There
|
||||
by the entrance, stands a Blue Truck. Paps, Jack and Moria are next to it.
|
||||
|
||||
If the car has less then 100% health:
|
||||
Paps: I told you not a single scratch, Dani. What do you think should we
|
||||
do with a broken car?
|
||||
|
||||
Message: Assignment Failed.
|
||||
|
||||
If the car is fully healthy:
|
||||
Paps: Excellent! One, day, if you prove yourself, I'll let you drive on the
|
||||
racetrack, Dani. Now get out.
|
||||
|
||||
If Dani gets out:
|
||||
Message: Assignment Passed.
|
||||
Moria takes the car and goes onto the racetrack on it.
|
||||
Game goes to next assignment.
|
||||
|
||||
______________________________________________________________________
|
||||
|
||||
Dani delivered the car to the racetrack and got out of the car. Moria took the car without talking much and drove it to the racetrack. Paps was left with Dani and Jack alone.
|
||||
|
||||
Paps: Jack.
|
||||
Jack: Yes.
|
||||
Paps: Go wait in the truck!
|
||||
|
||||
Jack goes into the truck. Sitting on the passenger's seat.
|
||||
|
||||
Paps: Dani. This is unbelievable. Well, okay... Jack didn't break the truck. But the fact that he came here without Neonspeedster is frankly insane to say the least. I know what we can do.
|
||||
Dani: Yes?
|
||||
Paps: You will drive the truck home with him as a passenger. He is supposed to be a professional race driver, but your 11 yr old sister already drives better than him! And now you, will drive him instead of him driving you. Well this is something. That will teach him a lesson.
|
||||
|
||||
Dani laughs a bit.
|
||||
|
||||
Paps: Dani. Go get the truck back home. Keep Jack inside.
|
||||
Dani: Okay.
|
||||
|
||||
Message: Bring the truck back home.
|
||||
|
||||
As soon as you sit into the truck and start going.
|
||||
|
||||
Jack: Let me guess... He is trying to punish me by making you drive the truck? Hm... He doesn't know me. It's not punishing. It's amazing! Also he probably told you that I didn't bring a car here. Well he is lying. I brought a car. It's in the truck right now. It's just not a Neonspeedster. And Moria apparently only likes Neonspeedsters. He is not punishing me for that, you know. He is punishing me for crashing on a tower spin. On a tower spin of all places! Who will not crash there? Even Moria barely made it through. Hell Tali Shtern crashed that day on the Tower Spin. And he is still punishing me for this.
|
||||
|
||||
As the truck is getting close to the house.
|
||||
|
||||
Jack: Wait, wait. Let's not go home. Wanna race?
|
||||
Dani: Yes.
|
||||
Jack: Let's go this way. There is a race coming up and we have a spare race car with us. Hell I'll let you race.
|
||||
Dani: Okay!
|
||||
|
||||
Message: Drive the truck to the race.
|
||||
|
||||
The previous assignment is aborted and now they are driving to a race beside a huge building. There are a few cars already waiting and ready to race.
|
||||
|
||||
As soon as you get there:
|
||||
|
||||
Jack: Press here to unload the car.
|
||||
Message: Press D to unload the car.
|
||||
|
||||
This is needed for later, when people could change their keybindings.
|
||||
|
||||
As soon as Dani is in the car, a circle appears into which you can drive.
|
||||
|
||||
Message: Press R to start the race.
|
||||
|
||||
The race starts. The race is very messy and with a lot of off-road-ing and breaking through stuff. A part of it goes through the place where Dani lives.
|
||||
|
||||
_____________________________________
|
||||
|
||||
Jack's Reactions to Dani's Driving.
|
||||
|
||||
Hitting cars:
|
||||
Dani, your will break the car!
|
||||
Dani, the car will break, dani!
|
||||
We are, wrecking the car!
|
||||
Paps will be pissed!
|
||||
Dani, what are you doing man!
|
||||
|
||||
"Oh God!":
|
||||
Dani, can you please concentrate, please!
|
||||
You almost killed us, dani!
|
||||
Ooooaaahhh!
|
||||
|
||||
Speeding up on a race:
|
||||
Triple caution!!!
|
||||
Dani! Double caution!!! Triple caution!!!
|
||||
Concentrate, Dani, Please!
|
||||
Concentrate!
|
||||
You are going too fast!
|
||||
We will miss the turn!
|
||||
Slow down! Listen to me! Dani!
|
||||
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -5,12 +5,16 @@
|
|||
import bge
|
||||
import aud
|
||||
|
||||
inCinema = False
|
||||
|
||||
def Main(w):
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
cont = bge.logic.getCurrentController()
|
||||
obj = cont.owner
|
||||
|
||||
global inCinema
|
||||
|
||||
inCinema = scene.objects["CinemaColider"]["InCinema"]
|
||||
|
||||
def cTprint(t):
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
# This script will make the cinema work.
|
||||
|
||||
|
||||
|
||||
import bge
|
||||
import aud
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
cont = bge.logic.getCurrentController()
|
||||
obj = cont.owner
|
||||
|
||||
inCinema = scene.objects["CinemaColider"]["InCinema"]
|
||||
|
||||
def cTprint(t):
|
||||
cText = scene.objects["CinemaText"]
|
||||
if cText["Text"] != t:
|
||||
cText["Text"] = t
|
||||
print(t)
|
||||
|
||||
black = scene.objects["CinemaScreen.Black"]
|
||||
|
||||
# Play the movie
|
||||
|
||||
|
||||
|
||||
if obj.get("Movie"):
|
||||
|
||||
cTprint("")
|
||||
|
||||
if not obj.get("Video"):
|
||||
movieTexture = bge.texture.VideoFFmpeg(obj.get("Movie"))
|
||||
|
||||
print(dir(movieTexture))
|
||||
|
||||
texture = bge.texture.Texture(obj, 0, 0)
|
||||
texture.source = movieTexture
|
||||
texture.source.play()
|
||||
texture.refresh(False)
|
||||
|
||||
width, height = movieTexture.size
|
||||
obj.scaling[1] = obj.scaling[1] / height * 1080
|
||||
|
||||
device = aud.Device()
|
||||
sound = aud.Sound(obj.get("Movie"))
|
||||
|
||||
obj["Sound"] = device.play(sound)
|
||||
|
||||
|
||||
obj["Video"] = texture
|
||||
obj["Time"] = bge.logic.getRealTime()
|
||||
obj["StartTime"] = bge.logic.getRealTime()
|
||||
obj["soundref"] = 100
|
||||
black.visible = False
|
||||
|
||||
|
||||
elif inCinema:
|
||||
|
||||
if obj.get("iTimer", 0):
|
||||
obj["iTimer"] = obj.get("iTimer", 1) -1
|
||||
|
||||
# Move the audio forward
|
||||
if 87 in bge.logic.globalDict["keys"] and not obj.get("iTimer", 0):
|
||||
obj["AudOffset"] = obj.get("AudOffset", 0) + 0.25
|
||||
obj["iTimer"] = 10
|
||||
elif 85 in bge.logic.globalDict["keys"] and not obj.get("iTimer", 0):
|
||||
obj["AudOffset"] = obj.get("AudOffset", 0) - 0.25
|
||||
obj["iTimer"] = 10
|
||||
|
||||
if bge.logic.getRealTime() - obj["Time"] > (1/30):
|
||||
|
||||
|
||||
obj["Video"].source.refresh()#obj["Sound"].position)
|
||||
obj["Video"].refresh(False)
|
||||
obj["Time"] = bge.logic.getRealTime()
|
||||
|
||||
#print(obj["Video"].source.framerate)
|
||||
#print("Video Refreshed at:", obj["Time"], obj["Sound"].position)
|
||||
|
||||
if not obj["soundref"]:
|
||||
|
||||
try:
|
||||
obj["Sound"].position = bge.logic.getRealTime()-obj["StartTime"]+obj.get("AudOffset", 0)
|
||||
except:
|
||||
|
||||
obj["Movie"] = None
|
||||
obj["Video"] = None
|
||||
black.visible = True
|
||||
obj.scaling[1] = 1
|
||||
|
||||
obj["cTfolder"] = obj["cTfolder"][:obj["cTfolder"].rfind("/")]
|
||||
obj["cTfolder"] = obj["cTfolder"][:obj["cTfolder"].rfind("/")] + "/"
|
||||
|
||||
obj["soundref"] = 100
|
||||
else:
|
||||
obj["soundref"] -= 1
|
||||
else:
|
||||
obj["Sound"].stop()
|
||||
obj["Video"].source.stop()
|
||||
obj["Movie"] = None
|
||||
obj["Video"] = None
|
||||
|
||||
obj.scaling[1] = 1
|
||||
|
||||
black.visible = True
|
||||
|
||||
obj["cTfolder"] = obj["cTfolder"][:obj["cTfolder"].rfind("/")]
|
||||
obj["cTfolder"] = obj["cTfolder"][:obj["cTfolder"].rfind("/")] + "/"
|
||||
|
||||
# FILE MANAGER ( I know I'm crazy )
|
||||
elif inCinema:
|
||||
|
||||
|
||||
import os
|
||||
|
||||
|
||||
|
||||
obj["cTfolder"] = obj.get("cTfolder", "/")
|
||||
obj["cTselect"] = obj.get("cTselect", 0)
|
||||
|
||||
# Files and folders
|
||||
|
||||
formats = [".mp4", ".ogg", ".ogv", ".avi"]
|
||||
|
||||
try:
|
||||
listdir = []
|
||||
for i in os.listdir(obj["cTfolder"]):
|
||||
for format in formats:
|
||||
if not os.path.isfile(obj["cTfolder"]+i) or i.endswith(format):
|
||||
listdir.append(i)
|
||||
break
|
||||
listdir = list(sorted(listdir))
|
||||
except:
|
||||
listdir = []
|
||||
|
||||
obj["Movie"] = obj["cTfolder"][:-1]
|
||||
|
||||
if not listdir:
|
||||
obj["cTfolder"] = obj["cTfolder"][:obj["cTfolder"].rfind("/")]
|
||||
obj["cTfolder"] = obj["cTfolder"][:obj["cTfolder"].rfind("/")] + "/"
|
||||
|
||||
if obj.get("iTimer", 0):
|
||||
obj["iTimer"] = obj.get("iTimer", 1) -1
|
||||
|
||||
|
||||
# Up and down
|
||||
if 72 in bge.logic.globalDict["keys"] and not obj.get("iTimer", 0):
|
||||
obj["cTselect"] = ( obj["cTselect"] -1 ) % len(listdir)
|
||||
obj["iTimer"] = 10
|
||||
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["checkpoint"]["sound"]) # Play a Ding
|
||||
elif 70 in bge.logic.globalDict["keys"] and not obj.get("iTimer", 0):
|
||||
obj["cTselect"] = ( obj["cTselect"] +1 ) % len(listdir)
|
||||
obj["iTimer"] = 10
|
||||
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["checkpoint"]["sound"]) # Play a Ding
|
||||
elif 7 in bge.logic.globalDict["keys"] and not obj.get("iTimer", 0):
|
||||
obj["cTfolder"] = obj["cTfolder"] + listdir[obj["cTselect"]] + "/"
|
||||
obj["cTselect"] = 0
|
||||
obj["iTimer"] = 10
|
||||
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["checkpoint"]["sound"]) # Play a Ding
|
||||
elif 59 in bge.logic.globalDict["keys"] and not obj.get("iTimer", 0):
|
||||
obj["cTfolder"] = obj["cTfolder"][:obj["cTfolder"].rfind("/")]
|
||||
obj["cTfolder"] = obj["cTfolder"][:obj["cTfolder"].rfind("/")] + "/"
|
||||
obj["cTselect"] = 0
|
||||
obj["iTimer"] = 10
|
||||
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["checkpoint"]["sound"]) # Play a Ding
|
||||
|
||||
# Drawing
|
||||
t = "[ "+obj["cTfolder"]+" ]\n\n"
|
||||
for n, f in enumerate(listdir[max(0,obj["cTselect"]-5):max(0,obj["cTselect"]-5)+10]):
|
||||
if listdir[obj["cTselect"]] == f:
|
||||
t = t + " [ "
|
||||
else:
|
||||
t = t + " "
|
||||
|
||||
t = t+f
|
||||
|
||||
if listdir[obj["cTselect"]] == f:
|
||||
t = t + " ] "
|
||||
else:
|
||||
t = t + " "
|
||||
|
||||
t = t + "\n"
|
||||
|
||||
cTprint(t)
|
|
@ -159,3 +159,45 @@ def IDcolor(ID):
|
|||
IDColors[ID] = c
|
||||
c = IDColors[ID]
|
||||
return c
|
||||
|
||||
|
||||
Presses = {}
|
||||
|
||||
def SimulatePress(name, MIN, MAX, SPEED):
|
||||
|
||||
import bge
|
||||
|
||||
if name not in Presses:
|
||||
Presses[name] = {}
|
||||
Presses[name]["value"] = 0.0
|
||||
|
||||
press = Presses[name]
|
||||
press["min"] = MIN
|
||||
press["max"] = MAX
|
||||
press["speed"] = SPEED
|
||||
press["frame"] = round(bge.logic.getRealTime(), 2)
|
||||
|
||||
press["value"] += SPEED
|
||||
press["value"] = max(min(press["value"], MAX), MIN)
|
||||
|
||||
return press["value"]
|
||||
|
||||
def UnpressSimulatedPresses():
|
||||
|
||||
import bge
|
||||
|
||||
frame = round(bge.logic.getRealTime(), 2)
|
||||
|
||||
for name in Presses:
|
||||
|
||||
press = Presses[name]
|
||||
|
||||
if frame-0.2 > press["frame"]:
|
||||
|
||||
MIN = press["min"]
|
||||
MAX = press["max"]
|
||||
SPEED = press["speed"]
|
||||
press["value"] -= SPEED * 4
|
||||
press["value"] = max(min(press["value"], MAX), MIN)
|
||||
|
||||
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
import random
|
||||
|
||||
# Common things needed for various things
|
||||
|
||||
# Colors are used to make the
|
||||
clr = {
|
||||
"norm":"\033[00m", # Reset to normal
|
||||
"bold":"\033[01m", # Bold Text
|
||||
"ital":"\033[03m", # Italic Text
|
||||
"undr":"\033[04m", # Underlined
|
||||
"blnk":"\033[05m", # Blinking
|
||||
|
||||
# Text
|
||||
"tdbl":"\033[30m", # Dark Black
|
||||
"tdrd":"\033[31m", # Dark Red
|
||||
"tdgr":"\033[32m", # Dark Green
|
||||
"tdyl":"\033[33m", # Dark Yellow
|
||||
"tdbu":"\033[34m", # Dark Blue
|
||||
"tdma":"\033[35m", # Dark Magenta
|
||||
"tdcy":"\033[36m", # Dark Cyan
|
||||
"tdwh":"\033[37m", # Dark White
|
||||
|
||||
"tbbl":"\033[90m", # Bright Black
|
||||
"tbrd":"\033[91m", # Bright Red
|
||||
"tbgr":"\033[92m", # Bright Green
|
||||
"tbyl":"\033[93m", # Bright Yellow
|
||||
"tbbu":"\033[94m", # Bright Blue
|
||||
"tbma":"\033[95m", # Bright Magenta
|
||||
"tbcy":"\033[96m", # Bright Cyan
|
||||
"tbwh":"\033[97m", # Bright White
|
||||
# Background
|
||||
"bdbl":"\033[40m", # Dark Black
|
||||
"bdrd":"\033[41m", # Dark Red
|
||||
"bdgr":"\033[42m", # Dark Green
|
||||
"bdyl":"\033[43m", # Dark Yellow
|
||||
"bdbu":"\033[44m", # Dark Blue
|
||||
"bdma":"\033[45m", # Dark Magenta
|
||||
"bdcy":"\033[46m", # Dark Cyan
|
||||
"bdwh":"\033[47m", # Dark White
|
||||
|
||||
"bbbl":"\033[100m", # Bright Black
|
||||
"bbrd":"\033[101m", # Bright Red
|
||||
"bbgr":"\033[102m", # Bright Green
|
||||
"bbyl":"\033[103m", # Bright Yellow
|
||||
"bbbu":"\033[104m", # Bright Blue
|
||||
"bbma":"\033[105m", # Bright Magenta
|
||||
"bbcy":"\033[106m", # Bright Cyan
|
||||
"bbwh":"\033[108m" # Bright White
|
||||
}
|
||||
|
||||
keycodes = {
|
||||
"A":23,
|
||||
"B":24,
|
||||
"C":25,
|
||||
"D":26,
|
||||
"E":27,
|
||||
"F":28,
|
||||
"G":29,
|
||||
"H":30,
|
||||
"I":31,
|
||||
"J":32,
|
||||
"K":33,
|
||||
"L":34,
|
||||
"M":35,
|
||||
"N":36,
|
||||
"O":37,
|
||||
"P":38,
|
||||
"Q":39,
|
||||
"R":40,
|
||||
"S":41,
|
||||
"T":42,
|
||||
"U":43,
|
||||
"V":44,
|
||||
"W":45,
|
||||
"X":46,
|
||||
"Y":47,
|
||||
"Z":48,
|
||||
|
||||
"0":13,
|
||||
"1":14,
|
||||
"2":15,
|
||||
"3":16,
|
||||
"4":17,
|
||||
"5":18,
|
||||
"6":19,
|
||||
"7":20,
|
||||
"8":21,
|
||||
"9":22,
|
||||
|
||||
"F1" :88,
|
||||
"F2" :89,
|
||||
"F3" :90,
|
||||
"F4" :91,
|
||||
"F5" :92,
|
||||
"F6" :93,
|
||||
"F7" :94,
|
||||
"F8" :95,
|
||||
"F9" :96,
|
||||
"F10":97,
|
||||
"F11":98,
|
||||
"F12":99,
|
||||
|
||||
"LShift" :55,
|
||||
"RShift" :54,
|
||||
"LCtrl" :50,
|
||||
"RCtrl" :53,
|
||||
"LAlt" :51,
|
||||
"RAlt" :52,
|
||||
"Tab" :57,
|
||||
"Space" :8,
|
||||
"Enter" :7,
|
||||
"BackSpace" :59,
|
||||
"Delete" :60,
|
||||
"Home" :110,
|
||||
"End" :109,
|
||||
"PageUp" :111,
|
||||
"PageDown" :112,
|
||||
|
||||
"UpArrow" :72,
|
||||
"DownArrow" :70,
|
||||
"RightArrow":71,
|
||||
"LeftArrow" :69
|
||||
|
||||
}
|
||||
|
||||
mousecodes = {
|
||||
|
||||
"RMB" : 118,
|
||||
"MMB" : 117,
|
||||
"LMB" : 116
|
||||
}
|
||||
|
||||
IDColors = {}
|
||||
|
||||
def consoleForm(obj):
|
||||
|
||||
# Function that prints a pretty object info about
|
||||
|
||||
ID = hex(id(obj))[2:].upper()
|
||||
NAME = str(obj)
|
||||
|
||||
# Coloring
|
||||
if ID not in IDColors:
|
||||
r = random.random()
|
||||
g = random.random()
|
||||
b = random.random()
|
||||
|
||||
ct = clr["tdbl"]
|
||||
if (r + g + b )/3 < 0.5:
|
||||
ct = clr["tbwh"]
|
||||
|
||||
c = "\033[48;2;"+str(int(r*256))+";"+str(int(g*256))+";"+str(int(b*256))+"m"+ct
|
||||
IDColors[ID] = c
|
||||
c = IDColors[ID]
|
||||
|
||||
return clr["bold"] + c + " " + ID + " " + NAME + " " + clr["norm"]
|
|
@ -10,6 +10,7 @@ import mathutils
|
|||
import types
|
||||
|
||||
from Scripts import Reuse
|
||||
from Scripts import Vehicle
|
||||
from Scripts import Opt
|
||||
from Scripts import Multiplayer_Shared
|
||||
|
||||
|
@ -103,13 +104,13 @@ def Smoke(point, strength=0.5, size=1.0):
|
|||
|
||||
# Adding some sparks to the fire
|
||||
particles("SmokeBurst", point,
|
||||
despawn = 10,
|
||||
despawn = 10*size,
|
||||
amount = random.randint(0, 3),
|
||||
max = 50,
|
||||
spread = 0.5,
|
||||
normal = 0.01,
|
||||
velocity = [0,0,0.1],
|
||||
scale=random.uniform(0.2,1.0))
|
||||
scale=random.uniform(size, size*2))
|
||||
|
||||
if Opt.GoodFPS("Smoke", strength):
|
||||
do(point)
|
||||
|
@ -135,22 +136,40 @@ def Dust(point, strength=0.5):
|
|||
|
||||
def FireElementTextureLogic(obj):
|
||||
|
||||
# This function runs the smoke / fire element animation
|
||||
# moving the tiled texture by 0.1th steps.
|
||||
|
||||
if type(obj) == bge.types.SCA_PythonController:
|
||||
obj = obj.owner
|
||||
|
||||
# Alighining object to camera
|
||||
|
||||
vect = obj.getVectTo(cam)
|
||||
obj.alignAxisToVect((0,0,1), 2, 1)
|
||||
obj.alignAxisToVect(vect[1], 1, 1)
|
||||
obj.blenderObject["fire"] -= 0.1
|
||||
|
||||
|
||||
|
||||
# Simulating velocity distortion
|
||||
|
||||
try: v = obj.parent.worldLinearVelocity.copy()
|
||||
except:
|
||||
try: v = obj.parent.parent.worldLinearVelocity.copy()
|
||||
except:return
|
||||
except:pass
|
||||
|
||||
v = -v + mathutils.Vector((0,0,30))
|
||||
obj.alignAxisToVect(v, 2, 1)
|
||||
try:
|
||||
v = -v + mathutils.Vector((0,0,30))
|
||||
obj.alignAxisToVect(v, 2, 1)
|
||||
except: pass
|
||||
|
||||
# Making it slower with size of the object.
|
||||
|
||||
size = obj.scaling.x * obj.get("timing", 1.0)
|
||||
if size < 1: size = 1
|
||||
if "frame" not in obj: obj["frame"] = 1
|
||||
if obj["frame"] % int(size) == 0:
|
||||
obj.blenderObject["fire"] -= 0.1
|
||||
|
||||
obj["frame"] += 1
|
||||
|
||||
|
||||
def AttatchFireBall(point, attachment=None, size=1, duration=0):
|
||||
|
||||
|
@ -202,11 +221,12 @@ def DeleteFireBall(FireBall):
|
|||
Reuse.Delete(FireBall)
|
||||
FireBall.removeParent()
|
||||
|
||||
def FireBurst(point, size):
|
||||
def FireBurst(point, size, timing=1.0):
|
||||
|
||||
# This will make a short burst of fire.
|
||||
|
||||
FireBurst = Reuse.Create("FireBurst", 10)
|
||||
FireBurst = Reuse.Create("FireBurst", 10*size*timing*0.85)
|
||||
FireBurst["timing"] = timing
|
||||
FireBurst.position = point.copy()
|
||||
FireBurst.scaling = [size, size, size]
|
||||
FireBurst.blenderObject["fire"] = 1
|
||||
|
@ -324,6 +344,10 @@ def Explosion(point, visible=True, size=3, mass=10, effectcars=True):
|
|||
|
||||
# Calculating direction of the force
|
||||
vector = object.getVectTo(point)[1] * -force
|
||||
|
||||
# Starting explosion timer on cars
|
||||
if "speed" in object and distance < size / 2:
|
||||
object["explosion-timer"] = random.randint(10,50)
|
||||
|
||||
# Applying force
|
||||
try:
|
||||
|
@ -378,7 +402,7 @@ def Explosion(point, visible=True, size=3, mass=10, effectcars=True):
|
|||
# velocity = [0,0,0.01],
|
||||
# scale = 2)
|
||||
|
||||
FireBurst(point, size/2)
|
||||
FireBurst(point, size/2, timing=0.2)
|
||||
|
||||
particles("Sparkle", point,
|
||||
despawn = random.randint(0, 100),
|
||||
|
@ -461,7 +485,7 @@ def WoodGate_level0(cont):
|
|||
if car:
|
||||
cv = car.getLinearVelocity()
|
||||
chunk.setLinearVelocity( cv / 2)
|
||||
|
||||
Vehicle.PolicePursuit(car)
|
||||
|
||||
|
||||
|
||||
|
@ -574,6 +598,8 @@ def LightStand(cont):
|
|||
cv = car.getLinearVelocity()
|
||||
if head: head.setLinearVelocity( cv )
|
||||
if tail: tail.setLinearVelocity( cv )
|
||||
|
||||
Vehicle.PolicePursuit(car)
|
||||
|
||||
# Deleting the light stand
|
||||
Reuse.Delete(part)
|
||||
|
|
|
@ -1,683 +0,0 @@
|
|||
# This is full of destruction stuff
|
||||
|
||||
import bge
|
||||
import aud
|
||||
|
||||
import random
|
||||
import numpy
|
||||
import math
|
||||
import mathutils
|
||||
import types
|
||||
|
||||
from Scripts import Reuse
|
||||
from Scripts import Opt
|
||||
from Scripts import Multiplayer_Shared
|
||||
|
||||
from Scripts.Common import *
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
cam = scene.active_camera
|
||||
|
||||
if "Destruction" not in bge.logic.globalDict:
|
||||
bge.logic.globalDict["Destruction"] = {}
|
||||
|
||||
database = bge.logic.globalDict["Destruction"]
|
||||
|
||||
# Particle system
|
||||
def particles(object, # Particle object
|
||||
point, # Point where to spawn them
|
||||
despawn, # Time ( in frames before disappearing )
|
||||
amount=5, # Amount of them to spawn
|
||||
max=50, # Max amount of them in the scene
|
||||
spread=0, # Spread of particles on start
|
||||
normal=0.05, # Spread of particles over time
|
||||
velocity=[0,0,0], # Velocity of particles
|
||||
scale = 1 # Scale of the particle object
|
||||
):
|
||||
|
||||
# Performance kill switch
|
||||
if not Opt.GoodFPS("particles", 0.5):
|
||||
return
|
||||
|
||||
|
||||
# Not do the effect if not in view
|
||||
if cam.getDistanceTo(point) > 100 or not cam.pointInsideFrustum(point) == cam.INSIDE:
|
||||
return
|
||||
|
||||
# We will need a place to register particles
|
||||
if "particles-registry" not in bge.logic.globalDict:
|
||||
bge.logic.globalDict["particles-registry"] = {}
|
||||
registry = bge.logic.globalDict["particles-registry"]
|
||||
|
||||
# Making sure that registry contains particle type
|
||||
if object not in registry:
|
||||
registry[object] = []
|
||||
|
||||
for i in range(amount):
|
||||
|
||||
# If we reached max, we abort
|
||||
inscene = len( registry[object] )
|
||||
inreuse = len( Reuse.reuse.get(object, []) )
|
||||
spawned = inscene - inreuse
|
||||
|
||||
if spawned > max:
|
||||
return
|
||||
|
||||
# Making particle
|
||||
particle = Reuse.Create(object, despawn)
|
||||
particle.scaling = [scale, scale, scale]
|
||||
|
||||
# Recording into registry
|
||||
if particle not in registry[object]:
|
||||
registry[object].append(particle)
|
||||
|
||||
# Puting it into position ( adding the spread )
|
||||
particle.position = point + mathutils.Vector([random.uniform(-spread, spread),
|
||||
random.uniform(-spread, spread),
|
||||
random.uniform(-spread, spread)])
|
||||
|
||||
# The next part will require an actuator
|
||||
|
||||
# Introducting random spread over time
|
||||
particle.actuators["Motion"].dLoc = mathutils.Vector([random.uniform(-normal, normal),
|
||||
random.uniform(-normal, normal),
|
||||
random.uniform(-normal, normal)])
|
||||
|
||||
# Adding the velocity
|
||||
particle.actuators["Motion"].dLoc += mathutils.Vector(velocity)
|
||||
|
||||
def Smoke(point, strength=0.5):
|
||||
|
||||
# Not do the effect if not in view
|
||||
if cam.getDistanceTo(point) > 100 or not cam.pointInsideFrustum(point) == cam.INSIDE:
|
||||
return
|
||||
|
||||
if numpy.random.choice([True, False], p=[strength, 1-strength]):
|
||||
|
||||
# Performance kill switch
|
||||
def do(point):
|
||||
|
||||
smokeParticle = Reuse.Create("Smoke", random.randint(30, 60))
|
||||
smokeParticle.position = point
|
||||
|
||||
if Opt.GoodFPS("Smoke", strength):
|
||||
do(point)
|
||||
|
||||
def Dust(point, strength=0.5):
|
||||
|
||||
# Not do the effect if not in view
|
||||
if cam.getDistanceTo(point) > 100 or not cam.pointInsideFrustum(point) == cam.INSIDE:
|
||||
return
|
||||
|
||||
if numpy.random.choice([True, False], p=[strength, 1-strength]):
|
||||
|
||||
# Performance kill switch
|
||||
def do(point):
|
||||
|
||||
smokeParticle = Reuse.Create("Dust", random.randint(30, 60))
|
||||
smokeParticle.position = point
|
||||
|
||||
if Opt.GoodFPS("Dust", 0.85):
|
||||
do(point)
|
||||
else:
|
||||
pass
|
||||
|
||||
def FireElementTextureLogic(obj):
|
||||
|
||||
if type(obj) == bge.types.SCA_PythonController:
|
||||
obj = obj.owner
|
||||
|
||||
vect = obj.getVectTo(cam)
|
||||
obj.alignAxisToVect((0,0,1), 2, 1)
|
||||
obj.alignAxisToVect(vect[1], 1, 1)
|
||||
obj.blenderObject["fire"] -= 0.1
|
||||
|
||||
|
||||
try: v = obj.parent.worldLinearVelocity.copy()
|
||||
except:
|
||||
try: v = obj.parent.parent.worldLinearVelocity.copy()
|
||||
except:return
|
||||
|
||||
v = -v + mathutils.Vector((0,0,30))
|
||||
obj.alignAxisToVect(v, 2, 1)
|
||||
|
||||
def AttatchFireBall(point, attachment=None, size=1, duration=0):
|
||||
|
||||
# This function will attach a fireball to a point.
|
||||
|
||||
# Making the FireBall
|
||||
FireBall = Reuse.Create("FireBall", duration)
|
||||
|
||||
# Attatching the Fireball
|
||||
FireBall.position = point.copy()
|
||||
FireBall.scaling = [size, size, size]
|
||||
if attachment:
|
||||
FireBall.setParent(attachment, True)
|
||||
|
||||
# Attatching a light to it.
|
||||
if not duration:
|
||||
if "Light" not in FireBall:
|
||||
|
||||
light = Reuse.Create("FireLamp")
|
||||
|
||||
light.position = FireBall.position
|
||||
light.setParent(FireBall)
|
||||
FireBall["Light"] = light
|
||||
|
||||
light = FireBall["Light"]
|
||||
light.blenderObject.data.use_shadow = False
|
||||
|
||||
# In case the fireball is farther than 50 meters
|
||||
# from the camera, we execute this ones.
|
||||
FireElementTextureLogic(FireBall)
|
||||
|
||||
# Storring it and returning
|
||||
|
||||
#ID = Multiplayer_Shared.RandomString()
|
||||
#database[ID] = FireBall
|
||||
#FireBall["ID"] = ID
|
||||
|
||||
return FireBall
|
||||
|
||||
def DeleteFireBall(FireBall):
|
||||
|
||||
# To save space we gonna do that.
|
||||
if "Light" in FireBall:
|
||||
|
||||
light = FireBall["Light"]
|
||||
light.removeParent()
|
||||
Reuse.Delete(light)
|
||||
|
||||
Reuse.Delete(FireBall)
|
||||
FireBall.removeParent()
|
||||
|
||||
def FireBurst(point, size):
|
||||
|
||||
# This will make a short burst of fire.
|
||||
|
||||
FireBurst = Reuse.Create("FireBurst", 10)
|
||||
FireBurst.position = point.copy()
|
||||
FireBurst.scaling = [size, size, size]
|
||||
FireBurst.blenderObject["fire"] = 1
|
||||
|
||||
def SpreadOnGround(object, point, size, spread, amount, duration=0, randomDuration=True):
|
||||
|
||||
# This works similarly to particles, but
|
||||
# instead puts the objects onto the ground.
|
||||
|
||||
for i in range(amount):
|
||||
|
||||
if randomDuration:
|
||||
d = random.uniform( duration / 2 , duration )
|
||||
else: d = duration
|
||||
|
||||
obj = Reuse.Create(object, d)
|
||||
|
||||
|
||||
obj.position = mathutils.Vector(point) + mathutils.Vector([random.uniform(-spread, spread),
|
||||
random.uniform(-spread, spread),
|
||||
random.uniform(-spread, spread)])
|
||||
|
||||
obj.scaling = [size, size, size]
|
||||
|
||||
# Puttin the object on the flor
|
||||
obj.position.z += spread + 1
|
||||
topos = obj.position.copy()
|
||||
topos.z -= 200
|
||||
ray = obj.rayCast(topos)
|
||||
if ray[1]: obj.position = ray[1]
|
||||
|
||||
|
||||
def Fire(point, strength=0.5):
|
||||
|
||||
|
||||
# Not do the effect if not in view
|
||||
if cam.getDistanceTo(point) > 100 or not cam.pointInsideFrustum(point) == cam.INSIDE:
|
||||
return
|
||||
|
||||
if numpy.random.choice([True, False], p=[strength, 1-strength]):
|
||||
|
||||
# Performance kill switch
|
||||
def do(point):
|
||||
|
||||
#fireParticle = Reuse.Create("Fire", random.randint(30, 60))
|
||||
#fireParticle.position = point
|
||||
#FireBurst(point, 0.5)
|
||||
|
||||
# Adding some sparks to the fire
|
||||
particles("FireBurst", point,
|
||||
despawn = 10,
|
||||
amount = random.randint(0, 3),
|
||||
max = 50,
|
||||
spread = 0.5,
|
||||
normal = 0.01,
|
||||
velocity = [0,0,0.1],
|
||||
scale=random.uniform(0.2,1.0))
|
||||
|
||||
if Opt.GoodFPS("Fire", strength):
|
||||
do(point)
|
||||
|
||||
def WaterSplash(point, strength=0.5, rot=0, force=1):
|
||||
|
||||
if numpy.random.choice([True, False], p=[strength, 1-strength]):
|
||||
waterSplash = Reuse.Create("WaterSplashCar", random.randint(10, 20))
|
||||
waterSplash.position = point
|
||||
waterSplash.orientation = [0,0,rot]
|
||||
waterSplash.scaling = [
|
||||
random.uniform(0.6, 1.4),
|
||||
random.uniform(0.6, 1.4),
|
||||
random.uniform(0.6*force, 1.4*force)
|
||||
]
|
||||
|
||||
# Sound
|
||||
device = bge.logic.globalDict["SoundDevice"]
|
||||
|
||||
s = "//sfx/splash.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]
|
||||
sound["play"] = device.play(sound["sound"])
|
||||
sound["play"].location = point
|
||||
sound["play"].relative = False
|
||||
sound["play"].distance_maximum = 100
|
||||
sound["play"].distance_reference = 1
|
||||
sound["play"].attenuation = 1
|
||||
sound["play"].pitch = random.uniform(0.6, 1.4)
|
||||
sound["play"].volume = 5 * min(2, force)
|
||||
|
||||
def Explosion(point, visible=True, size=3, mass=10, effectcars=True):
|
||||
|
||||
# Shockwave
|
||||
|
||||
# Shockwave will be done using math applied to every object within
|
||||
# a certain size to the explosion.
|
||||
|
||||
dani = scene.objects["Dani_Box"]
|
||||
if dani.get("driving"):
|
||||
dani["driving"]["shake"] = mass * 10 / dani.getDistanceTo(point)
|
||||
|
||||
for object in scene.objects:
|
||||
|
||||
# Getting distance to the object
|
||||
distance = object.getDistanceTo(point)
|
||||
|
||||
# Skipping every object outside of the size of the explosion
|
||||
if distance > size:
|
||||
continue
|
||||
|
||||
# Calculating forces on the object ( father away less forces ).
|
||||
force = ( 1 - distance / size ) * mass * object.mass
|
||||
|
||||
# Calculating direction of the force
|
||||
vector = object.getVectTo(point)[1] * -force
|
||||
|
||||
# Applying force
|
||||
try:
|
||||
object.applyImpulse(point, vector)
|
||||
|
||||
|
||||
# If it is a car we can apply damage to it, by sending it a fake
|
||||
# impulse of collision.
|
||||
|
||||
# But first we need to make sure to have the data for this
|
||||
# operation
|
||||
Apoint = types.SimpleNamespace()
|
||||
Apoint.worldPoint = mathutils.Vector(point)
|
||||
Apoint.appliedImpulse = force * 10
|
||||
points = [Apoint]
|
||||
|
||||
# Then we send it over
|
||||
for callback in object.collisionCallbacks:
|
||||
callback(None, point, None, points)
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
# Then we also have objects that use this very module to be
|
||||
# destructable. The all have a collision actuator listening
|
||||
# to a collision with a property "explosion" to execute their
|
||||
# function.
|
||||
|
||||
if "spawned_by" in object:
|
||||
for controller in object.controllers:
|
||||
|
||||
# This is a bit hacky, but it works.
|
||||
try:
|
||||
if "Destruction" in controller.script:
|
||||
exec(controller.script.replace("Scripts.Destruction.", "")+"(controller)")
|
||||
except: pass
|
||||
|
||||
# And also we want to unsuspend it's physics.
|
||||
|
||||
object.restoreDynamics()
|
||||
|
||||
|
||||
# Fire particles
|
||||
if visible:
|
||||
|
||||
# particles("Fire", point,
|
||||
# despawn = random.randint(int(size/2), int(size)),
|
||||
# amount = random.randint(int(size/2), int(size)),
|
||||
# max = 200,
|
||||
# spread = 0,
|
||||
# normal = 0.2,
|
||||
# velocity = [0,0,0.01],
|
||||
# scale = 2)
|
||||
|
||||
FireBurst(point, size/2)
|
||||
|
||||
particles("Sparkle", point,
|
||||
despawn = random.randint(0, 100),
|
||||
amount = random.randint(10, 50),
|
||||
max = 100,
|
||||
spread = size/2,
|
||||
normal = 0.5,
|
||||
velocity = [0,0,0.01])
|
||||
|
||||
Smoke(point, 1)
|
||||
|
||||
#AttatchFireBall(point,
|
||||
# size = 0.5,
|
||||
# duration = 200)
|
||||
|
||||
SpreadOnGround("FireBall",
|
||||
point,
|
||||
0.5,
|
||||
size/2,
|
||||
10,
|
||||
500)
|
||||
|
||||
|
||||
# Sound
|
||||
device = bge.logic.globalDict["SoundDevice"]
|
||||
|
||||
s = "//sfx/boom.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]
|
||||
sound["play"] = device.play(sound["sound"])
|
||||
sound["play"].location = point
|
||||
sound["play"].relative = False
|
||||
sound["play"].distance_maximum = 100
|
||||
sound["play"].distance_reference = 1
|
||||
sound["play"].attenuation = 1
|
||||
sound["play"].pitch = random.uniform(0.6, 1.4)
|
||||
sound["play"].volume = 20
|
||||
|
||||
|
||||
def DeclareBroken(cont):
|
||||
|
||||
#cont = bge.logic.getCurrentController()
|
||||
scene = bge.logic.getCurrentScene()
|
||||
part = cont.owner
|
||||
|
||||
part["spawned_by"]["broken"] = True
|
||||
|
||||
def WoodGate_level0(cont):
|
||||
|
||||
|
||||
#cont = bge.logic.getCurrentController()
|
||||
scene = bge.logic.getCurrentScene()
|
||||
part = cont.owner
|
||||
|
||||
part["spawned_by"]["broken"] = True
|
||||
|
||||
|
||||
colision = cont.sensors["Collision"]
|
||||
car = colision.hitObject
|
||||
|
||||
def do(cont, car, scene, part):
|
||||
|
||||
# Optimization trick
|
||||
if len(Reuse.reuse.get("GatePart.Level0", [])) >= 4:
|
||||
|
||||
|
||||
# Spawning madness
|
||||
for i in range(4):
|
||||
chunk = Reuse.Create("GatePart.Level0", 10, selfDestructInactive=True)
|
||||
Reuse.SelfDestruct(chunk, 500)
|
||||
chunk.mass = 0
|
||||
chunk.position = part.position
|
||||
chunk.orientation = part.orientation
|
||||
chunk.applyMovement( [ 0, i*1.24-2.45, 0 ] , True)
|
||||
|
||||
if car:
|
||||
cv = car.getLinearVelocity()
|
||||
chunk.setLinearVelocity( cv / 2)
|
||||
|
||||
|
||||
|
||||
|
||||
# Sound
|
||||
device = bge.logic.globalDict["SoundDevice"]
|
||||
|
||||
s = "//sfx/wood.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]
|
||||
sound["play"] = device.play(sound["sound"])
|
||||
sound["play"].location = chunk.position
|
||||
sound["play"].velocity = chunk.getLinearVelocity()
|
||||
sound["play"].relative = False
|
||||
sound["play"].distance_maximum = 100
|
||||
sound["play"].distance_reference = 1
|
||||
sound["play"].attenuation = 1
|
||||
sound["play"].pitch = random.uniform(0.6, 1.4)
|
||||
sound["play"].volume = 5
|
||||
|
||||
# Deleting the wooden gate
|
||||
Reuse.Delete(part)
|
||||
|
||||
if Opt.GoodFPS("WoodGate_level0", 0.8) or (car and car.get("active")):
|
||||
do(cont, car, scene, part)
|
||||
else:
|
||||
Opt.ScheduleTask("WoodGate_level0 ["+str(id(part))+"]", 0.8, do,
|
||||
cont, car, scene, part)
|
||||
|
||||
def WoodGate_level1(cont):
|
||||
|
||||
# Performance kill switch
|
||||
if not Opt.GoodFPS("WoodGate_level1", 0.7):
|
||||
return
|
||||
|
||||
|
||||
#cont = bge.logic.getCurrentController()
|
||||
scene = bge.logic.getCurrentScene()
|
||||
part = cont.owner
|
||||
|
||||
|
||||
# Optimization trick
|
||||
if len(Reuse.reuse.get("GatePart.Level1", [])) >= 4:
|
||||
|
||||
|
||||
# Spawning madness
|
||||
chunks = []
|
||||
for i in range(4):
|
||||
chunk = Reuse.Create("GatePart.Level1", 10, selfDestructInactive=True)
|
||||
Reuse.SelfDestruct(chunk, 100)
|
||||
chunk.mass = 0
|
||||
chunk.position = part.position
|
||||
chunk.orientation = part.orientation
|
||||
chunks.append(chunk)
|
||||
|
||||
|
||||
chunks[0].applyMovement( [ 0, 0, 0.75 ] , True)
|
||||
chunks[0].applyRotation( [ math.pi/2, 0, 0 ] , True)
|
||||
|
||||
chunks[1].applyMovement( [ 0, -0.75, 0 ] , True)
|
||||
|
||||
chunks[2].applyMovement( [ 0.1, 0, 0 ] , True)
|
||||
chunks[2].applyRotation( [ math.pi/4, 0, 0 ] , True)
|
||||
|
||||
chunks[3].applyRotation( [ -( math.pi/4 ), 0, 0, ] , True)
|
||||
|
||||
# Deleting the wooden part
|
||||
Reuse.Delete(part)
|
||||
|
||||
def LightStand(cont):
|
||||
|
||||
|
||||
|
||||
|
||||
#cont = bge.logic.getCurrentController()
|
||||
scene = bge.logic.getCurrentScene()
|
||||
part = cont.owner
|
||||
|
||||
colision = cont.sensors["Collision"]
|
||||
car = colision.hitObject
|
||||
|
||||
def do(cont, car, scene, part):
|
||||
|
||||
part["spawned_by"]["broken"] = True
|
||||
|
||||
|
||||
|
||||
head = None
|
||||
tail = None
|
||||
if Reuse.reuse.get("LightStand.Borked.Head"):
|
||||
# Head ( top part )
|
||||
head = Reuse.Create("LightStand.Borked.Head", 300, selfDestructInactive=True)
|
||||
Reuse.SelfDestruct(head, 600)
|
||||
head.position = part.position
|
||||
head.orientation = part.orientation
|
||||
|
||||
if Reuse.reuse.get("LightStand.Borked.Tail"):
|
||||
# Tail ( or leg )
|
||||
tail = Reuse.Create("LightStand.Borked.Tail", 300, selfDestructInactive=True)
|
||||
Reuse.SelfDestruct(tail, 600)
|
||||
tail.position = part.position
|
||||
tail.orientation = part.orientation
|
||||
tail.applyMovement( [ 0, 0, -1.3 ] , True)
|
||||
tail.localAngularVelocity = [random.uniform(-1,1),random.uniform(-1,1),random.uniform(-1,1)]
|
||||
|
||||
if car:
|
||||
cv = car.getLinearVelocity()
|
||||
if head: head.setLinearVelocity( cv )
|
||||
if tail: tail.setLinearVelocity( cv )
|
||||
|
||||
# Deleting the light stand
|
||||
Reuse.Delete(part)
|
||||
|
||||
if head:
|
||||
|
||||
# Sound
|
||||
device = bge.logic.globalDict["SoundDevice"]
|
||||
|
||||
s = "//sfx/hit.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]
|
||||
sound["play"] = device.play(sound["sound"])
|
||||
sound["play"].location = head.position
|
||||
sound["play"].velocity = head.getLinearVelocity()
|
||||
sound["play"].relative = False
|
||||
sound["play"].distance_maximum = 100
|
||||
sound["play"].distance_reference = 1
|
||||
sound["play"].attenuation = 1
|
||||
sound["play"].pitch = random.uniform(0.6, 1.4)
|
||||
sound["play"].volume = 5
|
||||
|
||||
if Opt.GoodFPS("LightStand", 0.9) or (car and car.get("active")):
|
||||
do(cont, car, scene, part)
|
||||
else:
|
||||
Opt.ScheduleTask("LightStand ["+str(id(part))+"]", 0.8, do,
|
||||
cont, car, scene, part)
|
||||
|
||||
def HouseShelf(cont):
|
||||
|
||||
# Performance kill switch
|
||||
if not Opt.GoodFPS("HouseShelf", 0.5):
|
||||
return
|
||||
|
||||
|
||||
#cont = bge.logic.getCurrentController()
|
||||
scene = bge.logic.getCurrentScene()
|
||||
part = cont.owner
|
||||
|
||||
part["spawned_by"]["broken"] = True
|
||||
|
||||
# -753 -940 412
|
||||
|
||||
despawn = 200
|
||||
|
||||
# Shelfs
|
||||
for i in range(5):
|
||||
shelf = Reuse.Create("Shelf", despawn)
|
||||
shelf.position = part.position
|
||||
shelf.orientation = part.orientation
|
||||
shelf.applyMovement([0.09,0,(0.3*i)-0.65], True)
|
||||
|
||||
# Legs
|
||||
leg = Reuse.Create("Shelf_Leg1", despawn)
|
||||
leg.position = part.position
|
||||
leg.orientation = part.orientation
|
||||
leg.applyMovement([1.3,0,0], True)
|
||||
|
||||
leg = Reuse.Create("Shelf_Leg2", despawn)
|
||||
leg.position = part.position
|
||||
leg.orientation = part.orientation
|
||||
leg.applyMovement([-1.1,0,0], True)
|
||||
|
||||
# Lego bricks
|
||||
brick = Reuse.Create("LegoBrick", despawn)
|
||||
brick.position = part.position
|
||||
brick.orientation = part.orientation
|
||||
brick.applyMovement([0.3,0,0.31], True)
|
||||
brick.applyRotation([0,0,-(math.pi/4)], True)
|
||||
|
||||
brick = Reuse.Create("LegoBrick", despawn)
|
||||
brick.position = part.position
|
||||
brick.orientation = part.orientation
|
||||
brick.applyMovement([-0.2,0,0], True)
|
||||
brick.applyRotation([0,0,-(math.pi/4)], True)
|
||||
|
||||
# Toy Boxes
|
||||
box = Reuse.Create("Toy_Box", despawn)
|
||||
box.position = part.position
|
||||
box.orientation = part.orientation
|
||||
box.applyMovement([-0.6,0,0], True)
|
||||
|
||||
box = Reuse.Create("Toy_Box", despawn)
|
||||
box.position = part.position
|
||||
box.orientation = part.orientation
|
||||
box.applyMovement([0.3,0,0.7], True)
|
||||
|
||||
box = Reuse.Create("Toy_Box", despawn)
|
||||
box.position = part.position
|
||||
box.orientation = part.orientation
|
||||
box.applyMovement([0.3,0,-0.7], True)
|
||||
|
||||
# Deleting the light stand
|
||||
Reuse.Delete(part)
|
||||
|
||||
# Sound
|
||||
device = bge.logic.globalDict["SoundDevice"]
|
||||
|
||||
s = "//sfx/wood.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]
|
||||
sound["play"] = device.play(sound["sound"])
|
||||
sound["play"].location = box.position
|
||||
sound["play"].velocity = box.getLinearVelocity()
|
||||
sound["play"].relative = False
|
||||
sound["play"].distance_maximum = 100
|
||||
sound["play"].distance_reference = 1
|
||||
sound["play"].attenuation = 1
|
||||
sound["play"].pitch = random.uniform(0.6, 1.4)
|
||||
sound["play"].volume = 5
|
|
@ -1,3 +0,0 @@
|
|||
# GPLv3-or-later
|
||||
# (C) J.Y.Amihud ( blenderdumbass )
|
||||
|
|
@ -26,11 +26,14 @@ from Scripts import Money
|
|||
from Scripts import Garage
|
||||
from Scripts import Racing
|
||||
from Scripts import Mouse
|
||||
from Scripts import Music
|
||||
|
||||
|
||||
from Scripts import Character_Controll
|
||||
from Scripts import Character
|
||||
from Scripts import Multiplayer_Client
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
|
||||
|
@ -48,7 +51,7 @@ def main():
|
|||
#dani["driving"]["nitro"] = 10.0
|
||||
|
||||
#Script.Story["Jack"].position = dani.position
|
||||
#Character_Controll.getOutCar(Script.Story["Jack"])
|
||||
#Character.getOutCar(Script.Story["Jack"])
|
||||
#Script.Story["DarkShadow"] = dani["driving"]
|
||||
# try:
|
||||
# Destruction.Explosion(dani["driving"].position, mass=10, size=10)
|
||||
|
@ -229,6 +232,8 @@ def main():
|
|||
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
|
||||
|
@ -775,7 +780,7 @@ def main():
|
|||
|
||||
|
||||
|
||||
|
||||
UnpressSimulatedPresses()
|
||||
|
||||
if keys and settings.get("dev-cheats"):
|
||||
|
||||
|
@ -796,7 +801,9 @@ def main():
|
|||
"DarkShadowBox": "DARKSHADOW",
|
||||
"TruckBox": "THETRUCK",
|
||||
"HatchBack01Box": "HATCHBACK1",
|
||||
"HatchBack02Box": "HATCHBACK2",
|
||||
"KartBox": "KARTCAR",
|
||||
|
||||
}
|
||||
|
||||
for i in cheats:
|
||||
|
@ -850,12 +857,16 @@ def main():
|
|||
|
||||
if code == numericalcode:
|
||||
if not dani.get("driving"):
|
||||
Character_Controll.ChangeCameraTarget(dani.children["Dani_cam_Target"], 100, [1,1,1])
|
||||
Character.ChangeCameraTarget(dani.children["Dani_cam_Target"], 100, [1,1,1])
|
||||
dani.position = i[0]
|
||||
|
||||
else:
|
||||
car = dani["driving"]
|
||||
zoom = car["specs"].get("cameraZoom", 3)
|
||||
Character.ChangeCameraTarget(car.children["CarCamTarget"], 40, [zoom,zoom,zoom])
|
||||
dani["driving"].position = i[0]
|
||||
dani["driving"].position.z += 2
|
||||
|
||||
|
||||
bge.logic.globalDict["cheat"] = [0]
|
||||
|
||||
|
@ -944,6 +955,16 @@ def main():
|
|||
bge.logic.globalDict["cheat"] = [0]
|
||||
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"]) # Play a Ding
|
||||
|
||||
# Policify the car
|
||||
code = bge.logic.globalDict["cheat"][-(len("policify")):]
|
||||
if code == [38,37,34,31,25,31,28,47]:
|
||||
car = dani.get("driving")
|
||||
Vehicle.Policify(car)
|
||||
bge.logic.globalDict["print"] = "You are a Policeman now, Sir."
|
||||
bge.logic.globalDict["cheat"] = [0]
|
||||
bge.logic.globalDict["SoundDevice"].play(bge.logic.globalDict["sounds"]["active"]["sound"]) # Play a Ding
|
||||
|
||||
|
||||
# Color Car code:
|
||||
code = bge.logic.globalDict["cheat"][-(len("colorcar")):]
|
||||
if code == [25, 37, 34, 37, 40, 25, 23, 40]:
|
||||
|
@ -1085,7 +1106,10 @@ def main():
|
|||
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")
|
||||
if dani["checkpoint"]+1 == len(race["checkpoints"]):
|
||||
nextcheck["cylinder"] = Reuse.Create("Starter.Cylinder")
|
||||
else:
|
||||
nextcheck["cylinder"] = Reuse.Create("Tag.Cylinder")
|
||||
nextcheck["cylinder"].position = nextcheck["location"]
|
||||
nextcheck["cylinder"].orientation = nextcheck["rotation"]
|
||||
nextcheck["cylinder"].scaling[0] = nextcheck["radius"] * 0.8
|
||||
|
@ -1106,9 +1130,11 @@ def main():
|
|||
|
||||
# Logging speed for better AI
|
||||
#if "raceData" not in race:
|
||||
nextcheck["speed"] = -dani["driving"].localLinearVelocity[1]
|
||||
nextcheck["time"] = currentRaceTime
|
||||
nextcheck["rot"] = list(dani["driving"].orientation.to_euler())
|
||||
try:
|
||||
nextcheck["speed"] = -dani["driving"].localLinearVelocity[1]
|
||||
nextcheck["time"] = currentRaceTime
|
||||
nextcheck["rot"] = list(dani["driving"].orientation.to_euler())
|
||||
except:pass
|
||||
#if race["positions"].index(dani) == 0:
|
||||
# race["raceData"]["speed"][dani["checkpoint"]] = -dani["driving"].localLinearVelocity[1]
|
||||
# race["raceData"]["time"][dani["checkpoint"]] = currentRaceTime
|
||||
|
@ -1400,6 +1426,14 @@ def main():
|
|||
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 FOR CHUNKS OF THE ROAD #############
|
||||
if "LODchunks" not in bge.logic.globalDict:
|
||||
bge.logic.globalDict["LODchunks"] = {"TheRacetrack":{
|
||||
|
@ -1679,3 +1713,15 @@ def main():
|
|||
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
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,7 +27,7 @@ import math
|
|||
import mathutils
|
||||
|
||||
from Scripts import Reuse
|
||||
from Scripts import Character_Controll
|
||||
from Scripts import Character
|
||||
from Scripts import Vehicle
|
||||
|
||||
def UpdateMapUI():
|
||||
|
@ -75,7 +75,7 @@ def UpdateMapUI():
|
|||
|
||||
mdi = scene.objects["Map_Dani_Indicator"]
|
||||
|
||||
rig = Character_Controll.getRig(dani)
|
||||
rig = Character.getRig(dani)
|
||||
r = (2*math.pi)-rig.worldOrientation.to_euler().z
|
||||
|
||||
r += cr
|
||||
|
|
192
Scripts/Map.py~
192
Scripts/Map.py~
|
@ -1,192 +0,0 @@
|
|||
# This file is for map functions.
|
||||
|
||||
# The points where the map image file ends in the
|
||||
# space of the game.
|
||||
|
||||
# ( Note the map is 180 degrees rotated from the in game orientation of everything.
|
||||
# This is due to modeling of the map ( while Moria's Race movie was being made ) was
|
||||
# made before the lore for whether this place is was made up. )
|
||||
|
||||
xs = -2633 # The most east point
|
||||
xe = 2383 # The most west point
|
||||
ys = -1911 # The most north point
|
||||
ye = 3106 # THe most south point
|
||||
|
||||
# Widths of that image file in meters.
|
||||
|
||||
xd = xe - xs
|
||||
yd = ye - ys
|
||||
|
||||
rr = 730 # Radius to the edge of the map in meters
|
||||
mr = 0.05 # Same radius by as a point on the map.
|
||||
map_factor = mr / rr # The factor by which the relative point is calculated.
|
||||
|
||||
|
||||
import bge
|
||||
import math
|
||||
import mathutils
|
||||
|
||||
from Scripts import Reuse
|
||||
from Scripts import Character_Controll
|
||||
from Scripts import Vehicle
|
||||
|
||||
def UpdateMapUI():
|
||||
|
||||
# Scene stuff
|
||||
scene = bge.logic.getCurrentScene()
|
||||
dani = scene.objects["Dani_Box"]
|
||||
cam = scene.active_camera
|
||||
|
||||
# Map widget
|
||||
cui = scene.objects["Map_UI"]
|
||||
|
||||
# Rotation
|
||||
|
||||
# We use the orientation of the camera
|
||||
# and rotating it 180 degrees for the map.
|
||||
|
||||
r = cam.orientation.to_euler().z
|
||||
r += math.pi
|
||||
if r > 2*math.pi: r -= 2*math.pi
|
||||
r = [0,0,r]
|
||||
cui.blenderObject["orientation"] = r
|
||||
|
||||
# Position
|
||||
|
||||
# This one is a bit harder, since it will
|
||||
# move the mapping of the image texture arround
|
||||
# in the material. And it's hard to tell it just
|
||||
# the coordinations ( also there is 180 degree flip ).
|
||||
|
||||
dl = dani.position
|
||||
|
||||
px = 1-( ( dl.x - xs ) / xd ) - 0.13
|
||||
py = 1-( ( dl.y - ys ) / yd ) - 0.12
|
||||
|
||||
p = [px,py,0]
|
||||
cui.blenderObject["position"] = p
|
||||
|
||||
# Map Dani Indicator
|
||||
|
||||
# This is even harder. Since the map is rotated with camera
|
||||
# this widget should by ofsetted by the camera rotation.
|
||||
|
||||
cr = r[2]
|
||||
|
||||
mdi = scene.objects["Map_Dani_Indicator"]
|
||||
|
||||
rig = Character_Controll.getRig(dani)
|
||||
r = (2*math.pi)-rig.worldOrientation.to_euler().z
|
||||
|
||||
r += cr
|
||||
if r > 2*math.pi: r -= 2*math.pi
|
||||
r = [0,r,0]
|
||||
|
||||
mdi.localOrientation = r
|
||||
|
||||
# Removing old show marks
|
||||
|
||||
database = bge.logic.globalDict.get("map-icons", {})
|
||||
for ID in list(database.keys()):
|
||||
data = database[ID]
|
||||
|
||||
#if data["obj"] in Reuse.reuse.get(str(data["obj"]), [])\
|
||||
|
||||
if data["updated"]+0.5 < bge.logic.getRealTime():
|
||||
|
||||
print("Removed", data["updated"], bge.logic.getRealTime())
|
||||
Reuse.Delete(data["icon"])
|
||||
del database[ID]
|
||||
|
||||
def Show(obj, color=[1,0,0], icon="Map_Icon_Directional", ID=""):
|
||||
|
||||
# This function will show things on the map.
|
||||
|
||||
# Scene stuff
|
||||
scene = bge.logic.getCurrentScene()
|
||||
dani = scene.objects["Dani_Box"]
|
||||
cam = scene.active_camera
|
||||
cui = scene.objects["Map_UI"]
|
||||
|
||||
# Making the icon database to track changes.
|
||||
if "map-icons" not in bge.logic.globalDict:
|
||||
bge.logic.globalDict["map-icons"] = {}
|
||||
|
||||
database = bge.logic.globalDict["map-icons"]
|
||||
|
||||
# Making sure that there is an object in the database
|
||||
if not ID:
|
||||
if type(obj) == list: ID = str(obj)
|
||||
else: ID = str(id(obj))
|
||||
|
||||
if ID not in database:
|
||||
database[ID] = {"obj":obj}
|
||||
|
||||
data = database[ID]
|
||||
data["updated"] = bge.logic.getRealTime()
|
||||
|
||||
# Making sure that there is an icon in the data
|
||||
|
||||
if "icon" not in data:
|
||||
|
||||
# Making an icon
|
||||
icon = Reuse.Create(icon, frompoint=cui)
|
||||
icon.setParent(cui, True, True)
|
||||
icon.worldScale = cui.worldScale * 2
|
||||
|
||||
|
||||
icon.applyRotation([math.pi/2,0,0], True)
|
||||
icon.blenderObject["color"] = color
|
||||
|
||||
data["icon"] = icon
|
||||
|
||||
icon = data["icon"]
|
||||
|
||||
# Now that we have the icon we can map it to the map
|
||||
|
||||
|
||||
f = map_factor
|
||||
|
||||
# Getting vector to the target
|
||||
try:
|
||||
t = obj.worldPosition.copy()
|
||||
torot = True
|
||||
except:
|
||||
t = mathutils.Vector(obj)
|
||||
torot = False
|
||||
|
||||
|
||||
d = dani.getDistanceTo(t)
|
||||
|
||||
if d > rr: # If the target out of range of the map
|
||||
f = mr / d # This puts the icon on the edge of the map
|
||||
|
||||
f *= cui.worldScale.x * 2
|
||||
|
||||
t = t - dani.worldPosition
|
||||
|
||||
cr = cam.worldOrientation.to_euler()
|
||||
cr = mathutils.Euler((0,0,-cr.z))
|
||||
t.rotate(cr)
|
||||
|
||||
|
||||
t = t * f
|
||||
t.z = 0.001
|
||||
|
||||
icon.worldPosition = Vehicle.RelativePoint(cui, t)
|
||||
|
||||
# Rotation
|
||||
if torot:
|
||||
|
||||
cr = cr.z
|
||||
|
||||
r = obj.worldOrientation.to_euler().z
|
||||
|
||||
r += cr
|
||||
if r > 2*math.pi: r -= 2*math.pi
|
||||
r = [math.pi/2,0,r]
|
||||
|
||||
icon.localOrientation = r
|
||||
|
||||
else:
|
||||
icon.localOrientation = [math.pi/2, 0,0]
|
|
@ -1,3 +0,0 @@
|
|||
# GPLv3 or later
|
||||
# (C) J.Y.Amihud ( blenderdumbass )
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
# Gpl3 or later
|
||||
# (C) J.Y.Amihud 2024
|
||||
|
||||
# Stuff related to mouse control
|
||||
|
||||
import bge
|
||||
|
||||
def MouseLook(cont):
|
||||
MouseLookActual(cont)
|
||||
|
||||
def MouseLookActual(cont, workanyway=False):
|
||||
|
||||
if not bge.logic.globalDict.get("mouse-active", True):
|
||||
return
|
||||
|
||||
|
||||
# We need this to be able disable mouse look from the
|
||||
# the code.
|
||||
|
||||
# Getting object that will rotate.
|
||||
if type(cont) == bge.types.SCA_PythonController:
|
||||
obj = cont.owner
|
||||
else: obj = cont
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
dani = scene.objects["Dani_Box"]
|
||||
|
||||
# Disabling the camera rotation
|
||||
if not workanyway and dani.get("driving") and dani["driving"].get("dynamiccam", True):
|
||||
return
|
||||
|
||||
|
||||
# Getting mouse position on the screen.
|
||||
mouse = bge.logic.mouse
|
||||
pos = list(mouse.position)
|
||||
|
||||
# Mouse positions are normalized to be 0.5 at the center.
|
||||
# We need center to be 0.0.
|
||||
pos[0] -= 0.5
|
||||
pos[1] -= 0.5
|
||||
|
||||
if round(pos[0], 2) == 0:
|
||||
pos[0] = 0
|
||||
|
||||
if round(pos[1], 2) == 0:
|
||||
pos[1] = 0
|
||||
|
||||
# Getting factor information about how to move the mouse
|
||||
# from the object.
|
||||
my = -obj.get("mouse_Y", 1.0)
|
||||
mx = -obj.get("mouse_X", 1.0)
|
||||
mg = obj.get("mouse_global", True)
|
||||
|
||||
# Applying the rotation.
|
||||
obj.applyRotation((pos[1]*my, 0, pos[0]*mx), mg)
|
||||
|
||||
# Centring the mouse.
|
||||
CenterCursor()
|
||||
|
||||
def CenterCursor():
|
||||
if not bge.logic.globalDict.get("mouse-active", True):
|
||||
return
|
||||
bge.render.setMousePosition(int(bge.render.getWindowWidth() / 2), int(bge.render.getWindowHeight() / 2))
|
||||
|
|
@ -11,7 +11,7 @@ import zlib
|
|||
import traceback
|
||||
|
||||
from Scripts import Vehicle
|
||||
from Scripts import Character_Controll
|
||||
from Scripts import Character
|
||||
from Scripts import Opt
|
||||
from Scripts import Settings
|
||||
from Scripts.Multiplayer_Shared import *
|
||||
|
@ -39,7 +39,7 @@ def DescribeScene():
|
|||
if addr not in data:
|
||||
data[addr] = []
|
||||
|
||||
danidata = Character_Controll.Encode(dani)
|
||||
danidata = Character.Encode(dani)
|
||||
data[addr].append(danidata)
|
||||
|
||||
userId = bge.logic.globalDict.get("userId")
|
||||
|
@ -204,7 +204,7 @@ def SceneDecode(data):
|
|||
if obj.get("type") == "veh":
|
||||
Vehicle.Decode(obj, network=True)
|
||||
elif obj.get("type") == "chr":
|
||||
Character_Controll.Decode(obj, network=True)
|
||||
Character.Decode(obj, network=True)
|
||||
|
||||
rIds.append(obj.get("netId"))
|
||||
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
# GPLv3 or later
|
||||
# (C) J.Y.Amihud ( blenderdumbass ) 2024
|
||||
|
||||
# Multiplayer client functions
|
||||
|
||||
import bge
|
||||
import time
|
||||
import json
|
||||
import zlib
|
||||
|
||||
from Scripts import Vehicle
|
||||
from Scripts import Character_Controll
|
||||
from Scripts import Opt
|
||||
from Scripts import Settings
|
||||
from Scripts.Multiplayer_Shared import *
|
||||
from Scripts import Reuse
|
||||
|
||||
from Scripts.Common import *
|
||||
|
||||
|
||||
settings = Settings.load_settings()
|
||||
host = settings.get("mp-host", "")
|
||||
|
||||
def DescribeScene():
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
dani = scene.objects["Dani_Box"]
|
||||
cam = scene.active_camera
|
||||
|
||||
chunksize = 250
|
||||
|
||||
data = {}
|
||||
addr = Opt.Address(dani.position, chunksize)
|
||||
if addr not in data:
|
||||
data[addr] = []
|
||||
|
||||
danidata = Character_Controll.Encode(dani)
|
||||
data[addr].append(danidata)
|
||||
|
||||
for car in bge.logic.globalDict["allcars"]:
|
||||
if car.get("inview"):
|
||||
addr = Opt.Address(car.position, chunksize)
|
||||
cardata = Vehicle.Encode(car)
|
||||
if addr not in data:
|
||||
data[addr] = []
|
||||
data[addr].append(cardata)
|
||||
|
||||
return data
|
||||
|
||||
def MainLoop():
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
dani = scene.objects["Dani_Box"]
|
||||
cam = scene.active_camera
|
||||
chunksize = 250
|
||||
|
||||
while True:
|
||||
try:
|
||||
|
||||
|
||||
# Testing if the game is still runing.
|
||||
# it will fail when the game engine stops.
|
||||
try: bge.logic.getRealTime()
|
||||
except: return
|
||||
|
||||
# A bit of delay, to not owerwhelm the server
|
||||
time.sleep(0.2)
|
||||
|
||||
|
||||
######### SENDING THE DATA TO SERVER ############
|
||||
|
||||
data = {}
|
||||
|
||||
# Login
|
||||
LoginEncode(data)
|
||||
|
||||
# Scene
|
||||
data["scene"] = DescribeScene()
|
||||
data["vision"] = Opt.Surround(cam.position,
|
||||
chunksize,
|
||||
cam.orientation.to_euler())
|
||||
|
||||
|
||||
######### DEALING WITH RESPONSE ############
|
||||
|
||||
data = Send(host, data)
|
||||
|
||||
for key in data:
|
||||
|
||||
payload = data[key]
|
||||
|
||||
if key == "login":
|
||||
LoginDecode(payload)
|
||||
elif key == "scene":
|
||||
SceneDecode(payload)
|
||||
|
||||
else:
|
||||
print(key, payload)
|
||||
|
||||
except Exception as e:
|
||||
print(clr["tdrd"], e, clr["norm"])
|
||||
|
||||
|
||||
|
||||
def LoginEncode(data):
|
||||
|
||||
data["login"] = {}
|
||||
data["login"]["userId"] = bge.logic.globalDict.get("userId")
|
||||
data["login"]["username"] = settings.get("mp-name")
|
||||
data["login"]["room"] = settings.get("mp-room")
|
||||
|
||||
def LoginDecode(data):
|
||||
|
||||
if data.get("userId"):
|
||||
bge.logic.globalDict["userId"] = data["userId"]
|
||||
|
||||
def SceneDecode(data):
|
||||
|
||||
netObjects = bge.logic.globalDict["netObjects"]
|
||||
|
||||
if not data:
|
||||
return
|
||||
|
||||
for addr in data:
|
||||
chunk = data[addr]
|
||||
|
||||
for obj in chunk:
|
||||
|
||||
# Sometimes we want to update some things like netId.
|
||||
if obj.get("ID") in netObjects["pythonId"]\
|
||||
and obj.get("name") == netObjects["pythonId"][obj["ID"]].name:
|
||||
netObjects["pythonId"][obj["ID"]]["netId"] = obj.get("netId")
|
||||
|
||||
|
||||
else:
|
||||
|
||||
if obj.get("type") == "veh":
|
||||
Vehicle.Decode(obj)
|
||||
|
||||
# elif obj.get("netId") not in netObjects["netId"]:
|
||||
|
||||
# try:
|
||||
# OBJ = Reuse.Create(obj.get("name"))
|
||||
# except:
|
||||
# OBJ = Reuse.Create("MoriaBox")
|
||||
|
||||
# netObjects["netId"][obj.get("netId")] = OBJ
|
||||
|
||||
# OBJ = netObjects["netId"][obj.get("netId")]
|
||||
# OBJ.position = obj.get("position", (0,0,0))
|
||||
# OBJ.orientation = obj.get("orientation", (0,0,0))
|
||||
|
||||
|
|
@ -1,470 +0,0 @@
|
|||
# GNU GPL v3 or later
|
||||
# ( C ) J.Y.Amihud ( blenderdumbass ) 2024
|
||||
|
||||
import os
|
||||
import sys
|
||||
import zlib
|
||||
import json
|
||||
import time
|
||||
import threading
|
||||
import subprocess
|
||||
|
||||
import Settings
|
||||
from Common import *
|
||||
from Multiplayer_Shared import *
|
||||
|
||||
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
class handler(BaseHTTPRequestHandler):
|
||||
|
||||
def do_POST(self):
|
||||
|
||||
data = self.Recieve()
|
||||
response = ParseRequest(data)
|
||||
self.Send(response)
|
||||
|
||||
def Send(self, data):
|
||||
|
||||
# Compressing
|
||||
data = json.dumps(data)
|
||||
data = data.encode("utf-8")
|
||||
data = zlib.compress(data)
|
||||
|
||||
# Sending
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type","application/zip")
|
||||
self.end_headers()
|
||||
self.wfile.write(data)
|
||||
|
||||
def Recieve(self):
|
||||
|
||||
length = int(self.headers.get('content-length'))
|
||||
data = self.rfile.read(length)
|
||||
|
||||
data = zlib.decompress(data)
|
||||
data = json.loads(data)
|
||||
return data
|
||||
|
||||
def log_message(self, format, *args):
|
||||
# I don't want any logs.
|
||||
return
|
||||
|
||||
def ParseRequest(data):
|
||||
|
||||
resp = {}
|
||||
|
||||
for key in data:
|
||||
|
||||
payload = data[key]
|
||||
|
||||
if "login" == key:
|
||||
resp[key] = Login(payload)
|
||||
|
||||
|
||||
elif "change-ownership" == key:
|
||||
resp[key] = ChangeOwnership(payload)
|
||||
|
||||
elif "scene" == key:
|
||||
resp[key] = Scene(data)
|
||||
|
||||
elif "vision" == key:
|
||||
pass
|
||||
|
||||
else:
|
||||
print(key, payload)
|
||||
|
||||
# Timing data
|
||||
resp["timing"] = Timing(data)
|
||||
resp["serverTime"] = time.time()
|
||||
|
||||
userId = data.get("login", {}).get("userId")
|
||||
room = Safe(data.get("login", {}).get("room"))
|
||||
messages = LoadData("messages", {}, room)
|
||||
if messages.get(userId):
|
||||
resp["message"] = messages[userId].pop(0)
|
||||
SaveData("messages", messages, room)
|
||||
|
||||
return resp
|
||||
|
||||
def Timing(data):
|
||||
|
||||
users = LoadData("users", {})
|
||||
room = data.get('login', {}).get("room", "")
|
||||
resp = {}
|
||||
for userId in users:
|
||||
user = users[userId]
|
||||
if user.get("room") == room:
|
||||
resp[userId] = {}
|
||||
resp[userId]["ping"] = user.get("ping")
|
||||
resp[userId]["timestamp"] = user.get("timestamp")
|
||||
|
||||
return resp
|
||||
|
||||
def Login(data):
|
||||
|
||||
resp = {}
|
||||
newuser = False
|
||||
|
||||
# Checking userId
|
||||
if not data.get("userId"):
|
||||
resp["userId"] = RandomString()
|
||||
|
||||
|
||||
# Checking room
|
||||
if not data.get("room"):
|
||||
resp["room"] = "MainRoom"
|
||||
elif data.get("room") != Safe(data.get("room", "")):
|
||||
resp["room"] = Safe(data["room"])
|
||||
|
||||
data["timestamp"] = time.time()
|
||||
|
||||
# Storring users data.
|
||||
|
||||
users = LoadData("users", {})
|
||||
|
||||
if data.get("userId") and data.get("userId") not in users:
|
||||
newuser = True
|
||||
|
||||
if data.get("userId"):
|
||||
users[data["userId"]] = data
|
||||
|
||||
SaveData("users", users)
|
||||
|
||||
if newuser:
|
||||
userId = data.get("userId")
|
||||
name = data.get("username")
|
||||
room = Safe(data.get("room"))
|
||||
NotifyOthers(userId, name+" joined game.", room)
|
||||
print(Format(userId), "JOINED GAME!")
|
||||
|
||||
return resp
|
||||
|
||||
def ChangeOwnership(data):
|
||||
|
||||
print(Format(data.get("userId")), "GRABBED", Format(data.get("netId")))
|
||||
|
||||
objects = LoadData("objects", {})
|
||||
if data.get("netId") in objects:
|
||||
obj = objects[data.get("netId")]
|
||||
obj["ownerId"] = data.get("userId")
|
||||
|
||||
SaveData("objects", objects)
|
||||
|
||||
# Changing ownership in chunk
|
||||
addr = obj.get("chunk")
|
||||
room = Safe(obj.get("room"))
|
||||
chunk = LoadData(addr, {}, room)
|
||||
for o in chunk:
|
||||
if o.get("netId") == data.get("netId"):
|
||||
o["ownerId"] = data.get("userId")
|
||||
SaveData(addr, chunk, room)
|
||||
|
||||
return True
|
||||
else:
|
||||
print(Format(data.get("netId")),"netId:",data.get("netId"), "NOT FOUND, WHILE CHANGING OWNERSHIP!")
|
||||
return False
|
||||
|
||||
def Scene(data):
|
||||
|
||||
scene = data["scene"]
|
||||
userId = data.get("login", {}).get("userId")
|
||||
room = Safe(data.get("login", {}).get("room", "MainRoom"))
|
||||
|
||||
# We are not updating scene if there is no userId yet.
|
||||
if not userId:
|
||||
return
|
||||
|
||||
# Reading scene payload.
|
||||
|
||||
resp = {}
|
||||
objects = LoadData("objects", {})
|
||||
|
||||
for addr in scene:
|
||||
chunk = scene[addr]
|
||||
|
||||
for obj in chunk:
|
||||
|
||||
# Some people might want to cheat by inputing
|
||||
# values for other users.
|
||||
if obj.get("netId"):
|
||||
|
||||
|
||||
obj["ownerId"] = objects.get(obj.get("netId"), {}).get("ownerId")
|
||||
if not obj["ownerId"]:
|
||||
obj["ownerId"] = userId
|
||||
|
||||
if obj.get("ownerId") and obj.get("ownerId") != userId:
|
||||
chunk.remove(obj)
|
||||
|
||||
|
||||
|
||||
|
||||
# Saving chunks data.
|
||||
|
||||
for addr in scene:
|
||||
chunk = scene[addr]
|
||||
saved = LoadData(addr, [], room)
|
||||
add = []
|
||||
|
||||
# Cleaning up
|
||||
for obj in saved:
|
||||
if obj.get("netId") not in objects or objects[obj.get("netId")].get("chunk") != addr:
|
||||
saved.remove(obj)
|
||||
|
||||
ids = []
|
||||
for obj in saved:
|
||||
ids.append(obj.get("netId"))
|
||||
|
||||
for obj in chunk:
|
||||
|
||||
# If object is Dani and it has no netId
|
||||
# we assume that somebody new joined the
|
||||
# room.
|
||||
|
||||
if obj.get("name") == "Dani_Box" and not obj.get("netId"):
|
||||
obj["netId"] = userId
|
||||
obj["ownerId"] = userId
|
||||
add.append(obj)
|
||||
|
||||
|
||||
elif not obj.get("netId"):
|
||||
obj["netId"] = RandomString()
|
||||
obj["ownerId"] = userId
|
||||
add.append(obj)
|
||||
|
||||
if obj.get("netId") not in ids:
|
||||
saved.append(obj)
|
||||
|
||||
else:
|
||||
saved[ids.index(obj.get("netId"))] = obj
|
||||
|
||||
|
||||
objects[obj["netId"]] = {"chunk":addr,
|
||||
"name":obj.get("name"),
|
||||
"timestamp":time.time(),
|
||||
"ownerId":obj.get("ownerId"),
|
||||
"room":room}
|
||||
|
||||
SaveData(addr, saved, room)
|
||||
|
||||
if addr in data.get("vision", []):
|
||||
resp[addr] = []
|
||||
for obj in saved:
|
||||
if obj.get("ownerId") != userId:
|
||||
resp[addr].append(obj)
|
||||
for obj in add:
|
||||
resp[addr].append(obj)
|
||||
|
||||
|
||||
SaveData("objects", objects)
|
||||
|
||||
|
||||
|
||||
return resp
|
||||
|
||||
def Notify(userId, message, room):
|
||||
|
||||
messages = LoadData("messages", {}, room)
|
||||
if userId not in messages:
|
||||
messages[userId] = []
|
||||
messages[userId].append(message)
|
||||
SaveData("messages", messages, room)
|
||||
|
||||
def NotifyOthers(userId, message, room):
|
||||
|
||||
users = LoadData("users", {})
|
||||
for user in users:
|
||||
if user != userId and users[user].get("room") == room:
|
||||
Notify(user, message, room)
|
||||
|
||||
def SaveData(name, data, room=None):
|
||||
|
||||
# Making folder for server stuff
|
||||
folder = Settings.get_settings_folder()+"/server/"
|
||||
if room: folder = folder+str(room)+"/"
|
||||
try: os.makedirs(folder)
|
||||
except: pass
|
||||
|
||||
# Saving the json
|
||||
with open(folder+str(name)+".json", "w") as save:
|
||||
json.dump(data, save, indent=4)
|
||||
|
||||
def LoadData(name, otherwise=None, room=None):
|
||||
|
||||
try:
|
||||
folder = Settings.get_settings_folder()+"/server/"
|
||||
if room: folder = folder+str(room)+"/"
|
||||
with open(folder+str(name)+".json") as o:
|
||||
return json.load(o)
|
||||
except: return otherwise
|
||||
|
||||
def Safe(string):
|
||||
|
||||
# This function stripts strings from any unsafe
|
||||
# characters.
|
||||
|
||||
good = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_"
|
||||
new = ""
|
||||
for i in string:
|
||||
if i in good: new = new + i
|
||||
else: new = new + "_"
|
||||
|
||||
return new
|
||||
|
||||
def Format(netId, room=True):
|
||||
|
||||
objects = LoadData("objects",{})
|
||||
users = LoadData("users",{})
|
||||
|
||||
if netId in users:
|
||||
name = users[netId].get("username", "Unknown")
|
||||
room = users[netId].get("room", "Unknown Room")
|
||||
ownerId = netId
|
||||
owner = ""
|
||||
else:
|
||||
name = objects.get(netId, {}).get("name", "Unknown Object")
|
||||
room = objects.get(netId, {}).get("room", "Unknown Room")
|
||||
ownerId = objects.get(netId, {}).get("ownerId")
|
||||
owner = users.get(ownerId, {}).get("username", "Unknown")
|
||||
|
||||
string = IDcolor(room)+" "+room+" "+IDcolor(netId)+" "+netId[-4:]+" "+name
|
||||
if owner and ownerId:
|
||||
string = string + " " + IDcolor(ownerId) + " by "+ownerId[-4:]+" " + owner
|
||||
string = string + " " + clr["norm"]
|
||||
|
||||
return string
|
||||
|
||||
|
||||
|
||||
###### RUNNING THE SERVER #####
|
||||
|
||||
def ArgumentsHandler():
|
||||
|
||||
port = 6969
|
||||
ipv6 = "-4"
|
||||
|
||||
if "--help" in sys.argv or "-h" in sys.argv:
|
||||
print("""
|
||||
This is the Multiplayer server for Dani's Race.
|
||||
It is technically an HTTP server that handles
|
||||
POST requests send by the game. Those requests
|
||||
are in a JSON format compressed with python's
|
||||
ZLIB library. There is no webpage, so trying to
|
||||
access it with a browser will probably spit out
|
||||
an error.
|
||||
|
||||
"""+clr["bold"]+clr["tdyl"]+"""RUN THIS SERVER FROM THE "Scripts" FOLDER!"""+clr["norm"]+"""
|
||||
|
||||
--help , -h : This Help Text.
|
||||
--port """+clr["tdyl"]+"""<number>"""+clr["norm"]+""" : Sets up a port on which the
|
||||
server will listen.
|
||||
--ipv6 , -6 : Use IPv6 connection for global network.
|
||||
|
||||
""")
|
||||
exit()
|
||||
|
||||
if "--port" in sys.argv:
|
||||
try:
|
||||
port = int(sys.argv[ sys.argv.index("--port")+1 ])
|
||||
except:
|
||||
print("Didn't specify port number.\nExample ( for port 8080 ): $ python3 Multiplayer_Server.py --port 8080")
|
||||
exit()
|
||||
|
||||
if "--ipv6" in sys.argv or "-6" in sys.argv:
|
||||
ipv6 = "-6"
|
||||
|
||||
return port, ipv6
|
||||
|
||||
PORT, IPV6 = ArgumentsHandler()
|
||||
|
||||
print(clr["bold"]+"Dani's Race Multiplayer Server!"+clr["norm"])
|
||||
|
||||
###### CLEANUPS #####
|
||||
|
||||
def CleanUps():
|
||||
|
||||
while True:
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
# Cleaning up users
|
||||
|
||||
users = LoadData("users", {})
|
||||
delete = []
|
||||
for userId in users:
|
||||
user = users[userId]
|
||||
room = user.get("room")
|
||||
name = user.get("username")
|
||||
|
||||
# If user missing for 10 seconds, he is gone.
|
||||
if user.get("timestamp", 0) < time.time() -10:
|
||||
|
||||
NotifyOthers(userId, name+" left the game.", room)
|
||||
print(Format(userId), "LEFT GAME!")
|
||||
delete.append(userId)
|
||||
|
||||
for i in delete:
|
||||
del users[i]
|
||||
|
||||
SaveData("users", users)
|
||||
|
||||
objects = LoadData("objects", {})
|
||||
delete = []
|
||||
for netId in objects:
|
||||
obj = objects[netId]
|
||||
|
||||
# Deleting objects after 5 missing seconds
|
||||
if obj.get("timestamp", 0) < time.time() -5:
|
||||
delete.append(netId)
|
||||
|
||||
for i in delete:
|
||||
del objects[i]
|
||||
|
||||
SaveData("objects", objects)
|
||||
|
||||
|
||||
cleanups = threading.Thread(target=CleanUps)
|
||||
cleanups.daemon = True
|
||||
cleanups.start()
|
||||
print("Started cleanups thread.")
|
||||
|
||||
|
||||
print(clr["bold"]+"Starting server:", clr["norm"])
|
||||
|
||||
try:
|
||||
IP = subprocess.check_output(["hostname", "-I"]).decode("utf-8").split(" ")[0]
|
||||
except:
|
||||
try:
|
||||
# Some versions of hostname just have the -i option that acts like -I in
|
||||
# other versions.
|
||||
IP = subprocess.check_output(["hostname", "-i"]).decode("utf-8").split(" ")[0]
|
||||
except:
|
||||
IP = clr["tdrd"]+"127.0.0.1"+clr["norm"]
|
||||
|
||||
if not IP or IP == "\n":
|
||||
IP = clr["tdrd"]+"127.0.0.1"+clr["norm"]
|
||||
print(" Local IP:", clr["bold"], IP, clr["norm"])
|
||||
|
||||
try:
|
||||
GLOBALIP = subprocess.check_output(["curl", "-s", IPV6, "ifconfig.co"]).decode("utf-8")[:-1]
|
||||
print(" Global IP:", clr["bold"], GLOBALIP, clr["norm"])
|
||||
except:
|
||||
GLOBALIP = None
|
||||
print(" Global IP:",clr["tdrd"]+clr["bold"], "No connection to Global Network.", clr["norm"])
|
||||
|
||||
print(" Port:", clr["bold"], PORT, clr["norm"])
|
||||
print(" Local Hostname:", clr["bold"], "http://"+IP+":"+str(PORT), clr["norm"])
|
||||
if GLOBALIP:
|
||||
if IPV6 == "-4":
|
||||
print(" Global Hostname:", clr["bold"], "http://"+GLOBALIP+":"+str(PORT), clr["norm"])
|
||||
else:
|
||||
print(" Global Hostname:", clr["bold"], "http://["+GLOBALIP+"]:"+str(PORT), clr["norm"])
|
||||
|
||||
print()
|
||||
serve = HTTPServer(("", PORT), handler)
|
||||
try:
|
||||
serve.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
print("Server Exited!")
|
|
@ -1,40 +0,0 @@
|
|||
# GPLv3 or later
|
||||
# ( C ) J.Y.Amihud ( blenderdumbass ) 2024
|
||||
|
||||
import os
|
||||
import json
|
||||
import zlib
|
||||
import random
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
|
||||
def RandomString(size=64):
|
||||
|
||||
# This will generate random strings, primarily
|
||||
# for the purpose of recognizing the same objects
|
||||
# on the network.
|
||||
|
||||
good = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
|
||||
|
||||
text = ""
|
||||
for i in range(size):
|
||||
text = text + random.choice(good)
|
||||
|
||||
return text
|
||||
|
||||
def Send(host, data):
|
||||
|
||||
# Compressing
|
||||
data = json.dumps(data)
|
||||
data = data.encode("utf-8")
|
||||
data = zlib.compress(data)
|
||||
|
||||
# Sending
|
||||
req = urllib.request.Request(host, data=data)
|
||||
|
||||
# Recieving
|
||||
data = urllib.request.urlopen(req).read()
|
||||
data = zlib.decompress(data)
|
||||
data = json.loads(data)
|
||||
|
||||
return data
|
515
Scripts/Opt.py~
515
Scripts/Opt.py~
|
@ -1,515 +0,0 @@
|
|||
import bge
|
||||
import math
|
||||
import numpy
|
||||
import mathutils
|
||||
|
||||
r = math.radians
|
||||
|
||||
from Scripts import Reuse
|
||||
from Scripts.Common import *
|
||||
|
||||
# Chunks to store data about parts of the world
|
||||
chunks = {}
|
||||
bge.logic.globalDict["Opt.chunks"] = chunks
|
||||
|
||||
camspeed = 0.0
|
||||
camposition = mathutils.Vector((0,0,0))
|
||||
camspeedframe = 0.0
|
||||
|
||||
def CameraSpeed():
|
||||
|
||||
# This function gives the average speed of the
|
||||
# camera at any given frame.
|
||||
frame = round(bge.logic.getRealTime(), 2)
|
||||
|
||||
global camspeed
|
||||
global camposition
|
||||
global camspeedframe
|
||||
|
||||
if frame != camspeedframe:
|
||||
camspeedframe = frame
|
||||
|
||||
# Getting velocity of the camera
|
||||
p = bge.logic.getCurrentScene().active_camera.worldPosition
|
||||
v = p - camposition
|
||||
camposition = p.copy()
|
||||
|
||||
# Averaging the velocity
|
||||
av = 0
|
||||
for i in v:
|
||||
if i > 0: av += i
|
||||
else : av -= i
|
||||
av /= 3
|
||||
|
||||
# Storing the value
|
||||
camspeed = av
|
||||
|
||||
# Returning the value
|
||||
return camspeed
|
||||
|
||||
|
||||
|
||||
|
||||
def ToFPS():
|
||||
|
||||
# Return a fraction that is useful to adjust FPS
|
||||
# sensitive values like gravity.
|
||||
|
||||
return 60/bge.logic.getAverageFrameRate()
|
||||
|
||||
# Global Variables for GoodFPS function to work.
|
||||
fpshistory = {} # History of last 200 or so frames FPS
|
||||
targetFPS = 1 # Target FPS which to aim to preserve
|
||||
FPStargets = {} # Database of how much a given function effects FPS
|
||||
testingTarget = False # Fuction that is being tested for how much it effects FPS
|
||||
testingTargetFrame = 0 # Frame where the test is started
|
||||
testFPS = 60 # The FPS before the test started
|
||||
limitframe = 0 # The Frame that is currently being calculated for expected FPS
|
||||
expectedfps = 60 # Expected FPS with running functions tested effects removed from current FPS
|
||||
|
||||
|
||||
def GoodFPS(func="", factor=1, boolean=True, traceback=False, ):
|
||||
|
||||
settings = bge.logic.globalDict.get("settings", {})
|
||||
|
||||
global targetFPS
|
||||
|
||||
# Recording the framerate into buffer
|
||||
# This buffer will be used to regulate the target FPS
|
||||
|
||||
fps = bge.logic.getAverageFrameRate()
|
||||
frame = round(bge.logic.getRealTime(), 2)
|
||||
camspeed = min(CameraSpeed(), 1)
|
||||
global fpshistory
|
||||
fpshistory[frame] = fps
|
||||
|
||||
# Limiting execution based on camera speed.
|
||||
if boolean and numpy.random.choice([True, False], p=[camspeed, 1-camspeed]):
|
||||
return False
|
||||
|
||||
# Setting the target fps
|
||||
if frame > 5:# and fps > targetFPS:
|
||||
|
||||
if not settings.get("autofps"):
|
||||
targetFPS = bge.logic.getLogicTicRate()
|
||||
|
||||
else:
|
||||
targetFPS = max(fpshistory.values())
|
||||
targetFPS *= 1.1
|
||||
if not boolean and int(frame) % 30 == 0:
|
||||
bge.logic.setLogicTicRate(int(targetFPS))
|
||||
|
||||
|
||||
# Slicing buffer to contain only last 300 records
|
||||
newfpshistory = {}
|
||||
for i in list(fpshistory.keys())[-300:]:
|
||||
newfpshistory[i] = fpshistory[i]
|
||||
fpshistory = newfpshistory
|
||||
|
||||
# Calculating the fraction ( of how much are we within the target FPS )
|
||||
fraction = ( sum( min(f, targetFPS) for f in fpshistory.values()) / len(fpshistory) ) / targetFPS
|
||||
|
||||
# Testing FPS impacts of various functions to see
|
||||
# how much to limit them.
|
||||
global FPStargets
|
||||
global testFPS
|
||||
global testingTarget
|
||||
global testingTargetFrame
|
||||
|
||||
# This runs when the target for testing is already setup
|
||||
if testingTarget:
|
||||
|
||||
# If we have some decrease in performace, we calculate how much it effects the FPS
|
||||
if frame > testingTargetFrame and fps+1 < testFPS:
|
||||
FPStargets[testingTarget] = {"fraction":fps / testFPS, "frame":frame}
|
||||
testingTarget = False
|
||||
|
||||
# Otherwise we cancel the test
|
||||
elif frame -2 > testingTargetFrame:
|
||||
testingTarget = False
|
||||
|
||||
# While we testing, we want to return False, so nothing else will effect the FPS
|
||||
if boolean: return False
|
||||
else: return 0.0
|
||||
|
||||
# This runs to start the test
|
||||
if ( func and func not in FPStargets and 10 < frame or FPStargets.get(func, {}).get("frame", frame) + 60 < frame ) and fraction > factor:
|
||||
testFPS = fps
|
||||
testingTarget = func
|
||||
testingTargetFrame = frame
|
||||
|
||||
# And we want to return True so the function will get launched.
|
||||
if boolean: return True
|
||||
else: return 1.0
|
||||
|
||||
# Limiting functions based on the tests
|
||||
global limitframe
|
||||
global expectedfps
|
||||
|
||||
# Findinf the limiting factor
|
||||
try:
|
||||
targetFactor = min(n.get("fraction") for n in FPStargets.values()) * factor
|
||||
except:
|
||||
targetFactor = factor
|
||||
|
||||
# Limiting
|
||||
if expectedfps * FPStargets.get(func, {}).get("fraction", 1) < targetFPS * targetFactor:
|
||||
if boolean: return False
|
||||
|
||||
# If we allow the function to run
|
||||
# we want to recalculate the expected FPS
|
||||
# based on the tests
|
||||
if limitframe != frame:
|
||||
|
||||
# If the tests data is flawed
|
||||
if int(expectedfps) > int(fps)+2:
|
||||
FPStargets = {}
|
||||
|
||||
# Calculating expected FPS
|
||||
expectedfps = fps*FPStargets.get(func, {}).get("fraction", 1)
|
||||
limitframe = frame
|
||||
else:
|
||||
expectedfps *= FPStargets.get(func, {}).get("fraction", 1)
|
||||
|
||||
# Returning
|
||||
if boolean:
|
||||
return True#fraction > factor
|
||||
else:
|
||||
return fraction
|
||||
|
||||
|
||||
def Address(location, precision):
|
||||
|
||||
# This function will return an adress of any given location
|
||||
# Which could be used to compare between objects to see if they
|
||||
# are close enough together.
|
||||
|
||||
ret = ""
|
||||
for axis in location[:2]:
|
||||
ret = ret + str(round(axis/precision))+":"
|
||||
return ret
|
||||
|
||||
def Surround(location, precision, camera=None):
|
||||
|
||||
# This function will give a list of addresses around a certain point.
|
||||
|
||||
ret = []
|
||||
ORL = []
|
||||
addedtypes = []
|
||||
for axis in location[:2]:
|
||||
ORL.append(round(axis/precision))
|
||||
|
||||
ret.append(Address(ORL, 1))
|
||||
|
||||
|
||||
|
||||
if not camera:
|
||||
# X
|
||||
if (location[0]/precision) - round(location[0]/precision) < 0.5:
|
||||
ret.append(Address([ORL[0]-1, ORL[1]], 1))
|
||||
addedtypes.append("-x")
|
||||
elif (location[0]/precision) - round(location[0]/precision) > 0.5:
|
||||
ret.append(Address([ORL[0]+1, ORL[1]], 1))
|
||||
addedtypes.append("+x")
|
||||
|
||||
# Y
|
||||
if (location[1]/precision) - round(location[1]/precision) < 0.5:
|
||||
ret.append(Address([ORL[0], ORL[1]-1], 1))
|
||||
addedtypes.append("-y")
|
||||
elif (location[1]/precision) - round(location[1]/precision) > 0.5:
|
||||
ret.append(Address([ORL[0], ORL[1]+1], 1))
|
||||
addedtypes.append("+y")
|
||||
|
||||
# Diagonals
|
||||
if "+x" in addedtypes and "+y" in addedtypes:
|
||||
ret.append(Address([ORL[0]+1, ORL[1]+1], 1))
|
||||
elif "-x" in addedtypes and "-y" in addedtypes:
|
||||
ret.append(Address([ORL[0]-1, ORL[1]-1], 1))
|
||||
elif "-x" in addedtypes and "+y" in addedtypes:
|
||||
ret.append(Address([ORL[0]-1, ORL[1]+1], 1))
|
||||
elif "+x" in addedtypes and "-y" in addedtypes:
|
||||
ret.append(Address([ORL[0]+1, ORL[1]-1], 1))
|
||||
|
||||
else:
|
||||
if r(70) >= camera[2] >= r(-70):
|
||||
ret.append(Address([ORL[0], ORL[1]+1], 1))
|
||||
|
||||
if r(25) >= camera[2] >= r(-115):
|
||||
ret.append(Address([ORL[0]+1, ORL[1]+1], 1))
|
||||
|
||||
if r(-20) >= camera[2] >= r(-160):
|
||||
ret.append(Address([ORL[0]+1, ORL[1]], 1))
|
||||
|
||||
if r(-65) >= camera[2] >= r(-180) or r(180) > camera[2] >= r(155):
|
||||
ret.append(Address([ORL[0]+1, ORL[1]-1], 1))
|
||||
|
||||
if r(-110) >= camera[2] >= r(-180) or r(180) > camera[2] >= r(110):
|
||||
ret.append(Address([ORL[0], ORL[1]-1], 1))
|
||||
|
||||
if r(-155) >= camera[2] >= r(180) or r(180) > camera[2] >= r(65):
|
||||
ret.append(Address([ORL[0]-1, ORL[1]-1], 1))
|
||||
|
||||
if r(160) >= camera[2] >= r(20):
|
||||
ret.append(Address([ORL[0]-1, ORL[1]], 1))
|
||||
|
||||
if r(115) >= camera[2] >= r(-25):
|
||||
ret.append(Address([ORL[0]-1, ORL[1]+1], 1))
|
||||
|
||||
|
||||
|
||||
return ret
|
||||
|
||||
previousSurround = {}
|
||||
|
||||
def SurroundChanged(key, surround):
|
||||
|
||||
# This returns whether surround was changed between frames
|
||||
|
||||
if key not in previousSurround:
|
||||
previousSurround[key] = surround.copy()
|
||||
|
||||
changed = surround != previousSurround[key]
|
||||
|
||||
previousSurround[key] = surround.copy()
|
||||
|
||||
return changed
|
||||
|
||||
def RegisterObject(object, precision, delete=True):
|
||||
|
||||
# This will move an object from scene.objects into
|
||||
# chunks. So that they could be stored without
|
||||
# effecting the BGE Depsgraph performance.
|
||||
|
||||
# Creating chunk
|
||||
addr = Address(object.position, precision)
|
||||
if addr not in chunks:
|
||||
chunks[addr] = {"loaded":False,
|
||||
"objects":[]}
|
||||
|
||||
# Adding properties
|
||||
virtualObject = {}
|
||||
virtualObject["name"] = object.name
|
||||
virtualObject["position"] = object.position.copy()
|
||||
virtualObject["orientation"] = object.orientation.to_euler()
|
||||
virtualObject["scaling"] = object.scaling.copy()
|
||||
|
||||
for i in object.blenderObject.game.properties:
|
||||
virtualObject[i.name] = i.value
|
||||
|
||||
|
||||
# Adding the object to the chunk
|
||||
chunks[addr]["objects"].append(virtualObject)
|
||||
|
||||
# Deleting real object
|
||||
if delete:
|
||||
object.endObject()
|
||||
|
||||
# Returning
|
||||
return virtualObject
|
||||
|
||||
def SortByDistance(l, cam, withdistance=False):
|
||||
|
||||
# This sorts a chunk by the distance
|
||||
distanced = []
|
||||
for n, i in enumerate(l):
|
||||
d = cam.getDistanceTo(i["position"])
|
||||
distanced.append([d, n, i])
|
||||
|
||||
distanced = sorted(distanced)
|
||||
|
||||
if withdistance:
|
||||
return distanced
|
||||
|
||||
ret = []
|
||||
for i in distanced:
|
||||
ret.append(i[2])
|
||||
return ret
|
||||
|
||||
def UpdateScene(camobject, precision, camera=None):
|
||||
|
||||
# This function will update the scene. According to the camera
|
||||
# view.
|
||||
|
||||
location = camobject.position
|
||||
|
||||
# Getting addresses
|
||||
addrs = Surround(location, precision, camera)
|
||||
|
||||
# Checking if any of addresses are not up to date.
|
||||
for addr in chunks:
|
||||
|
||||
# Delete object if address not in view
|
||||
|
||||
# It is done in a separate loop and first,
|
||||
# because we might need elements from it
|
||||
# to spawn later. Otherwise we might cache
|
||||
# way too many objects into memory.
|
||||
|
||||
if addr not in addrs and chunks[addr]["loaded"]:
|
||||
for object in chunks[addr]["objects"]:
|
||||
if object.get("object"):
|
||||
Reuse.Delete(object["object"])
|
||||
object["object"] = None
|
||||
chunks[addr]["loaded"] = False
|
||||
|
||||
# Breaking to skip to next frame and
|
||||
# re-evaluate whether the FPS is good
|
||||
return
|
||||
|
||||
lookthroughchunks = chunks
|
||||
if addrs[0] in chunks:
|
||||
lookthroughchunks = [chunks[addrs[0]]]+list(chunks.keys())
|
||||
|
||||
|
||||
# Fixing random items at the chunks.
|
||||
for i in range(5):
|
||||
addr = random.choice(list(chunks.keys()))
|
||||
item = random.choice(chunks[addr]["objects"])
|
||||
if item.get("broken"):
|
||||
item["broken"] = False
|
||||
print(consoleForm(item["name"]), "Fixed")
|
||||
|
||||
|
||||
for addr in chunks:
|
||||
|
||||
# Create objects when addres in view
|
||||
if addr in addrs and not chunks[addr]["loaded"]:
|
||||
|
||||
for object in SortByDistance(chunks[addr]["objects"], camobject):
|
||||
if not object.get("object") and not object.get("broken"):
|
||||
object["object"] = Reuse.Create(object["name"])
|
||||
object["object"].position = object["position"]
|
||||
object["object"].orientation = object["orientation"]
|
||||
object["object"].scaling = object["scaling"]
|
||||
|
||||
# Some objects have a height adjustment value
|
||||
object["object"].position[2] += object["object"].get("movez", 0)
|
||||
|
||||
# Some effects require a reference point
|
||||
object["object"]["spawned_by"] = object
|
||||
|
||||
# Some objects need dynamics to be suspended
|
||||
if object.get("suspendDynamics"):
|
||||
object["object"].suspendDynamics(True)
|
||||
|
||||
# Some objects might change mesh during game
|
||||
if object["object"].get("good"):
|
||||
object["object"].replaceMesh(object["object"]["good"])
|
||||
|
||||
chunks[addr]["loaded"] = True
|
||||
|
||||
# Breaking to skip to next frame and
|
||||
# re-evaluate whether the FPS is good
|
||||
return
|
||||
|
||||
# Level Of Details for spawn objects
|
||||
|
||||
# This is needed because normal LOD system
|
||||
# with those objects sometimes gives a
|
||||
# segmentation fault.
|
||||
|
||||
elif addr in addrs and chunks[addr]["loaded"]:
|
||||
|
||||
sortedObjects = SortByDistance(chunks[addr]["objects"], camobject, True)
|
||||
|
||||
# closestUnspawned = [1000000, 0, {}]
|
||||
# for object in sortedObjects:
|
||||
# if not object[2].get("object") and object[0] < closestUnspawned[0]:
|
||||
# closestUnspawned = object
|
||||
#
|
||||
# if Reuse.reuse.get(closestUnspawned[2].get("name")):
|
||||
# closestUnspawned[2]["object"] = Reuse.Create(closestUnspawned[2].get("name"))
|
||||
# closestUnspawned[2]["object"].position = closestUnspawned[2]["position"]
|
||||
# closestUnspawned[2]["object"].orientation = closestUnspawned[2]["orientation"]
|
||||
# closestUnspawned[2]["object"].scaling = closestUnspawned[2]["scaling"]
|
||||
#
|
||||
# # Some objects have a height adjustment value
|
||||
# closestUnspawned[2]["object"].position[2] += closestUnspawned[2]["object"].get("movez", 0)
|
||||
#
|
||||
# # Some effects require a reference point
|
||||
# closestUnspawned[2]["object"]["spawned_by"] = closestUnspawned[2]
|
||||
#
|
||||
# # Some objects need dynamics to be suspended
|
||||
# if closestUnspawned[2].get("suspendDynamics"):
|
||||
# closestUnspawned[2]["object"].suspendDynamics(True)
|
||||
|
||||
|
||||
|
||||
for distance, n, object in sortedObjects:
|
||||
#
|
||||
# if object["name"] == closestUnspawned[2].get("name") and distance > closestUnspawned[0] and object.get("object"):
|
||||
# Reuse.Delete(object["object"])
|
||||
# object["object"] = None
|
||||
|
||||
if "lods" in object and object.get("object"):
|
||||
distance = object["object"].getDistanceTo(location)
|
||||
for lod in object["lods"]:
|
||||
|
||||
lodDistance = object["lods"][lod]
|
||||
if int(distance) <= lodDistance:
|
||||
break
|
||||
|
||||
if object["object"].name != lod:
|
||||
|
||||
Reuse.Delete(object["object"])
|
||||
object["object"] = Reuse.Create(lod)
|
||||
object["object"].position = object["position"]
|
||||
object["object"].orientation = object["orientation"]
|
||||
object["object"].scaling = object["scaling"]
|
||||
|
||||
# Some objects have a height adjustment value
|
||||
object["object"].position[2] += object["object"].get("movez", 0)
|
||||
|
||||
# Some effects require a reference point
|
||||
object["object"]["spawned_by"] = object
|
||||
|
||||
# Some objects need dynamics to be suspended
|
||||
if object.get("suspendDynamics"):
|
||||
object["object"].suspendDynamics(True)
|
||||
|
||||
taskschedule = {}
|
||||
|
||||
def ScheduleTask(taskname, FPSfactor, task, *args):
|
||||
|
||||
# This function adds a function to the schedule
|
||||
|
||||
taskObject = {"FPSfactor":FPSfactor,
|
||||
"task":task,
|
||||
"args":args}
|
||||
taskschedule[taskname] = taskObject
|
||||
|
||||
def ExecuteScheduled():
|
||||
|
||||
# This function executes a scheduled task
|
||||
|
||||
# for taskname in taskschedule:
|
||||
# print("Scheduled:", taskname)
|
||||
# print()
|
||||
|
||||
# Trying to execute something
|
||||
for taskname in taskschedule:
|
||||
|
||||
taskObject = taskschedule[taskname]
|
||||
|
||||
if GoodFPS("[Scheduled] "+taskname, taskObject["FPSfactor"]):
|
||||
del taskschedule[taskname]
|
||||
taskObject["task"](*taskObject["args"])
|
||||
return
|
||||
|
||||
def Force(value):
|
||||
|
||||
# This function adjusts acceleration
|
||||
# to fps
|
||||
|
||||
return value * ( ToFPS() ** 2 )
|
||||
|
||||
def Velocity(value):
|
||||
|
||||
# This function adjusts velocity
|
||||
# to fps
|
||||
|
||||
return value * ToFPS()
|
||||
|
||||
def PrintTime():
|
||||
# This function is used for testing
|
||||
print(bge.logic.getRealTime())
|
|
@ -1,3 +0,0 @@
|
|||
# GPLv3 or later
|
||||
# ( C ) J.Y.Amihud 2024
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
import bge
|
||||
import aud
|
||||
from Scripts import Reuse
|
||||
from Scripts import Character_Controll
|
||||
from Scripts import Character
|
||||
from Scripts import Vehicle
|
||||
from Scripts import Map
|
||||
from Scripts import Main_update
|
||||
|
@ -129,7 +129,7 @@ def emote(dani, data, sound):
|
|||
emotion = emotion[1]
|
||||
|
||||
if start < sound.position < end:
|
||||
Character_Controll.ApplyAnimation(dani, emotion)
|
||||
Character.ApplyAnimation(dani, emotion)
|
||||
|
||||
def StatusText(text, bold=[]):
|
||||
|
||||
|
@ -236,7 +236,7 @@ def scene(scene, dani):
|
|||
|
||||
# Animation of dani holding the phone
|
||||
if "dialogue01" in Story:
|
||||
Character_Controll.ApplyAnimation(dani, "AnswerPhone")
|
||||
Character.ApplyAnimation(dani, "AnswerPhone")
|
||||
|
||||
# Emoting to the phone conversation
|
||||
emotion_data = [
|
||||
|
@ -256,7 +256,7 @@ def scene(scene, dani):
|
|||
StatusUpdate(stages, 0)
|
||||
|
||||
# Animation of putting away the phone
|
||||
Character_Controll.ApplyAnimation(dani, "PutPhoneAway")
|
||||
Character.ApplyAnimation(dani, "PutPhoneAway")
|
||||
|
||||
# We we will a neonspeedste at a specific point in the garage for this to work
|
||||
# relying on the spawn system is stupid, since it might decide that we will not
|
||||
|
@ -363,7 +363,7 @@ def scene(scene, dani):
|
|||
|
||||
StatusUpdate(stages, 2)
|
||||
|
||||
#Character_Controll.ApplyAnimation(Story["Paps"], "Stand")
|
||||
#Character.ApplyAnimation(Story["Paps"], "Stand")
|
||||
|
||||
Reuse.Delete(Story["stage1"])
|
||||
del Story["stage1"]
|
||||
|
@ -393,11 +393,11 @@ def scene(scene, dani):
|
|||
|
||||
|
||||
if 50 > Story["Paps"].getDistanceTo(dani) > 4:
|
||||
Character_Controll.walkToward(Story["Paps"], dani)
|
||||
Character.walkToward(Story["Paps"], dani)
|
||||
if 50 > Story["Moria"].getDistanceTo(dani) > 4:
|
||||
Character_Controll.walkToward(Story["Moria"], dani)
|
||||
Character.walkToward(Story["Moria"], dani)
|
||||
if 50 > Story["Jack"].getDistanceTo(dani) > 4:
|
||||
Character_Controll.walkToward(Story["Jack"], dani)
|
||||
Character.walkToward(Story["Jack"], dani)
|
||||
|
||||
|
||||
|
||||
|
@ -430,9 +430,9 @@ Story["01_Bring_Neonspeedster_To_Racetrack"] = scene
|
|||
def scene(scene, dani):
|
||||
|
||||
global Story
|
||||
|
||||
|
||||
# Stopping this scene from working in the night
|
||||
if "stage" not in Story:
|
||||
if "stage" not in Story and "Truck" not in Story:
|
||||
timeis = bge.logic.globalDict.get("time", 0)
|
||||
if timeis > 19 or timeis < 8:
|
||||
return
|
||||
|
@ -448,7 +448,7 @@ def scene(scene, dani):
|
|||
|
||||
# Moria goes to the car
|
||||
if not dani.get("driving") and not Story["Moria"].get("driving"):
|
||||
Character_Controll.getIntoCar(Story["Moria"], Story["Neonspeedster"])
|
||||
Character.getIntoCar(Story["Moria"], Story["Neonspeedster"])
|
||||
|
||||
|
||||
if Story["Moria"].get("driving"):
|
||||
|
@ -477,7 +477,7 @@ def scene(scene, dani):
|
|||
if Story["Moria"].get("driving"):
|
||||
Story["Moria"]["driving"]["racing"] = False
|
||||
Reuse.Delete(Story["Moria"]["driving"])
|
||||
Character_Controll.getOutCar(Story["Moria"])
|
||||
Character.getOutCar(Story["Moria"])
|
||||
Reuse.Delete(Story["Moria"])
|
||||
del Story["Moria"]
|
||||
|
||||
|
@ -501,7 +501,7 @@ def scene(scene, dani):
|
|||
Reuse.Delete(Story["Jack"])
|
||||
|
||||
if Story["Jack"].get("driving"):
|
||||
Character_Controll.getOutCar(Story["Jack"])
|
||||
Character.getOutCar(Story["Jack"])
|
||||
|
||||
del Story["Jack"]
|
||||
dani["race"] = ""
|
||||
|
@ -583,7 +583,7 @@ def scene(scene, dani):
|
|||
|
||||
# Paps coming to Dani
|
||||
if 100 > Story["Paps"].getDistanceTo(dani) > 4:
|
||||
Character_Controll.walkToward(Story["Paps"], dani)
|
||||
Character.walkToward(Story["Paps"], dani)
|
||||
|
||||
# Not restoring Moria.
|
||||
|
||||
|
@ -610,7 +610,7 @@ def scene(scene, dani):
|
|||
if "dialogue1" in Story and not Story["dialogue1"].status:
|
||||
|
||||
if Story["Jack"].get("driving") != Story["Truck"]:
|
||||
Character_Controll.getIntoCar(Story["Jack"], Story["Truck"], passanger=True)
|
||||
Character.getIntoCar(Story["Jack"], Story["Truck"], passanger=True)
|
||||
else:
|
||||
Story["stage"] = 1
|
||||
del Story["dialogue1"]
|
||||
|
@ -621,7 +621,7 @@ def scene(scene, dani):
|
|||
# Paps coming to Dani
|
||||
if "Paps" in Story:
|
||||
if 100 > Story["Paps"].getDistanceTo(dani) > 4:
|
||||
Character_Controll.walkToward(Story["Paps"], dani)
|
||||
Character.walkToward(Story["Paps"], dani)
|
||||
|
||||
if "dialogue2" not in Story:
|
||||
Story["dialogue2"] = PlayDialogue("brief", Story["Paps"])
|
||||
|
@ -792,14 +792,16 @@ def scene(scene, dani):
|
|||
|
||||
if not Story["DarkShadow"].get("isCargo"):
|
||||
Story["stage"] = 5
|
||||
Character_Controll.getOutCar(Story["Jack"])
|
||||
Character.getOutCar(Story["Jack"])
|
||||
pointer.visible = False
|
||||
|
||||
# Jack goes into the car that you've brought.
|
||||
if Story.get("stage") == 5:
|
||||
|
||||
if Story["Jack"].get("driving") != Story["DarkShadow"]:
|
||||
Character_Controll.getIntoCar(Story["Jack"], Story["DarkShadow"], passanger=True)
|
||||
Character.getIntoCar(Story["Jack"], Story["DarkShadow"], passanger=True)
|
||||
if Story["Jack"].getDistanceTo(Story["DarkShadow"]) > 100:
|
||||
Character.getIntoCar(Story["Jack"], Story["DarkShadow"], immediately=True, passanger=True)
|
||||
|
||||
# Detecting when the race ends.
|
||||
if not dani.get("race"):
|
||||
|
@ -826,7 +828,7 @@ def scene(scene, dani):
|
|||
|
||||
|
||||
if "dialogue5" in Story and not Story["dialogue5"].status:
|
||||
Character_Controll.getOutCar(Story["Jack"])
|
||||
Character.getOutCar(Story["Jack"])
|
||||
Story["stage"] = 7
|
||||
bge.logic.globalDict["print"] = "Pick the car up with the truck."
|
||||
|
||||
|
@ -834,7 +836,9 @@ def scene(scene, dani):
|
|||
if Story.get("stage") == 7:
|
||||
|
||||
if Story["Jack"].get("driving") != Story["Truck"]:
|
||||
Character_Controll.getIntoCar(Story["Jack"], Story["Truck"], passanger=True)
|
||||
Character.getIntoCar(Story["Jack"], Story["Truck"], passanger=True)
|
||||
if Story["Jack"].getDistanceTo(Story["Truck"]) > 100:
|
||||
Character.getIntoCar(Story["Jack"], Story["Truck"], immediately=True, passanger=True)
|
||||
|
||||
elif dani.get("driving") == Story["Truck"]:
|
||||
Story["stage"] = 8
|
||||
|
@ -888,7 +892,7 @@ def scene(scene, dani):
|
|||
# If we are at the place.
|
||||
if Story["Truck"].getDistanceTo(fixGaragePosition) < 60:
|
||||
Story["stage"] = 10
|
||||
Character_Controll.getOutCar(Story["Jack"])
|
||||
Character.getOutCar(Story["Jack"])
|
||||
pointer.visible = False
|
||||
|
||||
# Fixing the car.
|
||||
|
@ -897,7 +901,7 @@ def scene(scene, dani):
|
|||
if "Jack-got-to-garage-door" not in Story:
|
||||
garageDoor = [-789.7, -1035, 405.5]
|
||||
if Story["Jack"].getDistanceTo(garageDoor) > 1.5:
|
||||
Character_Controll.walkToward(Story["Jack"], garageDoor)
|
||||
Character.walkToward(Story["Jack"], garageDoor)
|
||||
else:
|
||||
Story["Jack-got-to-garage-door"] = True
|
||||
|
||||
|
@ -911,7 +915,7 @@ def scene(scene, dani):
|
|||
|
||||
fixToolPoint = [-754.1, -1039, 405.8]
|
||||
if Story["Jack"].getDistanceTo(fixToolPoint) > 1:
|
||||
Character_Controll.walkToward(Story["Jack"], fixToolPoint, avoidObstacles=False)
|
||||
Character.walkToward(Story["Jack"], fixToolPoint, avoidObstacles=False)
|
||||
|
||||
elif "dialogue8" in Story and not Story["dialogue8"].status:
|
||||
if Story["DarkShadow"] in Garage.Inside():
|
||||
|
@ -949,7 +953,7 @@ def scene(scene, dani):
|
|||
|
||||
fixComputerPoint = [-755, -1047, 405.8]
|
||||
if Story["Jack"].getDistanceTo(fixComputerPoint) > 1:
|
||||
Character_Controll.walkToward(Story["Jack"], fixComputerPoint, avoidObstacles=False)
|
||||
Character.walkToward(Story["Jack"], fixComputerPoint, avoidObstacles=False)
|
||||
|
||||
else:
|
||||
# Jack is buing parts that the car is missing.
|
||||
|
@ -973,7 +977,7 @@ def scene(scene, dani):
|
|||
if Story.get("stage") == 13:
|
||||
|
||||
if Story["Jack"].getDistanceTo(dani) > 3:
|
||||
Character_Controll.walkToward(Story["Jack"], dani)
|
||||
Character.walkToward(Story["Jack"], dani)
|
||||
|
||||
if "dialogue10" not in Story and ( not Story["Jack"].get("saying") or not Story["Jack"]["saying"].status ):
|
||||
Story["dialogue10"] = PlayDialogue("seems_we_have_everything", Story["Jack"])
|
||||
|
@ -1002,7 +1006,7 @@ def scene(scene, dani):
|
|||
if Story.get("stage") == 14:
|
||||
|
||||
if Story["Jack"].getDistanceTo(dani) > 3:
|
||||
Character_Controll.walkToward(Story["Jack"], dani)
|
||||
Character.walkToward(Story["Jack"], dani)
|
||||
|
||||
if "dialogue11" not in Story and ( not Story["Jack"].get("saying") or not Story["Jack"]["saying"].status ):
|
||||
Story["dialogue11"] = PlayDialogue("tidy_from_below", Story["Jack"])
|
||||
|
@ -1019,24 +1023,25 @@ def scene(scene, dani):
|
|||
if Story["DarkShadow"].getDistanceTo(fixGaragePosition) < 2:
|
||||
Story["stage"] = 15
|
||||
|
||||
|
||||
if Story.get("stage") == 15:
|
||||
|
||||
# Spawning neonspeedster
|
||||
if "NeonSpeedster" not in Story:
|
||||
Story["NeonSpeedster"] = Vehicle.Spawn("NeonSpeedsterBox",
|
||||
(-798.3, -1006, 405.5),
|
||||
(-814.7, -1029.3, 405.5),
|
||||
(0,0,0))
|
||||
|
||||
if "Moria" not in Story:
|
||||
Story["Moria"] = Reuse.Create("MoriaBox")
|
||||
Character_Controll.getIntoCar(Story["Moria"],
|
||||
Character.getIntoCar(Story["Moria"],
|
||||
Story["NeonSpeedster"],
|
||||
immediately=True)
|
||||
|
||||
|
||||
if "Paps" not in Story:
|
||||
Story["Paps"] = Reuse.Create("PapsBox")
|
||||
Character_Controll.getIntoCar(Story["Paps"],
|
||||
Character.getIntoCar(Story["Paps"],
|
||||
Story["NeonSpeedster"],
|
||||
passanger=True,
|
||||
immediately=True)
|
||||
|
@ -1053,8 +1058,8 @@ def scene(scene, dani):
|
|||
Vehicle.TargetedNPC(Story["NeonSpeedster"])
|
||||
|
||||
else:
|
||||
Character_Controll.getOutCar(Story["Paps"])
|
||||
Character_Controll.getOutCar(Story["Moria"])
|
||||
Character.getOutCar(Story["Paps"])
|
||||
Character.getOutCar(Story["Moria"])
|
||||
|
||||
Story["stage"] = 16
|
||||
|
||||
|
@ -1124,9 +1129,9 @@ def scene(scene, dani):
|
|||
|
||||
# Paps and Jack walking after you.
|
||||
if Story["Jack"].getDistanceTo(dani) > 3:
|
||||
Character_Controll.walkToward(Story["Jack"], dani)
|
||||
Character.walkToward(Story["Jack"], dani)
|
||||
if Story["Paps"].getDistanceTo(dani) > 3:
|
||||
Character_Controll.walkToward(Story["Paps"], dani)
|
||||
Character.walkToward(Story["Paps"], dani)
|
||||
|
||||
if "dialogue13" in Story and not Story["dialogue13"].status:
|
||||
Story["stage"] = 17
|
||||
|
@ -1146,6 +1151,8 @@ def scene(scene, dani):
|
|||
|
||||
if dani.getDistanceTo(roomPosition) < 7:
|
||||
|
||||
pointer.visible = False
|
||||
|
||||
bge.logic.globalDict["print"] = "Mission Passed!"
|
||||
|
||||
if "Moria" in Story:
|
||||
|
|
1193
Scripts/Script.py~
1193
Scripts/Script.py~
File diff suppressed because it is too large
Load diff
|
@ -13,7 +13,7 @@ try:
|
|||
from Scripts import Script
|
||||
from Scripts import Money
|
||||
from Scripts import Garage
|
||||
from Scripts import Character_Controll
|
||||
from Scripts import Character
|
||||
from Scripts import Vehicle
|
||||
|
||||
from Scripts.Common import *
|
||||
|
@ -139,6 +139,7 @@ def Execute():
|
|||
"veh_auto_gear":"autogear",
|
||||
"veh_dynamcam" :"dynamcam",
|
||||
"veh_upload" :"unload",
|
||||
"veh_horn" :"horn",
|
||||
"chr_forward" :"forward",
|
||||
"chr_backward" :"backward",
|
||||
"chr_left" :"left",
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
# Gplv3 or any later version
|
||||
# (C) J.Y.Amihud 2024
|
||||
|
||||
import os
|
||||
import json
|
||||
|
||||
# Those modules don't work everywhere
|
||||
try:
|
||||
import bge
|
||||
import bpy
|
||||
|
||||
from Scripts import Main_update
|
||||
from Scripts import Script
|
||||
from Scripts import Money
|
||||
from Scripts import Garage
|
||||
from Scripts import Character_Controll
|
||||
from Scripts import Vehicle
|
||||
|
||||
from Scripts.Common import *
|
||||
except:
|
||||
pass
|
||||
|
||||
def get_settings_folder():
|
||||
|
||||
game = "danisrace"
|
||||
|
||||
try:
|
||||
data_dir = os.environ["XDG_DATA_HOME"] + "/" + game
|
||||
except:
|
||||
data_dir = os.path.expanduser("~/.local/share/"+game)
|
||||
|
||||
try:
|
||||
os.makedirs(data_dir)
|
||||
except:
|
||||
pass
|
||||
|
||||
return data_dir
|
||||
|
||||
def load_settings():
|
||||
|
||||
folder = get_settings_folder()
|
||||
f = folder+"/config.json"
|
||||
|
||||
try:
|
||||
with open(f) as o:
|
||||
return json.load(o)
|
||||
except: return {}
|
||||
|
||||
def Execute():
|
||||
|
||||
|
||||
# This function will execute the various settings inside of the game
|
||||
|
||||
data = load_settings()
|
||||
if not data: return
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
|
||||
# SHADOWS
|
||||
|
||||
for obj in scene.lights:
|
||||
|
||||
# Use Shadow
|
||||
try: obj.blenderObject.data.use_shadow = data.get("shadows", True)
|
||||
except: pass
|
||||
|
||||
# Use Contact Shadow
|
||||
try: obj.blenderObject.use_contact_shadow = data.get("cntctshadows", True)
|
||||
except: pass
|
||||
|
||||
# Softshadows
|
||||
bpy.data.scenes["Scene"].eevee.use_soft_shadows = data.get("softshadows", True)
|
||||
|
||||
# Reflections
|
||||
bpy.data.scenes["Scene"].eevee.use_ssr = data.get("reflections", True)
|
||||
|
||||
|
||||
# Samples TODO figure it out
|
||||
bpy.data.scenes["Scene"].eevee.taa_render_samples = data.get("samples", 1)
|
||||
|
||||
# Volume samples
|
||||
bpy.data.scenes["Scene"].eevee.volumetric_samples = data.get("volumesamples", 32)
|
||||
|
||||
# Compositor
|
||||
|
||||
if data.get("compositor"):
|
||||
bpy.context.space_data.shading.use_compositor = 'ALWAYS'
|
||||
else:
|
||||
bpy.context.space_data.shading.use_compositor = 'DISABLED'
|
||||
|
||||
# Skin samples
|
||||
bpy.data.scenes["Scene"].eevee.sss_samples = data.get("skinsamples", 5)
|
||||
|
||||
# Volume shadows
|
||||
bpy.data.scenes["Scene"].eevee.use_volumetric_shadows = data.get("volumeshadow", False)
|
||||
|
||||
# Volume lights
|
||||
bpy.data.scenes["Scene"].eevee.use_volumetric_lights = data.get("volumelight", True)
|
||||
|
||||
# Volume shadows samp
|
||||
bpy.data.scenes["Scene"].eevee.volumetric_shadow_samples = data.get("volshadsampl", 3)
|
||||
|
||||
# Cube Shadow res
|
||||
bpy.data.scenes["Scene"].eevee.shadow_cube_size = data.get("shadowslamps", "512")
|
||||
|
||||
# Sun shadow res
|
||||
bpy.data.scenes["Scene"].eevee.shadow_cascade_size = data.get("shadowssun", "1024")
|
||||
|
||||
# Logic Steps
|
||||
#bge.logic.setMaxLogicFrame(100)
|
||||
|
||||
|
||||
# Controlls
|
||||
|
||||
controlmap = {
|
||||
"veh_forward" :"forward",
|
||||
"veh_backward" :"backward",
|
||||
"veh_left" :"left",
|
||||
"veh_right" :"right",
|
||||
"veh_drift" :"drift",
|
||||
"veh_nitro" :"nitro",
|
||||
"veh_resque" :"resque",
|
||||
"veh_gear_up" :"gearup",
|
||||
"veh_gear_down":"geardown",
|
||||
"veh_auto_gear":"autogear",
|
||||
"veh_dynamcam" :"dynamcam",
|
||||
"veh_upload" :"unload",
|
||||
"chr_forward" :"forward",
|
||||
"chr_backward" :"backward",
|
||||
"chr_left" :"left",
|
||||
"chr_right" :"right",
|
||||
"chr_jump" :"jump",
|
||||
"chr_get_car" :"getcar",
|
||||
"chr_swimdown" :"swimdown"
|
||||
|
||||
}
|
||||
|
||||
for control in controlmap:
|
||||
if control.startswith("chr"): folder = bge.logic.globalDict["chr_controls"]
|
||||
else: folder = bge.logic.globalDict["veh_controls"]
|
||||
|
||||
try: folder[controlmap[control]] = keycodes[data[control]]
|
||||
except Exception as e:
|
||||
print("Error assigning controls",e)
|
||||
|
||||
|
||||
|
||||
|
||||
def SaveGame():
|
||||
|
||||
# Let's generate the data to save.
|
||||
|
||||
data = {
|
||||
"currentEvent" : Script.Story["currentEvent"],
|
||||
"passedEvents" : Script.Story["passed"]
|
||||
}
|
||||
|
||||
data["cars"] = Garage.Encode()
|
||||
data["money"] = Money.Get()
|
||||
|
||||
data["inventory"] = Garage.inventory
|
||||
|
||||
data["time"] = bge.logic.globalDict["time"]
|
||||
|
||||
folder = get_settings_folder()
|
||||
f = folder+"/save.json"
|
||||
|
||||
try:
|
||||
with open(f, "w") as save:
|
||||
json.dump(data, save, indent=4, sort_keys=True)
|
||||
print(clr["bold"]+clr["tdgr"]+"Game saved!"+clr["norm"], f)
|
||||
except Exception as e:
|
||||
print(clr["bold"]+clr["tdrd"]+"Failed to save game:"+clr["norm"], e)
|
||||
|
||||
def LoadGame():
|
||||
|
||||
# loading game
|
||||
|
||||
folder = get_settings_folder()
|
||||
f = folder+"/save.json"
|
||||
|
||||
try:
|
||||
with open(f) as o:
|
||||
data = json.load(o)
|
||||
except Exception as e:
|
||||
print("Couldn't Load Game:", e)
|
||||
return
|
||||
|
||||
bge.logic.globalDict["garage-saved"] = data.get("cars", [])
|
||||
Script.Story["currentEvent"] = data.get("currentEvent", "01_Bring_Neonspeedster_To_Racetrack")
|
||||
Script.Story["passed"] = data.get("passedEvents", [])
|
||||
|
||||
Money.Set(data.get("money", 0.0))
|
||||
|
||||
Garage.inventory = data.get("inventory", {})
|
||||
Garage.UpdateShelfs()
|
||||
|
||||
bge.logic.globalDict["start-time"] = data.get("time")
|
||||
|
|
@ -451,10 +451,19 @@ def Boxify(obj, orcenter=False):
|
|||
|
||||
|
||||
else:
|
||||
box.position = obj.position
|
||||
center = obj.position
|
||||
box.orientation = obj.orientation
|
||||
box.scaling = obj.blenderObject.dimensions
|
||||
try:
|
||||
box.position = obj.position
|
||||
center = obj.position
|
||||
except:
|
||||
box.position = obj
|
||||
center = obj
|
||||
|
||||
try:
|
||||
box.orientation = obj.orientation
|
||||
box.scaling = obj.blenderObject.dimensions
|
||||
except:
|
||||
box.orientation = [0,0,0]
|
||||
box.scaling = [1,1,1]
|
||||
|
||||
|
||||
return center
|
||||
|
|
|
@ -1,516 +0,0 @@
|
|||
# GPLv3 or any later version
|
||||
# (C) J.Y.Amihud ( blenderdumbass )
|
||||
|
||||
# This file will dealwith tools and stuff.
|
||||
|
||||
import bge
|
||||
import bpy
|
||||
import aud
|
||||
import math
|
||||
import mathutils
|
||||
|
||||
from Scripts import Reuse
|
||||
|
||||
from Scripts.Common import *
|
||||
|
||||
from Scripts import Vehicle
|
||||
from Scripts import Script
|
||||
from Scripts import Garage
|
||||
|
||||
def MainLoop():
|
||||
|
||||
keys = bge.logic.globalDict["keys"]
|
||||
mouse = bge.logic.globalDict["mouse"]
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
dani = scene.objects["Dani_Box"]
|
||||
|
||||
if dani.get("driving"):
|
||||
return
|
||||
|
||||
camera = scene.active_camera
|
||||
hand = scene.objects["Tool_Hand"]
|
||||
hc = scene.objects["Health_Circle"]
|
||||
|
||||
box = scene.objects["Boxify"]
|
||||
if box.get("timer"): box["timer"] -= 1
|
||||
else: box.position = [0,0,-1000]
|
||||
|
||||
# If dani is using a fix tool
|
||||
if str(dani.get("tool")) == "FixTool":
|
||||
|
||||
dis = 10000
|
||||
car = None
|
||||
|
||||
for thecar in bge.logic.globalDict["allcars"]:
|
||||
cd = thecar.getDistanceTo(dani)
|
||||
if cd < dis:
|
||||
dis = cd
|
||||
car = thecar
|
||||
|
||||
ray = DaniPoint(dani, camera)
|
||||
|
||||
found = False
|
||||
|
||||
if car:
|
||||
|
||||
# First we gonna create a list of all objects
|
||||
# that the car can get fixed.
|
||||
|
||||
attachment = dani.get("tool-attachment")
|
||||
|
||||
objs = []
|
||||
|
||||
if not Vehicle.OnGround(car):
|
||||
objs = [car]
|
||||
|
||||
for wheel in car["wheels"]:
|
||||
if ( wheel.visible and not attachment ) or attachment == "Wheels" :
|
||||
objs.append(wheel)
|
||||
|
||||
for door in car.get("doors", []):
|
||||
if ( door.visible and not attachment ) or attachment == "Parts" :
|
||||
objs.append(door)
|
||||
|
||||
if "NitroCanProxy" in car.childrenRecursive and\
|
||||
(( not car.get("NitroCan") and attachment == "Nitros") or ( car.get("NitroCan") and not attachment )):
|
||||
objs.append(car.childrenRecursive["NitroCanProxy"])
|
||||
|
||||
if "SpoilerProxy" in car.childrenRecursive and\
|
||||
( ( not car.get("Spoiler") and "Spoiler" in str(attachment) ) or ( car.get("Spoiler") and not attachment )):
|
||||
objs.append(car.childrenRecursive["SpoilerProxy"])
|
||||
|
||||
if ray[1]:
|
||||
|
||||
point = ray[1]
|
||||
d = 10
|
||||
c = None
|
||||
for obj in objs:
|
||||
od = obj.getDistanceTo(point)
|
||||
if od < d:
|
||||
d = od
|
||||
c = obj
|
||||
|
||||
if c:
|
||||
found = True
|
||||
|
||||
if c not in car["wheels"]:
|
||||
center = Boxify(c)
|
||||
else:
|
||||
center = Boxify(c, True)
|
||||
|
||||
text = ""
|
||||
if c in car["wheels"]:
|
||||
text = "Wheel"
|
||||
|
||||
elif str(c) == "NitroCanProxy":
|
||||
text = "Nitros"
|
||||
|
||||
elif "Spoiler" in str(c):
|
||||
text = "Spoiler"
|
||||
|
||||
elif c == car:
|
||||
text = "Engine and Chassis"
|
||||
|
||||
elif c in car["doors"]:
|
||||
text = "Bodywork"
|
||||
|
||||
orange = range(len(text))
|
||||
text = text + "\n" + str(int(round(c.get("health", 1.0)*100)))+"%"
|
||||
|
||||
Script.StatusText(text, orange)
|
||||
|
||||
# Activate the tool
|
||||
if mousecodes["LMB"] in mouse:
|
||||
|
||||
FixToolSound()
|
||||
|
||||
if str(c) == "NitroCanProxy":
|
||||
Vehicle.AddNitroCan(car)
|
||||
dani["tool-attachment"] = None
|
||||
car["nitro"] = 10.0
|
||||
|
||||
if str(c) == "SpoilerProxy" and attachment:
|
||||
spoilertype = Garage.shop.get(attachment, {}).get("usemodel")
|
||||
Vehicle.AddSpoiler(car, spoilertype)
|
||||
dani["tool-attachment"] = None
|
||||
|
||||
c["health"] = c.get("health", 1.0) + 0.01
|
||||
if c["health"] >= 1.0:
|
||||
c["health"] = 1.0
|
||||
|
||||
# Replacing mesh, to looks nice.
|
||||
if c.get("Good"):
|
||||
c.replaceMesh(c.get("Good"))
|
||||
|
||||
# Doors
|
||||
if c in car["doors"]:
|
||||
c["locked"] = True
|
||||
|
||||
rot = door.orientation.to_euler()
|
||||
for i in range(3):
|
||||
if i == door.get("axis",2):
|
||||
rot[i] = door.get("lockat", 0)
|
||||
else:
|
||||
rot[i] = 0
|
||||
c.orientation = rot
|
||||
c.suspendPhysics()
|
||||
|
||||
door.orientation = rot
|
||||
|
||||
if c == car:
|
||||
Vehicle.ChangeBody(car, good=True)
|
||||
|
||||
if c == car:
|
||||
car["blown"] = False
|
||||
|
||||
if c["health"] > 0.1:
|
||||
|
||||
if not c.visible:
|
||||
dani["tool-attachment"] = None
|
||||
c.visible = True
|
||||
|
||||
# Removing parts
|
||||
if mousecodes["RMB"] in mouse:
|
||||
|
||||
FixToolSound()
|
||||
|
||||
# Removing spoilers
|
||||
if str(c) == "SpoilerProxy" and not attachment:
|
||||
spoilertype = Vehicle.RemoveSpoiler(car)
|
||||
for name in Garage.shop:
|
||||
item = Garage.shop[name]
|
||||
if item.get("usemodel") == spoilertype:
|
||||
dani["tool-attachment"] = name
|
||||
|
||||
# Removing nitros
|
||||
if str(c) == "NitroCanProxy" and not attachment:
|
||||
Vehicle.RemoveNitroCan(car)
|
||||
dani["tool-attachment"] = "Nitros"
|
||||
|
||||
# Removing bodywork
|
||||
if c in car["doors"] and not attachment:
|
||||
c["health"] = 0.0
|
||||
c.visible = False
|
||||
dani["tool-attachment"] = "Parts"
|
||||
|
||||
# Removing wheels
|
||||
elif c in car["wheels"] and not attachment:
|
||||
c["health"] = 0.0
|
||||
c.visible = False
|
||||
dani["tool-attachment"] = "Wheels"
|
||||
|
||||
|
||||
# Shelf
|
||||
|
||||
if not found:
|
||||
|
||||
tool = dani["tool"]
|
||||
|
||||
closest = 5
|
||||
theitem = ""
|
||||
themodel = None
|
||||
|
||||
for name in Garage.inventory:
|
||||
|
||||
amount = Garage.inventory[name]
|
||||
item = Garage.shop.get(name, {})
|
||||
model = item.get('model')
|
||||
if model: model= scene.objects[model]
|
||||
|
||||
if ( amount or name == dani.get("tool-attachment") ) and model:
|
||||
|
||||
d = dani.getDistanceTo(model)
|
||||
if d < closest:
|
||||
closest = d
|
||||
theitem = name
|
||||
themodel = model
|
||||
|
||||
if themodel:
|
||||
|
||||
name = theitem
|
||||
amount = Garage.inventory[name]
|
||||
item = Garage.shop.get(name, {})
|
||||
printname = item.get("name", name)
|
||||
|
||||
|
||||
Boxify(themodel)
|
||||
Script.StatusText(printname+"\nIn Stock: "+str(amount), range(len(printname)))
|
||||
|
||||
if mousecodes["LMB"] in mouse and not tool.get("active-timer"):
|
||||
tool["active-timer"] = 30
|
||||
|
||||
print("pressed", dani.get("tool-attachment"))
|
||||
|
||||
if not dani.get("tool-attachment"):
|
||||
|
||||
dani["tool-attachment"] = name
|
||||
Garage.Use(name)
|
||||
|
||||
else:
|
||||
|
||||
name = dani["tool-attachment"]
|
||||
|
||||
if name not in Garage.inventory: Garage.inventory[name] = 1
|
||||
else: Garage.inventory[name] += 1
|
||||
Garage.UpdateShelfs()
|
||||
|
||||
dani["tool-attachment"] = None
|
||||
|
||||
# If not model
|
||||
else:
|
||||
|
||||
ray = DaniPoint(dani, camera)
|
||||
|
||||
if dani.get("tool-attachment"):
|
||||
|
||||
# Telling the user that her can drop the part
|
||||
|
||||
if ray[1]:
|
||||
box.position = ray[1]
|
||||
box.position.z += 1
|
||||
box.scaling = (1,1,1)
|
||||
|
||||
# Dropping the part
|
||||
if mousecodes["LMB"] in mouse and ray[1] and not tool.get("active-timer"):
|
||||
|
||||
name = dani["tool-attachment"]
|
||||
item = Garage.shop.get(name, {})
|
||||
usemodel = item.get("usemodel")
|
||||
dropmodel = Reuse.Create(usemodel)
|
||||
dropmodel.position = box.position
|
||||
dropmodel.blenderObject["MainColor"] = [1.000000, 0.008796, 0.000000]
|
||||
dropmodel.blenderObject["SecondaryColor"] = [1.000000, 0.500000, 0.000000]
|
||||
|
||||
# Remembering what it was
|
||||
dropmodel["tool-attachment"] = dani["tool-attachment"]
|
||||
|
||||
if "dropped" not in bge.logic.globalDict:
|
||||
bge.logic.globalDict["dropped"] = []
|
||||
|
||||
bge.logic.globalDict["dropped"].append(dropmodel)
|
||||
|
||||
|
||||
dani["tool-attachment"] = None
|
||||
tool["active-timer"] = 10
|
||||
|
||||
elif ray[1]:
|
||||
|
||||
closest = None
|
||||
cldist = 10000
|
||||
|
||||
for dropmodel in bge.logic.globalDict.get("dropped", []):
|
||||
|
||||
distance = dropmodel.getDistanceTo(ray[1])
|
||||
if distance < cldist:
|
||||
closest = dropmodel
|
||||
cldist = distance
|
||||
|
||||
if closest:
|
||||
dropmodel = closest
|
||||
Boxify(dropmodel)
|
||||
|
||||
# Taking it back
|
||||
if ( mousecodes["LMB"] in mouse or mousecodes["RMB"] in mouse ) and not tool["active-timer"]:
|
||||
dani["tool-attachment"] = dropmodel.get("tool-attachment")
|
||||
Reuse.Delete(dropmodel)
|
||||
tool["active-timer"] = 10
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if tool.get("active-timer"): tool["active-timer"] -= 1
|
||||
|
||||
# Tool attachment
|
||||
if dani.get("tool-attachment"):
|
||||
|
||||
name = dani["tool-attachment"]
|
||||
item = Garage.shop.get(name, {})
|
||||
usemodel = item.get("usemodel")
|
||||
|
||||
if not dani.get("tool-attachment-model") and usemodel:
|
||||
|
||||
dani["tool-attachment-model"] = Reuse.Create(usemodel)
|
||||
dani["tool-attachment-model"].suspendPhysics()
|
||||
dani["tool-attachment-model"].blenderObject["MainColor"] = [1.000000, 0.008796, 0.000000]
|
||||
dani["tool-attachment-model"].blenderObject["SecondaryColor"] = [1.000000, 0.500000, 0.000000]
|
||||
|
||||
s = item.get("usescale", 1)
|
||||
dani["tool-attachment-model"].scaling = [s,s,s]
|
||||
|
||||
|
||||
else:
|
||||
|
||||
usemodel = dani["tool-attachment-model"]
|
||||
usemodel.position = Vehicle.RelativePoint(dani, (-0.5,-0.5,0.5))
|
||||
usemodel.applyRotation((0.03,-0.01,0.05),False)
|
||||
|
||||
elif dani.get("tool-attachment-model"):
|
||||
Reuse.Delete(dani["tool-attachment-model"])
|
||||
dani["tool-attachment-model"] = None
|
||||
|
||||
|
||||
# If dani is using a paint tool
|
||||
elif str(dani.get("tool")) == "PaintTool":
|
||||
|
||||
ray = DaniPoint(dani, camera)
|
||||
tool = dani["tool"]
|
||||
|
||||
if ray[0] in bge.logic.globalDict["allcars"]:
|
||||
|
||||
car = ray[0]
|
||||
Boxify(car)
|
||||
if mousecodes["LMB"] in mouse:
|
||||
|
||||
PaintToolSound()
|
||||
|
||||
if not tool.get("active-timer"):
|
||||
Vehicle.SmartColor(car, "pallete")
|
||||
tool["active-timer"] = 30
|
||||
|
||||
elif mousecodes["RMB"] in mouse:
|
||||
|
||||
PaintToolSound()
|
||||
|
||||
if not tool.get("active-timer"):
|
||||
Vehicle.SmartColor(car)
|
||||
tool["active-timer"] = 30
|
||||
|
||||
if tool.get("active-timer"): tool["active-timer"] -= 1
|
||||
|
||||
def UpdateTool(tool):
|
||||
|
||||
|
||||
tool = tool.owner
|
||||
scene = bge.logic.getCurrentScene()
|
||||
dani = scene.objects["Dani_Box"]
|
||||
hand = scene.objects["Tool_Hand"]
|
||||
box = scene.objects["Boxify"]
|
||||
icon = scene.objects["Dani_Tool_Icon"]
|
||||
|
||||
if "taken" not in tool:
|
||||
tool["taken"] = None
|
||||
tool["wasat"] = tool.position.copy()
|
||||
|
||||
if not tool["taken"]:
|
||||
|
||||
if dani.getDistanceTo(tool["wasat"]) < 2 and not tool.get("timer") and not dani.get("tool"):
|
||||
tool["taken"] = dani
|
||||
tool["timer"] = 100
|
||||
dani["tool"] = tool
|
||||
|
||||
tool.position = hand.position
|
||||
tool.orientation = hand.orientation
|
||||
tool.setParent(hand, True)
|
||||
|
||||
icon.blenderObject["raw"] = tool.get("icon_raw", 1)
|
||||
icon.blenderObject["column"] = tool.get("icon_column", 0)
|
||||
|
||||
tool.applyRotation([0,0,0.1], False)
|
||||
|
||||
elif dani.getDistanceTo(tool["wasat"]) < 2 and not tool.get("timer"):
|
||||
|
||||
tool["taken"] = None
|
||||
tool["timer"] = 100
|
||||
dani["tool"] = None
|
||||
box.position = [0,0,-1000]
|
||||
|
||||
tool.removeParent()
|
||||
|
||||
tool.position = tool["wasat"]
|
||||
tool.orientation = [0,0,0]
|
||||
|
||||
Script.StatusText(" ")
|
||||
|
||||
icon.blenderObject["raw"] = 1
|
||||
icon.blenderObject["column"] = 0
|
||||
|
||||
if tool.get("timer"): tool["timer"] -= 1
|
||||
|
||||
def Boxify(obj, orcenter=False):
|
||||
|
||||
# This function will draw a box around the object
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
box = scene.objects["Boxify"]
|
||||
box["timer"] = 10
|
||||
|
||||
if not orcenter:
|
||||
|
||||
# Finding bounding box
|
||||
bbox = obj.blenderObject.bound_box
|
||||
|
||||
# finding the center of the box
|
||||
center = 0.125 * sum((mathutils.Vector(b) for b in bbox), mathutils.Vector())
|
||||
|
||||
center.rotate(obj.orientation)
|
||||
center * obj.scaling
|
||||
center = obj.position + center
|
||||
box.position = center
|
||||
|
||||
|
||||
else:
|
||||
box.position = obj.position
|
||||
center = obj.position
|
||||
box.orientation = obj.orientation
|
||||
box.scaling = obj.blenderObject.dimensions
|
||||
|
||||
|
||||
return center
|
||||
|
||||
def DaniPoint(dani, camera):
|
||||
|
||||
# Then we want to see if any of them are pointed at
|
||||
fro = dani.position.copy()
|
||||
fro.z += 1
|
||||
|
||||
to = fro.copy()
|
||||
to.z -= 1
|
||||
to -= fro
|
||||
to.rotate(camera.worldOrientation.to_euler())
|
||||
to += fro
|
||||
|
||||
ray = Vehicle.BeautyRayCast(dani, "tool", to, fro, dist=5)
|
||||
|
||||
return ray
|
||||
|
||||
|
||||
#### SOUNDS #####
|
||||
|
||||
def FixToolSound():
|
||||
|
||||
# Engine Sound
|
||||
|
||||
device = bge.logic.globalDict["SoundDevice"]
|
||||
|
||||
code = "//sfx/fixtool.ogg"
|
||||
if code not in bge.logic.globalDict["sounds"]:
|
||||
bge.logic.globalDict["sounds"][code] = {"sound":aud.Sound(bge.logic.expandPath(code)),
|
||||
"play":None}
|
||||
|
||||
sound = bge.logic.globalDict["sounds"][code]
|
||||
|
||||
if not sound["play"] or not sound["play"].status:
|
||||
sound["play"] = device.play(sound["sound"])
|
||||
|
||||
sound["play"].volume = 1
|
||||
|
||||
def PaintToolSound():
|
||||
|
||||
# Engine Sound
|
||||
|
||||
device = bge.logic.globalDict["SoundDevice"]
|
||||
|
||||
code = "//sfx/painttool.ogg"
|
||||
if code not in bge.logic.globalDict["sounds"]:
|
||||
bge.logic.globalDict["sounds"][code] = {"sound":aud.Sound(bge.logic.expandPath(code)),
|
||||
"play":None}
|
||||
|
||||
sound = bge.logic.globalDict["sounds"][code]
|
||||
|
||||
if not sound["play"] or not sound["play"].status:
|
||||
sound["play"] = device.play(sound["sound"])
|
||||
|
||||
sound["play"].volume = 1
|
||||
|
File diff suppressed because it is too large
Load diff
4560
Scripts/Vehicle.py~
4560
Scripts/Vehicle.py~
File diff suppressed because it is too large
Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,61 +0,0 @@
|
|||
{
|
||||
|
||||
"Talk":{
|
||||
"Action":"DaniEmotions",
|
||||
"Frames":[0, 10],
|
||||
"kwargs":{"layer":3}
|
||||
},
|
||||
|
||||
"Laugh":{
|
||||
"Action":"DaniEmotions",
|
||||
"Frames":[10, 20],
|
||||
"kwargs":{"layer":3}
|
||||
},
|
||||
|
||||
"Stand":{
|
||||
"Frames":[0, 290]
|
||||
},
|
||||
|
||||
"Walk":{
|
||||
"Frames":[301, 313]
|
||||
},
|
||||
|
||||
"Drive":{
|
||||
"Frames":[330,330]
|
||||
},
|
||||
|
||||
"Swim":{
|
||||
"Frames":[340,353]
|
||||
},
|
||||
|
||||
"Fly":{
|
||||
"Frames":[358,371],
|
||||
"kwargs":{"priority":-1,
|
||||
"blendin":5}
|
||||
},
|
||||
|
||||
"Hang":{
|
||||
"Frames":[390,390],
|
||||
"kwargs":{"priority":-1}
|
||||
},
|
||||
|
||||
"Land":{
|
||||
"Frames":[371,384],
|
||||
"kwargs":{"priority":-1}
|
||||
|
||||
},
|
||||
|
||||
|
||||
"AnswerPhone":{
|
||||
"Action":"DanisPhone",
|
||||
"Frames":[32, 100],
|
||||
"kwargs":{"layer":2},
|
||||
"Keep":true
|
||||
},
|
||||
|
||||
"PutPhoneAway":{
|
||||
"Action":"DanisPhone",
|
||||
"Frames":[0, 32],
|
||||
"kwargs":{"layer":2}
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
{
|
||||
|
||||
"Stand":{
|
||||
"Frames":[0,300]
|
||||
},
|
||||
|
||||
"Walk":{
|
||||
"Frames":[330, 350]
|
||||
},
|
||||
|
||||
"Drive":{
|
||||
"Frames":[360,361]
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
|
||||
"Stand":{
|
||||
"Frames":[0,276]
|
||||
},
|
||||
|
||||
"Walk":{
|
||||
"Frames":[300, 320]
|
||||
},
|
||||
|
||||
"Drive":{
|
||||
"Frames":[325,325]
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
|
||||
"Stand":{
|
||||
"Frames":[0,276]
|
||||
}
|
||||
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"Walk":{
|
||||
"Frames":[301, 330]
|
||||
},
|
||||
|
||||
"Stand":{
|
||||
"Frames":[0, 290]
|
||||
},
|
||||
|
||||
"Talk":{
|
||||
"Action":"PapsTalk",
|
||||
"Frames":[0, 10],
|
||||
"kwargs":{"layer":3}
|
||||
}
|
||||
|
||||
|
||||
}
|
BIN
assembly.blend
BIN
assembly.blend
Binary file not shown.
BIN
assembly.blend1
BIN
assembly.blend1
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
"name":"Dark Shadow",
|
||||
"probability":1,
|
||||
"type":"race-car",
|
||||
|
||||
"material":{"MainColor" :[0.033096, 0.033096, 0.033096],
|
||||
"SecondaryColor":[1.000000, 0.147027, 0.000000]},
|
||||
|
||||
"wheels":[
|
||||
{ "radius":0.425, "xyz":[ 0.915, -1.427, -0.150], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":""},
|
||||
{ "radius":0.425, "xyz":[-0.915, -1.427, -0.150], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":".001"},
|
||||
{ "radius":0.425, "xyz":[-0.915, 1.184, -0.150], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".003"},
|
||||
{ "radius":0.425, "xyz":[ 0.915, 1.184, -0.150], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".002"}
|
||||
],
|
||||
|
||||
"mass" : 1993 ,
|
||||
"hp" : 610 ,
|
||||
"torque" : 100 ,
|
||||
"drag" : 0.5 ,
|
||||
"roll" : -0.4 ,
|
||||
"grip" : 0.3 ,
|
||||
"maxturn" : 0.8 ,
|
||||
"brakes" : 2.0 ,
|
||||
"abs" : 0.01 ,
|
||||
"downforce" : 2.0 ,
|
||||
"suspention" : 100.0 ,
|
||||
"suspentionDamping" : 0.8 ,
|
||||
"maxrpm" : 8000 ,
|
||||
"idle" : 1100 ,
|
||||
"redline" : 6000 ,
|
||||
|
||||
"gears":[
|
||||
5.00,
|
||||
3.00,
|
||||
2.00,
|
||||
1.00,
|
||||
0.75,
|
||||
0.50,
|
||||
0.25,
|
||||
0.20,
|
||||
0.15
|
||||
]
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"name":"Dark Shadow",
|
||||
"probability":1,
|
||||
|
||||
"wheels":[
|
||||
{ "radius":0.425, "xyz":[ 0.915, -1.427, -0.150], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":""},
|
||||
{ "radius":0.425, "xyz":[-0.915, -1.427, -0.150], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":".001"},
|
||||
{ "radius":0.425, "xyz":[-0.915, 1.184, -0.150], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".003"},
|
||||
{ "radius":0.425, "xyz":[ 0.915, 1.184, -0.150], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".002"}
|
||||
],
|
||||
|
||||
"mass" : 1993 ,
|
||||
"hp" : 610 ,
|
||||
"torque" : 100 ,
|
||||
"drag" : 0.5 ,
|
||||
"roll" : -0.4 ,
|
||||
"grip" : 0.2 ,
|
||||
"maxturn" : 0.8 ,
|
||||
"brakes" : 2.0 ,
|
||||
"abs" : 0.01 ,
|
||||
"downforce" : 2.0 ,
|
||||
"suspention" : 100.0 ,
|
||||
"suspentionDamping" : 0.8 ,
|
||||
"maxrpm" : 8000 ,
|
||||
"idle" : 1100 ,
|
||||
"redline" : 6000 ,
|
||||
|
||||
"gears":[
|
||||
5.00,
|
||||
3.00,
|
||||
2.00,
|
||||
1.00,
|
||||
0.75,
|
||||
0.50,
|
||||
0.25,
|
||||
0.20,
|
||||
0.15
|
||||
]
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"name":"Hatchback Model 1",
|
||||
"probability":10,
|
||||
"type":"street-car",
|
||||
|
||||
"wheels":[
|
||||
{ "radius":0.383, "xyz":[ 0.919, -1.519, -0.200], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":""},
|
||||
{ "radius":0.383, "xyz":[-0.919, -1.519, -0.200], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":".001"},
|
||||
{ "radius":0.383, "xyz":[-0.919, 1.522, -0.200], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".003"},
|
||||
{ "radius":0.383, "xyz":[ 0.919, 1.522, -0.200], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".002"}
|
||||
],
|
||||
|
||||
"mass" : 1993 ,
|
||||
"hp" : 50 ,
|
||||
"torque" : 50 ,
|
||||
"drag" : 1.5 ,
|
||||
"roll" : 0.4 ,
|
||||
"grip" : 0.1 ,
|
||||
"maxturn" : 0.8 ,
|
||||
"brakes" : 1.0 ,
|
||||
"abs" : 0.1 ,
|
||||
"downforce" : 0.5 ,
|
||||
"suspention" : 50.0 ,
|
||||
"suspentionDamping" : 0.8 ,
|
||||
"maxrpm" : 6000 ,
|
||||
"idle" : 1100 ,
|
||||
"redline" : 5000 ,
|
||||
|
||||
"gears":[
|
||||
5.00,
|
||||
2.00,
|
||||
1.00,
|
||||
0.50
|
||||
]
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
"name":"Neonspeedster",
|
||||
"probability":1,
|
||||
"type":"race-car",
|
||||
|
||||
"material":{"MainColor" :[0.051525, 0.514757, 1.000000],
|
||||
"SecondaryColor":[0.051525, 0.514757, 1.000000]},
|
||||
|
||||
"wheels":[
|
||||
{ "radius":0.42, "xyz":[ 0.89, -1.25, -0.100], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":""},
|
||||
{ "radius":0.42, "xyz":[-0.89, -1.25, -0.100], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":".001"},
|
||||
{ "radius":0.42, "xyz":[-0.89, 1.65, -0.100], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".003"},
|
||||
{ "radius":0.42, "xyz":[ 0.89, 1.65, -0.100], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".002"}
|
||||
],
|
||||
|
||||
"mass" : 1800 ,
|
||||
"hp" : 600 ,
|
||||
"torque" : 120 ,
|
||||
"drag" : 0.25 ,
|
||||
"roll" : -0.4 ,
|
||||
"grip" : 0.3 ,
|
||||
"maxturn" : 0.8 ,
|
||||
"brakes" : 2.0 ,
|
||||
"abs" : 0.01 ,
|
||||
"downforce" : 2.0 ,
|
||||
"suspention" : 200.0 ,
|
||||
"suspentionDamping" : 0.6 ,
|
||||
"maxrpm" : 8000 ,
|
||||
"idle" : 1100 ,
|
||||
"redline" : 6000 ,
|
||||
|
||||
"gears":[
|
||||
5.00,
|
||||
3.00,
|
||||
2.00,
|
||||
1.00,
|
||||
0.75,
|
||||
0.50,
|
||||
0.25,
|
||||
0.20,
|
||||
0.15
|
||||
]
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
"name":"Red Kiss",
|
||||
"probability":1,
|
||||
"type":"race-car",
|
||||
|
||||
"material":{"MainColor" :[1.000000, 0.008796, 0.000000],
|
||||
"SecondaryColor":[1.000000, 0.500000, 0.000000]},
|
||||
|
||||
"wheels":[
|
||||
{ "radius":0.469, "xyz":[ 0.959, -1.333, -0.100], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":""},
|
||||
{ "radius":0.469, "xyz":[-0.959, -1.333, -0.100], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":true , "object":".001"},
|
||||
{ "radius":0.469, "xyz":[-0.959, 1.538, -0.100], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".003"},
|
||||
{ "radius":0.469, "xyz":[ 0.959, 1.538, -0.100], "down":[0,0,-1], "axel":[-1,0,0], "suspensionRest": 0.2, "front":false, "object":".002"}
|
||||
],
|
||||
|
||||
"mass" : 1800 ,
|
||||
"hp" : 580 ,
|
||||
"torque" : 120 ,
|
||||
"drag" : 0.25 ,
|
||||
"roll" : -0.4 ,
|
||||
"grip" : 0.2 ,
|
||||
"maxturn" : 0.8 ,
|
||||
"brakes" : 2.0 ,
|
||||
"abs" : 0.01 ,
|
||||
"downforce" : 2.0 ,
|
||||
"suspention" : 200.0 ,
|
||||
"suspentionDamping" : 0.6 ,
|
||||
"maxrpm" : 8000 ,
|
||||
"idle" : 1100 ,
|
||||
"redline" : 6000 ,
|
||||
|
||||
"gears":[
|
||||
5.00,
|
||||
3.00,
|
||||
2.00,
|
||||
1.00,
|
||||
0.75,
|
||||
0.50,
|
||||
0.25,
|
||||
0.20,
|
||||
0.15
|
||||
]
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
* Cars
|
||||
** AI
|
||||
*** Spawn System [2/3]
|
||||
**** DONE Cars spawn all over the place
|
||||
**** DONE Not enough cars
|
||||
**** TODO Performace optimization
|
||||
*** AI NPC [4/7]
|
||||
**** DONE Stupid driving
|
||||
**** DONE Forward vision
|
||||
**** DONE Avoid Going Into Walls
|
||||
**** DONE Do not british
|
||||
**** TODO Angry Pursuit
|
||||
**** TODO Racing AI
|
||||
**** TODO Spawn Points Corrections [2/5]
|
||||
- [X] Loop Around
|
||||
- [X] To Racetrack
|
||||
- [X] Through Sand
|
||||
- [ ] Deep Down
|
||||
- [ ] Small Round
|
||||
** Controlls
|
||||
*** Breaking system [1/2]
|
||||
**** DONE Fix car tombling from breaking
|
||||
**** TODO Fix the Handbrake, to feel better
|
||||
** Camera
|
||||
*** DONE Don't Roll if car is upside down
|
||||
*** DONE While camera is in fly mode, track the target
|
||||
*** TODO Avoid walls and stuff, to see car
|
||||
* Characters
|
||||
* Story
|
|
@ -1,76 +0,0 @@
|
|||
{
|
||||
"speed": [
|
||||
26.358402252197266 ,
|
||||
21.851234436035156 ,
|
||||
22.34600830078125 ,
|
||||
35.7989501953125 ,
|
||||
6.217530250549316 ,
|
||||
26.85378074645996 ,
|
||||
33.8651123046875 ,
|
||||
23.299406051635742 ,
|
||||
22.026166915893555 ,
|
||||
23.528913497924805 ,
|
||||
26.148305892944336 ,
|
||||
30.280473709106445 ,
|
||||
23.370298385620117 ,
|
||||
28.574520111083984 ,
|
||||
29.749557495117188 ,
|
||||
19.382225036621094 ,
|
||||
36.2252197265625 ,
|
||||
43.09573745727539 ,
|
||||
46.76814270019531 ,
|
||||
47.48198699951172 ,
|
||||
50.24925994873047 ,
|
||||
52.846805572509766 ,
|
||||
30.805631637573242
|
||||
],
|
||||
"time":[
|
||||
170.65272959100002 ,
|
||||
172.79986740700002 ,
|
||||
175.59592075900002 ,
|
||||
178.357206599 ,
|
||||
182.51325741 ,
|
||||
186.291296247 ,
|
||||
189.72518670600004 ,
|
||||
192.36938303800002 ,
|
||||
198.250241647 ,
|
||||
201.33201389100003 ,
|
||||
205.44794146200002 ,
|
||||
209.12922035900004 ,
|
||||
213.11044018900003 ,
|
||||
219.506708898 ,
|
||||
221.33645230900004 ,
|
||||
225.15496903500002 ,
|
||||
233.56188715400003 ,
|
||||
235.41891638500005 ,
|
||||
237.67381141600004 ,
|
||||
240.81052518 ,
|
||||
243.59788943300003 ,
|
||||
246.41590875000003 ,
|
||||
248.44874652100003
|
||||
],
|
||||
"rot":[
|
||||
[-0.015924813225865364, 0.0011410210281610489, -0.4768390655517578] ,
|
||||
[-0.010619524866342545, 0.006157155614346266, 0.819098711013794] ,
|
||||
[-0.01246673334389925, 0.002614065306261182, 2.2400927543640137] ,
|
||||
[-0.04152778163552284, -0.004130885470658541, 1.943183422088623] ,
|
||||
[-0.04403195157647133, 0.08712327480316162, 2.8876852989196777] ,
|
||||
[-0.029080595821142197, 0.13835664093494415, 2.829178810119629] ,
|
||||
[0.08981640636920929, 0.15955263376235962, -2.9285950660705566] ,
|
||||
[0.24162724614143372, -0.06017084792256355, 2.941547155380249] ,
|
||||
[0.23552058637142181, -0.007189183495938778, 3.119412422180176] ,
|
||||
[0.21812723577022552, -0.037734098732471466, 2.6612043380737305] ,
|
||||
[-0.11147090047597885, -0.17597346007823944, 2.991697311401367] ,
|
||||
[0.6546691656112671, -0.054870348423719406, -2.769106388092041] ,
|
||||
[0.18609264492988586, -0.4377727508544922, -1.875230312347412] ,
|
||||
[0.013437599875032902, -0.023461028933525085, -1.3867586851119995] ,
|
||||
[0.13140811026096344, -0.08332643657922745, -1.9279202222824097] ,
|
||||
[0.15664435923099518, 0.06593117117881775, -2.0268445014953613] ,
|
||||
[-0.28711217641830444, 0.015364741906523705, 0.31375741958618164] ,
|
||||
[-0.32474762201309204, -0.002328319475054741, 0.24374638497829437] ,
|
||||
[-0.32376036047935486, -0.00781808141618967, 0.22786971926689148] ,
|
||||
[-0.20297476649284363, 0.003622535616159439, 0.2503244876861572] ,
|
||||
[-0.15761759877204895, -0.020702043548226357, 0.1932581514120102] ,
|
||||
[-0.15772217512130737, 0.0015355173964053392, 0.25058653950691223] ,
|
||||
[-0.13799037039279938, -0.017578350380063057, 0.1344577968120575]
|
||||
]}
|
20
run.py
20
run.py
|
@ -19,7 +19,7 @@ import urllib.parse
|
|||
#
|
||||
###############################################
|
||||
|
||||
VERSION = "08-08-24"
|
||||
VERSION = "25-09-24"
|
||||
|
||||
###############################################
|
||||
|
||||
|
@ -432,6 +432,16 @@ def set_settings(w):
|
|||
|
||||
box.pack_start(shadowcascadebox, 0,5,5)
|
||||
|
||||
|
||||
########### SOUND ##############################
|
||||
|
||||
box.pack_start(Gtk.HSeparator(), 0,5,5) #############################
|
||||
box.pack_start(Gtk.Label("Sound"), 0,5,5)
|
||||
|
||||
music = Gtk.CheckButton("Music")
|
||||
box.pack_start(music, 0,5,5)
|
||||
|
||||
|
||||
############ CONTROLS ########################
|
||||
box.pack_start(Gtk.HSeparator(), 0,5,5) #############################
|
||||
box.pack_start(Gtk.Label("Controls"), 0,5,5)
|
||||
|
@ -484,12 +494,13 @@ def set_settings(w):
|
|||
"veh_right" :"Steer Right",
|
||||
"veh_drift" :"Handbrake",
|
||||
"veh_nitro" :"Use Nitro",
|
||||
"veh_resque" :"Resque During Race",
|
||||
"veh_resque" :"Rescue During Race",
|
||||
"veh_gear_up" :"Shift Gears Up",
|
||||
"veh_gear_down":"Shift Gears Down",
|
||||
"veh_auto_gear":"Switch Automatic Gearbox",
|
||||
"veh_dynamcam" :"Switch Dynamic Camera",
|
||||
"veh_upload" :"Truck Deploy Cargo",
|
||||
"veh_horn" :"Car Horn",
|
||||
"chr_forward" :"Walk Forward",
|
||||
"chr_backward" :"Walk Backward",
|
||||
"chr_left" :"Walk Left",
|
||||
|
@ -514,6 +525,7 @@ def set_settings(w):
|
|||
"veh_auto_gear":"Q",
|
||||
"veh_dynamcam" :"C",
|
||||
"veh_upload" :"D",
|
||||
"veh_horn" :"H",
|
||||
"chr_forward" :"W",
|
||||
"chr_backward" :"S",
|
||||
"chr_left" :"A",
|
||||
|
@ -672,6 +684,7 @@ def set_settings(w):
|
|||
autoFPS.set_active( data.get("autofps", True ) )
|
||||
opt_scale.set_value( data.get("opt", 1.0 ) )
|
||||
turn_scale.set_value( data.get("turn", 1.0 ) )
|
||||
music.set_active( data.get("music", True ) )
|
||||
|
||||
for control in controlwidgets:
|
||||
try:
|
||||
|
@ -732,7 +745,8 @@ def set_settings(w):
|
|||
"ao" :ao.get_active(),
|
||||
"autofps" :autoFPS.get_active(),
|
||||
"opt" :opt_scale.get_value(),
|
||||
"turn" :turn_scale.get_value()
|
||||
"turn" :turn_scale.get_value(),
|
||||
"music" :music.get_active()
|
||||
}
|
||||
|
||||
for control in controlwidgets:
|
||||
|
|
813
run.py~
813
run.py~
|
@ -1,813 +0,0 @@
|
|||
# GPL3 or any later version
|
||||
# (C) J.Y.Amihud ( blenderdumbass ) 2024
|
||||
|
||||
# This is the launcher of the game.
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
import json
|
||||
import threading
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GLib
|
||||
import urllib.request
|
||||
import urllib.parse
|
||||
|
||||
# V E R S I O N
|
||||
#
|
||||
###############################################
|
||||
|
||||
VERSION = "07-07-24"
|
||||
|
||||
###############################################
|
||||
|
||||
|
||||
|
||||
def getData(link):
|
||||
|
||||
try:
|
||||
req = urllib.request.Request(link)
|
||||
f = urllib.request.urlopen(req)
|
||||
data = json.loads(f.read().decode('utf-8'))
|
||||
return data
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
from Scripts.Common import *
|
||||
|
||||
#### MAKING THE WINDOW ####
|
||||
|
||||
win = Gtk.Window()
|
||||
win.set_title("Dani's Race")
|
||||
win.set_size_request(799, 280)
|
||||
win.connect("destroy", Gtk.main_quit)
|
||||
win.set_default_icon_from_file("SettingUI/icon.png")
|
||||
box = Gtk.VBox()
|
||||
win.add(box)
|
||||
|
||||
#### Building the UI itself ###
|
||||
|
||||
banner = Gtk.Image.new_from_file('SettingUI/banner.jpg')
|
||||
box.pack_start(banner, 0,0,0)
|
||||
|
||||
pannel = Gtk.HeaderBar()
|
||||
pannel.set_show_close_button(True)
|
||||
win.set_titlebar(pannel)
|
||||
|
||||
playbox = Gtk.HBox()
|
||||
pannel.pack_start(playbox)
|
||||
|
||||
def play(w):
|
||||
|
||||
data = load_settings()
|
||||
if data:
|
||||
blenderplayer = data.get("blenderplayer")
|
||||
|
||||
command = [blenderplayer]
|
||||
|
||||
if data.get("fullscreen"):
|
||||
command.append("-f")
|
||||
else:
|
||||
command.append("-w")
|
||||
|
||||
|
||||
command.append(data.get("resolution").split(":")[0])
|
||||
command.append(data.get("resolution").split(":")[1])
|
||||
|
||||
# The file of the game
|
||||
command.append(os.getcwd()+"/assembly.blend")
|
||||
|
||||
# print(command)
|
||||
subprocess.Popen(command)
|
||||
|
||||
else:
|
||||
set_settings(w)
|
||||
|
||||
playbutton = Gtk.Button("Start Game")
|
||||
playbutton.connect("clicked", play)
|
||||
playbox.pack_start(playbutton, 0,5,5)
|
||||
|
||||
|
||||
################### SETTINGS #########################
|
||||
|
||||
def set_settings(w):
|
||||
|
||||
settingsWindow = Gtk.Dialog("Dani's Race Settings",
|
||||
buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||
Gtk.STOCK_OK, Gtk.ResponseType.OK),
|
||||
)
|
||||
|
||||
settingsWindow.set_size_request(600, 400)
|
||||
|
||||
box = settingsWindow.get_content_area()
|
||||
|
||||
# Scroller
|
||||
scrl = Gtk.ScrolledWindow()
|
||||
box.pack_start(scrl, 1,1,1)
|
||||
|
||||
# Actuall useful box
|
||||
box = Gtk.VBox()
|
||||
scrl.add(box)
|
||||
|
||||
# UPBGE executable
|
||||
|
||||
upbgebox = Gtk.HBox()
|
||||
upbgelabel = Gtk.Label("UPBGE executable: ")
|
||||
upbgeinput = Gtk.Entry()
|
||||
|
||||
def get_upbge_do(w):
|
||||
os.system("xdg-open https://github.com/UPBGE/upbge/releases/download/v0.36.1/upbge-0.36.1-linux-x86_64.tar.xz")
|
||||
downloadUPBGE = Gtk.Button("Get UPBGE")
|
||||
downloadUPBGE.connect("clicked", get_upbge_do)
|
||||
downloadUPBGE.set_tooltip_text("Download the latest working UPBGE for GNU / Linux.")
|
||||
|
||||
upbgeinput.set_text("blenderplayer")
|
||||
upbgeinput.set_tooltip_text("Location of the blenderplayer executable on the system ( should in UPBGE folder ).")
|
||||
|
||||
upbgebox.pack_start(upbgelabel, 0,5,5)
|
||||
upbgebox.pack_start(upbgeinput, 1,5,5)
|
||||
upbgebox.pack_start(downloadUPBGE, 0,5,5)
|
||||
|
||||
box.pack_start(upbgebox, 0,5,5)
|
||||
|
||||
###### GRAPHICS / COMPLEXITY #####
|
||||
|
||||
box.pack_start(Gtk.Label("Graphics"), 0,5,5)
|
||||
|
||||
# Resolution
|
||||
|
||||
resbox = Gtk.HBox()
|
||||
resfull = Gtk.CheckButton("Fullscreen")
|
||||
resfull.set_tooltip_text("Whether to run the game Fullscreen.")
|
||||
|
||||
resmenu = Gtk.ComboBoxText()
|
||||
resmenu.set_tooltip_text("What resolution to run the game at.")
|
||||
|
||||
resolutions = [
|
||||
"7680:4320",
|
||||
"5120:2880",
|
||||
"3840:2160",
|
||||
"2560:1440",
|
||||
"1920:1080",
|
||||
"1600:900",
|
||||
"1366:768",
|
||||
"1280:720",
|
||||
"1024:576",
|
||||
"960:540",
|
||||
"854:480",
|
||||
"640:360"
|
||||
]
|
||||
|
||||
for i in resolutions:
|
||||
resmenu.append_text(i)
|
||||
resmenu.set_active(4)
|
||||
|
||||
resbox.pack_start(resfull, 0,5,5)
|
||||
resbox.pack_end(resmenu, 0,5,5)
|
||||
|
||||
box.pack_start(resbox, 0,5,5)
|
||||
|
||||
# Target FPS
|
||||
|
||||
def hide_show_target_fps(w):
|
||||
fpsbox.set_visible(not w.get_active())
|
||||
|
||||
autoFPS = Gtk.CheckButton("Automatic Target FPS")
|
||||
autoFPS.set_active(True)
|
||||
autoFPS.connect("clicked", hide_show_target_fps)
|
||||
autoFPS.set_tooltip_text("Set Target FPS automatically to decrease input lag.")
|
||||
box.pack_start(autoFPS, 0,5,5)
|
||||
|
||||
fpsbox = Gtk.HBox()
|
||||
box.pack_start(fpsbox, 0,5,5)
|
||||
|
||||
fpsbox.pack_start(Gtk.Label("Target FPS"), 0,5,5)
|
||||
fpsbox.set_tooltip_text("FPS that the engine will try to render.\nDo not put more than the computer can handle.\nOtherwise the game will have way too much input lag.")
|
||||
|
||||
fpsadjust = Gtk.Adjustment(30, lower=1, upper=1000, step_increment=1)
|
||||
fps = Gtk.SpinButton(adjustment=fpsadjust, digits=0)
|
||||
fpsbox.pack_end(fps, 0,5,5)
|
||||
|
||||
|
||||
# Vsync
|
||||
|
||||
vsyncbox = Gtk.HBox()
|
||||
box.pack_start(vsyncbox, 0,5,5)
|
||||
|
||||
vsyncbox.pack_start(Gtk.Label("Vsync"), 0,5,5)
|
||||
vsyncoptions = ["On", "Off", "Adaptive"]
|
||||
vsyncmenu = Gtk.ComboBoxText()
|
||||
for i in vsyncoptions:
|
||||
vsyncmenu.append_text(i)
|
||||
vsyncmenu.set_active(1)
|
||||
vsyncbox.pack_end(vsyncmenu, 0,5,5)
|
||||
|
||||
|
||||
# Compositing
|
||||
|
||||
compositor = Gtk.CheckButton("Post Processing Effects")
|
||||
compositor.set_tooltip_text("Bloom, sun beams, film and color grading effects.")
|
||||
compositor.set_active(True)
|
||||
box.pack_start(compositor, 0,5,5)
|
||||
|
||||
# Reflections
|
||||
|
||||
reflections = Gtk.CheckButton("Screen-Space Reflections")
|
||||
reflections.set_tooltip_text("Pseudo-accurate reflections.")
|
||||
reflections.set_active(True)
|
||||
box.pack_start(reflections, 0,5,5)
|
||||
|
||||
# Ambient Occlusion
|
||||
|
||||
ao = Gtk.CheckButton("Ambient Occlusion")
|
||||
ao.set_tooltip_text("Makes the shadow areas darker when objects are close together.")
|
||||
ao.set_active(False)
|
||||
box.pack_start(ao, 0,5,5)
|
||||
|
||||
# Trees, Poles, Fenses
|
||||
|
||||
tplbox = Gtk.HBox()
|
||||
|
||||
trees = Gtk.CheckButton("Trees")
|
||||
trees.set_tooltip_text("Whether to spawn Trees.")
|
||||
trees.set_active(True)
|
||||
|
||||
poles = Gtk.CheckButton("Light Poles")
|
||||
poles.set_tooltip_text("Whether to spawn Light Poles.")
|
||||
poles.set_active(True)
|
||||
|
||||
fences = Gtk.CheckButton("Fences")
|
||||
fences.set_tooltip_text("Whether to spawn Metal and or Wooden fences.")
|
||||
fences.set_active(True)
|
||||
|
||||
tplbox.pack_start(trees, 1,5,5)
|
||||
tplbox.pack_start(poles, 1,5,5)
|
||||
tplbox.pack_start(fences, 1,5,5)
|
||||
|
||||
box.pack_start(tplbox, 0,5,5)
|
||||
|
||||
# Amount of cars
|
||||
carsbox = Gtk.HBox()
|
||||
carsbox.pack_start(Gtk.Label("Traffic Density"), 0,5,5)
|
||||
maxcarsadjust = Gtk.Adjustment(4, lower=1, upper=20, step_increment=1)
|
||||
maxcarsinput = Gtk.SpinButton(adjustment=maxcarsadjust, digits=0)
|
||||
maxcarsinput.set_tooltip_text("How many NPC cars to spawn on roads.")
|
||||
carsbox.pack_end(maxcarsinput, 0,5,5)
|
||||
box.pack_start(carsbox, 0,5,5)
|
||||
|
||||
|
||||
# Sampling
|
||||
|
||||
samplesbox = Gtk.HBox()
|
||||
sampleslabel = Gtk.Label("Main Samples: ")
|
||||
samplesadjust = Gtk.Adjustment(1, lower=1, upper=64, step_increment=1)
|
||||
samplesinput = Gtk.SpinButton(adjustment=samplesadjust, digits=0)
|
||||
|
||||
samplesinput.set_sensitive(False)
|
||||
|
||||
samplesinput.set_tooltip_text("How many times to render the image per frame. More gives more accurate soft shadows and anti-aliasing. Less is faster.")
|
||||
|
||||
samplesbox.pack_start(sampleslabel, 0,5,5)
|
||||
samplesbox.pack_end(samplesinput, 0,5,5)
|
||||
|
||||
box.pack_start(samplesbox, 0,5,5)
|
||||
|
||||
# Subsurface Sampling
|
||||
|
||||
skinsamplesbox = Gtk.HBox()
|
||||
skinsampleslabel = Gtk.Label("Skin Samples: ")
|
||||
skinsamplesadjust = Gtk.Adjustment(5, lower=1, upper=64, step_increment=1)
|
||||
skinsamplesinput = Gtk.SpinButton(adjustment=skinsamplesadjust, digits=0)
|
||||
|
||||
skinsamplesinput.set_sensitive(False)
|
||||
|
||||
skinsamplesinput.set_tooltip_text("How accurate the subsurface materials ( skin ) should be. More, prettier, less faster.")
|
||||
|
||||
skinsamplesbox.pack_start(skinsampleslabel, 0,5,5)
|
||||
skinsamplesbox.pack_end(skinsamplesinput, 0,5,5)
|
||||
|
||||
box.pack_start(skinsamplesbox, 0,5,5)
|
||||
|
||||
# Volumetric sampling
|
||||
|
||||
box.pack_start(Gtk.HSeparator(), 0,5,5) #############################
|
||||
|
||||
volumesamplesbox = Gtk.HBox()
|
||||
volumesampleslabel = Gtk.Label("Volumetric Samples: ")
|
||||
volumesamplesadjust = Gtk.Adjustment(32, lower=1, upper=64, step_increment=1)
|
||||
volumesamplesinput = Gtk.SpinButton(adjustment=volumesamplesadjust, digits=0)
|
||||
|
||||
volumesamplesinput.set_tooltip_text("How accurate should be fog, smoke and fire effects. More prettier, less faster.")
|
||||
|
||||
volumesamplesbox.pack_start(volumesampleslabel, 0,5,5)
|
||||
volumesamplesbox.pack_end(volumesamplesinput, 0,5,5)
|
||||
|
||||
box.pack_start(volumesamplesbox, 0,5,5)
|
||||
|
||||
|
||||
# Volumetric lighting
|
||||
|
||||
volumelight = Gtk.CheckButton("Volumetric Lighting")
|
||||
volumelight.set_active(True)
|
||||
volumelight.set_tooltip_text("Enable light to interact with volumetric materials.")
|
||||
|
||||
box.pack_start(volumelight, 0,5,5)
|
||||
|
||||
# Volumetric shadow
|
||||
|
||||
def show_hide_volume_shadows(w):
|
||||
volumeshadowsamplesbox.set_visible( w.get_active() )
|
||||
|
||||
volumeshadow = Gtk.CheckButton("Volumetric Shadows")
|
||||
volumeshadow.set_active(False)
|
||||
volumeshadow.set_tooltip_text("Enable volumetrics to cast shadows ( Very slow ).")
|
||||
volumeshadow.connect("clicked", show_hide_volume_shadows)
|
||||
|
||||
box.pack_start(volumeshadow, 0,5,5)
|
||||
|
||||
# Volumetric shadow sampling
|
||||
|
||||
volumeshadowsamplesbox = Gtk.HBox()
|
||||
volumeshadowsampleslabel = Gtk.Label("Volumetric Shadows Samples: ")
|
||||
volumeshadowsamplesadjust = Gtk.Adjustment(3, lower=1, upper=64, step_increment=1)
|
||||
volumeshadowsamplesinput = Gtk.SpinButton(adjustment=volumeshadowsamplesadjust, digits=0)
|
||||
|
||||
volumeshadowsamplesinput.set_tooltip_text("How accurate should be volumentric shadows. More prettier, less faster.")
|
||||
|
||||
volumeshadowsamplesbox.pack_start(volumeshadowsampleslabel, 0,5,5)
|
||||
volumeshadowsamplesbox.pack_end(volumeshadowsamplesinput, 0,5,5)
|
||||
|
||||
box.pack_start(volumeshadowsamplesbox, 0,5,5)
|
||||
|
||||
# Shadows
|
||||
|
||||
box.pack_start(Gtk.HSeparator(), 0,5,5) #############################
|
||||
|
||||
def show_hide_shadows(w):
|
||||
softshadows.set_visible( w.get_active() )
|
||||
contactshadows.set_visible( w.get_active() )
|
||||
shadowcubebox.set_visible( w.get_active() )
|
||||
shadowcascadebox.set_visible( w.get_active() )
|
||||
|
||||
|
||||
shadows = Gtk.CheckButton("Shadows")
|
||||
shadows.set_active(True)
|
||||
shadows.set_tooltip_text("Whether to render Shadows.")
|
||||
shadows.connect("clicked", show_hide_shadows)
|
||||
|
||||
box.pack_start(shadows, 0,5,5)
|
||||
|
||||
# Soft Shadows
|
||||
|
||||
softshadows = Gtk.CheckButton("Soft Shadows")
|
||||
softshadows.set_active(True)
|
||||
softshadows.set_tooltip_text("Whether to try rendering soft Shadows. ( Requires more than one Sample )")
|
||||
|
||||
box.pack_start(softshadows, 0,5,5)
|
||||
|
||||
# Contact Shadows
|
||||
|
||||
contactshadows = Gtk.CheckButton("Contact Shadows")
|
||||
contactshadows.set_active(True)
|
||||
contactshadows.set_tooltip_text("Render a special pass of shadows to fill up small cracks.")
|
||||
|
||||
box.pack_start(contactshadows, 0,5,5)
|
||||
|
||||
# Shadow resolution
|
||||
|
||||
shadowresolutions = [
|
||||
"4096",
|
||||
"2048",
|
||||
"1024",
|
||||
"512",
|
||||
"256",
|
||||
"128",
|
||||
"64"
|
||||
]
|
||||
|
||||
shadowcubebox = Gtk.HBox()
|
||||
shadowcubelabel = Gtk.Label("Lamp Shadow Resolution: ")
|
||||
shadowcubemenu = Gtk.ComboBoxText()
|
||||
|
||||
for i in shadowresolutions:
|
||||
shadowcubemenu.append_text(i)
|
||||
|
||||
shadowcubemenu.set_active(3)
|
||||
|
||||
shadowcubebox.pack_start(shadowcubelabel,0,5,5)
|
||||
shadowcubebox.pack_end(shadowcubemenu,0,5,5)
|
||||
|
||||
box.pack_start(shadowcubebox, 0,5,5)
|
||||
|
||||
|
||||
# Shadow cascade size
|
||||
|
||||
shadowcascadebox = Gtk.HBox()
|
||||
shadowcascadelabel = Gtk.Label("Sun Shadow Resolution: ")
|
||||
shadowcascademenu = Gtk.ComboBoxText()
|
||||
|
||||
for i in shadowresolutions:
|
||||
shadowcascademenu.append_text(i)
|
||||
|
||||
shadowcascademenu.set_active(2)
|
||||
|
||||
shadowcascadebox.pack_start(shadowcascadelabel,0,5,5)
|
||||
shadowcascadebox.pack_end(shadowcascademenu,0,5,5)
|
||||
|
||||
box.pack_start(shadowcascadebox, 0,5,5)
|
||||
|
||||
############ CONTROLS ########################
|
||||
box.pack_start(Gtk.HSeparator(), 0,5,5) #############################
|
||||
box.pack_start(Gtk.Label("Controls"), 0,5,5)
|
||||
|
||||
def show_hide_car_controls(w):
|
||||
controlboxes["veh_forward"].set_visible( not w.get_active() )
|
||||
controlboxes["veh_backward"].set_visible( not w.get_active() )
|
||||
controlboxes["veh_left"].set_visible( not w.get_active() )
|
||||
controlboxes["veh_right"].set_visible( not w.get_active() )
|
||||
|
||||
carmouseguides.set_visible( w.get_active() )
|
||||
carmouseshow.set_visible( w.get_active() )
|
||||
|
||||
|
||||
controlcarmouse = Gtk.CheckButton("Control Car With a Mouse")
|
||||
controlcarmouse.connect("clicked", show_hide_car_controls )
|
||||
controlcarmouse.set_tooltip_text("Use the mouse to control the car. Allows for more precise input. Has a learning curve.")
|
||||
box.pack_start(controlcarmouse, 0,5,5)
|
||||
|
||||
carmouseguides = Gtk.CheckButton("Mouse Control Guides")
|
||||
carmouseguides.set_active(True)
|
||||
carmouseguides.set_tooltip_text("Show guides on the screen when controlling the car with the mouse.")
|
||||
box.pack_start(carmouseguides, 0,5,5)
|
||||
|
||||
carmouseshow = Gtk.CheckButton("Show Mouse Cursor")
|
||||
carmouseshow.set_tooltip_text("Show mouse cursor when controlling the car with the mouse. ( Easier to understand than the guides, but can obstruct the view ).")
|
||||
box.pack_start(carmouseshow, 0,5,5)
|
||||
|
||||
controlnames = {
|
||||
"veh_forward" :"Drive Forward",
|
||||
"veh_backward" :"Drive Backward",
|
||||
"veh_left" :"Steer Left",
|
||||
"veh_right" :"Steer Right",
|
||||
"veh_drift" :"Handbrake",
|
||||
"veh_nitro" :"Use Nitro",
|
||||
"veh_resque" :"Resque During Race",
|
||||
"veh_gear_up" :"Shift Gears Up",
|
||||
"veh_gear_down":"Shift Gears Down",
|
||||
"veh_auto_gear":"Switch Automatic Gearbox",
|
||||
"veh_dynamcam" :"Switch Dynamic Camera",
|
||||
"veh_upload" :"Truck Deploy Cargo",
|
||||
"chr_forward" :"Walk Forward",
|
||||
"chr_backward" :"Walk Backward",
|
||||
"chr_left" :"Walk Left",
|
||||
"chr_right" :"Walk Right",
|
||||
"chr_jump" :"Jump",
|
||||
"chr_get_car" :"Enter Car",
|
||||
"chr_swimdown" :"Swim Down"
|
||||
|
||||
|
||||
}
|
||||
|
||||
controldefaults = {
|
||||
"veh_forward" :"UpArrow",
|
||||
"veh_backward" :"DownArrow",
|
||||
"veh_left" :"LeftArrow",
|
||||
"veh_right" :"RightArrow",
|
||||
"veh_drift" :"Space",
|
||||
"veh_nitro" :"Z",
|
||||
"veh_resque" :"BackSpace",
|
||||
"veh_gear_up" :"W",
|
||||
"veh_gear_down":"S",
|
||||
"veh_auto_gear":"Q",
|
||||
"veh_dynamcam" :"C",
|
||||
"veh_upload" :"D",
|
||||
"chr_forward" :"W",
|
||||
"chr_backward" :"S",
|
||||
"chr_left" :"A",
|
||||
"chr_right" :"D",
|
||||
"chr_jump" :"Space",
|
||||
"chr_get_car" :"Enter",
|
||||
"chr_swimdown" :"LShift"
|
||||
|
||||
}
|
||||
|
||||
controlwidgets = {}
|
||||
controlboxes = {}
|
||||
|
||||
for control in controlnames:
|
||||
|
||||
cbox = Gtk.HBox()
|
||||
box.pack_start(cbox, 0,5,5)
|
||||
controlboxes[control] = cbox
|
||||
|
||||
cbox.pack_start(Gtk.Label(controlnames[control]), 0,5,5)
|
||||
controlwidgets[control] = Gtk.ComboBoxText()
|
||||
cbox.pack_end(controlwidgets[control], 0,5,5)
|
||||
|
||||
for key in keycodes:
|
||||
controlwidgets[control].append_text(key)
|
||||
controlwidgets[control].set_active( list(keycodes.keys()).index(controldefaults[control]) )
|
||||
|
||||
|
||||
|
||||
######## NETWORK ######
|
||||
|
||||
box.pack_start(Gtk.HSeparator(), 0,5,5) #############################
|
||||
box.pack_start(Gtk.Label("Multiplayer"), 0,5,5)
|
||||
|
||||
def show_hide_multiplayer(w):
|
||||
|
||||
hostbox.set_visible( w.get_active() )
|
||||
usernamebox.set_visible( w.get_active() )
|
||||
multiplayerroombox.set_visible( w.get_active() )
|
||||
|
||||
multiplayer = Gtk.CheckButton("Multiplayer")
|
||||
multiplayer.connect("clicked", show_hide_multiplayer)
|
||||
box.pack_start(multiplayer, 0,5,5)
|
||||
|
||||
|
||||
hostbox = Gtk.HBox()
|
||||
hostbox.pack_start(Gtk.Label("Hostname:"), 0,5,5)
|
||||
hostname = Gtk.Entry()
|
||||
hostbox.pack_end(hostname, 0,5,5)
|
||||
box.pack_start(hostbox, 0,5,5)
|
||||
|
||||
usernamebox = Gtk.HBox()
|
||||
usernamebox.pack_start(Gtk.Label("Username:"),0,5,5)
|
||||
username = Gtk.Entry()
|
||||
usernamebox.pack_end(username,0,5,5)
|
||||
box.pack_start(usernamebox, 0,5,5)
|
||||
|
||||
multiplayerroombox = Gtk.HBox()
|
||||
multiplayerroombox.pack_start(Gtk.Label("Room:"),0,5,5)
|
||||
multiplayerroom = Gtk.Entry()
|
||||
multiplayerroombox.pack_end(multiplayerroom,0,5,5)
|
||||
box.pack_start(multiplayerroombox, 0,5,5)
|
||||
|
||||
|
||||
|
||||
|
||||
######### TIME ########
|
||||
|
||||
|
||||
box.pack_start(Gtk.HSeparator(), 0,5,5) #############################
|
||||
box.pack_start(Gtk.Label("In Game Time"), 0,5,5)
|
||||
|
||||
clockspeedbox = Gtk.HBox()
|
||||
clockspeedbox.pack_start(Gtk.Label("In Game Clock Speed:"), 0,5,5)
|
||||
clockspeedadjustment = Gtk.Adjustment(20, lower=0.1, upper=10000, step_increment=0.1)
|
||||
clockspeedentry = Gtk.SpinButton(adjustment=clockspeedadjustment, digits=2)
|
||||
clockspeedentry.set_tooltip_text("How much the clock in the game is faster than the real clock. 1 is real time speed. 10 is ten times faster.")
|
||||
clockspeedbox.pack_end(clockspeedentry, 0,5,5)
|
||||
|
||||
box.pack_start(clockspeedbox, 0,5,5)
|
||||
|
||||
|
||||
|
||||
############################################# DEV SETTINGS #####################
|
||||
|
||||
box.pack_start(Gtk.HSeparator(), 0,5,5) #############################
|
||||
|
||||
box.pack_start(Gtk.Label("For Developers"), 0,5,5)
|
||||
|
||||
def show_hide_devmode(w):
|
||||
devmode_cheats.set_visible( w.get_active() )
|
||||
devmode_visible_rays.set_visible( w.get_active() )
|
||||
|
||||
if not w.get_active():
|
||||
devmode_cheats.set_active( False )
|
||||
devmode_visible_rays.set_active( False )
|
||||
|
||||
devmode = Gtk.CheckButton("Developer Mode")
|
||||
devmode.set_tooltip_text("Developer mode is mode used in development of the game.")
|
||||
box.pack_start(devmode, 0,5,5)
|
||||
devmode.connect("clicked", show_hide_devmode )
|
||||
|
||||
devmode_cheats = Gtk.CheckButton("Developer Keyboard Cheatcodes")
|
||||
devmode_cheats.set_tooltip_text("Enable keyboards cheat codes, for testing purposes.")
|
||||
box.pack_start(devmode_cheats, 0,5,5)
|
||||
|
||||
devmode_visible_rays = Gtk.CheckButton("Developer Visible Rays")
|
||||
devmode_visible_rays.set_tooltip_text("Show the rays that are used for AIs to see.")
|
||||
box.pack_start(devmode_visible_rays, 0,5,5)
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
|
||||
|
||||
# Loading settings
|
||||
data = load_settings()
|
||||
|
||||
if data:
|
||||
upbgeinput.set_text( data.get("blenderplayer", "blenderplayer") )
|
||||
resfull.set_active( data.get("fullscreen", False ) )
|
||||
resmenu.set_active( resolutions.index( data.get("resolution", "1920:1080" ) ) )
|
||||
compositor.set_active( data.get("compositor", True ) )
|
||||
reflections.set_active( data.get("reflections", True ) )
|
||||
trees.set_active( data.get("trees", True ) )
|
||||
poles.set_active( data.get("poles", True ) )
|
||||
fences.set_active( data.get("fences", True ) )
|
||||
samplesadjust.set_value( data.get("samples", 1 ) )
|
||||
skinsamplesadjust.set_value( data.get("skinsamples", 5 ) )
|
||||
volumesamplesadjust.set_value( data.get("volumesamples", 32 ) )
|
||||
volumelight.set_active( data.get("volumelight", True ) )
|
||||
volumeshadow.set_active( data.get("volumeshadow", False ) )
|
||||
volumeshadowsamplesadjust.set_value( data.get("volshadsampl", 3 ) )
|
||||
shadows.set_active( data.get("shadows", True ) )
|
||||
softshadows.set_active( data.get("softshadows", True ) )
|
||||
contactshadows.set_active( data.get("cntctshadows", True ) )
|
||||
shadowcubemenu.set_active( shadowresolutions.index( data.get("shadowslamps", "512" ) ) )
|
||||
shadowcascademenu.set_active( shadowresolutions.index( data.get("shadowssun", "1024" ) ) )
|
||||
devmode.set_active( data.get("devmode", False ) )
|
||||
devmode_cheats.set_active( data.get("dev-cheats", False ) )
|
||||
devmode_visible_rays.set_active(data.get("dev-rays", False ) )
|
||||
clockspeedadjustment.set_value( data.get("clockspeed", 20.0 ) )
|
||||
controlcarmouse.set_active( data.get("veh_mouse", False ) )
|
||||
maxcarsadjust.set_value( data.get("maxcars", 4 ) )
|
||||
carmouseguides.set_active( data.get("veh_mouse_guides",True ) )
|
||||
carmouseshow.set_active( data.get("veh_mouse_cursor",False ) )
|
||||
multiplayer.set_active( data.get("multiplayer", False ) )
|
||||
hostname.set_text( data.get("mp-host", "http://localhost:6969") )
|
||||
username.set_text( data.get("mp-name", "Dani" ) )
|
||||
multiplayerroom.set_text( data.get("mp-room", "Main" ) )
|
||||
fpsadjust.set_value( data.get("fps", 30 ) )
|
||||
vsyncmenu.set_active( vsyncoptions.index( data.get("vsync", "Off" )))
|
||||
ao.set_active( data.get("ao", False ) )
|
||||
autoFPS.set_active( data.get("autofps", True ) )
|
||||
|
||||
for control in controlwidgets:
|
||||
try:
|
||||
controlwidgets[control].set_active( list(keycodes.keys()).index(data.get(control)) )
|
||||
except:
|
||||
controlwidgets[control].set_active( list(keycodes.keys()).index(controldefaults[control]) )
|
||||
|
||||
|
||||
|
||||
settingsWindow.show_all()
|
||||
|
||||
show_hide_shadows(shadows)
|
||||
show_hide_volume_shadows(volumeshadow)
|
||||
show_hide_devmode(devmode)
|
||||
show_hide_car_controls(controlcarmouse)
|
||||
show_hide_multiplayer(multiplayer)
|
||||
hide_show_target_fps(autoFPS)
|
||||
|
||||
response = settingsWindow.run()
|
||||
|
||||
if response == Gtk.ResponseType.OK:
|
||||
folder = get_settings_folder()
|
||||
f = folder+"/config.json"
|
||||
|
||||
data = {"blenderplayer":upbgeinput.get_text(),#
|
||||
"fullscreen" :resfull.get_active(),#
|
||||
"resolution" :resmenu.get_active_text(),#
|
||||
"compositor" :compositor.get_active(),#
|
||||
"reflections" :reflections.get_active(),#
|
||||
"trees" :trees.get_active(),#
|
||||
"poles" :poles.get_active(),#
|
||||
"fences" :fences.get_active(),#
|
||||
"samples" :int(samplesadjust.get_value()),#
|
||||
"skinsamples" :int(skinsamplesadjust.get_value()),#
|
||||
"volumesamples":int(volumesamplesadjust.get_value()),#
|
||||
"volumelight" :volumelight.get_active(),#
|
||||
"volumeshadow" :volumeshadow.get_active(),#
|
||||
"volshadsampl" :int(volumeshadowsamplesadjust.get_value()),#
|
||||
"shadows" :shadows.get_active(), #
|
||||
"softshadows" :softshadows.get_active(),#
|
||||
"cntctshadows" :contactshadows.get_active(),#
|
||||
"shadowslamps" :shadowcubemenu.get_active_text(),#
|
||||
"shadowssun" :shadowcascademenu.get_active_text(), #
|
||||
"devmode" :devmode.get_active(),
|
||||
"dev-cheats" :devmode_cheats.get_active(),
|
||||
"dev-rays" :devmode_visible_rays.get_active(),
|
||||
"clockspeed" :clockspeedadjustment.get_value(),
|
||||
"veh_mouse" :controlcarmouse.get_active(),
|
||||
"maxcars" :int(maxcarsadjust.get_value()),
|
||||
"veh_mouse_guides":carmouseguides.get_active(),
|
||||
"veh_mouse_cursor":carmouseshow.get_active(),
|
||||
"multiplayer" :multiplayer.get_active(),
|
||||
"mp-host" :hostname.get_text(),
|
||||
"mp-name" :username.get_text(),
|
||||
"mp-room" :multiplayerroom.get_text(),
|
||||
"fps" :int(fpsadjust.get_value()),
|
||||
"vsync" :vsyncmenu.get_active_text(),
|
||||
"ao" :ao.get_active(),
|
||||
"autofps" :autoFPS.get_active()
|
||||
}
|
||||
|
||||
for control in controlwidgets:
|
||||
data[control] = controlwidgets[control].get_active_text()
|
||||
|
||||
with open(f, "w") as save:
|
||||
json.dump(data, save, indent=4, sort_keys=True)
|
||||
|
||||
|
||||
settingsWindow.destroy()
|
||||
|
||||
settingsbutton = Gtk.Button("Settings")
|
||||
settingsbutton.connect("clicked", set_settings)
|
||||
settingsbutton.set_relief(Gtk.ReliefStyle.NONE)
|
||||
playbox.pack_start(settingsbutton, 0,5,5)
|
||||
|
||||
def do_updates(w):
|
||||
|
||||
updatesData = getData("https://blenderdumbass.codeberg.page/DanisRace/updates.json")
|
||||
|
||||
updatesWindow = Gtk.Dialog("Dani's Race Updates")
|
||||
|
||||
updatesWindow.set_size_request(600, 400)
|
||||
|
||||
box = updatesWindow.get_content_area()
|
||||
|
||||
# Scroller
|
||||
scrl = Gtk.ScrolledWindow()
|
||||
box.pack_start(scrl, 1,1,1)
|
||||
|
||||
# Actuall useful box
|
||||
box = Gtk.VBox()
|
||||
scrl.add(box)
|
||||
|
||||
if updatesData:
|
||||
|
||||
for n, version in enumerate(updatesData):
|
||||
vdata = updatesData[version]
|
||||
|
||||
if version == VERSION:
|
||||
buttontext = "Installed"
|
||||
tooltip = "You already have version "+version
|
||||
elif vdata.get("available"):
|
||||
buttontext = "Download"
|
||||
tooltip = "Download page for version "+version
|
||||
else:
|
||||
buttontext = "Help Unlock"
|
||||
tooltip = "Dani's Race "+version+" is not unlocked yet. Help with unlocking it."
|
||||
|
||||
# For the fist one
|
||||
if n == 0:
|
||||
add = "NEWEST!!! "
|
||||
else:
|
||||
add = ""
|
||||
|
||||
verbox = Gtk.HBox()
|
||||
verbox.pack_start(Gtk.Label(add+"Dani's Race v"+version), 0,5,5)
|
||||
|
||||
def open_webpage(w, link):
|
||||
os.system("xdg-open "+link)
|
||||
|
||||
actionButton = Gtk.Button(buttontext)
|
||||
actionButton.set_tooltip_text(tooltip)
|
||||
actionButton.connect("clicked", open_webpage, vdata.get("page"))
|
||||
verbox.pack_end(actionButton, 0, 5, 5)
|
||||
|
||||
box.pack_start(verbox, 0,5,5)
|
||||
box.pack_start(Gtk.HSeparator(), 0,5,5)
|
||||
else:
|
||||
box.pack_start(Gtk.Label("Could not get update information.\nCheck internet connection."), 1 , 5, 5)
|
||||
|
||||
updatesWindow.show_all()
|
||||
updatesWindow.run()
|
||||
updatesWindow.destroy()
|
||||
|
||||
updatesbutton = Gtk.Button("Updates")
|
||||
updatesbutton.connect("clicked", do_updates)
|
||||
updatesbutton.set_relief(Gtk.ReliefStyle.NONE)
|
||||
playbox.pack_start(updatesbutton, 0,5,5)
|
||||
|
||||
def get_settings_folder():
|
||||
|
||||
game = "danisrace"
|
||||
|
||||
try:
|
||||
data_dir = os.environ["XDG_DATA_HOME"] + "/" + game
|
||||
except:
|
||||
data_dir = os.path.expanduser("~/.local/share/"+game)
|
||||
|
||||
try:
|
||||
os.makedirs(data_dir)
|
||||
except:
|
||||
pass
|
||||
|
||||
return data_dir
|
||||
|
||||
def load_settings():
|
||||
|
||||
folder = get_settings_folder()
|
||||
f = folder+"/config.json"
|
||||
|
||||
try:
|
||||
with open(f) as o:
|
||||
return json.load(o)
|
||||
except: return None
|
||||
|
||||
|
||||
|
||||
#### Launching he ui ######
|
||||
|
||||
win.show_all()
|
||||
Gtk.main()
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Add table
Reference in a new issue