diff --git a/common/mhfmon/mhfmon.go b/common/mhfmon/mhfmon.go new file mode 100644 index 000000000..183a75bd8 --- /dev/null +++ b/common/mhfmon/mhfmon.go @@ -0,0 +1,366 @@ +package mhfmon + +const ( + Mon0 = iota + Rathian + Fatalis + Kelbi + Mosswine + Bullfango + YianKutKu + LaoShanLung + Cephadrome + Felyne + VeggieElder + Rathalos + Aptonoth + Genprey + Diablos + Khezu + Velociprey + Gravios + Mon18 + Vespoid + Gypceros + Plesioth + Basarios + Melynx + Hornetaur + Apceros + Monoblos + Velocidrome + Gendrome + Mon29 + Ioprey + Iodrome + Mon32 + Kirin + Cephalos + Giaprey + CrimsonFatalis + PinkRathian + BlueYianKutKu + PurpleGypceros + YianGaruga + SilverRathalos + GoldRathian + BlackDiablos + WhiteMonoblos + RedKhezu + GreenPlesioth + BlackGravios + DaimyoHermitaur + AzureRathalos + AshenLaoShanLung + Blangonga + Congalala + Rajang + KushalaDaora + ShenGaoren + GreatThunderbug + Shakalaka + YamaTsukami + Chameleos + RustedKushalaDaora + Blango + Conga + Remobra + Lunastra + Teostra + Hermitaur + ShogunCeanataur + Bulldrome + Anteka + Popo + WhiteFatalis + Mon72 + Ceanataur + Hypnocatrice + Lavasioth + Tigrex + Akantor + BrightHypnoc + RedLavasioth + Espinas + OrangeEspinas + WhiteHypnoc + AqraVashimu + AqraJebia + Berukyurosu + Mon86 + Mon87 + Mon88 + Pariapuria + WhiteEspinas + KamuOrugaron + NonoOrugaron + Raviente + Dyuragaua + Doragyurosu + Gurenzeburu + Burukku + Erupe + Rukodiora + Unknown + Gogomoa + Kokomoa + TaikunZamuza + Abiorugu + Kuarusepusu + Odibatorasu + Disufiroa + Rebidiora + Anorupatisu + Hyujikiki + Midogaron + Giaorugu + MiRu + Farunokku + Pokaradon + Shantien + Pokara + Mon118 + Goruganosu + Aruganosu + Baruragaru + Zerureusu + Gougarf + Uruki + Forokururu + Meraginasu + Diorex + GarubaDaora + Inagami + Varusaburosu + Poborubarumu + Block1Duremudira + Mon133 + Mon134 + Mon135 + Mon136 + Mon137 + Mon138 + Gureadomosu + Harudomerugu + Toridcless + Gasurabazura + Kusubami + YamaKurai + Block2Duremudira + Zinogre + Deviljho + Brachydios + BerserkRaviente + ToaTesukatora + Barioth + Uragaan + StygianZinogre + Guanzorumu + SavageDeviljho + Mon156 + Egyurasu + Voljang + Nargacuga + Keoaruboru + Zenaserisu + GoreMagala + BlinkingNargacuga + ShagaruMagala + Amatsu + Eruzerion + MusouDuremudira + Mon168 + Seregios + Bogabadorumu + Mon171 + MusouBogabadorumu + CostumedUruki + MusouZerureusu + Rappy + KingShakalaka +) + +type Monster struct { + Name string + Large bool +} + +var Monsters = []Monster{ + {"Mon0", false}, + {"Rathian", true}, + {"Fatalis", true}, + {"Kelbi", false}, + {"Mosswine", false}, + {"Bullfango", false}, + {"Yian Kut-Ku", true}, + {"Lao-Shan Lung", true}, + {"Cephadrome", true}, + {"Felyne", false}, + {"Veggie Elder", false}, + {"Rathalos", true}, + {"Aptonoth", false}, + {"Genprey", false}, + {"Diablos", true}, + {"Khezu", true}, + {"Velociprey", false}, + {"Gravios", true}, + {"Mon18", false}, + {"Vespoid", false}, + {"Gypceros", true}, + {"Plesioth", true}, + {"Basarios", true}, + {"Melynx", false}, + {"Hornetaur", false}, + {"Apceros", false}, + {"Monoblos", true}, + {"Velocidrome", true}, + {"Gendrome", true}, + {"Mon29", false}, + {"Ioprey", false}, + {"Iodrome", true}, + {"Mon32", false}, + {"Kirin", true}, + {"Cephalos", false}, + {"Giaprey", false}, + {"Crimson Fatalis", true}, + {"Pink Rathian", true}, + {"Blue Yian Kut-Ku", true}, + {"Purple Gypceros", true}, + {"Yian Garuga", true}, + {"Silver Rathalos", true}, + {"Gold Rathian", true}, + {"Black Diablos", true}, + {"White Monoblos", true}, + {"Red Khezu", true}, + {"Green Plesioth", true}, + {"Black Gravios", true}, + {"Daimyo Hermitaur", true}, + {"Azure Rathalos", true}, + {"Ashen Lao-Shan Lung", true}, + {"Blangonga", true}, + {"Congalala", true}, + {"Rajang", true}, + {"Kushala Daora", true}, + {"Shen Gaoren", true}, + {"Great Thunderbug", false}, + {"Shakalaka", false}, + {"Yama Tsukami", true}, + {"Chameleos", true}, + {"Rusted Kushala Daora", true}, + {"Blango", false}, + {"Conga", false}, + {"Remobra", false}, + {"Lunastra", true}, + {"Teostra", true}, + {"Hermitaur", false}, + {"Shogun Ceanataur", true}, + {"Bulldrome", true}, + {"Anteka", false}, + {"Popo", false}, + {"White Fatalis", true}, + {"Mon72", false}, + {"Ceanataur", false}, + {"Hypnocatrice", true}, + {"Lavasioth", true}, + {"Tigrex", true}, + {"Akantor", true}, + {"Bright Hypnocatrice", true}, + {"Red Lavasioth", true}, + {"Espinas", true}, + {"Orange Espinas", true}, + {"White Hypnocatrice", true}, + {"Aqra Vashimu", true}, + {"Aqra Jebia", true}, + {"Berukyurosu", true}, + {"Mon86", false}, + {"Mon87", false}, + {"Mon88", false}, + {"Pariapuria", true}, + {"White Espinas", true}, + {"Kamu Orugaron", true}, + {"Nono Orugaron", true}, + {"Raviente", true}, // + Violent + {"Dyuragaua", true}, + {"Doragyurosu", true}, + {"Gurenzeburu", true}, + {"Burukku", false}, + {"Erupe", false}, + {"Rukodiora", true}, + {"Unknown", true}, + {"Gogomoa", true}, + {"Kokomoa", false}, + {"Taikun Zamuza", true}, + {"Abiorugu", true}, + {"Kuarusepusu", true}, + {"Odibatorasu", true}, + {"Disufiroa", true}, + {"Rebidiora", true}, + {"Anorupatisu", true}, + {"Hyujikiki", true}, + {"Midogaron", true}, + {"Giaorugu", true}, + {"Mi-Ru", true}, // + Musou + {"Farunokku", true}, + {"Pokaradon", true}, + {"Shantien", true}, + {"Pokara", false}, + {"Mon118", false}, + {"Goruganosu", true}, + {"Aruganosu", true}, + {"Baruragaru", true}, + {"Zerureusu", true}, + {"Gougarf", true}, // Both + {"Uruki", false}, + {"Forokururu", true}, + {"Meraginasu", true}, + {"Diorex", true}, + {"Garuba Daora", true}, + {"Inagami", true}, + {"Varusablos", true}, + {"Poborubarumu", true}, + {"1st Block Duremudira", true}, + {"Mon133", false}, + {"Mon134", false}, + {"Mon135", false}, + {"Mon136", false}, + {"Mon137", false}, + {"Mon138", false}, + {"Gureadomosu", true}, + {"Harudomerugu", true}, + {"Toridcless", true}, + {"Gasurabazura", true}, + {"Kusubami", false}, + {"Yama Kurai", true}, + {"2nd Block Duremudira", true}, + {"Zinogre", true}, + {"Deviljho", true}, + {"Brachydios", true}, + {"Berserk Raviente", true}, + {"Toa Tesukatora", true}, + {"Barioth", true}, + {"Uragaan", true}, + {"Stygian Zinogre", true}, + {"Guanzorumu", true}, + {"Savage Deviljho", true}, // + Starving/Heavenly + {"Mon156", false}, + {"Egyurasu", false}, + {"Voljang", true}, + {"Nargacuga", true}, + {"Keoaruboru", true}, + {"Zenaserisu", true}, + {"Gore Magala", true}, + {"Blinking Nargacuga", true}, + {"Shagaru Magala", true}, + {"Amatsu", true}, + {"Eruzerion", true}, // + Musou + {"Musou Duremudira", true}, + {"Mon168", false}, + {"Seregios", true}, + {"Bogabadorumu", true}, + {"Mon171", false}, + {"Musou Bogabadorumu", true}, + {"Costumed Uruki", false}, + {"Musou Zerureusu", true}, + {"Rappy", false}, + {"King Shakalaka", false}, +} diff --git a/network/mhfpacket/msg_sys_record_log.go b/network/mhfpacket/msg_sys_record_log.go index 4266ec774..dcdf3e5a2 100644 --- a/network/mhfpacket/msg_sys_record_log.go +++ b/network/mhfpacket/msg_sys_record_log.go @@ -1,21 +1,19 @@ package mhfpacket -import ( - "errors" +import ( + "errors" - "erupe-ce/network/clientctx" - "erupe-ce/network" "erupe-ce/common/byteframe" + "erupe-ce/network" + "erupe-ce/network/clientctx" ) // MsgSysRecordLog represents the MSG_SYS_RECORD_LOG type MsgSysRecordLog struct { - AckHandle uint32 - Unk0 uint32 - Unk1 uint16 // Hardcoded 0 - HardcodedDataSize uint16 // Hardcoded 0x4AC - Unk3 uint32 // Some shared ID with MSG_MHF_GET_SEIBATTLE. World ID?? - DataBuf []byte + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Data []byte } // Opcode returns the ID associated with this packet type. @@ -27,10 +25,10 @@ func (m *MsgSysRecordLog) Opcode() network.PacketID { func (m *MsgSysRecordLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { m.AckHandle = bf.ReadUint32() m.Unk0 = bf.ReadUint32() - m.Unk1 = bf.ReadUint16() - m.HardcodedDataSize = bf.ReadUint16() - m.Unk3 = bf.ReadUint32() - m.DataBuf = bf.ReadBytes(uint(m.HardcodedDataSize)) + bf.ReadUint16() // Zeroed + size := bf.ReadUint16() + m.Unk1 = bf.ReadUint32() + m.Data = bf.ReadBytes(uint(size)) return nil } diff --git a/patch-schema/08-kill-counts.sql b/patch-schema/08-kill-counts.sql new file mode 100644 index 000000000..1c170cedd --- /dev/null +++ b/patch-schema/08-kill-counts.sql @@ -0,0 +1,12 @@ +CREATE TABLE public.kill_logs +( + id serial, + character_id integer NOT NULL, + monster integer NOT NULL, + quantity integer NOT NULL, + timestamp timestamp with time zone NOT NULL, + PRIMARY KEY (id) +); + +ALTER TABLE IF EXISTS public.guild_characters + ADD COLUMN box_claimed timestamp with time zone DEFAULT now(); \ No newline at end of file diff --git a/server/channelserver/handlers.go b/server/channelserver/handlers.go index 6af061b13..e39942671 100644 --- a/server/channelserver/handlers.go +++ b/server/channelserver/handlers.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "encoding/hex" "erupe-ce/common/mhfcourse" + "erupe-ce/common/mhfmon" ps "erupe-ce/common/pascalstring" "erupe-ce/common/stringsupport" _config "erupe-ce/config" @@ -305,9 +306,20 @@ func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) { func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) { pkt := p.(*mhfpacket.MsgSysRecordLog) + if _config.ErupeConfig.RealClientMode == _config.ZZ { + bf := byteframe.NewByteFrameFromBytes(pkt.Data) + bf.Seek(32, 0) + var val uint8 + for i := 0; i < 176; i++ { + val = bf.ReadUint8() + if val > 0 && mhfmon.Monsters[i].Large { + s.server.db.Exec(`INSERT INTO kill_logs (character_id, monster, quantity, timestamp) VALUES ($1, $2, $3, $4)`, s.charID, i, val, TimeAdjusted()) + } + } + } // remove a client returning to town from reserved slots to make sure the stage is hidden from board delete(s.stage.reservedClientSlots, s.charID) - doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) } func handleMsgSysEcho(s *Session, p mhfpacket.MHFPacket) {} diff --git a/server/channelserver/handlers_guild.go b/server/channelserver/handlers_guild.go index 6ef507b84..a1b4eb397 100644 --- a/server/channelserver/handlers_guild.go +++ b/server/channelserver/handlers_guild.go @@ -1867,15 +1867,51 @@ func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) { bf := byteframe.NewByteFrame() switch pkt.Operation { case 0: // Acquire - // Probably mark everything as claimed + s.server.db.Exec(`UPDATE guild_characters SET box_claimed=$1 WHERE character_id=$2`, TimeAdjusted(), s.charID) case 1: // Enumerate bf.WriteUint8(0) // Entries - /* Entry format - uint32 UnkID - uint32 MonID - */ + rows, err := s.server.db.Query(`SELECT kl.id, kl.monster FROM kill_logs kl + INNER JOIN guild_characters gc ON kl.character_id = gc.character_id + WHERE gc.guild_id=$1 + AND kl.timestamp >= (SELECT box_claimed FROM guild_characters WHERE character_id=$2) + `, pkt.GuildID, s.charID) + if err == nil { + var count uint8 + var huntID, monID uint32 + for rows.Next() { + err = rows.Scan(&huntID, &monID) + if err != nil { + continue + } + count++ + if count > 255 { + count = 255 + rows.Close() + break + } + bf.WriteUint32(huntID) + bf.WriteUint32(monID) + } + bf.Seek(0, 0) + bf.WriteUint8(count) + } case 2: // Check - bf.WriteBool(false) + guild, err := GetGuildInfoByCharacterId(s, s.charID) + if err == nil { + var count uint8 + err = s.server.db.QueryRow(`SELECT COUNT(*) FROM kill_logs kl + INNER JOIN guild_characters gc ON kl.character_id = gc.character_id + WHERE gc.guild_id=$1 + AND kl.timestamp >= (SELECT box_claimed FROM guild_characters WHERE character_id=$2) + `, guild.ID, s.charID).Scan(&count) + if err == nil && count > 0 { + bf.WriteBool(true) + } else { + bf.WriteBool(false) + } + } else { + bf.WriteBool(false) + } } doAckBufSucceed(s, pkt.AckHandle, bf.Data()) }