def __init__(self): self.physstate = 0 self.lifesequence = 0 self.move = 0 self.yaw = 0 self.roll = 0 self.pitch = 0 self.strafe = 0 self.o = vec(0, 0, 0) self.falling = vec(0, 0, 0) self.eyeheight = 14 self.vel = vec(0, 0, 0)
def toplane(self, *args): if len(args) == 2: n, p = args self.x = n.x self.y = n.y self.z = n.z self.offset = -self.dot(p) elif len(args) == 3: a, b, c = args self.cross(vec(b).sub(a), vec(c).sub(a)) mag = self.magnitude() if mag == 0.0: return False self.div(mag) self.offset = -self.dot(a) return True
def vecfromyawpitch(yaw, pitch, move, strafe): m = vec(0, 0, 0) if move: m.x = move * -math.sin(RAD * yaw) m.y = move * math.cos(RAD * yaw) else: m.x = m.y = 0 if pitch: m.x *= math.cos(RAD * pitch) m.y *= math.cos(RAD * pitch) m.z = move * math.sin(RAD * pitch) else: m.z = 0 if strafe: m.x += strafe * math.cos(RAD * yaw) m.y += strafe * math.sin(RAD * yaw) return m
def edgespan2vectorcube(self): if self.isentirelysolid() or self.isempty(): return for x in xrange(2): for y in xrange(2): for z in xrange(2): p = ivec(8 * x, 8 * y, 8 * z) v = vec(0, 0, 0) o = self.copy() genedgespanvert(p, o, v) self.setcubeedge( 0, y, z, edgeval(self.getcubeedge(0, y, z), x, int(v.x + 0.49)) ) self.setcubeedge( 1, z, x, edgeval(self.getcubeedge(1, z, x), y, int(v.y + 0.49)) ) self.setcubeedge( 2, x, y, edgeval(self.getcubeedge(2, x, y), z, int(v.z + 0.49)) )
def feetpos(self): return vec(0, 0, -self.eyeheight).add(self.o)
def copy(self): return vec(self.x, self.y, self.z)
def getphysics(self, peek=False): d = PhysicsState() physstate = self.getbyte() flags = self.getuint() for k in range(3): n = self.getbyte() n |= self.getbyte() << 8 if flags & (1 << k): n |= self.getbyte() << 16 if n & 0x800000: n |= -1 << 24 d.o[k] = n dir = self.getbyte() dir |= self.getbyte() << 8 yaw = dir % 360 pitch = clamp(dir / 360, 0, 180) - 90 roll = clamp(int(self.getbyte()), 0, 180) - 90 mag = self.getbyte() if flags & (1 << 3): mag |= self.getbyte() << 8 dir = self.getbyte() dir |= self.getbyte() << 8 d.vel = vecfromyawpitch(dir % 360, clamp(dir / 360, 0, 180) - 90, 1, 0) if flags & (1 << 4): mag = self.getbyte() if flags & (1 << 5): mag |= self.getbyte() << 8 if flags & (1 << 6): dir = self.getbyte() dir |= self.getbyte() << 8 falling = vecfromyawpitch(dir % 360, clamp(dir / 360, 0, 180) - 90, 1, 0) else: falling = vec(0, 0, -1) else: falling = vec(0, 0, 0) d.falling = falling seqcolor = (physstate >> 3) & 1 d.yaw = yaw d.pitch = pitch d.roll = roll if (physstate >> 4) & 2: d.move = -1 else: d.move = (physstate >> 4) & 1 if (physstate >> 6) & 2: d.strafe = -1 else: d.strafe = (physstate >> 6) & 1 d.physstate = physstate & 7 return d
def write_physics_state(cds, physics_state): d = physics_state # TODO: replace this with an actual lookup for which material is at a particular position lookupmaterial = dummy_air_material_lookup # 3 bits phys state, 1 bit life sequence, 2 bits move, 2 bits strafe physstate = ( d.physstate | ((d.lifesequence & 1) << 3) | ((d.move & 3) << 4) | ((d.strafe & 3) << 6) ) cds.putbyte(physstate) o = ivec(vec(d.o.x, d.o.y, d.o.z - d.eyeheight)) vel = min(int(d.vel.magnitude() * DVELF), 0xFFFF) fall = min(int(d.falling.magnitude() * DVELF), 0xFFFF) # 3 bits position, 1 bit velocity, 3 bits falling, 1 bit material flags = 0 if o.x < 0 or o.x > 0xFFFF: flags |= 1 << 0 if o.y < 0 or o.y > 0xFFFF: flags |= 1 << 1 if o.z < 0 or o.z > 0xFFFF: flags |= 1 << 2 if vel > 0xFF: flags |= 1 << 3 if fall > 0: flags |= 1 << 4 if fall > 0xFF: flags |= 1 << 5 if d.falling.x or d.falling.y or d.falling.z > 0: flags |= 1 << 6 if ( lookupmaterial(d.feetpos()) & material_types.MATF_CLIP == empty_material_types.MAT_GAMECLIP ): flags |= 1 << 7 cds.putuint(flags) for k in xrange(3): cds.putbyte(o[k] & 0xFF) cds.putbyte((o[k] >> 8) & 0xFF) if o[k] < 0 or o[k] > 0xFFFF: cds.putbyte((o[k] >> 16) & 0xFF) if d.yaw < 0: dir = 360 + int(d.yaw) % 360 else: dir = int(d.yaw) % 360 dir += clamp(int(d.pitch + 90), 0, 180) * 360 cds.putbyte(dir & 0xFF) cds.putbyte((dir >> 8) & 0xFF) cds.putbyte(clamp(int(d.roll + 90), 0, 180)) cds.putbyte(vel & 0xFF) if vel > 0xFF: cds.putbyte((vel >> 8) & 0xFF) velyaw, velpitch = vectoyawpitch(d.vel) if velyaw < 0: veldir = 360 + int(velyaw) % 360 else: veldir = int(velyaw) % 360 veldir += clamp(int(velpitch + 90), 0, 180) * 360 cds.putbyte(veldir & 0xFF) cds.putbyte((veldir >> 8) & 0xFF) if fall > 0: cds.putbyte(fall & 0xFF) if fall > 0xFF: cds.putbyte((fall >> 8) & 0xFF) if d.falling.x or d.falling.y or d.falling.z > 0: fallyaw, fallpitch = vectoyawpitch(d.falling) if fallyaw < 0: falldir = 360 + int(fallyaw) % 360 else: falldir = int(fallyaw) % 360 falldir += clamp(int(fallpitch + 90), 0, 180) * 360 cds.putbyte(falldir & 0xFF) cds.putbyte((falldir >> 8) & 0xFF)
def read_map_data(map_filename): meta_data = {"vars": {}, "ents": []} with gzip.open(map_filename) as f: magic, version, headersize, worldsize, numents, numpvs, lightmaps = struct.unpack( "4s6i", f.read(28)) meta_data["version"] = version meta_data["headersize"] = headersize meta_data["worldsize"] = worldsize meta_data["numents"] = numents meta_data["numpvs"] = numpvs meta_data["lightmaps"] = lightmaps if version <= 28: lightprecision, lighterror, lightlod = struct.unpack( "3i", f.read(12)) ambient = struct.unpack("B", f.read(1)) watercolor = struct.unpack("3B", f.read(3)) blendmap = struct.unpack("B", f.read(1)) lerpangle = struct.unpack("B", f.read(1)) lerpsubdiv = struct.unpack("B", f.read(1)) lerpsubdivsize = struct.unpack("B", f.read(1)) bumperror = struct.unpack("B", f.read(1)) skylight = struct.unpack("3B", f.read(3)) lavacolor = struct.unpack("3B", f.read(3)) waterfallcolor = struct.unpack("3B", f.read(3)) reserved = struct.unpack("10B", f.read(10)) maptitle = struct.unpack("128s", f.read(128)) meta_data["vars"]["maptitle"] = maptitle else: if version <= 29: blendmap, numvars = struct.unpack("2i", f.read(8)) else: blendmap, numvars, numvslots = struct.unpack("3i", f.read(12)) if version <= 28: numvars = 0 if version <= 29: numvslots = 0 meta_data["blendmap"] = blendmap meta_data["numvars"] = numvars meta_data["numvslots"] = numvslots for i in xrange(numvars): var_type = struct.unpack("b", f.read(1))[0] ilen = struct.unpack("<H", f.read(2))[0] var_name = f.read(ilen) if var_type == cs_id_types.ID_VAR: var_value = struct.unpack("i", f.read(4))[0] elif var_type == cs_id_types.ID_FVAR: var_value = struct.unpack("f", f.read(4))[0] elif var_type == cs_id_types.ID_SVAR: slen = struct.unpack("H", f.read(2))[0] var_value = f.read(slen) # print "{:.8}: {:.32s} = {}".format(cs_id_types.by_value(var_type), var_name, var_value) meta_data["vars"][var_name] = var_value if version >= 16: gt_len = struct.unpack("b", f.read(1))[0] game_type = f.read(gt_len + 1) else: game_type = "fps" meta_data["gametype"] = game_type if version >= 16: eif = struct.unpack("H", f.read(2))[0] extra_size = struct.unpack("H", f.read(2))[0] edata = f.read(extra_size) print(eif, extra_size, edata) if version < 14: f.read(256) else: nummru = struct.unpack("H", f.read(2))[0] f.read(nummru * 2) for i in range(min(numents, MAXENTS)): x, y, z = struct.unpack("3f", f.read(12)) attrs = struct.unpack("5h", f.read(10)) ent_type, reserved = struct.unpack("2B", f.read(2)) ent = { "id": i, "type": ent_type, "x": x, "y": y, "z": z, "attrs": attrs, "reserved": reserved, } meta_data["ents"].append(ent) vslots = load_vslots(f, numvslots) worldroot = loadchildren(version, f, vec(0, 0, 0), worldsize >> 1) try: with gzip.open(map_filename) as f: meta_data["crc"] = zlib.crc32(f.read()) & 0xFFFFFFFF except IOError: meta_data["crc"] = 0 cube_map = CubeMap() cube_map.vslots = vslots cube_map.octants = worldroot cube_map.meta_data = meta_data return cube_map