[PlusEMU][Addon] Christmas Calander

Core

Member
Nov 10, 2016
356
138
Stop releasing on other forums and taking credits. This is a release for DevBest.
Habbo Advent Calendar
This is for the Habbo.com's 2016 Advent Calendar. Only difference is that the prizes which are given are not random, it's a fixed prize each day. I done this so it's more fair for users. This release is for the latest production of Habbo.com (12/12/2016 (PRODUCTION-201612121204-107735592)). This is also a very pointless releases as it's 19th December but Habbo has calender's all the time for different things so you will only need to change the event name. Or you could just use the same calendar and just change the text in external flash texts? e.g. "New Year Advent Calendar" xD!

However, the structure has remained the same since PRODUCTION-201610312204-296063264 and maybe even before then. It was this build when I first created this so I know for certain it's not changed since then.

b4da223d578e44d3a5459545c71a7c62.png


I didn't code "Force Open" but if you'd like to the packet id is 2799 and the structure is string, int. The string is the event name (xmas16) and the int is the day id. There is no use in this though and I'm lazy! xD - If you want it just edit the open gift and remove time check and check if user is an admin.

Now you will want to open GameClient.cs and find
Code:
_habbo.InitProcess();
Above that you want to add
Code:
if (PlusStaticGameSettings.CampaignCalendarEnabled)
    SendMessage(new CampaignCalendarDataComposer(_habbo.GetStats().openedGifts));

You may need to add this at the top of the GameClient.cs
Code:
using Plus.Communication.Packets.Outgoing.Campaigns;

Next you want to open PlusStaticGameSettings and find
Code:
public const bool NewUserTutorialBotEnabled = true;

and below that put
Code:
public const bool CampaignCalendarEnabled = true;

Now you want to create CampaignCalendarDataComposer and put
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Plus.Communication.Packets.Outgoing.Campaigns
{
    class CampaignCalendarDataComposer : ServerPacket
    {
        public CampaignCalendarDataComposer(List<int> OpenedGifts)
            : base(ServerPacketHeader.CampaignCalendarDataMessageComposer)
        {
            int currentDate = DateTime.Now.Day - 1;

            base.WriteString("xmas16"); //eventTrigger
            base.WriteString(string.Empty); //idk? same as habbo ;P
            base.WriteInteger(currentDate); //currentDate
            base.WriteInteger(25); //totalAmountOfDays

            base.WriteInteger(OpenedGifts.Count); //countOpenGifts
            foreach (int Opened in OpenedGifts)
            {
                base.WriteInteger(Opened); //giftDay
            }

            List<int> MissedGifts = Enumerable.Range(0, (currentDate - 2)).Where(Day => !OpenedGifts.Contains(Day)).ToList();

            base.WriteInteger(MissedGifts.Count); //countMissedGifts
            foreach (int Missed in MissedGifts)
            {
                base.WriteInteger(Missed); //giftDay
            }
        }
    }
}

Next you want to go to ServerPacketHeader.cs and add
Code:
public const int CampaignCalendarDataMessageComposer = 2740; //updated
public const int CampaignCalendarGiftMessageComposer = 163; //updated

Next you want to create an event called OpenCalendarBoxEvent and inside it put
Code:
using Plus.Communication.Packets.Outgoing.Inventory.Furni;
using Plus.Communication.Packets.Outgoing.LandingView;
using Plus.Database.Interfaces;
using Plus.HabboHotel.Items;
using Plus.HabboHotel.Users;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Plus.Communication.Packets.Incoming.LandingView
{
    class OpenCalendarBoxEvent : IPacketEvent
    {
        public void Parse(HabboHotel.GameClients.GameClient Session, ClientPacket Packet)
        {
            string eventName = Packet.PopString();
            int giftDay = Packet.PopInt();

            HabboStats habboStats = Session?.GetHabbo()?.GetStats();

            int currentDay = DateTime.Now.Day - 1;

            if (!PlusStaticGameSettings.CampaignCalendarEnabled || habboStats == null ||
                habboStats.openedGifts.Contains(giftDay) || giftDay < (currentDay-2) ||
                giftDay > currentDay || eventName != "xmas16")
            {
                return;
            }

            Item newItem = null;
            if(!PlusEnvironment.GetGame().GetLandingManager().GenerateCalendarItem(
                Session.GetHabbo(), eventName, giftDay, out newItem))
            {
                return;
            }

            habboStats.addOpenedGift(giftDay);
            Session.GetHabbo().GetInventoryComponent().TryAddItem(newItem);
            Session.SendMessage(new FurniListUpdateComposer());
            Session.SendMessage(new CampaignCalendarGiftComposer(newItem.Data.ItemName));
        }
    }
}

