def setlevel(session, args): from model import PlayerModel session.player.level = int(args[1]) session.player.onLevelUp() session.player.updateLevelProp() # 发送属性数据 PlayerModel.sendPropUpdateMsg(session.player)
def __init__(self, position=(0, 0, 0), rotation=(-20, 0), flying=False, game_mode=G.GAME_MODE, username="", local_player=True): super(Player, self).__init__(position, rotation, health=7, max_health=10, attack_power=2.0 / 3, attack_range=4) self.inventory = Inventory(27) self.quick_slots = Inventory(9) self.armor = Inventory(4) self.flying = flying self.game_mode = game_mode self.strafe = [0, 0] self.dy = 0 self.current_density = 1 # Current density of the block we're colliding with self._position = position self.last_sector = None self.last_damage_block = 0, 100, 0 # dummy temp value self.username = username self.local_player = local_player # for debug initial_items = [cake_block, torch_block, bed_item] for item in initial_items: self.inventory.add_item(item.id, item.max_stack_size) if not local_player: self.model = PlayerModel(position) self.momentum = (0, 0, 0)
def setlevel(session, args): from model import PlayerModel n = session.player.angerMax if len(args) >= 2: n = int(args[1]) session.player.addAnger(n) session.player.updateLevelProp() # 发送属性数据 PlayerModel.sendPropUpdateMsg(session.player)
def __init__(self, position=(0,0,0), rotation=(-20, 0), flying=False, game_mode=G.GAME_MODE, username="", local_player=True): super(Player, self).__init__(position, rotation, health=7, max_health=10, attack_power=2.0 / 3, attack_range=4) self.inventory = Inventory(27) self.quick_slots = Inventory(9) self.armor = Inventory(4) self.flying = flying self.game_mode = game_mode self.strafe = [0, 0] self.dy = 0 self.current_density = 1 # Current density of the block we're colliding with self._position = position self.last_sector = None self.last_damage_block = 0, 100, 0 # dummy temp value self.username = username self.local_player = local_player # for debug initial_items = [cake_block, torch_block, bed_item] for item in initial_items: self.inventory.add_item(item.id, item.max_stack_size) if not local_player: self.model = PlayerModel(position) self.momentum = (0,0,0)
def exe(self, owner, skill, objDest, param): #TODO from model import PlayerModel newX = owner.x + 2 newY = owner.y + 2 if not owner.mapObj.canMove(newX, newY): newX = owner.x newY = owner.y player = PlayerModel.Player() player.forkFrom(owner, self.paramPropRate) player.arenaCtrl.destPlayerRef = weakref.ref(objDest) player.session = owner.session owner.mapObj.playerEnterMap(player, newX, newY) from model import ArenaModel player.fsm.changeState(ffext.singleton(ArenaModel.ArenaStateAttack)) beginTm = ffext.getTime() def cb(): if ffext.getTime() - beginTm >= 20 or player.isDeath(): player.mapObj.playerLeaveMap(player) player.session = None else: try: player.fsm.update(player, ffext.getTimeMs()) except: pass ffext.timer(1000, cb) ffext.timer(1000, cb) return
def processCreateRoleReq(session, msg): print('CreateRoleReq', msg) if msg.gender != Base.Gender.MALE and msg.gender != Base.Gender.FEMAIL: msg.gender = Base.Gender.MALE roleTmp = PlayerModel.Role() roleTmp.uid = idtool.allocUid() if session.isWebDebug: msg.name = msg.name.encode('utf-8') roleTmp.name = msg.name roleTmp.job = msg.job roleTmp.gender = msg.gender if roleTmp.gender != Base.Gender.MALE and roleTmp.gender != Base.Gender.FEMAIL: roleTmp.gender = Base.Gender.MALE if roleTmp.job < Base.Job.ZHANSHI or roleTmp.job > Base.Job.YOUXIA: roleTmp.job = Base.Job.ZHANSHI def callback(db): retMsg = MsgDef.CreateRoleRet() if db.isOk(): retMsg.flag = True retMsg.uid = roleTmp.uid session.user.addRole(roleTmp) else: retMsg.flag = False retMsg.errMsg = '角色名已经存在' session.sendMsg(MsgDef.ServerCmd.CREATE_ROLE_RET, retMsg) MailModel.createMailRecrodAtFirstTime(roleTmp.uid) # 新增每日活动记录 DbService.getPlayerService().createDailyLoginAct( session.user.accountid) if retMsg.flag == True: # 创角(old)-记录log LogModel.logLoginData(session.user.accountid, roleTmp.uid, roleTmp.name, LogModel.LoginOpType.CREATE_PLAYER, 0) mapName = 10001 x = 27 y = 188 mapObj = MapMgr.getMapMgr().allocMap(mapName) if mapObj.cfg.reviveMap != None: mapName = mapObj.cfg.reviveMap.mapname x = mapObj.cfg.reviveMap.x y = mapObj.cfg.reviveMap.y DbService.getPlayerService().createRole(session.user, roleTmp, mapName, x, y, callback) return
def cb(dbSet): db = dbSet['player'] dbitem = dbSet['item'] dbPet = dbSet['pet'] session = ffext.SessionNone() player = PlayerModel.Player(db.result[0]) session.setPlayer(player) player.session = session if dbitem.isOk(): player.itemCtrl.fromData(dbitem.result) player.petCtrl.fromData(dbPet.result) player.direction = Base.Direction.RIGHT player.arenaCtrl.destPlayerRef = weakref.ref(playerSrc) #状态机 player.fsm = MonsterAI.FSM(player) def goTo(): mapObj.copyMapHandler.autoPlayerRef = weakref.ref(player) mapObj.playerEnterMap(player, 69, 72) player.fsm.changeState(ffext.singleton(ArenaStateAttack)) ffext.timer(1000, goTo) return
class Player(Entity): local_player = True def __init__(self, position=(0,0,0), rotation=(-20, 0), flying=False, game_mode=G.GAME_MODE, username="", local_player=True): super(Player, self).__init__(position, rotation, health=7, max_health=10, attack_power=2.0 / 3, attack_range=4) self.inventory = Inventory(27) self.quick_slots = Inventory(9) self.armor = Inventory(4) self.flying = flying self.game_mode = game_mode self.strafe = [0, 0] self.dy = 0 self.current_density = 1 # Current density of the block we're colliding with self._position = position self.last_sector = None self.last_damage_block = 0, 100, 0 # dummy temp value self.username = username self.local_player = local_player # for debug initial_items = [cake_block, torch_block, bed_item] for item in initial_items: self.inventory.add_item(item.id, item.max_stack_size) if not local_player: self.model = PlayerModel(position) self.momentum = (0,0,0) def add_item(self, item_id, quantity=1): if self.quick_slots.add_item(item_id, quantity=quantity): return True elif self.inventory.add_item(item_id, quantity=quantity): return True return False def change_health(self, change): self.health += change if self.health > self.max_health: self.health = self.max_health @property def position(self): return self._position @position.setter def position(self, value): self._position = value if not self.local_player: self.model.update_position(value) def on_deactivate(self): self.strafe = [0, 0] def on_key_release(self, symbol, modifiers): if symbol == G.MOVE_FORWARD_KEY: self.strafe[0] += 1 elif symbol == G.MOVE_BACKWARD_KEY: self.strafe[0] -= 1 elif symbol == G.MOVE_LEFT_KEY: self.strafe[1] += 1 elif symbol == G.MOVE_RIGHT_KEY: self.strafe[1] -= 1 elif (symbol == G.JUMP_KEY or symbol == G.CROUCH_KEY) and self.flying: self.dy = 0 def on_key_press(self, symbol, modifiers): if symbol == G.MOVE_FORWARD_KEY: self.strafe[0] -= 1 elif symbol == G.MOVE_BACKWARD_KEY: self.strafe[0] += 1 elif symbol == G.MOVE_LEFT_KEY: self.strafe[1] -= 1 elif symbol == G.MOVE_RIGHT_KEY: self.strafe[1] += 1 elif symbol == G.JUMP_KEY: if self.flying: self.dy = 0.045 # jump speed elif self.dy == 0: self.dy = 0.016 # jump speed G.CLIENT.send_jump() elif symbol == G.CROUCH_KEY: if self.flying: self.dy = -0.045 # inversed jump speed elif symbol == G.FLY_KEY and self.game_mode == G.CREATIVE_MODE: self.dy = 0 self.flying = not self.flying def get_motion_vector(self, multiplier=1): if any(self.strafe): x, y = self.rotation y_r = radians(y) x_r = radians(x) strafe = atan2(*self.strafe) if self.flying: m = cos(y_r) dy = sin(y_r) if self.strafe[1]: dy = 0.0 m = 1 if self.strafe[0] > 0: dy *= -1 x_r += strafe dx = cos(x_r) * m dz = sin(x_r) * m else: dy = 0.0 x_r += strafe dx = cos(x_r) dz = sin(x_r) else: dy = 0.0 dx = 0.0 dz = 0.0 return dx*multiplier, dy*multiplier, dz*multiplier def get_sight_vector(self): x, y = self.rotation y_r = radians(y) x_r = radians(x) m = cos(y_r) dy = sin(y_r) x_r -= G.HALF_PI dx = cos(x_r) * m dz = sin(x_r) * m return dx, dy, dz # get sight direction # retval[0]: E/S/W/N # retval[1]: angle between sight vector and east direction def get_sight_direction(self): dx, dy, dz = self.get_sight_vector() dz = -dz angle = 0 if dz == 0: if dx > 0: angle = 0 elif dx < 0: angle = pi elif dz > 0: angle = acos(dx / sqrt(dx * dx + dz * dz)) else: angle = -acos(dx / sqrt(dx * dx + dz * dz)) if angle < 0: angle += 2 * pi angle *= 180 / pi if 0 < angle <= 45 or 315 < angle <= 360: direction = G.EAST elif 45 < angle <= 135: direction = G.NORTH elif 135 < angle <= 225: direction = G.WEST elif 225 < angle <= 315: direction = G.SOUTH return (dx, dy, dz), direction, angle def update(self, dt, parent): # walking if self.local_player: speed = 15 if self.flying else 5*self.current_density dx, dy, dz = self.get_motion_vector(multiplier=(dt * speed)) else: dx, dy, dz = self.momentum dx, dy, dz = dx*dt, dy*dt, dz*dt # gravity if not self.flying: self.dy -= dt * 0.022 # g force, should be = jump_speed * 0.5 / max_jump_height self.dy = max(self.dy, -0.5) # terminal velocity dy += self.dy # collisions x, y, z = self.position self.position = self.collide(parent, (x + dx, y + dy, z + dz), 2) def collide(self, parent, position, height): pad = 0.25 p = list(position) np = normalize(position) self.current_density = 1 # Reset it, incase we don't hit any water for face in FACES: # check all surrounding blocks for i in xrange(3): # check each dimension independently if not face[i]: continue d = (p[i] - np[i]) * face[i] if d < pad: continue for dy in xrange(height): # check each height op = list(np) op[1] -= dy op[i] += face[i] op = tuple(op) # If there is no block or if the block is not a cube, # we can walk there. if op not in parent.world \ or parent.world[op].vertex_mode != G.VERTEX_CUBE: continue # if density <= 1 then we can walk through it. (water) if parent.world[op].density < 1: self.current_density = parent.world[op].density continue # if height <= 1 then we can walk on top of it. (carpet, half-blocks, etc...) if parent.world[op].height < 0.5: #current_height = parent.world[op].height #x, y, z = self.position #new_pos = (x, y + current_height, z) #self.position = new_pos continue if parent.world[op].player_damage > 0: if self.last_damage_block != np: # this keeps a player from taking the same damage over and over... self.change_health( - parent.world[op].player_damage) parent.item_list.update_health() self.last_damage_block = np continue else: #do nothing continue p[i] -= (d - pad) * face[i] if face == (0, -1, 0) or face == (0, 1, 0): # jump damage if self.game_mode == G.SURVIVAL_MODE: damage = self.dy * -1000.0 damage = 3.0 * damage / 22.0 damage -= 2.0 if damage >= 0.0: health_change = 0 if damage <= 0.839: health_change = 0 elif damage <= 1.146: health_change = -1 elif damage <= 1.44: health_change = -2 elif damage <= 2.26: health_change = -2 else: health_change = -3 if health_change != 0: self.change_health(health_change) parent.item_list.update_health() self.dy = 0 break return tuple(p)
class Player(Entity): local_player = True def __init__(self, position=(0, 0, 0), rotation=(-20, 0), flying=False, game_mode=G.GAME_MODE, username="", local_player=True): super(Player, self).__init__(position, rotation, health=7, max_health=10, attack_power=2.0 / 3, attack_range=4) self.inventory = Inventory(27) self.quick_slots = Inventory(9) self.armor = Inventory(4) self.flying = flying self.game_mode = game_mode self.strafe = [0, 0] self.dy = 0 self.current_density = 1 # Current density of the block we're colliding with self._position = position self.last_sector = None self.last_damage_block = 0, 100, 0 # dummy temp value self.username = username self.local_player = local_player # for debug initial_items = [cake_block, torch_block, bed_item] for item in initial_items: self.inventory.add_item(item.id, item.max_stack_size) if not local_player: self.model = PlayerModel(position) self.momentum = (0, 0, 0) def add_item(self, item_id, quantity=1): if self.quick_slots.add_item(item_id, quantity=quantity): return True elif self.inventory.add_item(item_id, quantity=quantity): return True return False def change_health(self, change): self.health += change if self.health > self.max_health: self.health = self.max_health @property def position(self): return self._position @position.setter def position(self, value): self._position = value if not self.local_player: self.model.update_position(value) def on_deactivate(self): self.strafe = [0, 0] def on_key_release(self, symbol, modifiers): if symbol == G.MOVE_FORWARD_KEY: self.strafe[0] += 1 elif symbol == G.MOVE_BACKWARD_KEY: self.strafe[0] -= 1 elif symbol == G.MOVE_LEFT_KEY: self.strafe[1] += 1 elif symbol == G.MOVE_RIGHT_KEY: self.strafe[1] -= 1 elif (symbol == G.JUMP_KEY or symbol == G.CROUCH_KEY) and self.flying: self.dy = 0 def on_key_press(self, symbol, modifiers): if symbol == G.MOVE_FORWARD_KEY: self.strafe[0] -= 1 elif symbol == G.MOVE_BACKWARD_KEY: self.strafe[0] += 1 elif symbol == G.MOVE_LEFT_KEY: self.strafe[1] -= 1 elif symbol == G.MOVE_RIGHT_KEY: self.strafe[1] += 1 elif symbol == G.JUMP_KEY: if self.flying: self.dy = 0.045 # jump speed elif self.dy == 0: self.dy = 0.016 # jump speed G.CLIENT.send_jump() elif symbol == G.CROUCH_KEY: if self.flying: self.dy = -0.045 # inversed jump speed elif symbol == G.FLY_KEY and self.game_mode == G.CREATIVE_MODE: self.dy = 0 self.flying = not self.flying def get_motion_vector(self, multiplier=1): if any(self.strafe): x, y = self.rotation y_r = radians(y) x_r = radians(x) strafe = atan2(*self.strafe) if self.flying: m = cos(y_r) dy = sin(y_r) if self.strafe[1]: dy = 0.0 m = 1 if self.strafe[0] > 0: dy *= -1 x_r += strafe dx = cos(x_r) * m dz = sin(x_r) * m else: dy = 0.0 x_r += strafe dx = cos(x_r) dz = sin(x_r) else: dy = 0.0 dx = 0.0 dz = 0.0 return dx * multiplier, dy * multiplier, dz * multiplier # Replace index 1 with dy*multiplier def get_sight_vector(self): x, y = self.rotation y_r = radians(y) x_r = radians(x) m = cos(y_r) dy = sin(y_r) x_r -= G.HALF_PI dx = cos(x_r) * m dz = sin(x_r) * m return dx, dy, dz # get sight direction # retval[0]: E/S/W/N # retval[1]: angle between sight vector and east direction def get_sight_direction(self): dx, dy, dz = self.get_sight_vector() dz = -dz angle = 0 if dz == 0: if dx > 0: angle = 0 elif dx < 0: angle = pi elif dz > 0: angle = acos(dx / sqrt(dx * dx + dz * dz)) else: angle = -acos(dx / sqrt(dx * dx + dz * dz)) if angle < 0: angle += 2 * pi angle *= 180 / pi if 0 < angle <= 45 or 315 < angle <= 360: direction = G.EAST elif 45 < angle <= 135: direction = G.NORTH elif 135 < angle <= 225: direction = G.WEST elif 225 < angle <= 315: direction = G.SOUTH return (dx, dy, dz), direction, angle def update(self, dt, parent): # walking if self.local_player: speed = 15 if self.flying else 5 * self.current_density dx, dy, dz = self.get_motion_vector(multiplier=(dt * speed)) else: dx, dy, dz = self.momentum dx, dy, dz = dx * dt, dy * dt, dz * dt # gravity if not self.flying: self.dy -= dt * 0.022 # g force, should be = jump_speed * 0.5 / max_jump_height self.dy = max(self.dy, -0.5) # terminal velocity dy += self.dy # collisions x, y, z = self.position self.position = self.collide(parent, (x + dx, y + dy, z + dz), 2) def collide(self, parent, position, height): pad = 0.25 p = list(position) np = normalize(position) self.current_density = 1 # Reset it, incase we don't hit any water for face in FACES: # check all surrounding blocks for i in range(3): # check each dimension independently if not face[i]: continue d = (p[i] - np[i]) * face[i] if d < pad: continue for dy in range(height): # check each height op = list(np) op[1] -= dy op[i] += face[i] op = tuple(op) # If there is no block or if the block is not a cube, # we can walk there. if op not in parent.world \ or parent.world[op].vertex_mode != G.VERTEX_CUBE: continue # if density <= 1 then we can walk through it. (water) if parent.world[op].density < 1: self.current_density = parent.world[op].density continue # if height <= 1 then we can walk on top of it. (carpet, half-blocks, etc...) if parent.world[op].height < 0.5: #current_height = parent.world[op].height #x, y, z = self.position #new_pos = (x, y + current_height, z) #self.position = new_pos continue if parent.world[op].player_damage > 0: if self.last_damage_block != np: # this keeps a player from taking the same damage over and over... self.change_health(-parent.world[op].player_damage) parent.item_list.update_health() self.last_damage_block = np continue else: #do nothing continue p[i] -= (d - pad) * face[i] if face == (0, -1, 0) or face == (0, 1, 0): # jump damage if self.game_mode == G.SURVIVAL_MODE: damage = self.dy * -1000.0 damage = 3.0 * damage / 22.0 damage -= 2.0 if damage >= 0.0: health_change = 0 if damage <= 0.839: health_change = 0 elif damage <= 1.146: health_change = -1 elif damage <= 1.44: health_change = -2 elif damage <= 2.26: health_change = -2 else: health_change = -3 if health_change != 0: self.change_health(health_change) parent.item_list.update_health() self.dy = 0 break return tuple(p)
def callback(db): session.user = PlayerModel.User() session.user.username = msg.username reconnectUid = msg.reconnectUid retRole = [] if db.result: accountId = long(db.result[0][0]) def funcToClose(sessOther): if sessOther.user.accountid == accountId: ffext.warn('check relogin accountId=%d, name=%s' % (accountId, sessOther.user.username)) #if reconnectUid: # session.sendMsg(MsgDef.ServerCmd.ERROR_MSG, buildErrMsg(MsgDef.ClientCmd.LOGIN, Base.lang('账号在其他地方登录'))) #else: # sessOther.close() # 登出-记录log LogModel.logLoginData(accountId, 0, '', LogModel.LoginOpType.LOGOUT, LogModel.LoginReason.KICKOUT) sessOther.sendMsg(MsgDef.ServerCmd.RELOGIN, MsgDef.ReLoginRet()) def cbClose(): sessOther.close() ffext.timer(500, cbClose) return True ffext.getSessionMgr().foreach_until(funcToClose) session.user.accountid = accountId else: session.user.accountid = idtool.allocUid() def cbNewUser(retNew): accountId = long(retNew.result[0][0]) session.user.accountid = accountId ffext.dump('cbNewUser', retNew, accountId) # 登录(new)-记录log LogModel.logLoginData(accountId, 0, '', LogModel.LoginOpType.LOGIN_ACCOUNT, LogModel.LoginReason.NEW_LOGIN) return DbService.getPlayerService().createUser(msg.username, cbNewUser) ffext.dump('load player', db.result) for row in db.result: roleTmp = PlayerModel.Role(row) session.user.addRole(roleTmp) tmpRoleMsg = MsgDef.RoleInfo(roleTmp.uid, roleTmp.name, roleTmp.job, roleTmp.gender, roleTmp.level, roleTmp.exp) retRole.append(tmpRoleMsg) #print(session.user.accountid, session.user.username) ffext.checkWebDebug(session, msg, MsgDef) retMsg = MsgDef.UserInfoRet(ffext.getTime(), retRole) if reconnectUid: #重连 processSelectRoleReq(session, MsgDef.SelectRoleReq(reconnectUid), msg.x, msg.y) else: session.sendMsg(MsgDef.ServerCmd.USER_INFO, retMsg) # 登录(old)-记录log-(TODO:ip,geo信息获取接口暂缺) LogModel.logLoginData(session.user.accountid, 0, '', LogModel.LoginOpType.LOGIN_ACCOUNT, LogModel.LoginReason.OLD_LOGIN)
def callback(dbSet): #异步载入数据库,需要验证session是否仍然有效,有可能下线了 db = dbSet['player'] if session.isValid() == False or session.player: return False if len(db.result) == 0: ffext.dump('no this role') return False else: player = PlayerModel.Player(db.result[0]) #ffext.dump(dbSet) session.setPlayer(player) if x != 0 and y != 0: player.x = x player.y = y #载入数据 ffext.dump('load player =%s' % (session.player.name)) session.verify_id(session.player.uid) dbTask = dbSet['task'] dbitem = dbSet['item'] dbFriend = dbSet['friend'] dbEnemy = dbSet['enemy'] dbGuild = dbSet['guild'] dbPet = dbSet['pet'] dbMail = dbSet['mail'] dbLoginAct = dbSet['login_activity'] if dbTask.isOk(): player.taskCtrl.fromData(dbTask.result) if dbitem.isOk(): player.itemCtrl.fromData(dbitem.result) #TaskHandler.processQueryTask(session) #初始化好友信息、仇人信息,屏蔽信息 if dbFriend.isOk(): player.friendCtrl.fromDataFriend(dbFriend.result) if dbEnemy.isOk(): player.friendCtrl.fromDataEnemy(dbEnemy.result) #初始化行会信息 if dbGuild.isOk(): player.guildCtrl.fromData(dbGuild.result) player.petCtrl.fromData(dbPet.result) if dbMail.isOk(): player.mailCtrl.fromData(dbMail.result) if dbLoginAct.isOk(): player.loginActCtrl.fromData(dbLoginAct.result) # 发送属性数据 PlayerModel.sendPropUpdateMsg(player) #发消息通知,通知上线 tmpReq = MsgDef.EnterMapReq(player.mapname, player.x, player.y) processEnterMapReq(session, tmpReq, True) #发送技能数据 SkillHandler.processQuerySkill(session) #发送包裹数据 ItemHandler.processQueryPkg(session) #发送装备数据 ItemHandler.processQueryEquip(session) #发送任务数据 TaskHandler.processQueryTask(session) #发送好友数据 FriendHandler.processListFriend( session, MsgDef.FriendListMsgReq(MsgDef.FriendListClientCmd.GET_FRIENDLIST)) #发送行会数据 GuildHandler.processGuildInfo(session) #发送结义数据 TeamHandler.processBrotherOps( session, MsgDef.BrotherOpsReq(MsgDef.BrotherClientCmd.GET_BROTHERLIST)) #发送安全码 processMoneyBankOps(session) processQueryPet(session) from handler import MarryHandler MarryHandler.processMarryOPS( session, MsgDef.MarriageOpsReq(MsgDef.MarriageClientCmd.MARRY_QUERY_STATUS)) SkillHandler.processAttackModeReq(session) #发送攻击模式 from handler import MailHandler MailHandler.processMarryOPS(session, MsgDef.MailOpsReq(0)) #msg = MsgDef.UpdateSkillPosReq({320:1}) #SkillHandler.processUpdateSkillPosReq(session, msg) #结义数据 # if player.brotherCtrl: # BrotherModel.handleQueryBrother(player) player.checkTimeAfterInit() # 登录(old)-记录log LogModel.logLoginData(accountid, player.uid, player.name, LogModel.LoginOpType.LOGIN_PLAYER, LogModel.LoginReason.OLD_LOGIN) return
def processRandNameReq(session, msg): print('processRandNameReq', msg) name = PlayerModel.getPlayerMgr().randName(msg.gender) session.sendMsg(MsgDef.ServerCmd.RAND_NAME, MsgDef.RandNameRet(name))
def __init__(self, loc, position=(0, 0, 0), rotation=(-20, 0)): super(Mob, self).__init__(position, rotation) self.model = PlayerModel(position, True, loc=loc) self.momentum = (0, 0, 0)
class Mob(Entity): local_player = True def __init__(self, loc, position=(0, 0, 0), rotation=(-20, 0)): super(Mob, self).__init__(position, rotation) self.model = PlayerModel(position, True, loc=loc) self.momentum = (0, 0, 0) def get_motion_vector(self, multiplier=1): if any(self.strafe): x, y = self.rotation x_r = radians(x) strafe = atan2(*self.strafe) dy = 0.0 x_r += strafe dx = cos(x_r) dz = sin(x_r) else: dy = 0.0 dx = 0.0 dz = 0.0 return dx * multiplier, dy * multiplier, dz * multiplier def change_health(self, change): self.health += change if self.health > self.max_health: self.health = self.max_health @property def position(self): return self._position @position.setter def position(self, value): self._position = value self.model.update_position(value) def on_deactivate(self): self.strafe = [0, 0] def get_sight_vector(self): x, y = self.rotation y_r = radians(y) x_r = radians(x) m = cos(y_r) dy = sin(y_r) x_r -= G.HALF_PI dx = cos(x_r) * m dz = sin(x_r) * m return dx, dy, dz # get sight direction # retval[0]: E/S/W/N # retval[1]: angle between sight vector and east direction def get_sight_direction(self): dx, dy, dz = self.get_sight_vector() dz = -dz angle = 0 if dz == 0: if dx > 0: angle = 0 elif dx < 0: angle = pi elif dz > 0: angle = acos(dx / sqrt(dx * dx + dz * dz)) else: angle = -acos(dx / sqrt(dx * dx + dz * dz)) if angle < 0: angle += 2 * pi angle *= 180 / pi if 0 < angle <= 45 or 315 < angle <= 360: direction = G.EAST elif 45 < angle <= 135: direction = G.NORTH elif 135 < angle <= 225: direction = G.WEST elif 225 < angle <= 315: direction = G.SOUTH else: raise RotationError() return (dx, dy, dz), direction, angle def update(self, dt, parent): # walking speed = 5 * self.current_density dx, dy, dz = self.get_motion_vector(multiplier=(dt * speed)) # gravity self.dy -= dt * 0.022 # g force, should be = jump_speed * 0.5 / max_jump_height self.dy = max(self.dy, -0.5) # terminal velocity dy += self.dy # collisions x, y, z = self.position self.position = self.collide(parent, (x + dx, y + dy, z + dz), 2) def collide(self, parent, position, height): pad = 0.25 p = list(position) np = normalize(position) self.current_density = 1 # Reset it, incase we don't hit any water for face in FACES: # check all surrounding blocks for i in range(3): # check each dimension independently if not face[i]: continue d = (p[i] - np[i]) * face[i] if d < pad: continue for dy in range(height): # check each height op = list(np) op[1] -= dy op[i] += face[i] op = tuple(op) # If there is no block or if the block is not a cube, # we can walk there. if op not in parent.world \ or parent.world[op].vertex_mode != G.VERTEX_CUBE: continue # if density <= 1 then we can walk through it. (water) if parent.world[op].density < 1: self.current_density = parent.world[op].density continue # if height <= 1 then we can walk on top of it. (carpet, half-blocks, etc...) if parent.world[op].height < 0.5: # current_height = parent.world[op].height # x, y, z = self.position # new_pos = (x, y + current_height, z) # self.position = new_pos continue if parent.world[op].player_damage > 0: if self.last_damage_block != np: # this keeps a player from taking the same damage over and over... self.change_health(-parent.world[op].player_damage) parent.item_list.update_health() self.last_damage_block = np continue else: # do nothing continue p[i] -= (d - pad) * face[i] if face == (0, -1, 0) or face == (0, 1, 0): # jump damage damage = self.dy * -1000.0 damage = 3.0 * damage / 22.0 damage -= 2.0 if damage >= 0.0: health_change = 0 if damage <= 0.839: health_change = 0 elif damage <= 1.146: health_change = -1 elif damage <= 1.44: health_change = -2 elif damage <= 2.26: health_change = -2 else: health_change = -3 if health_change != 0: self.change_health(health_change) parent.item_list.update_health() self.dy = 0 break return tuple(p)