MapleMultiBingo

Results 1 to 10 of 10
  1. #1
    ・ARC:+200 Yuuroido is offline
    MemberRank
    Jul 2010 Join Date
    Saitama, JPLocation
    333Posts

    wink MapleMultiBingo

    *This content is available after "You & I" update. (also called "Rising Heroes" in GMS v150)

    Send opcodes:
    Code:
    HBINGO_BINGO_GAME,
    HBINGO_HOST_NUMBER,
    HBINGO_HOST_NUMBER_READY,
    HBINGO_ADD_RANK,
    HBINGO_REMOVE_RANK,
    HBINGO_FINISH_RANK,
    HBINGO_CHECK_NUMBER_ACK,
    HBINGO_GAME_STATE
    values:
    Spoiler:
    Code:
    GMS
    v150: 0x373~0x37A
    v151: 0x374~0x37B
    v152: 0x37A~0x381
    v153: 0x378~0x37F
    v154: 0x38A~0x391
    v156: 0x39A~0x3A1
    v157: 0x3B6~0x3BD (0x3DE~0x3E3 for star planet?)
    v160: 0x3D4~0x3DB (0x404~0x409 for star planet?)
    v166: 0x420~0x427 (0x450~0x455 for star planet?)
    MSEAv155:0x3F0~0x3F7 (0x41B~0x420 for star planet?)

    Packet:
    Code:
    public static class Bingo {
    
        public static byte[] enterGame(int round, List<Byte> card) {
            MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
            mplew.writeShort(SendPacketOpcode.HBINGO_BINGO_GAME.getValue());
            mplew.writeInt(round);
            if (stage == 1) {
                mplew.writeInt(1);
                mplew.writeInt(6);//message size
                mplew.writeMapleAsciiString("Hey, wait a minute, yo.");//end
                mplew.writeMapleAsciiString("Click the numbers when they pop up!");
                mplew.writeMapleAsciiString("Press the Bingo button when you have a bingo.");
                mplew.writeMapleAsciiString("I say Bing! You say Go! Bing! Go! Bing! Go!");
                mplew.writeMapleAsciiString("Holler if you love Bingo!");
                mplew.writeMapleAsciiString("The game will begin soon!");//begin
            } else {
                mplew.writeInt(0);
            }
            mplew.writeInt(5);
            mplew.writeInt(5);
            mplew.writeInt(25);
            for (byte number : card) {
                mplew.writeInt(number);
            }
            return mplew.getPacket();
        }
    
        public static byte[] hostNumber(int number, int remain) {
            MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
            mplew.writeShort(SendPacketOpcode.HBINGO_HOST_NUMBER.getValue());
            mplew.writeInt(number);
            mplew.writeInt(remain);
            return mplew.getPacket();
        }
    
        public static byte[] hostNumberReady() {
            MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
            mplew.writeShort(SendPacketOpcode.HBINGO_HOST_NUMBER_READY.getValue());
            return mplew.getPacket();
        }
    
        public static byte[] addRank(int cid, String name, int round, int rank) {
            MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
            mplew.writeShort(SendPacketOpcode.HBINGO_ADD_RANK.getValue());
            mplew.writeInt(1);
            mplew.writeInt(cid);
            mplew.writeMapleAsciiString(name);
            mplew.writeInt(round);
            mplew.writeInt(rank);
            return mplew.getPacket();
        }
    
        /* no idea */
        public static byte[] addRankFail(int cid, String name) {
            MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
            mplew.writeShort(SendPacketOpcode.HBINGO_ADD_RANK.getValue());
            mplew.writeInt(0);
            mplew.writeInt(cid);
            mplew.writeMapleAsciiString(name);
            mplew.writeInt(0);
            mplew.writeInt(0);
            return mplew.getPacket();
        }
    
        /* for disconnected player? ...or hacker? lol */
        public static byte[] removeRank(int unk) {
            MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
            mplew.writeShort(SendPacketOpcode.HBINGO_REMOVE_RANK.getValue());
            mplew.writeInt(unk);//cid or rank or round :p
            return mplew.getPacket();
        }
    
        public static byte[] finishRank(int round, int rank) {
            MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
            mplew.writeShort(SendPacketOpcode.HBINGO_FINISH_RANK.getValue());
            mplew.writeInt(round);
            mplew.writeInt(rank);
            return mplew.getPacket();
        }
    
        public static byte[] checkNumberAck(byte index, byte number, List<Byte> bingoLines) {
            MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
            mplew.writeShort(SendPacketOpcode.HBINGO_CHECK_NUMBER_ACK.getValue());
            mplew.writeInt(index);
            mplew.writeInt(number);
            mplew.writeInt(0);
            mplew.writeInt(bingoLines.size());
            for (byte direction : bingoLines) {
                mplew.writeInt(direction);
            }
            return mplew.getPacket();
        }
    
        public static byte[] setGameState(int state, int round) {
            MaplePacketLittleEndianWriter mplew = new MaplePacketLittleEndianWriter();
            mplew.writeShort(SendPacketOpcode.HBINGO_GAME_STATE.getValue());
            mplew.writeInt(state);
            mplew.writeInt(round);
            return mplew.getPacket();
        }
    }

    Recv opcodes:
    Code:
    HBINGO_CHECK_NUMBER,
    HBINGO_CHECK_BINGO
    values: Please catch them yourself.

    Handler(e.g):
    Code:
    public static void checkBingoNumber(LittleEndianAccessor slea, MapleClient c) {
        MapleMultiBingo event = (MapleMultiBingo) ChannelServer.getInstance(c.getChannel()).getEvent(MapleEventType.Bingo);
        if (event.isRunning()) {
            event.checkBingoNumber(c, (byte) slea.readInt(), (byte) slea.readInt());
        }
    }
    
    public static void checkBingo(LittleEndianAccessor slea, MapleClient c) {
        MapleMultiBingo event = (MapleMultiBingo) ChannelServer.getInstance(c.getChannel()).getEvent(MapleEventType.Bingo);
        if (event.isRunning()) {
            event.checkBingo(c);
        }
    }


    How to implement: Please make your own code.


    ...Just in case, this is an example. (terrible)
    Please do not ask/mention about this code.
    Spoiler:
    Code:
    package server.events;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.LinkedHashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ScheduledFuture;
    
    import client.MapleCharacter;
    import client.MapleClient;
    import server.Randomizer;
    import server.Timer.EventTimer;
    import tools.packet.CField;
    
    
    /**
     * 
     @author Yuuroido
     */
    public class MapleMultiBingo extends MapleEvent {
        private static final int TOTAL_ROUND = 3;//1~5
        private ScheduledFuture<?> callSchedule;
        private ScheduledFuture<?> responseSchedule;
        private int round;
        private int remainCount;
        private final List<Byte> numbers;
        private final List<Integer> enabledPlayer;
        private final List<MapleCharacter> ranking;
        private final Map<Integer, List<MapleCharacter>> result;
        private final Map<Integer, List<Byte>> cardData;
        private final Map<Integer, List<Boolean>> markedCardData;
        //mapids:922290000(WaitingArea), 922290100(GameField), 922290200(WaitingArea)
        
        public MapleMultiBingo(final int channel, final MapleEventType type) {
            super(channel, type);
            this.round= -1;
            this.numbers = new LinkedList<>();
            this.enabledPlayer = new ArrayList<>();
            this.ranking = new ArrayList<>();
            this.result = new HashMap<>();
            this.cardData = new HashMap<>();
            this.markedCardData = new HashMap<>();
        }
        
        @Override
        public void finished(MapleCharacter chr) {
        }
        
        @Override
        public void startEvent() {
            this.round= 0;
            getMap(0).setClock(10);
            EventTimer.getInstance().schedule(this::warpMap, 10000);
        }
        
        @Override
        public void unreset() {
            for (int i = 0; i < type.mapids.length; i++) {
                for (MapleCharacter chr : getMap(i).getCharactersThreadsafe()) {
                    super.warpBack(chr);
                }
            }
            if (callSchedule != null) {
                callSchedule.cancel(false);
                callSchedule = null;
            }
            if (responseSchedule != null) {
                responseSchedule.cancel(false);
                responseSchedule = null;
            }
            super.unreset();
            this.round= -1;
            this.result.clear();
        }
        
        public void checkBingoNumber(MapleClient c, byte index, byte number) {
            if (numbers.contains(number)) {
                return;
            }
            int cid = c.getPlayer().getId();
            if (cardData.get(cid) == null || !cardData.get(cid).contains(number) || !cardData.get(cid).get(index).equals(number)) {
                c.getSession().close();
            } else {
                markedCardData.get(cid).set(index, true);
                List<Byte> bingoLines = checkBingoCard(cid, index);
                if (bingoLines.size() > 0) {
                    //why does nexon not let you automatically say "Bingo!"?
                    enabledPlayer.add(cid);
                }
                c.getSession().write(CField.Bingo.checkNumberAck(index, number, bingoLines));
            }
        }
        
        public void checkBingo(MapleClient c) {
            MapleCharacter chr = c.getPlayer();
            if (ranking.size() < 30) {
                if (!enabledPlayer.contains(chr.getId())) {
                    c.getSession().close();
                } else {
                    byte rank = (byte) (ranking.size() + 1);
                    this.ranking.add(chr);
                    getMap(1).broadcastMessage(CField.Bingo.addRank(chr.getId(), chr.getName(), round, rank));
                    if (rank == 30) {
                        finishRound();
                    }
                }
            } else {
                //hmm..?
                getMap(1).broadcastMessage(CField.Bingo.addRankFail(chr.getId(), chr.getName()));
            }
        }
        
        public int getRound() {
            return round;
        }
    
        /* use with NPC script (9000267) */
        public int getReward(MapleCharacter chr) {
            int bonus = 0;
            int rank;
            for (List<MapleCharacter> list :  result.values()) {
                rank = list.indexOf(chr) + 1;
                if (rank == 1) {
                    bonus += 50000000;
                } else if (rank == 2) {
                    bonus += 25000000;
                } else if (rank == 3) {
                    bonus += 10000000;
                } else if (rank <= 5) {
                    bonus += 5000000;
                } else if (rank <= 10) {
                    bonus += 2500000;
                } else if (rank <= 20) {
                    bonus += 1000000;
                } else if (rank <= 30) {
                    bonus += 500000;
                }
            }
            return bonus;
        }
        
        
        private void warpMap() {
            if (round == 0) {
                if (getMap(0).getCharactersSize() < 5) {
                    getMap(0).broadcastMessage(CWvsContext.InfoPacket.showInfo("The game will end due to a lack of participants."));
                    EventTimer.getInstance().schedule(this::unreset, 10000);
                    return;
                }
                this.round = 1;
                getMap(0).setClock(900);
                getMap(2).setClock(900);
                EventTimer.getInstance().schedule(this::unreset, 900000);
                EventTimer.getInstance().schedule(this::prepareNextRound, 15000);
                for (MapleCharacter chr : getMap(0).getCharactersThreadsafe()) {
                    chr.changeMap(getMap(1));
    //                chr.updateInfoQuest(14284, "R1=0;R2=0;R3=0");
                    sendBingoCard(chr);
                }
            } else {
                for (MapleCharacter chr : getMap(1).getCharactersThreadsafe()) {
                    chr.changeMap(getMap(2));
                }
            }
        }
        
        private void prepareNextRound() {
            if (round >= 2) {
                int rank = 1;
                for (MapleCharacter chr : ranking) {
                    chr.getClient().getSession().write(CField.Bingo.finishRank(round - 1, rank++));
                }
                result.put(round - 1, ranking);
            }
            this.remainCount = 50;
            this.enabledPlayer.clear();
            this.ranking.clear();
            this.numbers.clear();
            for (byte i = 1; i < 76; i++) {
                numbers.add(i);
            }
            Collections.shuffle(numbers);
            getMap(1).broadcastMessage(CField.Bingo.setGameState(2, round));//start announce (default)
            EventTimer.getInstance().schedule(this::prepareBingoCard, 3000);
        }
        
        private void prepareBingoCard() {
            if (round >= 2) {
                for (MapleCharacter chr : getMap(1).getCharactersThreadsafe()) {
                    sendBingoCard(chr);
                }
            }
            getMap(1).broadcastMessage(CField.Bingo.setGameState(3, round));//show bingo card
            EventTimer.getInstance().schedule(this::startRound, 5000);
        }
        
        private void startRound() {
            getMap(1).broadcastMessage(CField.environmentChange("kite/start", 9));
            getMap(1).broadcastMessage(CField.environmentChange("multiBingo/start", 5));
            getMap(1).broadcastMessage(CField.Bingo.setGameState(4, round));//stop announce
            EventTimer.getInstance().schedule(this::startCallSchedule, 1000);
        }
        
        private void startCallSchedule() {
            getMap(1).broadcastMessage(CField.Bingo.hostNumber(-1, remainCount));
            responseSchedule = EventTimer.getInstance().register(this::sendBingoResponse, 5000, 3000);
            callSchedule = EventTimer.getInstance().register(this::callNumber, 5000, 5000);
        }
    
        private void sendBingoResponse() {
            getMap(1).broadcastMessage(CField.Bingo.hostNumberReady());
        }
        
        private void callNumber() {
            if (remainCount <= 0 || ranking.size() >= 30) {
                finishRound();
            } else {
                byte number = numbers.remove(0);
                getMap(1).broadcastMessage(CField.Bingo.hostNumber(number, --remainCount));
            }
        }
        
        private void finishRound() {
            responseSchedule.cancel(false);
            callSchedule.cancel(false);
            getMap(1).broadcastMessage(CField.environmentChange("multiBingo/gameover", 5));
            getMap(1).broadcastMessage(CField.environmentChange("killing/first/finish", 9));
            getMap(1).broadcastMessage(CField.Bingo.setGameState(5, round));//disable bingo button & clear number log
            if (round < TOTAL_ROUND) {
                this.round++;
                EventTimer.getInstance().schedule(this::prepareNextRound, 5000);
            } else {
                this.round = -2;
                EventTimer.getInstance().schedule(this::warpMap, 10000);
            }
        }
        
        private void sendBingoCard(MapleCharacter chr) {
            List<Byte> card = createBingoCard();
            cardData.put(chr.getId(), card);
            List<Boolean> markedCard = new LinkedList<>();
            for (byte number : card) {
                markedCard.add(number == 0);//joker
            }
            markedCardData.put(chr.getId(), markedCard);
            chr.getClient().getSession().write(CField.Bingo.enterGame(round, card));
        }
        
        private List<Byte> createBingoCard() {
            List<Byte> card = new LinkedList<>();
            byte[][] tempCard = new byte[5][5];
            Set<Byte> temp = new LinkedHashSet<>();
            byte line = 0;
            byte count = 0;
            do {
                temp.add((byte) (15 * line + Randomizer.rand(1, 15)));
                if (temp.size() % 5 == 0) {
                    for (byte number : temp) {
                        tempCard[line][count] = number;
                        count++;
                    }
                    temp.clear();
                    line++;
                    count = 0;
                }
            } while (line < 5);
            for (byte i = 0; i < 5; i++) {
                for (byte j = 0; j < 5; j++) {
                    card.add(tempCard[j][i]);
                }
            }
            card.set(12, (byte) 0);//joker
            return card;
        }
        
        /*0:horizontal, 1:vertical, 2:lower right diagonal, 3:upper right diagonal*/
        private List<Byte> checkBingoCard(int cid, byte index) {
            List<Byte> bingoLines = new ArrayList<>();
            Boolean[] list = markedCardData.get(cid).toArray(new Boolean[]{});
            if (list[0]) {
                if (list[1] && list[2] && list[3] && list[4]
                    && index >= 0 && index <= 4) {
                    bingoLines.add((byte) 0);
                }
                if (list[5] && list[10] && list[15] && list[20]
                    && (index == 0 || index == 5 || index == 10 || index == 15 || index == 20)) {
                    bingoLines.add((byte) 1);
                }
                if (list[6] && list[12] && list[18] && list[24] 
                    && (index == 0 || index == 6 || index == 12 || index == 18 || index == 24)) {
                    bingoLines.add((byte) 2);
                }
            }
            if (list[1] && list[6] && list[11] && list[16] && list[21] 
                    && (index == 1 || index == 6 || index == 11 || index == 16 || index == 21) 
                || list[2] && list[7] && list[12] && list[17] && list[22]
                    && (index == 2 || index == 7 || index == 12 || index == 17 || index == 22) 
                || list[3] && list[8] && list[13] && list[18] && list[23] 
                    && (index == 3 || index == 8 || index == 13 || index == 18 || index == 23)) {
                bingoLines.add((byte) 1);
            }
            if (list[4]) {
                if (list[9] && list[14] && list[19] && list[24]
                    && (index == 4 || index == 9 || index == 14 || index == 19 || index == 24)) {
                    bingoLines.add((byte) 1);
                } 
                if (list[8] && list[12] && list[16] && list[20]
                    && (index == 4 || index == 8 || index == 12 || index == 16 || index == 20)) {
                    bingoLines.add((byte) 3);
                }
            }
            if (list[5] && list[6] && list[7] && list[8] && list[9]
                    && index >= 5 && index <= 9
                || list[10] && list[11] && list[12] && list[13] && list[14]
                    && index >= 10 && index <= 14 
                || list[15] && list[16] && list[17] && list[18] && list[19]
                    && index >= 15 && index <= 19
                || list[20] && list[21] && list[22] && list[23] && list[24]
                    && index >= 20 && index <= 24) {
                bingoLines.add((byte) 0);
            }
            return bingoLines;
        }
    }


    Video:

    Screenshot:
    Spoiler:


    [STRIKE]Sorry for incomplete release. (such as 'Unk' or 'no idea' or any other not-implemented things)[/STRIKE]
    -Edit-
    Update: opcode names.. lol

    Thanks for reading :)
    Last edited by Yuuroido; 05-12-18 at 09:54 PM. Reason: Hundred Bingo!


  2. #2
    Moderator Eric is offline
    ModeratorRank
    Jan 2010 Join Date
    DEV CityLocation
    3,188Posts

    Re: MapleMultiBingo

    Very nice! This is cool and I wish it was in lower versions, I like bingo xD

    Don't worry about the incomplete release! All people at this kind of version need as far as information is packets and handlers and what the bytes are, otherwise you're stuck with copy-pasters who can't implement in Java.. I do the same thing ;)

  3. #3
    Omega sunnyboy is offline
    MemberRank
    Mar 2010 Join Date
    6,109Posts

    Re: MapleMultiBingo

    That's pretty neat. They probably got influenced by the bingo npc that existed ages before they made this. Just like... pvp battles (we had it 1st!)

  4. #4
    ・ARC:+200 Yuuroido is offline
    MemberRank
    Jul 2010 Join Date
    Saitama, JPLocation
    333Posts

    Re: MapleMultiBingo

    Quote Originally Posted by Eric View Post
    Very nice! This is cool and I wish it was in lower versions, I like bingo xD

    Don't worry about the incomplete release! All people at this kind of version need as far as information is packets and handlers and what the bytes are, otherwise you're stuck with copy-pasters who can't implement in Java.. I do the same thing ;)
    Thanks :) I hope this may help people who want to play Bingo in higher version servers.


    Quote Originally Posted by sunnyboy View Post
    That's pretty neat. They probably got influenced by the bingo npc that existed ages before they made this. Just like... pvp battles (we had it 1st!)
    That reminds me of "Rebirth System" in JMST... (Maybe they failed to implement it but alternatively added "Free Job Advancement"..?)

  5. #5
    (O_o(o_O(O_O)o_O)O_o) Novak is offline
    MemberRank
    Apr 2009 Join Date
    The NetherlandsLocation
    1,120Posts

    Re: MapleMultiBingo

    This is even hotter than the previous bingo release lol xD

    Nice work, I like how you've included some opcodes for multiple versions that people who aren't that quick with them can use.

  6. #6
    Account Upgraded | Title Enabled! SuperLol is offline
    MemberRank
    Jun 2010 Join Date
    801Posts

    Re: MapleMultiBingo

    Very cool! Good work.

    For the sake of hard to read code you can also use a bitwise storage purely used to check if a row is complete.
    Example for 3x3: I am aware this should be 5x5
    1st row: 0x01, 0x02, 0x04
    2nd row: 0x08, 0x10, 0x20
    3rd row: 0x40, 0x80, 0x100

    If 2nd row, 3rd entry is marked then value |= 0x20.
    To check if 2nd row is complete, (value & 0x38) == 0x38. To check if 1st column is complete (value & 0x49) == 0x49.

    I'm not sure if this is worth it though, would like to see what you guys think.

  7. #7
    ・ARC:+200 Yuuroido is offline
    MemberRank
    Jul 2010 Join Date
    Saitama, JPLocation
    333Posts

    Re: MapleMultiBingo

    Quote Originally Posted by SuperLol View Post
    Very cool! Good work.

    For the sake of hard to read code you can also use a bitwise storage purely used to check if a row is complete.
    Example for 3x3: I am aware this should be 5x5
    1st row: 0x01, 0x02, 0x04
    2nd row: 0x08, 0x10, 0x20
    3rd row: 0x40, 0x80, 0x100

    If 2nd row, 3rd entry is marked then value |= 0x20.
    To check if 2nd row is complete, (value & 0x38) == 0x38. To check if 1st column is complete (value & 0x49) == 0x49.

    I'm not sure if this is worth it though, would like to see what you guys think.
    Like this? (get rid of List ver.)
    Spoiler:
    Code:
    //mark 
    markedCardData.put(cid, markedCardData.get(cid) | (1 << index));
    
    //check bingo
    private byte checkBingoCard(int cid, byte index) {
        int flag = markedCardData.get(cid);
        byte bingoLines = 0, count = 0;
        //horizontal
        if ((flag & 0x1F) == 0x1F && index / 5 == 0
            || (flag & 0x3E0) == 0x3E0 && index / 5 == 1
            || (flag & 0x7C00) == 0x7C00 && index / 5 == 2
            || (flag & 0xF8000) == 0xF8000  && index / 5 == 3
            || (flag & 0x1F00000) == 0x1F00000 && index / 5 == 4) {
            bingoLines |= 0x10;
            count++;
        }
        //vertical
        if ((flag & 0x108421) == 0x108421 && index % 5 == 0
            || (flag & 0x210842) == 0x210842 && index % 5 == 1
            || (flag & 0x421084) == 0x421084 && index % 5 == 2
            || (flag & 0x842108) == 0x842108 && index % 5 == 3
            || (flag & 0x1084210) == 0x1084210 && index % 5 == 4) {
            bingoLines |= 0x20;
            count++;
        }
        //lower right diagonal
        if ((flag & 0x1041041) == 0x1041041 && index % 6 == 0) {
            bingoLines |= 0x40;
            count++;
        }
        //upper right diagonal
        if ((flag & 0x111110) == 0x111110 && index % 4 == 0 && index != 0 && index != 24) {
            bingoLines |= 0x80;
            count++;
        }
        return  (byte) (bingoLines | count);
    }

    hmm.. looks better?
    Last edited by Yuuroido; 18-01-16 at 01:25 PM.

  8. #8
    Proficient Member ALotOfPosts is offline
    MemberRank
    Sep 2014 Join Date
    181Posts

    Re: MapleMultiBingo

    Looks super unmaintainable... I highly do not recommend. Maybe @SuperLol will use it. At least he recognizes that it's practically unreadable though. Reminiscent of some material from ThePack! Cool concept nevertheless.

  9. #9
    BloopBloop Hilia is offline
    MemberRank
    Aug 2012 Join Date
    905Posts

    Re: MapleMultiBingo

    Quote Originally Posted by ALotOfPosts View Post
    Looks super unmaintainable... I highly do not recommend. Maybe @SuperLol will use it. At least he recognizes that it's practically unreadable though. Reminiscent of some material from ThePack! Cool concept nevertheless.
    Place it in an enum and it becomes maintainable and readable if you implement it correctly.

  10. #10
    ・ARC:+200 Yuuroido is offline
    MemberRank
    Jul 2010 Join Date
    Saitama, JPLocation
    333Posts

    Re: MapleMultiBingo

    Tips for those who looking for send-op's values which is not in the list. (other version)
    By using STREDIT, you can easily to find them on IDA.
    Spoiler:

    1.Open the unpacked client with STREDIT. (Optional) Export a CSV (or Enumeration).
    2.Find the word which you want to search. (In this case, either of following words is what we are looking for.)
    Code:
    for GMS:"%d remaining!"
    for MSEA:"Remaining number: %d!"
    3.Copy or remember the value of it. (StringPool value)
    4.Open the idb with IDA.
    5.Search Immediate the value (Press Alt+I) on the IDA-View. (check the box "Find all occurrences")
    6.Result -> CField_HundredBingo::OnHostNumber, CFieldState_HundredBingo::OnHostNumber (for starplanet?)
    7.Profit -> CField(State)_HundredBingo::OnPacket, CField::OnPacket

    Finding HundredBingo may also help to determine related opcodes such as PoloFrito thingy or TypingGame, HundredOxQuiz.
    Last edited by Yuuroido; 21-04-16 at 01:57 PM.



Advertisement