Go to PacketManager.cs and find
Code:
this._incomingPackets.Add(ClientPacketHeader.GetPromoArticlesMessageEvent, new GetPromoArticlesEvent());
and then you want to add below this
Code:
this._incomingPackets.Add(ClientPacketHeader.OpenCalendarBoxMessageEvent, new OpenCalendarBoxEvent());

Then in the same file find
Code:
this._packetNames.Add(ClientPacketHeader.GetPromoArticlesMessageEvent, "RefreshPromoEvent");
and below this add
Code:
this._packetNames.Add(ClientPacketHeader.OpenCalendarBoxMessageEvent, "CampaignCalendarGiftEvent");

Now you want to go to ClientPacketHeader.cs and find
Code:
public const int UseWallItemMessageEvent = 3940;

Below you want to add
Code:
public const int OpenCalendarBoxMessageEvent = 693; //updated

Next create a server packet called CampaignCalendarGiftComposer.cs and put
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Plus.Communication.Packets.Outgoing.LandingView
{
    class CampaignCalendarGiftComposer : ServerPacket
    {
        public CampaignCalendarGiftComposer(string iconName = "throne")
            : base(ServerPacketHeader.CampaignCalendarGiftMessageComposer)
        {
            base.WriteBoolean(true); // never bothered to check
            base.WriteString("xmas14_starfish"); //productName
            base.WriteString(""); //customImage
            base.WriteString(iconName); //iconName
        }
    }
}

Second string is xmas14_starfish because doesn't worth if not valid item but it's likely to do with the bool xD I rushed this so didn't bother checking. Still works fine just given gift string is wrong but icon shows as the rare.

