func (scene *Scene) addCreature(creature CreatureInterface, cx ZoneCoord_t, cy ZoneCoord_t, dir Dir_t) { pt, err := findSuitablePosition(&scene.Zone, cx, cy, creature.CreatureInstance().MoveMode) if err == nil { if creature.CreatureClass() == CREATURE_CLASS_MONSTER { monster := creature.(*Monster) scene.monsterManager.addCreature(monster) // pkt = packet.AddMonsterPacket(pMonster, NULL) // broadcastPacket(cx, cy, pAddMonsterPacket, pMonster) } else if creature.CreatureClass() == CREATURE_CLASS_NPC { npc := creature.(*NPC) scene.npcManager.addCreature(npc) // gcAddNPC := packet.GCAddNPCPacket{} // broadcastPacket(pt.x, pt.y, &gcAddNPC) } scene.Tile(pt.X, pt.Y).addCreature(creature) c := creature.CreatureInstance() c.X = ZoneCoord_t(pt.X) c.Y = ZoneCoord_t(pt.Y) c.Dir = dir c.Scene = scene } else { log.Debugln("应该是运行到这里来了,是不是?") } }
func (manager EffectManager) heartbeat(now time.Time) { for _, eft := range manager.Effects { // effectclass := eft.EffectClass() effect := eft.EffectInstance() if now.After(effect.Deadline) { // 删除 eft.unaffect() delete(manager.Effects, effect.ObjectID) log.Debugln("effect unaffect...", eft) } else { if now.After(effect.NextTime) { log.Debugln("effect affact...", eft) eft.affect() } } } }
func (r *Reader) Read(reader io.Reader) (ret Packet, err error) { var id PacketID var sz uint32 var seq uint8 err = ReadHeader(reader, &id, &sz, &seq) if err != nil { return } r.Seq = seq log.Debugln("packet header:", id, sz, seq) if id >= PACKET_MAX { err = errors.New("packet id too large!") return } ret = packetTable[id] if ret == nil { log.Debugln("reading a not implement packet:", id) var buf [500]byte raw := RawPacket{ Id: id, Seq: seq, } if sz > uint32(len(buf)) { err = errors.New("too large raw packet") return } _, err = reader.Read(buf[:sz]) if err != nil { return } copy(raw.Data, buf[:sz]) err = NotImplementError{} return } err = ret.Read(reader, r.Code) if ret.PacketSize() != sz { log.Warnf("packet not read clean: id=%d, sz=%d, read=%d", id, sz, ret.PacketSize()) } return }
func InitPlayer(player *Player, conn net.Conn) { player.PlayerStatus = GPS_BEGIN_SESSION player.conn = conn read := make(chan packet.Packet, 1) write := make(chan packet.Packet, 1) player.send = write player.client = read go func() { reader := packet.NewReader() player.packetReader = reader for { data, err := reader.Read(player.conn) if err != nil { if _, ok := err.(packet.NotImplementError); ok { log.Errorln("读到一个未实现的包:", data.PacketID()) } else { if err == io.EOF { log.Infoln("后台gouroutine读客户端失败了:", err) player.conn.Close() // 关闭读channel会使得agent的goroutine退出,回收资源 close(read) return } else { log.Errorln("这是一个严重的错误:", err) return } } } log.Debugln("读到了一个packet:", data) read <- data } }() go func() { writer := packet.NewWriter() player.packetWriter = writer for { pkt, ok := <-write if !ok { // 关闭使读goroutine退出 player.conn.Close() return } log.Debugf("write channel get a pkt: %#v\n", pkt) err := writer.Write(player.conn, pkt) if err != nil { log.Errorln(err) continue } } }() }
func (agent *Agent) Loop() { heartbeat := time.Tick(200 * time.Millisecond) for { select { case msg, ok := <-agent.client: if !ok { log.Debugln("客户端关了") return } log.Debugln("agent收到一个packet:", msg) agent.handleClientMessage(msg) case <-heartbeat: if agent.PlayerCreatureInterface != nil { agent.heartbeat() } case f, _ := <-agent.computation: f() } } }
func (vampire *Vampire) PCInfo() data.PCInfo { if vampire == nil || vampire.Scene == nil { log.Errorln("f**k...Scene为空谁让你调这个函数了?") return nil } ret := &data.PCVampireInfo{ ObjectID: vampire.ObjectID, Name: vampire.Name, Level: vampire.Level, Sex: vampire.Sex, BatColor: vampire.BatColor, SkinColor: vampire.SkinColor, Alignment: vampire.Alignment, Rank: vampire.Rank, RankExp: vampire.RankExp, Exp: vampire.Exp, Fame: vampire.Fame, Gold: vampire.Gold, Sight: vampire.Sight, Bonus: vampire.Bonus, // HotKey: vampire.HotKey, SilverDamage: vampire.SilverDamage, Competence: vampire.Competence, GuildID: vampire.GuildID, GuildMemberRank: vampire.GuildMemberRank, UnionID: vampire.UnionID, AdvancementLevel: vampire.AdvancementLevel, AdvancementGoalExp: vampire.AdvancementGoalExp, ZoneID: vampire.Scene.ZoneID, ZoneX: Coord_t(vampire.X), ZoneY: Coord_t(vampire.Y), } log.Debugln("run here.......") ret.STR[ATTR_CURRENT] = vampire.STR[ATTR_CURRENT] ret.STR[ATTR_MAX] = vampire.STR[ATTR_MAX] ret.DEX[ATTR_CURRENT] = vampire.DEX[ATTR_CURRENT] ret.DEX[ATTR_MAX] = vampire.DEX[ATTR_MAX] ret.INI[ATTR_CURRENT] = vampire.INI[ATTR_CURRENT] ret.INI[ATTR_MAX] = vampire.INI[ATTR_MAX] ret.HP[ATTR_CURRENT] = vampire.HP[ATTR_CURRENT] ret.HP[ATTR_MAX] = vampire.HP[ATTR_MAX] return ret }
func (zone *Zone) moveCreatureBroadcast(creature CreatureInterface, x1 ZoneCoord_t, y1 ZoneCoord_t, x2 ZoneCoord_t, y2 ZoneCoord_t) { inst := creature.CreatureInstance() for ix, endx := max(0, int(x2)-int(MaxViewportWidth)-1), min(int(zone.Width)-1, int(x2)+int(MaxViewportWidth)+1); ix <= endx; ix++ { for iy, endy := max(0, int(y2)-int(MaxViewportUpperHeight)-1), min(int(zone.Height)-1, int(y2)+int(MaxViewportLowerHeight)+1); iy <= endy; iy++ { tile := zone.Tile(ix, iy) for _, obj := range tile.Objects { if agent, ok := obj.(*Agent); ok { pc := agent.PlayerCreatureInstance() log.Debugf("agent id=%d x=%d y=%d\n", pc.ObjectID, ix, iy) prevVS := getVisionState(pc.X, pc.Y, x1, y1) currVS := getVisionState(pc.X, pc.Y, x2, y2) if prevVS == OUT_OF_SIGHT && currVS == IN_SIGHT { if monster, ok := creature.(*Monster); ok { agent.sendPacket(&packet.GCAddMonster{ ObjectID: monster.ObjectID, MonsterType: monster.MonsterType, MonsterName: monster.Name, MainColor: monster.MainColor, SubColor: monster.SubColor, X: Coord_t(monster.X), Y: Coord_t(monster.Y), Dir: monster.Dir, // EffectInfo []EffectInfo CurrentHP: monster.HP[ATTR_CURRENT], MaxHP: monster.HP[ATTR_MAX], // FromFlag byte }) } } else if prevVS == IN_SIGHT && currVS == IN_SIGHT { move := &packet.GCMovePacket{ ObjectID: inst.ObjectID, X: Coord_t(inst.X), Y: Coord_t(inst.Y), Dir: inst.Dir, } agent.sendPacket(move) log.Debugln("broadcast a GCMovePacket", move) } else if prevVS == IN_SIGHT && currVS == OUT_OF_SIGHT { agent.sendPacket(&packet.GCDeleteObjectPacket{ ObjectID: inst.ObjectID, }) } } } } } }
func (scene *Scene) getCreature(objectID ObjectID_t) CreatureInterface { monster := scene.monsterManager.getCreature(objectID) if monster != nil { return monster } agent, ok := scene.players[objectID] if ok { return agent } log.Debugln("没有找到creature") // pCreature = m_pNPCManager->getCreature(objectID); return nil }
func (sc SharpChakram) ExecuteToSelf(skill *packet.CGSkillToSelfPacket, agent *Agent) { // weapon := agent.getWearItem(OUSTER_WEAR_RIGHTHAND) // if weapon == nil { // // TODO // return // } // sc.Check(skill.SkillType, agent) var input SkillInput var output SkillOutput sc.ComputeOutput(&input, &output) pc := agent.PlayerCreatureInstance() eft := new(EffectSharpChakram) eft.Deadline = time.Now().Add(time.Duration(output.Duration) * time.Millisecond) eft.Bonus = uint32(output.Damage) pc.addEffect(eft) pc.setFlag(eft.EffectClass()) agent.sendPacket(&packet.GCSkillToSelfOK1{ SkillType: skill.SkillType, CEffectID: skill.CEffectID, Duration: uint16(output.Duration), }) log.Debugln("运行到这里 发送SkillToSelfOK1...") pc.Scene.broadcastPacket(pc.X, pc.Y, &packet.GCSkillToSelfOK2{ ObjectID: pc.ObjectID, SkillType: skill.SkillType, Duration: Duration_t(output.Duration), }, agent) pc.Scene.broadcastPacket(pc.X, pc.Y, &packet.GCAddEffect{ ObjectID: pc.ObjectID, EffectID: EffectID_t(eft.EffectClass()), Duration: Duration_t(output.Duration), }, agent) // skillslot := pc.SkillSlot[skill.SkillType] // skillslot.setRunTime(output.Delay) }
func serve(conn net.Conn) { defer conn.Close() reader := packet.NewReader() writer := packet.NewWriter() for { pkt, err := reader.Read(conn) if err != nil { if _, ok := err.(packet.NotImplementError); !ok { log.Errorln("read packet error in loginserver's serve:", err) return } } log.Debugln("read a packet: ", pkt.PacketID()) switch pkt.PacketID() { case packet.PACKET_CL_GET_WORLD_LIST: writer.Write(conn, packet.LCWorldListPacket{}) case packet.PACKET_CL_LOGIN: writer.Write(conn, packet.LCLoginOKPacket{}) case packet.PACKET_CL_SELECT_SERVER: writer.Write(conn, &packet.LCPCListPacket{}) case packet.PACKET_CL_SELECT_WORLD: writer.Write(conn, &packet.LCServerListPacket{}) case packet.PACKET_CL_VERSION_CHECK: writer.Write(conn, packet.LCVersionCheckOKPacket{}) case packet.PACKET_CL_SELECT_PC: reconnect := &packet.LCReconnectPacket{ Ip: config.GameServerIP, Port: 9998, Key: 82180, } writer.Write(conn, reconnect) return default: log.Errorf("get a unknow packet: %d\n", pkt.PacketID()) } } }
func LoadPlayerCreature(name string, typ packet.PCType) (ptr PlayerCreatureInterface, zoneID ZoneID_t, err error) { fileName := config.DataDir + name log.Debugln("load文件", fileName) f, err := os.Open(fileName) if err != nil { return } defer f.Close() decoder := json.NewDecoder(f) switch typ { case packet.PC_VAMPIRE: return loadVampire(decoder) case packet.PC_OUSTER: return loadOuster(decoder) case packet.PC_SLAYER: return loadSlayer(decoder) } return nil, 0, errors.New("player type error!") }
func loadVampire(decoder *json.Decoder) (vampire *Vampire, zoneID ZoneID_t, err error) { var pcInfo data.PCVampireInfo err = decoder.Decode(&pcInfo) if err != nil { return } vampire = new(Vampire) vampire.Init() vampire.Name = pcInfo.Name vampire.Level = pcInfo.Level vampire.Sex = pcInfo.Sex vampire.SkinColor = pcInfo.SkinColor vampire.Alignment = pcInfo.Alignment vampire.STR = pcInfo.STR vampire.DEX = pcInfo.DEX vampire.INI = pcInfo.INI vampire.HP[ATTR_MAX] = pcInfo.HP[ATTR_MAX] vampire.HP[ATTR_CURRENT] = pcInfo.HP[ATTR_CURRENT] vampire.Rank = pcInfo.Rank vampire.RankExp = pcInfo.RankExp vampire.Exp = pcInfo.Exp vampire.Fame = pcInfo.Fame vampire.Sight = pcInfo.Sight vampire.Bonus = pcInfo.Bonus vampire.Competence = pcInfo.Competence vampire.GuildMemberRank = pcInfo.GuildMemberRank vampire.AdvancementLevel = pcInfo.AdvancementLevel zoneID = pcInfo.ZoneID vampire.X = ZoneCoord_t(pcInfo.ZoneX) vampire.Y = ZoneCoord_t(pcInfo.ZoneY) if vampire.X == 0 || vampire.Y == 0 { log.Debugln("不科学呀", vampire.X, vampire.Y) } return }
func Read(reader io.Reader, code uint8) (ret Packet, seq uint8, err error) { var id PacketID var sz uint32 err = ReadHeader(reader, &id, &sz, &seq) if err != nil { return } if id >= PACKET_MAX { err = errors.New("packet id too large!") return } ret = packetTable[id] if ret == nil { log.Debugln("reading a not implement packet:", id) var buf [500]byte raw := RawPacket{ Id: id, Seq: seq, } if sz > uint32(len(buf)) { err = errors.New("too large raw packet") return } _, err = reader.Read(buf[:sz]) if err != nil { return } copy(raw.Data, buf[:sz]) err = NotImplementError{} return } err = ret.Read(reader, code) return }
// moveMonster func (zone *Zone) moveCreature(creature CreatureInterface, nx ZoneCoord_t, ny ZoneCoord_t, dir Dir_t) { inst := creature.CreatureInstance() cx := inst.X cy := inst.Y tile := zone.Tile(int(cx), int(cy)) newTile := zone.Tile(int(nx), int(ny)) newTile.addCreature(creature) tile.deleteCreature(inst.ObjectID) log.Debugf("monster %d move: (%d,%d)->(%d,%d) zone=%p scene=%p\n", inst.ObjectID, cx, cy, nx, ny, zone, inst.Scene) log.Debugln("tile:", newTile) inst.X = nx inst.Y = ny inst.Dir = dir // checkMine(this, pCreature, nx, ny); // checkTrap(this, pCreature); zone.moveCreatureBroadcast(creature, cx, cy, nx, ny) }
func (zone *Zone) movePCBroadcast(agent *Agent, x1 ZoneCoord_t, y1 ZoneCoord_t, x2 ZoneCoord_t, y2 ZoneCoord_t) { beginX := x2 - ZoneCoord_t(MaxViewportWidth) - 1 if beginX < 0 { beginX = 0 } endX := x2 + ZoneCoord_t(MaxViewportWidth) + 1 if endX > zone.Width { endX = zone.Width } beginY := y2 - ZoneCoord_t(MaxViewportUpperHeight) - 1 if beginY < 0 { beginY = 0 } endY := y2 + ZoneCoord_t(MaxViewportUpperHeight) + 1 if endY > zone.Height { endY = zone.Height } for i := beginX; i < endX; i++ { for j := beginY; j < endY; j++ { tile := zone.Tile(int(i), int(j)) for _, v := range tile.Objects { objectClass := v.ObjectClass() if objectClass == OBJECT_CLASS_CREATURE { prevVS := getVisionState(x1, y1, ZoneCoord_t(i), ZoneCoord_t(j)) currVS := getVisionState(x2, y2, ZoneCoord_t(i), ZoneCoord_t(j)) switch v.(type) { case *Monster: monster := v.(*Monster) // 怪物进入玩家视线 if prevVS == OUT_OF_SIGHT && currVS == IN_SIGHT { agent.sendPacket(&packet.GCAddMonster{ ObjectID: monster.ObjectID, MonsterType: monster.MonsterType, MonsterName: monster.Name, // MainColor: monster.MainColor, // SubColor: monster.SubColor, X: Coord_t(monster.X), Y: Coord_t(monster.Y), Dir: monster.Dir, // EffectInfo []EffectInfo CurrentHP: monster.HP[ATTR_CURRENT], MaxHP: monster.HP[ATTR_MAX], // FromFlag byte }) log.Debugln("发现了一个怪物...") // 把玩家放到怪物的敌人列表中 monster.addEnemy(agent) } case *Slayer: // pc.sendPacket(packet.GCAddSlayer{}) slayer := v.(*Slayer) if canSee(slayer, agent) { // slayer.sendPacket(packet.GCAddSlayer{}) } else { // slayer.sendPacket(packet.GCDeleteObject{}) } case *Vampire: vampire := v.(*Vampire) if canSee(agent, vampire) { if vampire.IsFlag(EFFECT_CLASS_HIDE) { // pc.sendPacket(packet.GCAddBurrowingCreaturePacket{ // ObjectID: vampire.ObjectID, // Name: vampire.Name, // X: vampire.X, // Y: vampire.Y, // }) } else { // pc.sendPacket(packet.GCAddVampire{}) } } if canSee(vampire, agent) { // TODO:添加或者移除 } case *Ouster: ouster := v.(*Ouster) if canSee(agent, ouster) { // pc.sendPacket(packet.GCAddOuster{}) } if canSee(ouster, agent) { // TODO:添加或者移除 } case *NPC: // pc.sendPacket(packet.GCAddNPC{}) } } else if objectClass == OBJECT_CLASS_ITEM { item := v.(ItemInterface) itemClass := item.ItemClass() if itemClass == ITEM_CLASS_CORPSE { switch v.(type) { case *SlayerCorpse: // pc.sendPacket(packet.GCAddSlayerCorpse{}) case *VampireCorpse: // pc.sendPacket(packet.GCAddVampireCorpse{}) case *OusterCorpse: // pc.sendPacket(packet.GCAddOusterCorpse{}) case *MonsterCorpse: // pc.sendPacket(packet.GCAddMonsterCorpse{}) } } } else if objectClass == OBJECT_CLASS_EFFECT { // TODO:... // pc.sendPacket(packet.GCAddEffectToTile{}) } } } } }
func (effect *EffectSharpHail) affect() { castCreature := effect.Scene.getCreature(effect.UserObjectID) log.Debugln("userObjectID:", effect.UserObjectID, castCreature) tile := effect.Scene.Tile(int(effect.X), int(effect.Y)) for _, obj := range tile.Objects { if obj.ObjectClass() != OBJECT_CLASS_CREATURE { continue } creature := obj.(CreatureInterface) if !canAttack(castCreature, creature) || creature.CreatureInstance().isFlag(EFFECT_CLASS_COMA) { continue } // if (pCastCreature != NULL && !HitRoll::isSuccess(pCastCreature, pCreature ) ) continue; switch obj.(type) { case *Monster: monster := obj.(*Monster) effect.Scene.setDamage(monster, castCreature.(*Agent), Damage_t(effect.Damage)) // SKILL_SHARP_HAIL, NULL, &gcAttackerMI, true, true); log.Debugln("sharphail的effect对怪物affect了...") } // GCModifyInformation gcAttackerMI; // GCModifyInformation gcDefenderMI; // if (pCreature->isSlayer()) // { // Slayer* pSlayer = dynamic_cast<Slayer*>(pCreature); // // ::setDamage(pSlayer, m_Damage, pCastCreature, SKILL_SHARP_HAIL, &gcDefenderMI, &gcAttackerMI, true, true); // // Player* pPlayer = pSlayer->getPlayer(); // Assert(pPlayer != NULL); // pPlayer->sendPacket(&gcDefenderMI); // } // else if (pCreature->isVampire()) // { // Vampire* pVampire = dynamic_cast<Vampire*>(pCreature); // // ::setDamage(pVampire, m_Damage, pCastCreature, SKILL_SHARP_HAIL, &gcDefenderMI, &gcAttackerMI, true, true); // // Player* pPlayer = pVampire->getPlayer(); // Assert(pPlayer != NULL); // pPlayer->sendPacket(&gcDefenderMI); // } // else if (pCreature->isOusters() && isForce() ) // { // Ousters* pOusters = dynamic_cast<Ousters*>(pCreature); // // ::setDamage(pOusters, m_Damage, pCastCreature, SKILL_SHARP_HAIL, &gcDefenderMI, &gcAttackerMI, true, true); // // Player* pPlayer = pOusters->getPlayer(); // Assert(pPlayer != NULL); // pPlayer->sendPacket(&gcDefenderMI); // } // if (gcAttackerMI.getShortCount() != 0 || gcAttackerMI.getLongCount() != 0 ) // pCastCreature->getPlayer()->sendPacket(&gcAttackerMI); } effect.NextTime = effect.NextTime.Add(time.Duration(effect.Tick) * time.Millisecond) }
func (ai *MonsterAI) Deal(pEnemy CreatureInterface, currentTime time.Time) { for i, pDirective := range ai.DirectiveSet.Directives { if ai.checkDirective(pDirective, pEnemy) { switch pDirective.Action { case DIRECTIVE_ACTION_APPROACH: log.Debugln("动作是approach", i) ai.approach(pEnemy) case DIRECTIVE_ACTION_FLEE: log.Debugln("动作是逃跑") if !flee(pEnemy) { ai.setMoveRule(MOVE_RULE_NORMAL) rValue := ai.useSkill(pEnemy, SKILL_ATTACK_MELEE, 100) if rValue != 0 { ai.approach(pEnemy) } } case DIRECTIVE_ACTION_USE_SKILL: log.Debugln("动作是放技能", i) if ai.Body.isFlag(EFFECT_CLASS_BLOCK_HEAD) || ai.Body.isFlag(EFFECT_CLASS_TENDRIL) { continue } parameter := pDirective.Parameter ratio := pDirective.Ratio rValue := ai.useSkill(pEnemy, SkillType_t(parameter), ratio) if rValue != 0 { break } ai.setMoveRule(MOVE_RULE_NORMAL) case DIRECTIVE_ACTION_FORGET: // log.Debugln("动作是忘记敌人") if len(ai.Body.Enemies) != 0 { // ai.Body.Enemies = ai.Body.Enemies[1:] } ai.setMoveRule(MOVE_RULE_NORMAL) case DIRECTIVE_ACTION_CHANGE_ENEMY: log.Debugln("动作是切换敌人") ratio := pDirective.Parameter if rand.Intn(100) >= ratio { break } // pNewEnemy := ai.Body.Enemies[0] // 从ObjectID得到Creature // if pNewEnemy != nil { // pEnemy = pNewEnemy // } else { if len(ai.Body.Enemies) == 0 { // ai.Body.addEnemy(pEnemy) } // } case DIRECTIVE_ACTION_MOVE_RANDOM: log.Debugln("动作是随机移动") ratio := pDirective.Parameter if rand.Intn(100) >= ratio { break } // var ( // x ZoneCoord_t // y ZoneCoord_t // p TPOINT // ) // x = ai.Body.X // y = ai.Body.Y // p = getSafeTile(ai.Body.Zone, x, y) // if p.x == -1 { // break // } // x1 := p.x // y1 := p.y // if x != x1 || y != y1 { // move(x1, y1) // } case DIRECTIVE_ACTION_WAIT: log.Debugln("动作是等待") delay := 2 * time.Second ai.Body.addAccuDelay(delay) case DIRECTIVE_ACTION_FAST_FLEE: log.Debugln("动作是快速逃跑") result := false myX := ai.Body.X myY := ai.Body.Y nmX := pEnemy.CreatureInstance().X nmY := pEnemy.CreatureInstance().Y diffX := myX - nmX diffY := myY - nmY ratio := 5.0 / ZoneCoord_t(abs(int(diffX))+abs(int(diffY))) newX := (myX + diffX*ratio) newY := (myY + diffY*ratio) if isValidZoneCoord(&ai.Body.Scene.Zone, newX, newY) { result = ai.Body.Scene.moveFastMonster(ai.Body, myX, myY, newX, newY, SKILL_RAPID_GLIDING) } if !result { break } case DIRECTIVE_ACTION_SAY: log.Debugln("动作是说话") // parameter = pDirective.Parameter(); // GCSay gcSay // gcSay.ObjectID = ai.Body.ObjectID // gcSay.setMessage(g_pStringPool.getString(parameter )); // gcSay.setColor(0x00ffffff); // ai.Body.getZone().broadcastPacket(ai.Body.getX(), ai.Body.getY(), // &gcSay); } // break } } switch ai.LastAction { case LAST_ACTION_NONE: ai.setDelay(currentTime) case LAST_ACTION_MOVE: ai.setDelay(currentTime) case LAST_ACTION_SKILL: ai.setAttackDelay(currentTime) } ai.LastAction = LAST_ACTION_NONE if (rand.Int() & 0x0000007F) > 64 { //%100 > 50) if ai.bDamaged { ai.bDamaged = false ai.Panic = ai.PanicMax ai.Courage = ai.CourageMax } } }
func (info *PCSlayerInfo) Read(reader io.Reader) error { binary.Read(reader, binary.LittleEndian, &info.ObjectID) var szName uint8 var buf [256]byte binary.Read(reader, binary.LittleEndian, &szName) log.Debugln("szName=", szName) _, err := reader.Read(buf[:szName]) if err != nil { return err } info.Name = string(buf[:szName]) log.Debugln("sdkjfasdlgasjdfasdf", info.Name, szName) binary.Read(reader, binary.LittleEndian, &info.Sex) binary.Read(reader, binary.LittleEndian, &info.HairStyle) binary.Read(reader, binary.LittleEndian, &info.HairColor) binary.Read(reader, binary.LittleEndian, &info.SkinColor) binary.Read(reader, binary.LittleEndian, &info.MasterEffectColor) binary.Read(reader, binary.LittleEndian, &info.Alignment) binary.Read(reader, binary.LittleEndian, &info.STR[ATTR_CURRENT]) binary.Read(reader, binary.LittleEndian, &info.STR[ATTR_MAX]) binary.Read(reader, binary.LittleEndian, &info.STR[ATTR_BASIC]) binary.Read(reader, binary.LittleEndian, &info.DEX[ATTR_CURRENT]) binary.Read(reader, binary.LittleEndian, &info.DEX[ATTR_MAX]) binary.Read(reader, binary.LittleEndian, &info.DEX[ATTR_BASIC]) binary.Read(reader, binary.LittleEndian, &info.INI[ATTR_CURRENT]) binary.Read(reader, binary.LittleEndian, &info.INI[ATTR_MAX]) binary.Read(reader, binary.LittleEndian, &info.INI[ATTR_BASIC]) binary.Read(reader, binary.LittleEndian, &info.Rank) binary.Read(reader, binary.LittleEndian, &info.RankExp) binary.Read(reader, binary.LittleEndian, &info.STRExp) binary.Read(reader, binary.LittleEndian, &info.DEXExp) binary.Read(reader, binary.LittleEndian, &info.INIExp) binary.Read(reader, binary.LittleEndian, &info.HP[ATTR_CURRENT]) binary.Read(reader, binary.LittleEndian, &info.HP[ATTR_MAX]) binary.Read(reader, binary.LittleEndian, &info.MP[ATTR_CURRENT]) binary.Read(reader, binary.LittleEndian, &info.MP[ATTR_MAX]) binary.Read(reader, binary.LittleEndian, &info.Fame) binary.Read(reader, binary.LittleEndian, &info.Gold) for i := 0; i < SKILL_DOMAIN_VAMPIRE; i++ { binary.Read(reader, binary.LittleEndian, &info.DomainLevels[i]) binary.Read(reader, binary.LittleEndian, &info.DomainExps[i]) } binary.Read(reader, binary.LittleEndian, &info.Sight) for i := 0; i < 4; i++ { binary.Read(reader, binary.LittleEndian, &info.HotKey[i]) } binary.Read(reader, binary.LittleEndian, &info.Competence) binary.Read(reader, binary.LittleEndian, &info.GuildID) var szGuildName uint8 _, err = reader.Read(buf[:szGuildName]) if err != nil { return err } info.GuildName = string(buf[:szGuildName]) binary.Read(reader, binary.LittleEndian, &info.GuildMemberRank) binary.Read(reader, binary.LittleEndian, &info.UnionID) binary.Read(reader, binary.LittleEndian, &info.AdvancementLevel) binary.Read(reader, binary.LittleEndian, &info.AdvancementGoalExp) binary.Read(reader, binary.LittleEndian, &info.AttrBonus) return nil }
func (sharphail SharpHail) ExecuteToTile(skill *packet.CGSkillToTilePacket, agent *Agent) { // weapon := agent.getWearItem(OUSTER_WEAR_RIGHTHAND) // if weapon == nil || weapon.ItemClass() != ITEM_CLASS_OUSTERS_CHAKRAM { // // TODO // return // } if !sharphail.Check(skill.SkillType, agent) { // TODO return } pc := agent.PlayerCreatureInstance() // skillslot := pc.SkillSlot[skill.SkillType] var input SkillInput var output SkillOutput // input.SkillLevel = skillslot.Level // input.DomainLevel = input.STR = int(pc.STR[ATTR_CURRENT]) input.DEX = int(pc.DEX[ATTR_CURRENT]) input.INT = int(pc.INI[ATTR_CURRENT]) sharphail.ComputeOutput(&input, &output) scene := pc.Scene for x := skill.X - 2; x < skill.X+2; x++ { for y := skill.Y - 2; y < skill.Y+2; y++ { if x < 0 || ZoneCoord_t(x) >= scene.Width || y < 0 || ZoneCoord_t(y) >= scene.Height { continue } tile := scene.Tile(int(x), int(y)) if !tile.canAddEffect() { continue } var creatureItf CreatureInterface if tile.HasCreature(MOVE_MODE_WALKING) { creatureItf = tile.getCreature(MOVE_MODE_WALKING) } else { continue } damage := output.Damage damage += int(agent.computeDamage(creatureItf, false)) effect := new(EffectSharpHail) effect.X = ZoneCoord_t(x) effect.Y = ZoneCoord_t(y) effect.Scene = scene effect.UserObjectID = pc.ObjectID log.Debugln("userObjectID ---", pc.ObjectID) // effect.Deadline = time.Now().Add(time.Duration(output.Duration) * time.Millisecond) // effect.NextTime = time.Now().Add(3 * time.Millisecond) effect.Deadline = time.Now().Add(time.Duration(output.Duration) * time.Second) effect.NextTime = time.Now().Add(3 * time.Millisecond) effect.Tick = output.Tick effect.Damage = damage / 3 // effect.Level = skillslot.ExpLevel // TODO 加锁 scene.registeObject(effect) scene.effectManager.addEffect(effect) tile.addEffect(effect) } } // ok1是回复攻击者技能施放成功 agent.sendPacket(&packet.GCSkillToTileOK1{ SkillType: skill.SkillType, CEffectID: skill.CEffectID, X: skill.X, Y: skill.Y, Duration: Duration_t(output.Duration), Range: 5, }) // ok5是发给即能看到施放者,又能看到tile的玩家 ok5 := &packet.GCSkillToTileOK5{ ObjectID: pc.ObjectID, SkillType: skill.SkillType, X: skill.X, Y: skill.Y, Duration: Duration_t(output.Duration), } scene.broadcastSkillPacket(pc.X, pc.Y, ZoneCoord_t(skill.X), ZoneCoord_t(skill.Y), ok5, agent) // ok3是向施法者周围广播施放成功 scene.broadcastPacket(pc.X, pc.Y, &packet.GCSkillToTileOK3{ ObjectID: pc.ObjectID, SkillType: skill.SkillType, X: skill.X, Y: skill.Y, }, agent) // ok4是向tile周围广播 scene.broadcastPacket(ZoneCoord_t(skill.X), ZoneCoord_t(skill.Y), &packet.GCSkillToTileOK4{ SkillType: skill.SkillType, X: Coord_t(skill.X), Y: Coord_t(skill.Y), Duration: uint16(output.Duration), }, agent) }
// 注意:需要在agent的goroutine中执行的 func (melee AttackMelee) ExecuteToObject(sender CreatureInterface, target CreatureInterface) { rangeCheck := verifyDistance(sender, target) hitRoll := HitRoll(sender, target, 0) if rangeCheck && hitRoll { if agent, ok := sender.(*Agent); ok { damage := agent.computeDamage(target, false) // 这个伤害是要广播给地图周围玩家知道的 agent.scene <- DamageMessage{ Agent: agent, target: target, damage: damage, critical: false, } // 发给攻击者,告诉他攻击成功了 ok1 := packet.GCAttackMeleeOK1{ ObjectID: target.CreatureInstance().ObjectID, } agent.sendPacket(ok1) if slayer, ok := agent.PlayerCreatureInterface.(*Slayer); ok { weapon := slayer.getWearItem(SLAYER_WEAR_RIGHTHAND) switch weapon.ItemClass() { case ITEM_CLASS_BLADE: // increaseDomainExp(slayer, SKILL_DOMAIN_BLADE, 1, packet.GCAttackMeleeOK1{}, targetCreature.CreatureInstance().Level) case ITEM_CLASS_SWORD: // increaseDomainExp(slayer, SKILL_DOMAIN_BLADE, 1, packet.GCAttackMeleeOK1{}, targetCreature.CreatureInstance().Level) case ITEM_CLASS_CROSS: // increaseDomainExp(slayer, SKILL_DOMAIN_BLADE, 1, packet.GCAttackMeleeOK1{}, targetCreature.CreatureInstance().Level) case ITEM_CLASS_MACE: // increaseDomainExp(slayer, SKILL_DOMAIN_BLADE, 1, packet.GCAttackMeleeOK1{}, targetCreature.CreatureInstance().Level) default: log.Errorln("武器不对!") } } } if monster, ok := sender.(*Monster); ok { damage := monster.computeDamage(target, false) if agent, ok := target.(*Agent); ok { pc := agent.PlayerCreatureInstance() if pc.HP[ATTR_CURRENT] < HP_t(damage) { // 玩家被打死了 log.Debugln("玩家被打死还没实现") } else { pc.HP[ATTR_CURRENT] -= HP_t(damage) log.Debugln("怪物攻击玩家,广播状态信息的攻击成功") // 广播给所有玩家,攻击成功 ok3 := packet.GCAttackMeleeOK3{ ObjectID: sender.CreatureInstance().ObjectID, TargetObjectID: target.CreatureInstance().ObjectID, } pc.Scene.broadcastPacket(pc.X, pc.Y, ok3, agent) // 广播给所有玩家,状态变化 status := packet.GCStatusCurrentHP{ ObjectID: pc.ObjectID, CurrentHP: pc.HP[ATTR_CURRENT], } pc.Scene.broadcastPacket(pc.X, pc.Y, status, nil) } } else { log.Errorln("参数不对") } } switch agent := target.(type) { case *Agent: agent.sendPacket(packet.GCAttackMeleeOK2{ ObjectID: sender.CreatureInstance().ObjectID, }) case *Monster: // monster := target.(*Monster) // monster.addEnemy(agent) } } }