684 lines
22 KiB
Python
684 lines
22 KiB
Python
|
# 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
|