Next you want to go to LandingViewManager.cs and add the following function (these should be cached but I'm lazy xD and this was done for fun not a public release)
Code:
public bool GenerateCalendarItem(Habbo Habbo, string eventName, int eventDate, out Item newItem)
        {
            newItem = null;

            using (IQueryAdapter dbClient = PlusEnvironment.GetDatabaseManager().GetQueryReactor())
            {
                dbClient.SetQuery("SELECT `item_id` FROM `campaign_calendar_gifts` WHERE `event_name` = @eventName AND `base_id` = @dayId LIMIT 1");
                dbClient.AddParameter("eventName", eventName);
                dbClient.AddParameter("dayId", eventDate);

                DataRow row = dbClient.getRow();
                ItemData itemData = null;

                if (row?["item_id"] != null &&
                    PlusEnvironment.GetGame().GetItemManager().GetItem((string)row["item_id"], out itemData))
                {
                    newItem = ItemFactory.CreateSingleItemNullable(itemData, Habbo, "", "");
                    return newItem != null;
                }

                return false;
            }
        }

Next you want to open ItemDataManager.cs and find
Code:
public bool GetItem(int Id, out ItemData Item)

Above that put this
Code:
public bool GetItem(string itemName, out ItemData item)
        {
            item = this._items.Values.Where(x => x.ItemName == itemName).FirstOrDefault();
            return item != null;
        }

Now you want to go to HabboStats.cs and find
Code:
public int ForumPosts { get; set; }

Then blow that add
Code:
public List<int> openedGifts { get; private set; }

        public void addOpenedGift(int eventDate)
        {
            if (this.openedGifts.Contains(eventDate))
            {
                return;
            }

            this.openedGifts.Add(eventDate);
            string[] giftData = this.openedGifts.Select(giftDay => giftDay.ToString()).ToArray();

            using (IQueryAdapter dbClient = PlusEnvironment.GetDatabaseManager().GetQueryReactor())
            {
                dbClient.SetQuery("UPDATE `user_stats` SET `calendar_gifts` = @giftData WHERE `id` = @habboId LIMIT 1");
                dbClient.AddParameter("giftData", string.Join(",", giftData));
                dbClient.AddParameter("habboId", habboId);
                dbClient.RunQuery();
            }

        }

Now in the same file fine
Code:
this.ForumPosts = ForumPosts;

and below that add this
Code:
this.openedGifts = new List<int>();
            foreach (string subStr in openedGifts.Split(','))
            {
                int openedDay = 0;
                if (int.TryParse(subStr, out openedDay))
                {
                    this.openedGifts.Add(openedDay);
                }
            }

Then find
Code:
public HabboStats(

and just before the ) add
Code:
, string openedGifts

Then go to Habbo.cs and find
Code:
this._habboStats = new HabboStats(
and once again before the ); add
Code:
Convert.ToString(StatRow["calendar_gifts"])

You will also need to add (`calendar_gifts`) to the SELECT queries. I can't just page my query as I used this table for several things like nux status, which your table will not contain so will only give you errors.

Here is the database
Code:
/*
Navicat MySQL Data Transfer

Source Server         : local
Source Server Version : 50505
Source Host           : localhost:3306
Source Database       : plus

Target Server Type    : MYSQL
Target Server Version : 50505
File Encoding         : 65001

Date: 2016-12-19 18:30:09
*/

SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `campaign_calendar_gifts`
-- ----------------------------
DROP TABLE IF EXISTS `campaign_calendar_gifts`;
CREATE TABLE `campaign_calendar_gifts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `event_name` varchar(225) NOT NULL,
  `base_id` int(11) NOT NULL,
  `item_id` varchar(225) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of campaign_calendar_gifts
-- ----------------------------
INSERT INTO `campaign_calendar_gifts` VALUES ('1', 'xmas16', '1', 'throne');
INSERT INTO `campaign_calendar_gifts` VALUES ('2', 'xmas16', '2', 'typingmachine');
INSERT INTO `campaign_calendar_gifts` VALUES ('3', 'xmas16', '3', 'spyro');
INSERT INTO `campaign_calendar_gifts` VALUES ('4', 'xmas16', '4', 'rare_daffodil_rug');
INSERT INTO `campaign_calendar_gifts` VALUES ('5', 'xmas16', '5', 'rare_beehive_bulb');
INSERT INTO `campaign_calendar_gifts` VALUES ('6', 'xmas16', '6', 'rare_elephant_statue');
INSERT INTO `campaign_calendar_gifts` VALUES ('7', 'xmas16', '7', 'rare_stand');
INSERT INTO `campaign_calendar_gifts` VALUES ('8', 'xmas16', '8', 'rare_xmas_screen');
INSERT INTO `campaign_calendar_gifts` VALUES ('9', 'xmas16', '9', 'djesko_turntable');
INSERT INTO `campaign_calendar_gifts` VALUES ('10', 'xmas16', '10', 'rare_vdoll');
INSERT INTO `campaign_calendar_gifts` VALUES ('11', 'xmas16', '11', 'rare_mmmth');
INSERT INTO `campaign_calendar_gifts` VALUES ('12', 'xmas16', '12', 'rare_trex');
INSERT INTO `campaign_calendar_gifts` VALUES ('13', 'xmas16', '13', 'rare_ironmaiden');
INSERT INTO `campaign_calendar_gifts` VALUES ('14', 'xmas16', '14', 'rare_fountain_niko');
INSERT INTO `campaign_calendar_gifts` VALUES ('15', 'xmas16', '15', 'rare_dragonlamp_pink');
INSERT INTO `campaign_calendar_gifts` VALUES ('16', 'xmas16', '16', 'rare_trex');
INSERT INTO `campaign_calendar_gifts` VALUES ('17', 'xmas16', '17', 'rare_elephant_statue');
INSERT INTO `campaign_calendar_gifts` VALUES ('18', 'xmas16', '18', 'typingmachine');
INSERT INTO `campaign_calendar_gifts` VALUES ('19', 'xmas16', '19', 'rare_dragonlamp_pink');
INSERT INTO `campaign_calendar_gifts` VALUES ('20', 'xmas16', '20', 'typingmachine');
INSERT INTO `campaign_calendar_gifts` VALUES ('21', 'xmas16', '21', 'throne');
INSERT INTO `campaign_calendar_gifts` VALUES ('22', 'xmas16', '22', 'djesko_turntable');
INSERT INTO `campaign_calendar_gifts` VALUES ('23', 'xmas16', '23', 'pillow_bronze');
INSERT INTO `campaign_calendar_gifts` VALUES ('24', 'xmas16', '24', 'pillow_silver');
INSERT INTO `campaign_calendar_gifts` VALUES ('25', 'xmas16', '25', '0');

I am shit at tutorials! So if you was unable to follow this or need help just add me on skype StackOverflow-
I will be more than happy to implement this for you :p
 
Last edited:

Core

Member
Nov 10, 2016
356
138
It's sad to be 19 days late but a good add on. Thanks!
There are multiple calendars in the SWF :p Use one of them for something else? Like I said with new year calendar :D Give someone a gift for first x amount of days in january?
Current calendar isn't really x-mas themed so you could use that :p

My version is PRODUCTION-201.607.262.204-86.871.104 I don't know how to change it.

Link me to the Habbo.swf ?
 

Alexsander

New Member
Apr 21, 2016
7
0
There are multiple calendars in the SWF :p Use one of them for something else? Like I said with new year calendar :D Give someone a gift for first x amount of days in january?
Current calendar isn't really x-mas themed so you could use that :p
Link me to the Habbo.swf ?


Could you give me your skype?
 

Alexsander

New Member
Apr 21, 2016
7
0
Hello, I cannot understand, where should I put this code? (
Sorry for my poor understanding.)


Code:
public bool GenerateCalendarItem(Habbo Habbo, string eventName, int eventDate, out Item newItem)
        {
            newItem = null;

            using (IQueryAdapter dbClient = PlusEnvironment.GetDatabaseManager().GetQueryReactor())
            {
                dbClient.SetQuery("SELECT `item_id` FROM `campaign_calendar_gifts` WHERE `event_name` = @eventName AND `base_id` = @dayId LIMIT 1");
                dbClient.AddParameter("eventName", eventName);
                dbClient.AddParameter("dayId", eventDate);

                DataRow row = dbClient.getRow();
                ItemData itemData = null;

                if (row?["item_id"] != null &&
                    PlusEnvironment.GetGame().GetItemManager().GetItem((string)row["item_id"], out itemData))
                {
                    newItem = ItemFactory.CreateSingleItemNullable(itemData, Habbo, "", "");
                    return newItem != null;
                }

                return false;
            }
        }
 

Blasteh

Lord Farquaad
Apr 3, 2013
1,151
513
Hello, I cannot understand, where should I put this code? (
Sorry for my poor understanding.)


Code:
public bool GenerateCalendarItem(Habbo Habbo, string eventName, int eventDate, out Item newItem)
        {
            newItem = null;

            using (IQueryAdapter dbClient = PlusEnvironment.GetDatabaseManager().GetQueryReactor())
            {
                dbClient.SetQuery("SELECT `item_id` FROM `campaign_calendar_gifts` WHERE `event_name` = @eventName AND `base_id` = @dayId LIMIT 1");
                dbClient.AddParameter("eventName", eventName);
                dbClient.AddParameter("dayId", eventDate);

                DataRow row = dbClient.getRow();
                ItemData itemData = null;

                if (row?["item_id"] != null &&
                    PlusEnvironment.GetGame().GetItemManager().GetItem((string)row["item_id"], out itemData))
                {
                    newItem = ItemFactory.CreateSingleItemNullable(itemData, Habbo, "", "");
                    return newItem != null;
                }

                return false;
            }
        }
If you don't understand where to put this code after reading the thread. Then you shouldn't be trying to do this, because chances are you probably don't know how to use Visual Studio.
 

Alexsander

New Member
Apr 21, 2016
7
0
[QUOTE = "Blasteh, post: 392.765, membro: 30540"] Se você não entender onde colocar este código depois de ler a lista de discussão. Então você não deveria estar tentando fazer isso, porque as chances são que você provavelmente não sabe como usar o Visual Studio. [/ QUOTE]

If you answer where I should put the code, it is obvious that I'm going to hit, what is more necessary to know in visualStudio? Beyond Debug after the process?
 

arfeus

Member
Feb 15, 2014
33
2
I think that few people work with this production TradingUpdateComposer not Fixed anymore, so you cannot trade.. (Users Disconnect)
If you can help with TradingUpdateComposers for everyone to update and use the New Year Calendar would be very good
 

yoyok

Member
Apr 24, 2013
197
24
[QUOTE = "Blasteh, post: 392.765, membro: 30540"] Se você não entender onde colocar este código depois de ler a lista de discussão. Então você não deveria estar tentando fazer isso, porque as chances são que você provavelmente não sabe como usar o Visual Studio. [/ QUOTE]

If you answer where I should put the code, it is obvious that I'm going to hit, what is more necessary to know in visualStudio? Beyond Debug after the process?
You need to put it in LandingViewManager.cs
 

Core

Member
Nov 10, 2016
356
138
I think that few people work with this production TradingUpdateComposer not Fixed anymore, so you cannot trade.. (Users Disconnect)
If you can help with TradingUpdateComposers for everyone to update and use the New Year Calendar would be very good

Nothing is up with it? Structure hasn't changed in like 9999999999 builds xD
 

Core

Member
Nov 10, 2016
356
138
People keep asking me 'what folder should I put this'. Just follow the namespaces or here you go

Communication/Packets/Outgoing/Campaigns
-> CampaignCalendarDataComposer.cs
-> CampaignCalendarGiftComposer.cs

Communication/Packets/Incoming/LandingView
-> OpenCalendarBoxEvent.cs
 

Users who are viewing this thread

Top