mirror of
https://github.com/worldforge/cyphesis
synced 2026-08-13 12:26:04 -04:00
It's currently a copy of the Mason ruleset. Where Mason focuses on letting the users create the world themselves, Deeds instead focuses on allowing world authors to set up enticing worlds with gameplay and stories. In contrast to Mason there are more features available to the world authors which allow for automatic creation of entities and so on.
149 lines
5 KiB
Python
149 lines
5 KiB
Python
#This file is distributed under the terms of the GNU General Public license.
|
|
#Copyright (C) 2006 Al Riddoch (See the file COPYING for details).
|
|
|
|
from atlas import *
|
|
from physics import *
|
|
|
|
import math
|
|
import sys
|
|
import weakref
|
|
|
|
import server
|
|
|
|
class Heaping(server.Task):
|
|
""" A task for laying down built up terrain with a digging implement."""
|
|
class Obstructed(Exception):
|
|
"An exception indicating this task is obstructed by an entity>"
|
|
pass
|
|
|
|
def heap_operation(self, op):
|
|
""" Op handler for cut op which activates this task """
|
|
# print self.__class__.__name__,".setup"
|
|
|
|
if len(op) < 1:
|
|
sys.stderr.write("%s task has no target in setup op" % self.__class__.__name__)
|
|
|
|
self.target = server.world.get_object_ref(op[0].id)
|
|
self.tool = op.to
|
|
|
|
self.pos = Point3D(op[0].pos)
|
|
|
|
def tick_operation(self, op):
|
|
""" Op handler for regular tick op """
|
|
# print self.__class__.__name__,".tick"
|
|
|
|
if self.target() is None:
|
|
# print "Target is no more"
|
|
self.irrelevant()
|
|
return
|
|
|
|
|
|
old_rate = self.rate
|
|
|
|
self.rate = 0.5 / 0.75
|
|
self.progress += 0.5
|
|
|
|
if old_rate < 0.01:
|
|
self.progress = 0
|
|
|
|
# print "%s" % self.pos
|
|
|
|
if self.progress < 1:
|
|
# print "Not done yet"
|
|
return self.next_tick(0.75)
|
|
|
|
self.progress = 0
|
|
|
|
|
|
if not hasattr(self, 'terrain_mod') or self.terrain_mod() is None:
|
|
try:
|
|
mod = self._find_mod('motte')
|
|
except Heaping.Obstructed:
|
|
print "obstructed"
|
|
self.irrelevant()
|
|
return
|
|
if mod is None:
|
|
# There is no terrain mod where we are digging,
|
|
return self._create_initial_mod()
|
|
print "found existing mod"
|
|
self.terrain_mod = weakref.ref(mod)
|
|
|
|
return self._grow_mod()
|
|
|
|
def _grow_mod(self):
|
|
mod = self.terrain_mod()
|
|
|
|
# FIXME The face direction should be relative to the shape centre,
|
|
# rather than entity coords, then when the character is facing out,
|
|
# the shape should only grow in that direction
|
|
|
|
# Determine which way the user is facing relative to the mod
|
|
user_to_mod = (mod.location - self.character.location).unit_vector()
|
|
user_facing = Vector3D(1,0,0)
|
|
face_factor = user_facing.rotate(self.character.location.orientation)
|
|
|
|
area = mod.terrainmod.shape.area()
|
|
if face_factor > 0.2:
|
|
# Character is facing the centre. Heap up
|
|
mod.terrainmod.height += 1 / area
|
|
else:
|
|
# Character is facing away, Heap out
|
|
area_factor = math.sqrt((area + 1) / area)
|
|
mod.terrainmod.shape *= area_factor
|
|
area_map = {'shape': mod.terrainmod.shape.as_data(),
|
|
'layer': 7}
|
|
# FIXME This area is not getting broadcast
|
|
mod.area = area_map
|
|
|
|
box = mod.terrainmod.shape.footprint()
|
|
mod.bbox = [box.low_corner().x,
|
|
box.low_corner().y,
|
|
0,
|
|
box.high_corner().x,
|
|
box.high_corner().y,
|
|
mod.terrainmod.height]
|
|
|
|
# We have modified the attribute in place,
|
|
# so must send an update op to propagate
|
|
res=Oplist()
|
|
res.append(Operation("update", to=mod.id))
|
|
res.append(self.next_tick(0.75))
|
|
return res
|
|
def _find_mod(self, name):
|
|
mods = self.target().terrain.find_mods(self.pos)
|
|
if len(mods) != 0:
|
|
for mod in mods:
|
|
if hasattr(mod, 'name') and mod.name == name:
|
|
return mod
|
|
raise Heaping.Obstructed, "Another mod is in the way"
|
|
def _create_initial_mod(self):
|
|
print "no existing mod"
|
|
z=self.character.location.coordinates.z + 1.0
|
|
modmap = {'height': z,
|
|
'shape': Polygon([[ -0.7, -0.7 ],
|
|
[ -1.0, 0.0 ],
|
|
[ -0.7, 0.7 ],
|
|
[ 0.0, 1.0 ],
|
|
[ 0.7, 0.7 ],
|
|
[ 1.0, 0.0 ],
|
|
[ 0.7, -0.7 ],
|
|
[ 0.0, -1.0 ]]).as_data(),
|
|
'type': 'levelmod' }
|
|
area_map = {'shape': modmap['shape'],
|
|
'layer': 7}
|
|
|
|
mod_loc = Location(self.character.location.parent)
|
|
mod_loc.velocity = Vector3D()
|
|
mod_loc.coordinates = self.pos
|
|
|
|
mod_create=Operation("create",
|
|
Entity(name="motte",
|
|
type="path",
|
|
location = mod_loc,
|
|
terrainmod = modmap,
|
|
area = area_map),
|
|
to=self.target())
|
|
res=Oplist()
|
|
res.append(mod_create)
|
|
res.append(self.next_tick(0.75))
|
|
return res
|