You've already forked Arcturus-Morningstar-Extended
mirror of
https://github.com/duckietm/Arcturus-Morningstar-Extended.git
synced 2026-06-19 15:06:19 +00:00
🆙 Update to 4.0.2
This commit is contained in:
@@ -0,0 +1,672 @@
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- =====================================================
|
||||
-- SECTION 1: Pet System Emulator Settings
|
||||
-- =====================================================
|
||||
|
||||
INSERT INTO `emulator_settings` (`key`, `value`) VALUES
|
||||
-- Core pet limits
|
||||
('hotel.pets.max.room', '15'),
|
||||
('hotel.pets.max.inventory', '25'),
|
||||
('hotel.pets.name.length.min', '1'),
|
||||
('hotel.pets.name.length.max', '15'),
|
||||
('hotel.daily.respect.pets', '3'),
|
||||
|
||||
-- Command cooldown and spam prevention
|
||||
('pet.command.cooldown_ms', '2000'),
|
||||
('pet.command.max_same_spam', '3'),
|
||||
('pet.command.spam_reset_ms', '10000'),
|
||||
('pet.command.min_energy', '15'),
|
||||
('pet.command.min_happiness', '10'),
|
||||
('pet.command.base_obey_chance', '70'),
|
||||
|
||||
-- Pet behavior settings
|
||||
('pet.behavior.autonomous_action_delay', '5000'),
|
||||
('pet.behavior.idle_wander_min_ms', '10000'),
|
||||
('pet.behavior.idle_wander_max_ms', '30000'),
|
||||
|
||||
-- Pet stats decay/recovery rates (per cycle)
|
||||
('pet.stats.hunger_decay', '1'),
|
||||
('pet.stats.thirst_decay', '1'),
|
||||
('pet.stats.energy_decay', '1'),
|
||||
('pet.stats.happiness_decay', '1'),
|
||||
('pet.stats.energy_recovery', '5'),
|
||||
('pet.stats.happiness_recovery', '1'),
|
||||
|
||||
-- Pet thresholds (below this = needs attention)
|
||||
('pet.threshold.hungry', '50'),
|
||||
('pet.threshold.thirsty', '50'),
|
||||
('pet.threshold.tired', '30'),
|
||||
('pet.threshold.sad', '30'),
|
||||
|
||||
-- Pet breeding
|
||||
('pet.breeding.timeout_seconds', '120')
|
||||
ON DUPLICATE KEY UPDATE `value` = VALUES(`value`);
|
||||
|
||||
-- =====================================================
|
||||
-- SECTION 2: Pet Actions (Pet Type Definitions)
|
||||
-- =====================================================
|
||||
|
||||
DROP TABLE IF EXISTS `pet_actions`;
|
||||
CREATE TABLE `pet_actions` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`pet_type` int(11) NOT NULL,
|
||||
`pet_name` varchar(32) NOT NULL DEFAULT '',
|
||||
`offspring_type` int(11) NOT NULL DEFAULT -1,
|
||||
`happy_actions` varchar(100) NOT NULL DEFAULT 'sml',
|
||||
`tired_actions` varchar(100) NOT NULL DEFAULT 'trd',
|
||||
`random_actions` varchar(100) NOT NULL DEFAULT 'lov',
|
||||
`can_swim` enum('0','1') NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `pet_type` (`pet_type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO `pet_actions` (`pet_type`, `pet_name`, `offspring_type`, `happy_actions`, `tired_actions`, `random_actions`, `can_swim`) VALUES
|
||||
(0, 'Dog', 29, 'sml,wav,joy', 'trd,yng', 'lov,snf', '0'),
|
||||
(1, 'Cat', 28, 'sml,pur', 'trd,yng', 'lov,lck', '0'),
|
||||
(2, 'Crocodile', -1, 'sml', 'trd', 'lov,snp', '1'),
|
||||
(3, 'Terrier', 25, 'sml,wav,joy', 'trd,yng', 'lov,snf', '0'),
|
||||
(4, 'Bear', 24, 'sml,grw', 'trd,yng', 'lov', '0'),
|
||||
(5, 'Pig', 30, 'sml,oink', 'trd,yng', 'lov,rol', '0'),
|
||||
(6, 'Lion', -1, 'sml,ror', 'trd,yng', 'lov', '0'),
|
||||
(7, 'Rhino', -1, 'sml', 'trd,yng', 'lov', '0'),
|
||||
(8, 'Tarantula', -1, 'sml', 'trd', 'lov,crw', '0'),
|
||||
(9, 'Turtle', -1, 'sml', 'trd', 'lov', '1'),
|
||||
(10, 'Chick', -1, 'sml,chp', 'trd', 'lov,pck', '0'),
|
||||
(11, 'Frog', -1, 'sml,crk', 'trd', 'lov,jmp', '1'),
|
||||
(12, 'Dragon', -1, 'sml,flm', 'trd,smk', 'lov,fly', '0'),
|
||||
(13, 'Monster', -1, 'sml', 'trd', 'lov', '0'),
|
||||
(14, 'Monkey', -1, 'sml,ook', 'trd,yng', 'lov,swg', '0'),
|
||||
(15, 'Horse', -1, 'sml,nei', 'trd,yng', 'lov', '0'),
|
||||
(16, 'Monsterplant', -1, 'sml', 'trd', 'lov', '0'),
|
||||
(17, 'Bunny', -1, 'sml,hop', 'trd,yng', 'lov', '0'),
|
||||
(18, 'Evil Bunny', -1, 'sml', 'trd', 'lov', '0'),
|
||||
(19, 'Bored Bunny', -1, 'sml', 'trd', 'lov', '0'),
|
||||
(20, 'Cute Bunny', -1, 'sml,hop', 'trd', 'lov', '0'),
|
||||
(21, 'Wise Pigeon', -1, 'sml,coo', 'trd', 'lov,pck', '0'),
|
||||
(22, 'Evil Pigeon', -1, 'sml', 'trd', 'lov,pck', '0'),
|
||||
(23, 'Evil Monkey', -1, 'sml', 'trd', 'lov,swg', '0'),
|
||||
(24, 'Baby Bear', -1, 'sml', 'trd,yng', 'lov', '0'),
|
||||
(25, 'Baby Terrier', -1, 'sml', 'trd,yng', 'lov', '0'),
|
||||
(26, 'Gnome', -1, 'sml,grn', 'trd', 'lov', '0'),
|
||||
(27, 'Leprechaun', -1, 'sml,grn', 'trd', 'lov,jig', '0'),
|
||||
(28, 'Baby Cat', -1, 'sml', 'trd,yng', 'lov', '0'),
|
||||
(29, 'Baby Dog', -1, 'sml', 'trd,yng', 'lov', '0'),
|
||||
(30, 'Baby Pig', -1, 'sml', 'trd,yng', 'lov', '0'),
|
||||
(31, 'Haloompa', -1, 'sml', 'trd', 'lov', '0'),
|
||||
(32, 'Fools Pet', -1, 'sml', 'trd', 'lov', '0'),
|
||||
(33, 'Pterodactyl', -1, 'sml,sqk', 'trd', 'lov,fly', '0'),
|
||||
(34, 'Velociraptor', -1, 'sml,hss', 'trd', 'lov,clw', '0'),
|
||||
(35, 'Cow', -1, 'sml,moo', 'trd,yng', 'lov,chw', '0');
|
||||
|
||||
-- =====================================================
|
||||
-- SECTION 3: Pet Commands Data (English Command Names)
|
||||
-- =====================================================
|
||||
-- Command IDs mapped to PetManager.petActions:
|
||||
-- 0=Free, 1=Sit, 2=Down, 3=Here, 4=Beg, 5=PlayDead, 6=Stay, 7=Follow
|
||||
-- 8=Stand, 9=Jump, 10=Speak, 11=Play, 12=Silent, 13=Nest, 14=Drink
|
||||
-- 15=FollowLeft, 16=FollowRight, 17=PlayFootball, 18=Teleport, 19=Bounce
|
||||
-- 20=Flatten, 21=Dance, 22=Spin, 23=Switch, 24=MoveForward
|
||||
-- 25=TurnLeft, 26=TurnRight, 27=Relax, 28=Croak, 29=Dip, 30=Wave
|
||||
-- 31=Mambo, 32=HighJump, 33=ChickenDance, 34=TripleJump
|
||||
-- 35=Wings, 36=BreatheFire, 37=Hang, 38=Torch, 40=Swing, 41=Roll
|
||||
-- 42=RingOfFire, 43=Eat, 44=WagTail, 45=Count, 46=Breed
|
||||
|
||||
DROP TABLE IF EXISTS `pet_commands_data`;
|
||||
CREATE TABLE `pet_commands_data` (
|
||||
`command_id` int(11) NOT NULL,
|
||||
`text` varchar(25) NOT NULL,
|
||||
`required_level` int(11) NOT NULL DEFAULT 1,
|
||||
`reward_xp` int(11) NOT NULL DEFAULT 5,
|
||||
`cost_happiness` int(11) NOT NULL DEFAULT 0,
|
||||
`cost_energy` int(11) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`command_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
INSERT INTO `pet_commands_data` (`command_id`, `text`, `required_level`, `reward_xp`, `cost_happiness`, `cost_energy`) VALUES
|
||||
(0, 'free', 1, 5, 0, 0),
|
||||
(1, 'sit', 1, 5, 2, 2),
|
||||
(2, 'down', 2, 10, 3, 3),
|
||||
(3, 'come here', 2, 10, 2, 5),
|
||||
(4, 'beg', 2, 10, 3, 4),
|
||||
(5, 'play dead', 3, 15, 4, 5),
|
||||
(6, 'stay', 4, 10, 2, 3),
|
||||
(7, 'follow', 5, 15, 3, 8),
|
||||
(8, 'stand', 6, 15, 2, 3),
|
||||
(9, 'jump', 6, 15, 4, 8),
|
||||
(10, 'speak', 7, 10, 3, 3),
|
||||
(11, 'play', 8, 5, 5, 10),
|
||||
(12, 'silent', 8, 5, 2, 1),
|
||||
(13, 'nest', 5, 5, 0, 0),
|
||||
(14, 'drink', 1, 5, 0, 0),
|
||||
(15, 'follow left', 15, 15, 4, 10),
|
||||
(16, 'follow right', 15, 15, 4, 10),
|
||||
(17, 'play football', 10, 5, 5, 12),
|
||||
(18, 'teleport', 9, 5, 3, 5),
|
||||
(19, 'bounce', 9, 5, 5, 10),
|
||||
(20, 'flatten', 11, 5, 3, 4),
|
||||
(21, 'dance', 12, 10, 6, 12),
|
||||
(22, 'spin', 10, 5, 4, 8),
|
||||
(23, 'switch', 12, 5, 3, 3),
|
||||
(24, 'move forward', 17, 5, 2, 2),
|
||||
(25, 'turn left', 18, 5, 2, 2),
|
||||
(26, 'turn right', 18, 5, 2, 2),
|
||||
(27, 'relax', 13, 5, 0, 0),
|
||||
(28, 'croak', 14, 5, 3, 3),
|
||||
(29, 'dip', 14, 5, 5, 10),
|
||||
(30, 'wave', 5, 5, 2, 3),
|
||||
(31, 'mambo', 18, 5, 6, 12),
|
||||
(32, 'high jump', 18, 5, 5, 12),
|
||||
(33, 'chicken dance', 7, 5, 5, 10),
|
||||
(34, 'triple jump', 9, 5, 6, 15),
|
||||
(35, 'spread wings', 8, 5, 4, 6),
|
||||
(36, 'breathe fire', 10, 5, 5, 8),
|
||||
(37, 'hang', 12, 5, 4, 6),
|
||||
(38, 'torch', 6, 5, 3, 5),
|
||||
(40, 'swing', 13, 5, 4, 8),
|
||||
(41, 'roll', 10, 5, 5, 10),
|
||||
(42, 'ring of fire', 20, 10, 8, 15),
|
||||
(43, 'eat', 1, 5, 0, 0),
|
||||
(44, 'wag tail', 4, 5, 3, 4),
|
||||
(45, 'count', 6, 5, 4, 5),
|
||||
(46, 'breed', 1, 5, 10, 20);
|
||||
|
||||
-- =====================================================
|
||||
-- SECTION 4: Pet Commands (Pet Type -> Command Mapping)
|
||||
-- =====================================================
|
||||
|
||||
DROP TABLE IF EXISTS `pet_commands`;
|
||||
CREATE TABLE `pet_commands` (
|
||||
`pet_id` int(11) NOT NULL,
|
||||
`command_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`pet_id`, `command_id`),
|
||||
KEY `pet_id` (`pet_id`),
|
||||
KEY `command_id` (`command_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Dog (0) - Full standard pet commands
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9),
|
||||
(0, 10), (0, 11), (0, 12), (0, 13), (0, 14), (0, 15), (0, 16), (0, 17), (0, 24),
|
||||
(0, 25), (0, 26), (0, 43), (0, 44), (0, 46);
|
||||
|
||||
-- Cat (1) - Full standard pet commands + breed
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8), (1, 9),
|
||||
(1, 10), (1, 11), (1, 12), (1, 13), (1, 14), (1, 15), (1, 16), (1, 17), (1, 24),
|
||||
(1, 25), (1, 26), (1, 43), (1, 46);
|
||||
|
||||
-- Crocodile (2) - Standard commands (can swim)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (2, 7), (2, 8), (2, 9),
|
||||
(2, 10), (2, 11), (2, 12), (2, 13), (2, 14), (2, 15), (2, 16), (2, 17), (2, 24),
|
||||
(2, 25), (2, 26), (2, 29), (2, 43);
|
||||
|
||||
-- Terrier (3) - Standard commands + breed
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9),
|
||||
(3, 10), (3, 11), (3, 12), (3, 13), (3, 14), (3, 15), (3, 16), (3, 17), (3, 24),
|
||||
(3, 25), (3, 26), (3, 43), (3, 46);
|
||||
|
||||
-- Bear (4) - Standard commands + breed
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(4, 0), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (4, 7), (4, 8), (4, 9),
|
||||
(4, 10), (4, 11), (4, 12), (4, 13), (4, 14), (4, 15), (4, 16), (4, 17), (4, 24),
|
||||
(4, 25), (4, 26), (4, 43), (4, 46);
|
||||
|
||||
-- Pig (5) - Standard commands + breed
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6), (5, 7), (5, 8), (5, 9),
|
||||
(5, 10), (5, 11), (5, 12), (5, 13), (5, 14), (5, 15), (5, 16), (5, 17), (5, 24),
|
||||
(5, 25), (5, 26), (5, 43), (5, 46);
|
||||
|
||||
-- Lion (6) - Standard commands
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(6, 0), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6), (6, 7), (6, 8), (6, 9),
|
||||
(6, 10), (6, 11), (6, 12), (6, 13), (6, 14), (6, 15), (6, 16), (6, 17), (6, 24),
|
||||
(6, 25), (6, 26), (6, 43);
|
||||
|
||||
-- Rhino (7) - Standard commands
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(7, 0), (7, 1), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (7, 7), (7, 8), (7, 9),
|
||||
(7, 10), (7, 11), (7, 12), (7, 13), (7, 14), (7, 15), (7, 16), (7, 17), (7, 24),
|
||||
(7, 25), (7, 26), (7, 43);
|
||||
|
||||
-- Tarantula (8) - Spider commands (bounce, flatten, spin, etc.)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(8, 0), (8, 2), (8, 3), (8, 5), (8, 6), (8, 7), (8, 9), (8, 10), (8, 11), (8, 13),
|
||||
(8, 14), (8, 15), (8, 16), (8, 17), (8, 19), (8, 20), (8, 21), (8, 22), (8, 23),
|
||||
(8, 24), (8, 25), (8, 26), (8, 43);
|
||||
|
||||
-- Turtle (9) - Aquatic commands
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(9, 0), (9, 1), (9, 2), (9, 3), (9, 6), (9, 7), (9, 8), (9, 10), (9, 11), (9, 13),
|
||||
(9, 14), (9, 15), (9, 16), (9, 24), (9, 25), (9, 26), (9, 29), (9, 41), (9, 43);
|
||||
|
||||
-- Chick (10) - Bird commands
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(10, 0), (10, 2), (10, 3), (10, 6), (10, 7), (10, 11), (10, 13), (10, 15), (10, 16),
|
||||
(10, 17), (10, 33);
|
||||
|
||||
-- Frog (11) - Amphibian commands (croak, dip, wave, mambo)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(11, 0), (11, 1), (11, 2), (11, 3), (11, 4), (11, 5), (11, 6), (11, 7), (11, 9),
|
||||
(11, 13), (11, 14), (11, 15), (11, 16), (11, 17), (11, 27), (11, 28), (11, 29),
|
||||
(11, 30), (11, 31), (11, 43);
|
||||
|
||||
-- Dragon (12) - Dragon special commands (fire, hang, swing, ring of fire)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(12, 0), (12, 2), (12, 3), (12, 5), (12, 6), (12, 7), (12, 8), (12, 9), (12, 10),
|
||||
(12, 11), (12, 12), (12, 13), (12, 14), (12, 15), (12, 16), (12, 22), (12, 35),
|
||||
(12, 36), (12, 37), (12, 38), (12, 40), (12, 41), (12, 42), (12, 43);
|
||||
|
||||
-- Monster (13) - Basic commands
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(13, 0), (13, 2), (13, 3), (13, 6), (13, 7), (13, 13);
|
||||
|
||||
-- Monkey (14) - Monkey commands (wave, hang, swing)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(14, 0), (14, 1), (14, 2), (14, 3), (14, 4), (14, 5), (14, 6), (14, 7), (14, 9),
|
||||
(14, 13), (14, 14), (14, 15), (14, 16), (14, 17), (14, 27), (14, 29), (14, 30),
|
||||
(14, 31), (14, 37), (14, 40), (14, 43);
|
||||
|
||||
-- Horse (15) - Rideable pet commands + wag tail, count
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(15, 0), (15, 2), (15, 3), (15, 6), (15, 7), (15, 10), (15, 11), (15, 12), (15, 13),
|
||||
(15, 14), (15, 15), (15, 16), (15, 24), (15, 25), (15, 26), (15, 43), (15, 44), (15, 45);
|
||||
|
||||
-- Monsterplant (16) - Minimal commands
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(16, 0), (16, 14), (16, 43);
|
||||
|
||||
-- Bunnies (17-20) - Bunny commands
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(17, 0), (17, 2), (17, 3), (17, 6), (17, 7), (17, 11), (17, 13), (17, 15), (17, 16), (17, 17),
|
||||
(18, 0), (18, 2), (18, 3), (18, 6), (18, 7), (18, 11), (18, 13), (18, 15), (18, 16), (18, 17),
|
||||
(19, 0), (19, 2), (19, 3), (19, 6), (19, 7), (19, 11), (19, 13), (19, 15), (19, 16), (19, 17),
|
||||
(20, 0), (20, 2), (20, 3), (20, 6), (20, 7), (20, 11), (20, 13), (20, 15), (20, 16), (20, 17);
|
||||
|
||||
-- Pigeons (21-22)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(21, 0), (21, 2), (21, 3), (21, 6), (21, 7), (21, 11), (21, 13), (21, 15), (21, 16), (21, 17),
|
||||
(22, 0), (22, 2), (22, 3), (22, 6), (22, 7), (22, 11), (22, 13), (22, 15), (22, 16), (22, 17);
|
||||
|
||||
-- Evil Monkey (23) - Monkey commands
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(23, 0), (23, 1), (23, 2), (23, 3), (23, 4), (23, 5), (23, 6), (23, 7), (23, 9),
|
||||
(23, 13), (23, 14), (23, 15), (23, 16), (23, 17), (23, 25), (23, 26), (23, 27),
|
||||
(23, 29), (23, 30), (23, 31), (23, 37), (23, 40), (23, 43);
|
||||
|
||||
-- Baby Bear (24)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(24, 0), (24, 1), (24, 2), (24, 3), (24, 4), (24, 6), (24, 7), (24, 8), (24, 10),
|
||||
(24, 11), (24, 12), (24, 13), (24, 14), (24, 15), (24, 16), (24, 17), (24, 24),
|
||||
(24, 25), (24, 26), (24, 43);
|
||||
|
||||
-- Baby Terrier (25)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(25, 0), (25, 1), (25, 2), (25, 3), (25, 4), (25, 6), (25, 7), (25, 8), (25, 10),
|
||||
(25, 11), (25, 12), (25, 13), (25, 14), (25, 15), (25, 16), (25, 17), (25, 24),
|
||||
(25, 25), (25, 26), (25, 43);
|
||||
|
||||
-- Gnome (26)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(26, 0), (26, 1), (26, 2), (26, 3), (26, 4), (26, 6), (26, 7), (26, 8), (26, 13),
|
||||
(26, 14), (26, 15), (26, 16), (26, 17), (26, 25), (26, 26), (26, 43);
|
||||
|
||||
-- Leprechaun (27)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(27, 0), (27, 1), (27, 2), (27, 3), (27, 4), (27, 6), (27, 7), (27, 8), (27, 13),
|
||||
(27, 14), (27, 15), (27, 16), (27, 17), (27, 25), (27, 26), (27, 43);
|
||||
|
||||
-- Baby Cat (28)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(28, 0), (28, 1), (28, 2), (28, 3), (28, 4), (28, 6), (28, 7), (28, 8), (28, 10),
|
||||
(28, 11), (28, 12), (28, 13), (28, 14), (28, 15), (28, 16), (28, 17), (28, 24),
|
||||
(28, 25), (28, 26), (28, 43);
|
||||
|
||||
-- Baby Dog (29)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(29, 0), (29, 1), (29, 2), (29, 3), (29, 4), (29, 6), (29, 7), (29, 8), (29, 10),
|
||||
(29, 11), (29, 12), (29, 13), (29, 14), (29, 15), (29, 16), (29, 17), (29, 24),
|
||||
(29, 25), (29, 26), (29, 43);
|
||||
|
||||
-- Baby Pig (30)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(30, 0), (30, 1), (30, 2), (30, 3), (30, 4), (30, 6), (30, 7), (30, 8), (30, 10),
|
||||
(30, 11), (30, 12), (30, 13), (30, 14), (30, 15), (30, 16), (30, 17), (30, 24),
|
||||
(30, 25), (30, 26), (30, 43);
|
||||
|
||||
-- Haloompa (31)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(31, 0), (31, 1), (31, 2), (31, 3), (31, 4), (31, 6), (31, 7), (31, 8), (31, 13),
|
||||
(31, 14), (31, 15), (31, 16), (31, 17), (31, 25), (31, 26), (31, 43);
|
||||
|
||||
-- Fools Pet (32) - Full dance/trick set
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(32, 0), (32, 1), (32, 2), (32, 3), (32, 4), (32, 5), (32, 6), (32, 7), (32, 8),
|
||||
(32, 9), (32, 13), (32, 14), (32, 15), (32, 16), (32, 17), (32, 21), (32, 25),
|
||||
(32, 26), (32, 43);
|
||||
|
||||
-- Pterodactyl (33)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(33, 0), (33, 2), (33, 3), (33, 4), (33, 6), (33, 7), (33, 11), (33, 13), (33, 14),
|
||||
(33, 15), (33, 16), (33, 25), (33, 26), (33, 43);
|
||||
|
||||
-- Velociraptor (34)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(34, 0), (34, 1), (34, 2), (34, 3), (34, 6), (34, 7), (34, 8), (34, 10), (34, 12),
|
||||
(34, 13), (34, 14), (34, 15), (34, 16), (34, 17), (34, 21), (34, 26), (34, 43);
|
||||
|
||||
-- Cow (35)
|
||||
INSERT INTO `pet_commands` (`pet_id`, `command_id`) VALUES
|
||||
(35, 0), (35, 2), (35, 3), (35, 4), (35, 6), (35, 7), (35, 13), (35, 14), (35, 15),
|
||||
(35, 16), (35, 17), (35, 25), (35, 26), (35, 30), (35, 43);
|
||||
|
||||
-- =====================================================
|
||||
-- SECTION 5: Pet Vocals (Pet Speech Messages)
|
||||
-- =====================================================
|
||||
-- pet_id = -1 means general vocals for all pets
|
||||
-- pet_id >= 0 means specific to that pet type
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `pet_vocals` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`pet_id` int(11) NOT NULL DEFAULT -1,
|
||||
`type` varchar(20) NOT NULL,
|
||||
`message` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `pet_id` (`pet_id`),
|
||||
KEY `type` (`type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Clear existing vocals
|
||||
DELETE FROM `pet_vocals`;
|
||||
|
||||
-- =====================================================
|
||||
-- GENERAL VOCALS (pet_id = -1, used by all pets)
|
||||
-- =====================================================
|
||||
|
||||
-- GREET_OWNER - When owner enters room
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'GREET_OWNER', '*perks up excitedly*'),
|
||||
(-1, 'GREET_OWNER', 'You''re back!'),
|
||||
(-1, 'GREET_OWNER', '*bounces with joy*'),
|
||||
(-1, 'GREET_OWNER', 'I missed you!'),
|
||||
(-1, 'GREET_OWNER', '*runs in circles happily*'),
|
||||
(-1, 'GREET_OWNER', 'Yay! My favorite person!'),
|
||||
(-1, 'GREET_OWNER', '*jumps up and down*'),
|
||||
(-1, 'GREET_OWNER', 'Finally! You''re here!'),
|
||||
(-1, 'GREET_OWNER', '*tail wagging intensifies*');
|
||||
|
||||
-- LEVEL_UP - When pet gains a level
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'LEVEL_UP', '*jumps with joy!*'),
|
||||
(-1, 'LEVEL_UP', 'I leveled up!'),
|
||||
(-1, 'LEVEL_UP', 'I feel stronger!'),
|
||||
(-1, 'LEVEL_UP', 'Woohoo! New level!'),
|
||||
(-1, 'LEVEL_UP', '*celebrates*'),
|
||||
(-1, 'LEVEL_UP', 'I''m getting better!'),
|
||||
(-1, 'LEVEL_UP', 'Level up! Yeah!');
|
||||
|
||||
-- MUTED - When told to be silent
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'MUTED', '*stays quiet*'),
|
||||
(-1, 'MUTED', '...'),
|
||||
(-1, 'MUTED', '*zips lips*'),
|
||||
(-1, 'MUTED', '*nods silently*');
|
||||
|
||||
-- UNKNOWN_COMMAND - When pet doesn't understand
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'UNKNOWN_COMMAND', '*tilts head confused*'),
|
||||
(-1, 'UNKNOWN_COMMAND', 'Huh?'),
|
||||
(-1, 'UNKNOWN_COMMAND', 'I don''t understand...'),
|
||||
(-1, 'UNKNOWN_COMMAND', '*looks puzzled*'),
|
||||
(-1, 'UNKNOWN_COMMAND', 'What do you mean?'),
|
||||
(-1, 'UNKNOWN_COMMAND', '*scratches head*');
|
||||
|
||||
-- DISOBEY - When pet refuses command
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'DISOBEY', '*ignores command*'),
|
||||
(-1, 'DISOBEY', 'Maybe later...'),
|
||||
(-1, 'DISOBEY', 'I don''t feel like it'),
|
||||
(-1, 'DISOBEY', '*pretends not to hear*'),
|
||||
(-1, 'DISOBEY', 'Nah...'),
|
||||
(-1, 'DISOBEY', '*turns away*'),
|
||||
(-1, 'DISOBEY', 'Not right now'),
|
||||
(-1, 'DISOBEY', '*yawns dismissively*'),
|
||||
(-1, 'DISOBEY', 'Too tired for that'),
|
||||
(-1, 'DISOBEY', 'Ask me again later'),
|
||||
(-1, 'DISOBEY', '*looks the other way*'),
|
||||
(-1, 'DISOBEY', 'I''d rather not'),
|
||||
(-1, 'DISOBEY', '*shakes head*'),
|
||||
(-1, 'DISOBEY', 'No thanks'),
|
||||
(-1, 'DISOBEY', '*walks away slowly*'),
|
||||
(-1, 'DISOBEY', 'Can''t be bothered'),
|
||||
(-1, 'DISOBEY', '*pretends to be asleep*'),
|
||||
(-1, 'DISOBEY', 'You can''t make me!'),
|
||||
(-1, 'DISOBEY', '*stubbornly sits down*'),
|
||||
(-1, 'DISOBEY', 'I refuse!');
|
||||
|
||||
-- DRINKING - When drinking water
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'DRINKING', '*laps up water*'),
|
||||
(-1, 'DRINKING', 'Refreshing!'),
|
||||
(-1, 'DRINKING', '*gulp gulp*'),
|
||||
(-1, 'DRINKING', 'Ah, that''s good!'),
|
||||
(-1, 'DRINKING', '*slurp*');
|
||||
|
||||
-- EATING - When eating food
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'EATING', '*munches happily*'),
|
||||
(-1, 'EATING', 'Yum!'),
|
||||
(-1, 'EATING', 'Delicious!'),
|
||||
(-1, 'EATING', '*nom nom nom*'),
|
||||
(-1, 'EATING', 'This is tasty!'),
|
||||
(-1, 'EATING', '*chomps*'),
|
||||
(-1, 'EATING', 'More please!');
|
||||
|
||||
-- PLAYFUL - When in playful mood
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'PLAYFUL', '*bounces excitedly*'),
|
||||
(-1, 'PLAYFUL', 'Let''s play!'),
|
||||
(-1, 'PLAYFUL', '*runs around happily*'),
|
||||
(-1, 'PLAYFUL', 'Play with me!'),
|
||||
(-1, 'PLAYFUL', '*jumps around*'),
|
||||
(-1, 'PLAYFUL', 'I wanna play!'),
|
||||
(-1, 'PLAYFUL', '*brings a toy*'),
|
||||
(-1, 'PLAYFUL', 'Wheee!'),
|
||||
(-1, 'PLAYFUL', '*zooms around the room*'),
|
||||
(-1, 'PLAYFUL', 'Catch me if you can!');
|
||||
|
||||
-- SLEEPING - When sleeping
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'SLEEPING', '*snores softly*'),
|
||||
(-1, 'SLEEPING', 'Zzz...'),
|
||||
(-1, 'SLEEPING', '*mumbles in sleep*'),
|
||||
(-1, 'SLEEPING', 'ZzZzZz...'),
|
||||
(-1, 'SLEEPING', '*dreams peacefully*'),
|
||||
(-1, 'SLEEPING', '*twitches while dreaming*'),
|
||||
(-1, 'SLEEPING', '*snoozes*'),
|
||||
(-1, 'SLEEPING', '*breathes slowly*');
|
||||
|
||||
-- TIRED - When tired/low energy
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'TIRED', '*yawns*'),
|
||||
(-1, 'TIRED', 'So sleepy...'),
|
||||
(-1, 'TIRED', '*eyes drooping*'),
|
||||
(-1, 'TIRED', 'I need rest...');
|
||||
|
||||
-- THIRSTY - When thirsty
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'THIRSTY', '*pants*'),
|
||||
(-1, 'THIRSTY', 'Water please!'),
|
||||
(-1, 'THIRSTY', '*looks at water bowl*'),
|
||||
(-1, 'THIRSTY', 'So thirsty...'),
|
||||
(-1, 'THIRSTY', '*dry tongue*'),
|
||||
(-1, 'THIRSTY', 'Need a drink!'),
|
||||
(-1, 'THIRSTY', '*licks lips*'),
|
||||
(-1, 'THIRSTY', 'I''m parched!');
|
||||
|
||||
-- HUNGRY - When hungry
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'HUNGRY', '*stomach growls*'),
|
||||
(-1, 'HUNGRY', 'I need food!'),
|
||||
(-1, 'HUNGRY', '*looks at food bowl*'),
|
||||
(-1, 'HUNGRY', 'Feed me!'),
|
||||
(-1, 'HUNGRY', 'So hungry...'),
|
||||
(-1, 'HUNGRY', '*tummy rumbles*'),
|
||||
(-1, 'HUNGRY', 'Food please!'),
|
||||
(-1, 'HUNGRY', '*drools at thought of food*'),
|
||||
(-1, 'HUNGRY', 'Is it dinner time?'),
|
||||
(-1, 'HUNGRY', '*sniffs around for food*'),
|
||||
(-1, 'HUNGRY', 'I could eat a horse!'),
|
||||
(-1, 'HUNGRY', '*begs for food*'),
|
||||
(-1, 'HUNGRY', 'Starving over here!');
|
||||
|
||||
-- GENERIC_NEUTRAL - Random idle chat
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'GENERIC_NEUTRAL', '*looks around*'),
|
||||
(-1, 'GENERIC_NEUTRAL', '*sniffs the air*'),
|
||||
(-1, 'GENERIC_NEUTRAL', '*stretches*'),
|
||||
(-1, 'GENERIC_NEUTRAL', '*scratches ear*'),
|
||||
(-1, 'GENERIC_NEUTRAL', '*observes surroundings*'),
|
||||
(-1, 'GENERIC_NEUTRAL', '*sits quietly*'),
|
||||
(-1, 'GENERIC_NEUTRAL', '*watches curiously*');
|
||||
|
||||
-- GENERIC_SAD - When sad/low happiness
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'GENERIC_SAD', '*whimpers*'),
|
||||
(-1, 'GENERIC_SAD', '*looks sad*'),
|
||||
(-1, 'GENERIC_SAD', '*sighs*'),
|
||||
(-1, 'GENERIC_SAD', '*droops head*'),
|
||||
(-1, 'GENERIC_SAD', 'I''m lonely...'),
|
||||
(-1, 'GENERIC_SAD', '*mopes around*'),
|
||||
(-1, 'GENERIC_SAD', '*looks dejected*'),
|
||||
(-1, 'GENERIC_SAD', 'Nobody loves me...'),
|
||||
(-1, 'GENERIC_SAD', '*sulks in corner*');
|
||||
|
||||
-- GENERIC_HAPPY - When happy
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(-1, 'GENERIC_HAPPY', '*wags tail happily*'),
|
||||
(-1, 'GENERIC_HAPPY', '*jumps with joy*'),
|
||||
(-1, 'GENERIC_HAPPY', ':)'),
|
||||
(-1, 'GENERIC_HAPPY', 'Life is good!'),
|
||||
(-1, 'GENERIC_HAPPY', '*prances around*'),
|
||||
(-1, 'GENERIC_HAPPY', '*does a happy dance*'),
|
||||
(-1, 'GENERIC_HAPPY', 'I''m so happy!'),
|
||||
(-1, 'GENERIC_HAPPY', '*beams with joy*'),
|
||||
(-1, 'GENERIC_HAPPY', 'What a great day!'),
|
||||
(-1, 'GENERIC_HAPPY', '*grins*'),
|
||||
(-1, 'GENERIC_HAPPY', '*radiates happiness*'),
|
||||
(-1, 'GENERIC_HAPPY', 'Yippee!'),
|
||||
(-1, 'GENERIC_HAPPY', '*spins around happily*'),
|
||||
(-1, 'GENERIC_HAPPY', 'This is the best!');
|
||||
|
||||
-- =====================================================
|
||||
-- PET-SPECIFIC VOCALS
|
||||
-- =====================================================
|
||||
|
||||
-- Dog (0) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(0, 'GENERIC_HAPPY', 'Woof woof!'),
|
||||
(0, 'GENERIC_HAPPY', '*wags tail furiously*'),
|
||||
(0, 'GREET_OWNER', '*barks excitedly*'),
|
||||
(0, 'GREET_OWNER', 'Woof! You''re home!'),
|
||||
(0, 'PLAYFUL', '*drops ball at your feet*'),
|
||||
(0, 'PLAYFUL', 'Throw the ball!'),
|
||||
(0, 'HUNGRY', '*stares at food bowl*'),
|
||||
(0, 'DISOBEY', '*chases own tail instead*');
|
||||
|
||||
-- Cat (1) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(1, 'GENERIC_HAPPY', '*purrs*'),
|
||||
(1, 'GENERIC_HAPPY', 'Meow!'),
|
||||
(1, 'GENERIC_NEUTRAL', '*grooms self*'),
|
||||
(1, 'GREET_OWNER', '*rubs against leg*'),
|
||||
(1, 'DISOBEY', '*looks away disdainfully*'),
|
||||
(1, 'DISOBEY', '*yawns dismissively*'),
|
||||
(1, 'PLAYFUL', '*pounces on shadow*'),
|
||||
(1, 'SLEEPING', '*purrs while sleeping*');
|
||||
|
||||
-- Dragon (12) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(12, 'GENERIC_HAPPY', '*breathes small flames happily*'),
|
||||
(12, 'GENERIC_HAPPY', '*roars softly*'),
|
||||
(12, 'GENERIC_SAD', '*smoke puffs from nostrils*'),
|
||||
(12, 'DISOBEY', '*snorts flames*'),
|
||||
(12, 'DISOBEY', 'I am a DRAGON, not a servant!'),
|
||||
(12, 'HUNGRY', '*eyes the nearest villager*'),
|
||||
(12, 'HUNGRY', 'I require sustenance!'),
|
||||
(12, 'THIRSTY', '*smoke rises as throat dries*'),
|
||||
(12, 'PLAYFUL', '*chases own tail, breathing fire*'),
|
||||
(12, 'GREET_OWNER', '*bows majestic head*'),
|
||||
(12, 'SLEEPING', '*snores, causing small fires*'),
|
||||
(12, 'LEVEL_UP', '*ROARS triumphantly!*');
|
||||
|
||||
-- Horse (15) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(15, 'GENERIC_HAPPY', '*neighs happily*'),
|
||||
(15, 'GENERIC_NEUTRAL', '*swishes tail*'),
|
||||
(15, 'GREET_OWNER', '*whinnies in greeting*'),
|
||||
(15, 'DISOBEY', 'Nay. (Geddit?)'),
|
||||
(15, 'HUNGRY', '*looks at hay expectantly*'),
|
||||
(15, 'PLAYFUL', 'Let''s go for a ride!'),
|
||||
(15, 'TIRED', '*stamps hoof wearily*');
|
||||
|
||||
-- Tarantula (8) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(8, 'GREET_OWNER', 'You look more edible every time!'),
|
||||
(8, 'DISOBEY', '*hisses*'),
|
||||
(8, 'DISOBEY', 'I do not obey mammals'),
|
||||
(8, 'HUNGRY', 'Bring me fresh meat!'),
|
||||
(8, 'PLAYFUL', '*dances on eight legs*'),
|
||||
(8, 'GENERIC_HAPPY', '*clicks mandibles happily*');
|
||||
|
||||
-- Frog (11) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(11, 'GENERIC_HAPPY', 'Ribbit!'),
|
||||
(11, 'GENERIC_NEUTRAL', '*croaks*'),
|
||||
(11, 'GREET_OWNER', '*hops excitedly*'),
|
||||
(11, 'PLAYFUL', '*catches fly with tongue*'),
|
||||
(11, 'THIRSTY', '*seeks water*');
|
||||
|
||||
-- Cow (35) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(35, 'GENERIC_HAPPY', 'Moooo!'),
|
||||
(35, 'GREET_OWNER', 'Greetings. Did you bring kale?'),
|
||||
(35, 'EATING', '*chews grass thoughtfully*'),
|
||||
(35, 'DISOBEY', 'I''d rather meditate'),
|
||||
(35, 'LEVEL_UP', '*DING* I''m on the up!');
|
||||
|
||||
-- Lion (6) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(6, 'GENERIC_HAPPY', '*roars majestically*'),
|
||||
(6, 'GREET_OWNER', '*nods regally*'),
|
||||
(6, 'DISOBEY', 'I am the king!'),
|
||||
(6, 'HUNGRY', '*eyes prey*'),
|
||||
(6, 'PLAYFUL', '*pounces playfully*');
|
||||
|
||||
-- Bear (4) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(4, 'GENERIC_HAPPY', '*growls contentedly*'),
|
||||
(4, 'HUNGRY', '*sniffs for honey*'),
|
||||
(4, 'SLEEPING', '*hibernates*'),
|
||||
(4, 'GREET_OWNER', '*bear hug incoming*');
|
||||
|
||||
-- Monkey (14) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(14, 'GENERIC_HAPPY', 'Ook ook!'),
|
||||
(14, 'PLAYFUL', '*swings from furniture*'),
|
||||
(14, 'GREET_OWNER', '*does a backflip*'),
|
||||
(14, 'DISOBEY', '*throws something*'),
|
||||
(14, 'HUNGRY', '*looks for bananas*');
|
||||
|
||||
-- Bunny (17) specific vocals
|
||||
INSERT INTO `pet_vocals` (`pet_id`, `type`, `message`) VALUES
|
||||
(17, 'GENERIC_HAPPY', '*hops happily*'),
|
||||
(17, 'GREET_OWNER', '*twitches nose excitedly*'),
|
||||
(17, 'PLAYFUL', '*binkies around*'),
|
||||
(17, 'HUNGRY', '*nibbles on carrot*');
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.eu.habbo</groupId>
|
||||
<artifactId>Habbo</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<version>4.0.2</version>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
@@ -3,7 +3,10 @@ package com.eu.habbo.habbohotel.items;
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.interactions.*;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.InteractionGameTimer;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.*;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiPuck;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiSphere;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiTeleporter;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.InteractionBattleBanzaiTile;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.gates.InteractionBattleBanzaiGateBlue;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.gates.InteractionBattleBanzaiGateGreen;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.gates.InteractionBattleBanzaiGateRed;
|
||||
@@ -48,10 +51,10 @@ import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredBlob;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraOrEval;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraRandom;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredExtraUnseen;
|
||||
import com.eu.habbo.habbohotel.wired.highscores.WiredHighscoreManager;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.triggers.*;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.highscores.WiredHighscoreManager;
|
||||
import com.eu.habbo.messages.outgoing.inventory.AddHabboItemComposer;
|
||||
import com.eu.habbo.plugin.events.emulator.EmulatorLoadItemsManagerEvent;
|
||||
import com.eu.habbo.threading.runnables.QueryDeleteHabboItem;
|
||||
@@ -134,6 +137,8 @@ public class ItemManager {
|
||||
this.interactionsList.add(new ItemInteraction("pet_drink", InteractionPetDrink.class));
|
||||
this.interactionsList.add(new ItemInteraction("pet_food", InteractionPetFood.class));
|
||||
this.interactionsList.add(new ItemInteraction("pet_toy", InteractionPetToy.class));
|
||||
this.interactionsList.add(new ItemInteraction("pet_tree", InteractionPetTree.class));
|
||||
this.interactionsList.add(new ItemInteraction("pet_trampoline", InteractionPetTrampoline.class));
|
||||
this.interactionsList.add(new ItemInteraction("breeding_nest", InteractionPetBreedingNest.class));
|
||||
this.interactionsList.add(new ItemInteraction("obstacle", InteractionObstacle.class));
|
||||
this.interactionsList.add(new ItemInteraction("monsterplant_seed", InteractionMonsterPlantSeed.class));
|
||||
|
||||
+3
-3
@@ -121,9 +121,9 @@ public class InteractionPetBreedingNest extends HabboItem {
|
||||
if (this.petOne != null) {
|
||||
habbo.getClient().sendResponse(new PetPackageNameValidationComposer(this.getId(), PetPackageNameValidationComposer.CLOSE_WIDGET, ""));
|
||||
}
|
||||
if (this.petTwo.getUserId() != habbo.getHabboInfo().getId()) {
|
||||
Habbo owner = this.petTwo.getRoom().getHabbo(this.petTwo.getUserId());
|
||||
if (owner != null) {
|
||||
if (this.petTwo != null && this.petTwo.getUserId() != habbo.getHabboInfo().getId()) {
|
||||
Habbo owner = this.petTwo.getRoom() != null ? this.petTwo.getRoom().getHabbo(this.petTwo.getUserId()) : null;
|
||||
if (owner != null && owner.getClient() != null) {
|
||||
owner.getClient().sendResponse(new PetPackageNameValidationComposer(this.getId(), PetPackageNameValidationComposer.CLOSE_WIDGET, ""));
|
||||
}
|
||||
}
|
||||
|
||||
+105
-24
@@ -2,22 +2,27 @@ package com.eu.habbo.habbohotel.items.interactions.pets;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.achievements.AchievementManager;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionDefault;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.pets.RideablePet;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUserRotation;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer;
|
||||
import com.eu.habbo.habbohotel.rooms.*;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
import com.eu.habbo.threading.runnables.RoomUnitWalkToLocation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class InteractionPetDrink extends InteractionDefault {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(InteractionPetDrink.class);
|
||||
|
||||
public InteractionPetDrink(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
}
|
||||
@@ -26,32 +31,81 @@ public class InteractionPetDrink extends InteractionDefault {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canToggle(Habbo habbo, Room room) {
|
||||
return RoomLayout.tilesAdjecent(room.getLayout().getTile(this.getX(), this.getY()), habbo.getRoomUnit().getCurrentLocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(GameClient client, Room room, Object[] objects) throws Exception {
|
||||
if (client == null)
|
||||
return;
|
||||
|
||||
if (!this.canToggle(client.getHabbo(), room)) {
|
||||
RoomTile closestTile = null;
|
||||
for (RoomTile tile : room.getLayout().getTilesAround(room.getLayout().getTile(this.getX(), this.getY()))) {
|
||||
if (tile.isWalkable() && (closestTile == null || closestTile.distance(client.getHabbo().getRoomUnit().getCurrentLocation()) > tile.distance(client.getHabbo().getRoomUnit().getCurrentLocation()))) {
|
||||
closestTile = tile;
|
||||
}
|
||||
}
|
||||
|
||||
if (closestTile != null && !closestTile.equals(client.getHabbo().getRoomUnit().getCurrentLocation())) {
|
||||
List<Runnable> onSuccess = new ArrayList<>();
|
||||
onSuccess.add(() -> {
|
||||
this.change(room, this.getBaseItem().getStateCount() - 1);
|
||||
});
|
||||
|
||||
client.getHabbo().getRoomUnit().setGoalLocation(closestTile);
|
||||
Emulator.getThreading().run(new RoomUnitWalkToLocation(client.getHabbo().getRoomUnit(), closestTile, room, onSuccess, new ArrayList<>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
|
||||
super.onWalkOn(roomUnit, room, objects);
|
||||
|
||||
if (this.getExtradata() == null || this.getExtradata().isEmpty())
|
||||
this.setExtradata("0");
|
||||
|
||||
// Check if there's water left (state 0 = full, higher = less water)
|
||||
int currentState = 0;
|
||||
try {
|
||||
currentState = Integer.parseInt(this.getExtradata());
|
||||
} catch (NumberFormatException e) {
|
||||
currentState = 0;
|
||||
}
|
||||
|
||||
// If water bowl is empty (state >= max states), don't allow drinking
|
||||
if (currentState >= this.getBaseItem().getStateCount() - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
|
||||
if (pet != null) {
|
||||
// Don't let ridden pets drink
|
||||
if (pet instanceof RideablePet && ((RideablePet) pet).getRider() != null)
|
||||
return;
|
||||
if (pet != null && !(pet instanceof RideablePet && ((RideablePet) pet).getRider() != null)
|
||||
&& pet.getPetData().haveDrinkItem(this) && pet.levelThirst >= 35) {
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setGoalLocation(room.getLayout().getTile(this.getX(), this.getY()));
|
||||
pet.getRoomUnit().setRotation(RoomUserRotation.values()[this.getRotation()]);
|
||||
pet.getRoomUnit().clearStatus();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.EAT, pet.getRoomUnit().getCurrentLocation().getStackHeight() + "");
|
||||
pet.packetUpdate = true;
|
||||
|
||||
// Say drinking vocal
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DRINKING));
|
||||
|
||||
if (pet.getPetData().haveDrinkItem(this)) {
|
||||
if (pet.levelThirst >= 35) {
|
||||
pet.setTask(PetTasks.EAT);
|
||||
pet.getRoomUnit().setGoalLocation(room.getLayout().getTile(this.getX(), this.getY()));
|
||||
pet.getRoomUnit().setRotation(RoomUserRotation.values()[this.getRotation()]);
|
||||
pet.getRoomUnit().clearStatus();
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.MOVE);
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.EAT, "0");
|
||||
pet.addThirst(-75);
|
||||
room.sendComposer(new RoomUserStatusComposer(roomUnit).compose());
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.EAT, null, true), 500);
|
||||
// Faster drinking - 500ms instead of 1000ms
|
||||
Emulator.getThreading().run(() -> {
|
||||
pet.addThirst(-75);
|
||||
// Increase state to show less water (+1, not -1)
|
||||
this.change(room, 1);
|
||||
pet.getRoomUnit().clearStatus();
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.EAT, null, true), 0);
|
||||
pet.packetUpdate = true;
|
||||
}, 500);
|
||||
|
||||
AchievementManager.progressAchievement(Emulator.getGameEnvironment().getHabboManager().getHabbo(pet.getUserId()), Emulator.getGameEnvironment().getAchievementManager().getAchievement("PetFeeding"), 75);
|
||||
}
|
||||
}
|
||||
AchievementManager.progressAchievement(Emulator.getGameEnvironment().getHabboManager().getHabbo(pet.getUserId()), Emulator.getGameEnvironment().getAchievementManager().getAchievement("PetFeeding"), 75);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,4 +113,31 @@ public class InteractionPetDrink extends InteractionDefault {
|
||||
public boolean allowWiredResetState() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void change(Room room, int amount) {
|
||||
int state = 0;
|
||||
|
||||
if (this.getExtradata() == null || this.getExtradata().isEmpty()) {
|
||||
this.setExtradata("0");
|
||||
}
|
||||
|
||||
try {
|
||||
state = Integer.parseInt(this.getExtradata());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Caught exception", e);
|
||||
}
|
||||
|
||||
state += amount;
|
||||
if (state > this.getBaseItem().getStateCount() - 1) {
|
||||
state = this.getBaseItem().getStateCount() - 1;
|
||||
}
|
||||
|
||||
if (state < 0) {
|
||||
state = 0;
|
||||
}
|
||||
|
||||
this.setExtradata(state + "");
|
||||
this.needsUpdate(true);
|
||||
room.updateItemState(this);
|
||||
}
|
||||
}
|
||||
|
||||
+13
@@ -32,6 +32,19 @@ public class InteractionPetFood extends InteractionDefault {
|
||||
if (this.getExtradata().length() == 0)
|
||||
this.setExtradata("0");
|
||||
|
||||
// Check if there's food left (state < stateCount means food remaining)
|
||||
int currentState = 0;
|
||||
try {
|
||||
currentState = Integer.parseInt(this.getExtradata());
|
||||
} catch (NumberFormatException e) {
|
||||
currentState = 0;
|
||||
}
|
||||
|
||||
// If food is empty (state >= max states), don't allow eating
|
||||
if (currentState >= this.getBaseItem().getStateCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
|
||||
if (pet != null) {
|
||||
|
||||
+48
-13
@@ -1,15 +1,13 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.pets;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionDefault;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.RideablePet;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnit;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUserRotation;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.*;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
@@ -27,17 +25,41 @@ public class InteractionPetToy extends InteractionDefault {
|
||||
this.setExtradata("0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(GameClient client, Room room, Object[] objects) {
|
||||
// Toys are not clickable by users
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) {
|
||||
this.setExtradata("0");
|
||||
room.updateItem(this);
|
||||
|
||||
for (Pet pet : room.getPetsAt(oldLocation)) {
|
||||
pet.getRoomUnit().clearStatus();
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp(Room room) {
|
||||
this.setExtradata("0");
|
||||
|
||||
for (RoomTile tile : this.getOccupyingTiles(room.getLayout())) {
|
||||
for (Pet pet : room.getPetsAt(tile)) {
|
||||
pet.getRoomUnit().clearStatus();
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
|
||||
super.onWalkOn(roomUnit, room, objects);
|
||||
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
|
||||
if (pet != null) {
|
||||
// Don't let ridden pets play with toys
|
||||
if (pet instanceof RideablePet && ((RideablePet) pet).getRider() != null)
|
||||
return;
|
||||
|
||||
if (pet != null && pet.getPetData().haveToyItem(this.getBaseItem())) {
|
||||
if (pet.getEnergy() <= 35) {
|
||||
return;
|
||||
}
|
||||
@@ -46,15 +68,20 @@ public class InteractionPetToy extends InteractionDefault {
|
||||
pet.getRoomUnit().setGoalLocation(room.getLayout().getTile(this.getX(), this.getY()));
|
||||
pet.getRoomUnit().setRotation(RoomUserRotation.values()[this.getRotation()]);
|
||||
pet.getRoomUnit().clearStatus();
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.MOVE);
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.PLAY, "0");
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.PLAY, pet.getRoomUnit().getCurrentLocation().getStackHeight() + "");
|
||||
pet.packetUpdate = true;
|
||||
|
||||
// Say playful vocal
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
|
||||
HabboItem item = this;
|
||||
Emulator.getThreading().run(() -> {
|
||||
pet.addHappiness(25);
|
||||
item.setExtradata("0");
|
||||
room.updateItem(item);
|
||||
pet.getRoomUnit().clearStatus();
|
||||
new PetClearPosture(pet, RoomUnitStatus.PLAY, null, true).run();
|
||||
pet.packetUpdate = true;
|
||||
}, 2500 + (Emulator.getRandom().nextInt(20) * 500));
|
||||
this.setExtradata("1");
|
||||
room.updateItemState(this);
|
||||
@@ -69,10 +96,18 @@ public class InteractionPetToy extends InteractionDefault {
|
||||
|
||||
if (pet != null) {
|
||||
this.setExtradata("0");
|
||||
room.updateItemState(this);
|
||||
room.updateItem(this);
|
||||
pet.getRoomUnit().clearStatus();
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWalkOn(RoomUnit roomUnit, Room room, Object[] objects) {
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
return roomUnit.getRoomUnitType() == RoomUnitType.PET && pet != null && pet.getPetData().haveToyItem(this.getBaseItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowWiredResetState() {
|
||||
return false;
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.pets;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionDefault;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.rooms.*;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class InteractionPetTrampoline extends InteractionDefault {
|
||||
public InteractionPetTrampoline(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.setExtradata("0");
|
||||
}
|
||||
|
||||
public InteractionPetTrampoline(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.setExtradata("0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(GameClient client, Room room, Object[] objects) {
|
||||
// Trampolines are not clickable by users
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) {
|
||||
this.setExtradata("0");
|
||||
room.updateItem(this);
|
||||
|
||||
for (Pet pet : room.getPetsAt(oldLocation)) {
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.JUMP);
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp(Room room) {
|
||||
this.setExtradata("0");
|
||||
|
||||
for (Pet pet : room.getPetsAt(room.getLayout().getTile(this.getX(), this.getY()))) {
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.JUMP);
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
|
||||
super.onWalkOn(roomUnit, room, objects);
|
||||
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
|
||||
if (pet != null && pet.getPetData().haveToyItem(this.getBaseItem()) && this.getOccupyingTiles(room.getLayout()).contains(pet.getRoomUnit().getGoal())) {
|
||||
if (pet.getEnergy() <= 35) {
|
||||
return;
|
||||
}
|
||||
|
||||
pet.clearPosture();
|
||||
pet.setTask(PetTasks.JUMP);
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.JUMP, "");
|
||||
pet.packetUpdate = true;
|
||||
|
||||
Emulator.getThreading().run(() -> {
|
||||
new PetClearPosture(pet, RoomUnitStatus.JUMP, null, false);
|
||||
pet.getRoomUnit().setGoalLocation(room.getRandomWalkableTile());
|
||||
this.setExtradata("0");
|
||||
room.updateItemState(this);
|
||||
}, 4000);
|
||||
|
||||
pet.addHappiness(25);
|
||||
|
||||
this.setExtradata("1");
|
||||
room.updateItemState(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
|
||||
super.onWalkOff(roomUnit, room, objects);
|
||||
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
|
||||
if (pet != null) {
|
||||
this.setExtradata("0");
|
||||
room.updateItem(this);
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.JUMP);
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWalkOn(RoomUnit roomUnit, Room room, Object[] objects) {
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
return roomUnit.getRoomUnitType() == RoomUnitType.PET && pet != null && pet.getPetData().haveToyItem(this.getBaseItem());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowWiredResetState() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package com.eu.habbo.habbohotel.items.interactions.pets;
|
||||
|
||||
import com.eu.habbo.habbohotel.gameclients.GameClient;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionDefault;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.*;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Interaction for pet trees (dragon tree, monkey tree, etc.)
|
||||
* Pets can hang from these and perform special actions like Ring of Fire.
|
||||
*/
|
||||
public class InteractionPetTree extends InteractionDefault {
|
||||
public InteractionPetTree(ResultSet set, Item baseItem) throws SQLException {
|
||||
super(set, baseItem);
|
||||
this.setExtradata("0");
|
||||
}
|
||||
|
||||
public InteractionPetTree(int id, int userId, Item item, String extradata, int limitedStack, int limitedSells) {
|
||||
super(id, userId, item, extradata, limitedStack, limitedSells);
|
||||
this.setExtradata("0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(GameClient client, Room room, Object[] objects) {
|
||||
// Trees are not clickable by users
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMove(Room room, RoomTile oldLocation, RoomTile newLocation) {
|
||||
this.setExtradata("0");
|
||||
room.updateItem(this);
|
||||
|
||||
for (Pet pet : room.getPetsAt(oldLocation)) {
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.HANG);
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.SWING);
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.FLAME);
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickUp(Room room) {
|
||||
this.setExtradata("0");
|
||||
|
||||
for (Pet pet : room.getPetsAt(room.getLayout().getTile(this.getX(), this.getY()))) {
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.HANG);
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.SWING);
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.FLAME);
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalkOn(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
|
||||
super.onWalkOn(roomUnit, room, objects);
|
||||
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
|
||||
// Only dragons (type 12) can use the tree
|
||||
if (pet != null && pet.getPetData().getType() == 12 && this.getOccupyingTiles(room.getLayout()).contains(pet.getRoomUnit().getGoal())) {
|
||||
if (pet.getEnergy() <= 35) {
|
||||
return;
|
||||
}
|
||||
|
||||
RoomUnitStatus task = RoomUnitStatus.HANG;
|
||||
switch (pet.getTask()) {
|
||||
case RING_OF_FIRE:
|
||||
task = RoomUnitStatus.RINGOFFIRE;
|
||||
break;
|
||||
case SWING:
|
||||
task = RoomUnitStatus.SWING;
|
||||
break;
|
||||
default:
|
||||
// Default to HANG for all other tasks
|
||||
break;
|
||||
}
|
||||
|
||||
// Pet arrived at tree - set hang status
|
||||
pet.setTask(PetTasks.FREE);
|
||||
pet.getRoomUnit().setGoalLocation(room.getLayout().getTile(this.getX(), this.getY()));
|
||||
pet.getRoomUnit().setRotation(RoomUserRotation.values()[this.getRotation()]);
|
||||
pet.getRoomUnit().clearStatus();
|
||||
pet.getRoomUnit().setStatus(task, "");
|
||||
pet.packetUpdate = true;
|
||||
|
||||
// Say playful vocal
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
|
||||
this.setExtradata("1");
|
||||
room.updateItemState(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWalkOff(RoomUnit roomUnit, Room room, Object[] objects) throws Exception {
|
||||
super.onWalkOff(roomUnit, room, objects);
|
||||
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
|
||||
if (pet != null) {
|
||||
this.setExtradata("0");
|
||||
room.updateItem(this);
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.HANG);
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.SWING);
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.FLAME);
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWalkOn(RoomUnit roomUnit, Room room, Object[] objects) {
|
||||
Pet pet = room.getPet(roomUnit);
|
||||
return roomUnit.getRoomUnitType() == RoomUnitType.PET && pet != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowWiredResetState() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,9 @@ package com.eu.habbo.habbohotel.pets;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.achievements.AchievementManager;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetToy;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetTree;
|
||||
import com.eu.habbo.habbohotel.rooms.*;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
@@ -14,6 +17,7 @@ import com.eu.habbo.messages.outgoing.rooms.users.RoomUserRemoveComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserTalkComposer;
|
||||
import com.eu.habbo.plugin.events.pets.PetTalkEvent;
|
||||
import gnu.trove.map.hash.THashMap;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -52,6 +56,16 @@ public class Pet implements ISerialize, Runnable {
|
||||
private int stayStartedAt = 0;
|
||||
private int idleCommandTicks = 0;
|
||||
private int freeCommandTicks = -1;
|
||||
|
||||
// Command cooldown tracking to prevent spam
|
||||
private int lastCommandId = -1;
|
||||
private long lastCommandTime = 0;
|
||||
private int sameCommandCount = 0;
|
||||
|
||||
// New managers for improved pet behavior
|
||||
private PetStatsManager statsManager;
|
||||
private PetBehaviorManager behaviorManager;
|
||||
|
||||
|
||||
private PetTasks task = PetTasks.FREE;
|
||||
|
||||
@@ -78,6 +92,10 @@ public class Pet implements ISerialize, Runnable {
|
||||
this.levelThirst = set.getInt("thirst");
|
||||
this.levelHunger = set.getInt("hunger");
|
||||
this.level = PetManager.getLevel(this.experience);
|
||||
|
||||
// Initialize managers
|
||||
this.statsManager = new PetStatsManager(this);
|
||||
this.behaviorManager = new PetBehaviorManager(this);
|
||||
}
|
||||
|
||||
public Pet(int type, int race, String color, String name, int userId) {
|
||||
@@ -101,6 +119,10 @@ public class Pet implements ISerialize, Runnable {
|
||||
this.levelHunger = 0;
|
||||
this.created = Emulator.getIntUnixTimestamp();
|
||||
this.level = 1;
|
||||
|
||||
// Initialize managers
|
||||
this.statsManager = new PetStatsManager(this);
|
||||
this.behaviorManager = new PetBehaviorManager(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -216,10 +238,15 @@ public class Pet implements ISerialize, Runnable {
|
||||
}
|
||||
|
||||
public void cycle() {
|
||||
// Guard clause for null room or roomUnit
|
||||
if (this.room == null || this.roomUnit == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.idleCommandTicks++;
|
||||
|
||||
int time = Emulator.getIntUnixTimestamp();
|
||||
if (this.roomUnit != null && this.task != PetTasks.RIDE) {
|
||||
if (this.task != PetTasks.RIDE) {
|
||||
if (time - this.gestureTickTimeout > 5 && this.roomUnit.hasStatus(RoomUnitStatus.GESTURE)) {
|
||||
this.roomUnit.removeStatus(RoomUnitStatus.GESTURE);
|
||||
this.packetUpdate = true;
|
||||
@@ -254,17 +281,28 @@ public class Pet implements ISerialize, Runnable {
|
||||
if (this.levelThirst > 0)
|
||||
this.levelThirst--;
|
||||
|
||||
this.addEnergy(5);
|
||||
// Check if we're about to reach max energy before adding
|
||||
int maxEnergy = PetManager.maxEnergy(this.level);
|
||||
boolean wasResting = this.energy < maxEnergy;
|
||||
|
||||
// Nest gives faster regeneration than resting on floor
|
||||
int energyGain = (this.task == PetTasks.NEST) ? 5 : 2;
|
||||
this.addEnergy(energyGain);
|
||||
|
||||
this.addHappiness(1);
|
||||
|
||||
if (this.energy == PetManager.maxEnergy(this.level)) {
|
||||
// Wake up when fully rested
|
||||
if (wasResting && this.energy >= maxEnergy) {
|
||||
this.roomUnit.removeStatus(RoomUnitStatus.LAY);
|
||||
this.roomUnit.setCanWalk(true);
|
||||
this.roomUnit.setGoalLocation(this.room.getRandomWalkableTile());
|
||||
RoomTile tile = this.room.getRandomWalkableTile();
|
||||
if (tile != null) {
|
||||
this.roomUnit.setGoalLocation(tile);
|
||||
}
|
||||
this.task = null;
|
||||
this.roomUnit.setStatus(RoomUnitStatus.GESTURE, PetGestures.ENERGY.getKey());
|
||||
this.gestureTickTimeout = time;
|
||||
this.say(this.petData.randomVocal(PetVocalsType.GENERIC_HAPPY));
|
||||
}
|
||||
} else if (this.tickTimeout >= 5) {
|
||||
if (this.levelHunger < 100)
|
||||
@@ -319,6 +357,13 @@ public class Pet implements ISerialize, Runnable {
|
||||
this.say(this.petData.randomVocal(PetVocalsType.GENERIC_HAPPY));
|
||||
} else if (this.happiness < 15) {
|
||||
this.say(this.petData.randomVocal(PetVocalsType.GENERIC_SAD));
|
||||
// When bored and has energy, try to find a toy to play with
|
||||
if (this.energy > 40 && this.task == null) {
|
||||
this.findToy();
|
||||
}
|
||||
} else if (this.happiness < 40 && this.energy > 50 && this.task == null && Emulator.getRandom().nextInt(100) < 30) {
|
||||
// 30% chance to seek toy when moderately bored
|
||||
this.findToy();
|
||||
} else if (this.levelHunger > 50) {
|
||||
this.say(this.petData.randomVocal(PetVocalsType.HUNGRY));
|
||||
this.eat();
|
||||
@@ -363,10 +408,13 @@ public class Pet implements ISerialize, Runnable {
|
||||
case PLAY_FOOTBALL:
|
||||
case PLAY_DEAD:
|
||||
case FOLLOW:
|
||||
case FOLLOW_LEFT:
|
||||
case FOLLOW_RIGHT:
|
||||
case JUMP:
|
||||
case STAND:
|
||||
case NEST:
|
||||
case RIDE:
|
||||
case STAY:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
@@ -448,6 +496,9 @@ public class Pet implements ISerialize, Runnable {
|
||||
|
||||
|
||||
public void findNest() {
|
||||
if (this.room == null || this.room.getRoomSpecialTypes() == null || this.petData == null) {
|
||||
return;
|
||||
}
|
||||
HabboItem item = this.petData.randomNest(this.room.getRoomSpecialTypes().getNests());
|
||||
this.roomUnit.setCanWalk(true);
|
||||
if (item != null) {
|
||||
@@ -460,7 +511,37 @@ public class Pet implements ISerialize, Runnable {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds a suitable drink item for this pet in the current room.
|
||||
* @return The drink Item if found, null otherwise
|
||||
*/
|
||||
public Item findDrink() {
|
||||
if (this.room == null || this.room.getRoomSpecialTypes() == null || this.petData == null) {
|
||||
return null;
|
||||
}
|
||||
HabboItem drinkItem = this.petData.randomDrinkItem(this.room.getRoomSpecialTypes().getPetDrinks());
|
||||
return drinkItem != null ? drinkItem.getBaseItem() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a suitable food item for this pet in the current room.
|
||||
* @return The food Item if found, null otherwise
|
||||
*/
|
||||
public Item findFood() {
|
||||
if (this.room == null || this.room.getRoomSpecialTypes() == null || this.petData == null) {
|
||||
return null;
|
||||
}
|
||||
HabboItem foodItem = this.petData.randomFoodItem(this.room.getRoomSpecialTypes().getPetFoods());
|
||||
return foodItem != null ? foodItem.getBaseItem() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the pet walk to a drink item and drink from it.
|
||||
*/
|
||||
public void drink() {
|
||||
if (this.room == null || this.room.getRoomSpecialTypes() == null || this.petData == null) {
|
||||
return;
|
||||
}
|
||||
HabboItem item = this.petData.randomDrinkItem(this.room.getRoomSpecialTypes().getPetDrinks());
|
||||
if (item != null) {
|
||||
this.roomUnit.setCanWalk(true);
|
||||
@@ -468,26 +549,86 @@ public class Pet implements ISerialize, Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes the pet walk to a food item and eat from it.
|
||||
*/
|
||||
public void eat() {
|
||||
if (this.room == null || this.room.getRoomSpecialTypes() == null || this.petData == null) {
|
||||
return;
|
||||
}
|
||||
HabboItem item = this.petData.randomFoodItem(this.room.getRoomSpecialTypes().getPetFoods());
|
||||
{
|
||||
if (item != null) {
|
||||
this.roomUnit.setCanWalk(true);
|
||||
this.roomUnit.setGoalLocation(this.room.getLayout().getTile(item.getX(), item.getY()));
|
||||
}
|
||||
if (item != null) {
|
||||
this.roomUnit.setCanWalk(true);
|
||||
this.roomUnit.setGoalLocation(this.room.getLayout().getTile(item.getX(), item.getY()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void findToy() {
|
||||
HabboItem item = this.petData.randomToyItem(this.room.getRoomSpecialTypes().getPetToys());
|
||||
{
|
||||
if (item != null) {
|
||||
this.roomUnit.setCanWalk(true);
|
||||
this.roomUnit.setGoalLocation(this.room.getLayout().getTile(item.getX(), item.getY()));
|
||||
if (this.room == null || this.room.getRoomSpecialTypes() == null || this.petData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all pet toys in the room
|
||||
THashSet<InteractionPetToy> toys = this.room.getRoomSpecialTypes().getPetToys();
|
||||
if (toys.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// First try to find a toy this pet can use
|
||||
HabboItem item = this.petData.randomToyItem(toys);
|
||||
|
||||
// If no compatible toy found, just pick any toy in the room
|
||||
if (item == null) {
|
||||
for (InteractionPetToy toy : toys) {
|
||||
item = toy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item != null) {
|
||||
this.roomUnit.setCanWalk(true);
|
||||
this.setTask(PetTasks.PLAY);
|
||||
this.roomUnit.setGoalLocation(this.room.getLayout().getTile(item.getX(), item.getY()));
|
||||
this.say(this.petData.randomVocal(PetVocalsType.PLAYFUL));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a pet tree (for dragons/monkeys) and walks to it.
|
||||
* Used for hang, swing, ring of fire actions.
|
||||
*/
|
||||
public void findTree() {
|
||||
this.findPetItem(PetTasks.FREE, InteractionPetTree.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a pet item of a specific type and walks to it.
|
||||
* Used for trampolines, trees, and other special pet furniture.
|
||||
* @param task The task to set on the pet
|
||||
* @param type The class type of the item to find
|
||||
* @return true if an item was found and pet is walking to it
|
||||
*/
|
||||
public boolean findPetItem(PetTasks task, Class<? extends HabboItem> type) {
|
||||
if (this.room == null || this.room.getRoomSpecialTypes() == null || this.petData == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HabboItem item = this.petData.randomToyHabboItem(this.room.getRoomSpecialTypes().getItemsOfType(type));
|
||||
|
||||
if (item != null) {
|
||||
this.roomUnit.setCanWalk(true);
|
||||
this.setTask(task);
|
||||
if (this.getRoomUnit().getCurrentLocation().distance(this.room.getLayout().getTile(item.getX(), item.getY())) == 0) {
|
||||
try {
|
||||
item.onWalkOn(this.getRoomUnit(), this.getRoom(), null);
|
||||
} catch (Exception ignored) {}
|
||||
return true;
|
||||
}
|
||||
this.roomUnit.setGoalLocation(this.room.getLayout().getTile(item.getX(), item.getY()));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -753,4 +894,74 @@ public class Pet implements ISerialize, Runnable {
|
||||
public void setStayStartedAt(int stayStartedAt) {
|
||||
this.stayStartedAt = stayStartedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stats manager for this pet.
|
||||
* @return The PetStatsManager instance
|
||||
*/
|
||||
public PetStatsManager getStatsManager() {
|
||||
return this.statsManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the behavior manager for this pet.
|
||||
* @return The PetBehaviorManager instance
|
||||
*/
|
||||
public PetBehaviorManager getBehaviorManager() {
|
||||
return this.behaviorManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a command can be executed based on cooldown and spam prevention.
|
||||
* @param commandId The command ID to check
|
||||
* @return true if the command can be executed, false if on cooldown
|
||||
*/
|
||||
public boolean canExecuteCommand(int commandId) {
|
||||
long now = System.currentTimeMillis();
|
||||
int globalCooldownMs = Emulator.getConfig().getInt("pet.command.cooldown_ms", 2000);
|
||||
int maxSameCommandSpam = Emulator.getConfig().getInt("pet.command.max_same_spam", 3);
|
||||
int spamResetMs = Emulator.getConfig().getInt("pet.command.spam_reset_ms", 10000);
|
||||
|
||||
// Global cooldown - applies to ALL commands to prevent switching between commands
|
||||
if (now - this.lastCommandTime < globalCooldownMs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset spam counter if enough time has passed
|
||||
if (now - this.lastCommandTime > spamResetMs) {
|
||||
this.sameCommandCount = 0;
|
||||
}
|
||||
|
||||
// Check if same command is being spammed
|
||||
if (commandId == this.lastCommandId) {
|
||||
this.sameCommandCount++;
|
||||
|
||||
// Pet gets annoyed if same command spammed too much
|
||||
if (this.sameCommandCount > maxSameCommandSpam) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Different command - reset counter but still subject to global cooldown
|
||||
this.sameCommandCount = 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records that a command was executed.
|
||||
* @param commandId The command ID that was executed
|
||||
*/
|
||||
public void recordCommandExecution(int commandId) {
|
||||
this.lastCommandId = commandId;
|
||||
this.lastCommandTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of times the same command has been repeated.
|
||||
* @return The spam count
|
||||
*/
|
||||
public int getSameCommandCount() {
|
||||
return this.sameCommandCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
package com.eu.habbo.habbohotel.pets;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
|
||||
/**
|
||||
* Manages pet AI behavior using a state machine pattern.
|
||||
* Handles autonomous pet actions and state transitions.
|
||||
*/
|
||||
public class PetBehaviorManager {
|
||||
private final Pet pet;
|
||||
private PetBehaviorState currentState;
|
||||
private long stateEnteredAt;
|
||||
private long lastAutonomousAction;
|
||||
|
||||
// Configurable delays
|
||||
private int autonomousActionDelay;
|
||||
private int idleWanderMinMs;
|
||||
private int idleWanderMaxMs;
|
||||
|
||||
/**
|
||||
* Represents the various behavioral states a pet can be in.
|
||||
*/
|
||||
public enum PetBehaviorState {
|
||||
IDLE, // Standing around
|
||||
WANDERING, // Random walking
|
||||
FOLLOWING, // Following owner/habbo
|
||||
EXECUTING_COMMAND, // Doing a commanded action
|
||||
EATING, // At food bowl
|
||||
DRINKING, // At water bowl
|
||||
PLAYING, // With toy
|
||||
RESTING, // In nest/laying down
|
||||
BREEDING, // In breeding box
|
||||
DEAD // Monsterplant only
|
||||
}
|
||||
|
||||
public PetBehaviorManager(Pet pet) {
|
||||
this.pet = pet;
|
||||
this.currentState = PetBehaviorState.IDLE;
|
||||
this.stateEnteredAt = System.currentTimeMillis();
|
||||
this.lastAutonomousAction = 0;
|
||||
this.loadConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads configuration values from the emulator config.
|
||||
*/
|
||||
private void loadConfig() {
|
||||
this.autonomousActionDelay = Emulator.getConfig().getInt("pet.behavior.autonomous_action_delay", 5000);
|
||||
this.idleWanderMinMs = Emulator.getConfig().getInt("pet.behavior.idle_wander_min_ms", 10000);
|
||||
this.idleWanderMaxMs = Emulator.getConfig().getInt("pet.behavior.idle_wander_max_ms", 30000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transitions the pet to a new behavior state.
|
||||
* @param newState The new state to transition to
|
||||
*/
|
||||
public void transition(PetBehaviorState newState) {
|
||||
if (this.currentState == newState) return;
|
||||
|
||||
this.onExitState(this.currentState);
|
||||
this.currentState = newState;
|
||||
this.stateEnteredAt = System.currentTimeMillis();
|
||||
this.onEnterState(newState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when entering a new state to set up the appropriate room unit status.
|
||||
*/
|
||||
private void onEnterState(PetBehaviorState state) {
|
||||
if (this.pet.getRoomUnit() == null) return;
|
||||
|
||||
switch (state) {
|
||||
case RESTING -> {
|
||||
this.pet.getRoomUnit().setCanWalk(false);
|
||||
this.pet.getRoomUnit().setStatus(RoomUnitStatus.LAY, "0");
|
||||
}
|
||||
case EATING -> {
|
||||
this.pet.getRoomUnit().setStatus(RoomUnitStatus.EAT, "0");
|
||||
}
|
||||
case PLAYING -> {
|
||||
// Play status handled by specific toy interaction
|
||||
}
|
||||
case IDLE -> {
|
||||
// Clear any lingering action statuses
|
||||
}
|
||||
case FOLLOWING -> {
|
||||
this.pet.getRoomUnit().setCanWalk(true);
|
||||
}
|
||||
default -> {
|
||||
// No special handling needed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when exiting a state to clean up room unit status.
|
||||
*/
|
||||
private void onExitState(PetBehaviorState state) {
|
||||
if (this.pet.getRoomUnit() == null) return;
|
||||
|
||||
switch (state) {
|
||||
case RESTING -> {
|
||||
this.pet.getRoomUnit().removeStatus(RoomUnitStatus.LAY);
|
||||
this.pet.getRoomUnit().setCanWalk(true);
|
||||
}
|
||||
case EATING -> {
|
||||
this.pet.getRoomUnit().removeStatus(RoomUnitStatus.EAT);
|
||||
}
|
||||
case PLAYING -> {
|
||||
// Play status cleanup handled by toy interaction
|
||||
}
|
||||
default -> {
|
||||
// No special cleanup needed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes autonomous pet behavior each cycle.
|
||||
* Called every cycle to handle autonomous pet actions based on needs.
|
||||
*/
|
||||
public void processAutonomousBehavior() {
|
||||
// Rate limit autonomous actions
|
||||
if (System.currentTimeMillis() - this.lastAutonomousAction < this.autonomousActionDelay) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.pet.getRoom() == null) return;
|
||||
|
||||
PetStatsManager stats = this.pet.getStatsManager();
|
||||
if (stats == null) return;
|
||||
|
||||
// Priority-based autonomous behavior
|
||||
if (stats.needsRest() && this.currentState != PetBehaviorState.RESTING) {
|
||||
this.pet.findNest();
|
||||
this.lastAutonomousAction = System.currentTimeMillis();
|
||||
return;
|
||||
}
|
||||
|
||||
if (stats.needsFood() && this.currentState != PetBehaviorState.EATING) {
|
||||
this.pet.eat();
|
||||
this.lastAutonomousAction = System.currentTimeMillis();
|
||||
return;
|
||||
}
|
||||
|
||||
if (stats.needsWater() && this.currentState != PetBehaviorState.DRINKING) {
|
||||
this.pet.drink();
|
||||
this.lastAutonomousAction = System.currentTimeMillis();
|
||||
return;
|
||||
}
|
||||
|
||||
if (stats.needsAttention() && this.currentState == PetBehaviorState.IDLE) {
|
||||
this.pet.findToy();
|
||||
this.lastAutonomousAction = System.currentTimeMillis();
|
||||
return;
|
||||
}
|
||||
|
||||
// Random wandering when idle
|
||||
if (this.currentState == PetBehaviorState.IDLE) {
|
||||
long idleTime = System.currentTimeMillis() - this.stateEnteredAt;
|
||||
int wanderDelay = this.idleWanderMinMs + Emulator.getRandom().nextInt(
|
||||
this.idleWanderMaxMs - this.idleWanderMinMs);
|
||||
|
||||
if (idleTime > wanderDelay) {
|
||||
RoomTile tile = this.pet.getRoom().getRandomWalkableTile();
|
||||
if (tile != null && this.pet.getRoomUnit() != null) {
|
||||
this.pet.getRoomUnit().setGoalLocation(tile);
|
||||
this.transition(PetBehaviorState.WANDERING);
|
||||
}
|
||||
this.lastAutonomousAction = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the pet can currently accept commands.
|
||||
* @return true if the pet can accept commands
|
||||
*/
|
||||
public boolean canAcceptCommand() {
|
||||
return this.currentState != PetBehaviorState.DEAD
|
||||
&& this.currentState != PetBehaviorState.BREEDING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interrupts the current action and returns to idle state.
|
||||
*/
|
||||
public void interruptCurrentAction() {
|
||||
if (this.currentState == PetBehaviorState.EXECUTING_COMMAND
|
||||
|| this.currentState == PetBehaviorState.WANDERING) {
|
||||
this.transition(PetBehaviorState.IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current behavior state.
|
||||
* @return The current PetBehaviorState
|
||||
*/
|
||||
public PetBehaviorState getCurrentState() {
|
||||
return this.currentState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp when the current state was entered.
|
||||
* @return Timestamp in milliseconds
|
||||
*/
|
||||
public long getStateEnteredAt() {
|
||||
return this.stateEnteredAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets how long the pet has been in the current state.
|
||||
* @return Duration in milliseconds
|
||||
*/
|
||||
public long getTimeInCurrentState() {
|
||||
return System.currentTimeMillis() - this.stateEnteredAt;
|
||||
}
|
||||
}
|
||||
@@ -45,31 +45,75 @@ public class PetCommand implements Comparable<PetCommand> {
|
||||
}
|
||||
|
||||
public void handle(Pet pet, Habbo habbo, String[] data) {
|
||||
if (Emulator.getRandom().nextInt((pet.level - this.level <= 0 ? 2 : pet.level - this.level) + 2) == 0) {
|
||||
pet.say(pet.petData.randomVocal(PetVocalsType.DISOBEY));
|
||||
// Check command cooldown to prevent spam (global cooldown for ALL commands)
|
||||
if (!pet.canExecuteCommand(this.id)) {
|
||||
// Pet ignores spammed commands - maybe give a tired/annoyed response occasionally
|
||||
if (pet.getSameCommandCount() > Emulator.getConfig().getInt("pet.command.max_same_spam", 3)) {
|
||||
if (Emulator.getRandom().nextInt(3) == 0) {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if pet has enough energy to perform the command
|
||||
int minEnergy = Emulator.getConfig().getInt("pet.command.min_energy", 15);
|
||||
if (pet.getEnergy() < minEnergy || pet.getEnergy() < this.energyCost) {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.TIRED));
|
||||
pet.recordCommandExecution(this.id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if pet is too unhappy to obey
|
||||
int minHappiness = Emulator.getConfig().getInt("pet.command.min_happiness", 10);
|
||||
if (pet.getHappiness() < minHappiness) {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_SAD));
|
||||
pet.recordCommandExecution(this.id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Improved obedience formula - configurable base chance with level scaling
|
||||
int levelDifference = pet.getLevel() - this.level;
|
||||
int baseChance = Emulator.getConfig().getInt("pet.command.base_obey_chance", 70); // 70% base
|
||||
int levelBonus = Math.max(0, levelDifference * 5); // +5% per level above requirement
|
||||
int obeyChance = Math.min(95, baseChance + levelBonus); // Cap at 95%
|
||||
|
||||
if (Emulator.getRandom().nextInt(100) >= obeyChance) {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
pet.recordCommandExecution(this.id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.action != null) {
|
||||
if (this.action.petTask != pet.getTask()) {
|
||||
if (this.action.stopsPetWalking) {
|
||||
pet.getRoomUnit().setGoalLocation(pet.getRoomUnit().getCurrentLocation());
|
||||
// Allow repeating actions - removed the task comparison check
|
||||
if (this.action.stopsPetWalking) {
|
||||
pet.getRoomUnit().setGoalLocation(pet.getRoomUnit().getCurrentLocation());
|
||||
}
|
||||
if (this.action.apply(pet, habbo, data)) {
|
||||
// Set the pet's task from the action
|
||||
if (this.action.petTask != null) {
|
||||
pet.setTask(this.action.petTask);
|
||||
}
|
||||
if (this.action.apply(pet, habbo, data)) {
|
||||
for (RoomUnitStatus status : this.action.statusToRemove) {
|
||||
pet.getRoomUnit().removeStatus(status);
|
||||
}
|
||||
|
||||
for (RoomUnitStatus status : this.action.statusToSet) {
|
||||
pet.getRoomUnit().setStatus(status, "0");
|
||||
}
|
||||
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.GESTURE, this.action.gestureToSet);
|
||||
|
||||
pet.addEnergy(-this.energyCost);
|
||||
pet.addHappiness(-this.happinessCost);
|
||||
pet.addExperience(this.xp);
|
||||
|
||||
for (RoomUnitStatus status : this.action.statusToRemove) {
|
||||
pet.getRoomUnit().removeStatus(status);
|
||||
}
|
||||
|
||||
for (RoomUnitStatus status : this.action.statusToSet) {
|
||||
pet.getRoomUnit().setStatus(status, "0");
|
||||
}
|
||||
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.GESTURE, this.action.gestureToSet);
|
||||
|
||||
pet.addEnergy(-this.energyCost);
|
||||
pet.addHappiness(-this.happinessCost);
|
||||
pet.addExperience(this.xp);
|
||||
|
||||
// Mark pet for status update so clients see the animation
|
||||
pet.packetUpdate = true;
|
||||
|
||||
// Record successful command execution
|
||||
pet.recordCommandExecution(this.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,15 +97,22 @@ public class PetData implements Comparable<PetData> {
|
||||
|
||||
|
||||
boolean haveNest(Item nest) {
|
||||
// If no nest items are registered, allow all nest items
|
||||
if (this.nestItems.isEmpty() && PetData.generalNestItems.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return PetData.generalNestItems.contains(nest) || this.nestItems.contains(nest);
|
||||
}
|
||||
|
||||
|
||||
public HabboItem randomNest(THashSet<InteractionNest> items) {
|
||||
List<HabboItem> nestList = new ArrayList<>();
|
||||
|
||||
// If no nest items are registered, allow all nests in the room
|
||||
boolean allowAll = this.nestItems.isEmpty() && PetData.generalNestItems.isEmpty();
|
||||
|
||||
for (InteractionNest nest : items) {
|
||||
if (this.haveNest(nest)) {
|
||||
if (allowAll || this.haveNest(nest)) {
|
||||
nestList.add(nest);
|
||||
}
|
||||
}
|
||||
@@ -136,15 +143,22 @@ public class PetData implements Comparable<PetData> {
|
||||
|
||||
|
||||
boolean haveFoodItem(Item food) {
|
||||
// If no food items are registered, allow all food items
|
||||
if (this.foodItems.isEmpty() && PetData.generalFoodItems.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return this.foodItems.contains(food) || PetData.generalFoodItems.contains(food);
|
||||
}
|
||||
|
||||
|
||||
public HabboItem randomFoodItem(THashSet<InteractionPetFood> items) {
|
||||
List<HabboItem> foodList = new ArrayList<>();
|
||||
|
||||
// If no food items are registered, allow all food in the room
|
||||
boolean allowAll = this.foodItems.isEmpty() && PetData.generalFoodItems.isEmpty();
|
||||
|
||||
for (InteractionPetFood food : items) {
|
||||
if (this.haveFoodItem(food)) {
|
||||
if (allowAll || this.haveFoodItem(food)) {
|
||||
foodList.add(food);
|
||||
}
|
||||
}
|
||||
@@ -174,15 +188,22 @@ public class PetData implements Comparable<PetData> {
|
||||
|
||||
|
||||
boolean haveDrinkItem(Item item) {
|
||||
// If no drink items are registered, allow all drink items
|
||||
if (this.drinkItems.isEmpty() && PetData.generalDrinkItems.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return this.drinkItems.contains(item) || PetData.generalDrinkItems.contains(item);
|
||||
}
|
||||
|
||||
|
||||
public HabboItem randomDrinkItem(THashSet<InteractionPetDrink> items) {
|
||||
List<HabboItem> drinkList = new ArrayList<>();
|
||||
|
||||
// If no drink items are registered, allow all drinks in the room
|
||||
boolean allowAll = this.drinkItems.isEmpty() && PetData.generalDrinkItems.isEmpty();
|
||||
|
||||
for (InteractionPetDrink drink : items) {
|
||||
if (this.haveDrinkItem(drink)) {
|
||||
if (allowAll || this.haveDrinkItem(drink)) {
|
||||
drinkList.add(drink);
|
||||
}
|
||||
}
|
||||
@@ -212,15 +233,22 @@ public class PetData implements Comparable<PetData> {
|
||||
|
||||
|
||||
public boolean haveToyItem(Item toy) {
|
||||
// If no toy items are registered, allow all toy items
|
||||
if (this.toyItems.isEmpty() && PetData.generalToyItems.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return this.toyItems.contains(toy) || PetData.generalToyItems.contains(toy);
|
||||
}
|
||||
|
||||
|
||||
public HabboItem randomToyItem(THashSet<InteractionPetToy> toys) {
|
||||
List<HabboItem> toyList = new ArrayList<>();
|
||||
|
||||
// If no toy items are registered, allow all toys in the room
|
||||
boolean allowAll = this.toyItems.isEmpty() && PetData.generalToyItems.isEmpty();
|
||||
|
||||
for (InteractionPetToy toy : toys) {
|
||||
if (this.haveToyItem(toy)) {
|
||||
if (allowAll || this.haveToyItem(toy)) {
|
||||
toyList.add(toy);
|
||||
}
|
||||
}
|
||||
@@ -233,6 +261,30 @@ public class PetData implements Comparable<PetData> {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a random toy item from a generic set of HabboItems.
|
||||
* Used for finding pet items like trampolines, trees, etc.
|
||||
*/
|
||||
public HabboItem randomToyHabboItem(THashSet<HabboItem> items) {
|
||||
List<HabboItem> itemList = new ArrayList<>();
|
||||
|
||||
// If no toy items are registered, allow all toys in the room
|
||||
boolean allowAll = this.toyItems.isEmpty() && PetData.generalToyItems.isEmpty();
|
||||
|
||||
for (HabboItem item : items) {
|
||||
if (allowAll || this.haveToyItem(item)) {
|
||||
itemList.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (!itemList.isEmpty()) {
|
||||
Collections.shuffle(itemList);
|
||||
return itemList.get(0);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public PetVocal randomVocal(PetVocalsType type) {
|
||||
THashSet<PetVocal> petTypeVocals = this.petVocals.get(type);
|
||||
@@ -242,8 +294,10 @@ public class PetData implements Comparable<PetData> {
|
||||
int generalSize = generalVocals != null ? generalVocals.size() : 0;
|
||||
int totalSize = petTypeSize + generalSize;
|
||||
|
||||
if (totalSize == 0)
|
||||
return null;
|
||||
if (totalSize == 0) {
|
||||
// Return a default vocal instead of null
|
||||
return getDefaultVocal(type);
|
||||
}
|
||||
|
||||
int randomIndex = Emulator.getRandom().nextInt(totalSize);
|
||||
|
||||
@@ -262,7 +316,31 @@ public class PetData implements Comparable<PetData> {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return getDefaultVocal(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a default vocal message when no configured vocals exist for the type.
|
||||
* This prevents null pointer exceptions and silent pets.
|
||||
*/
|
||||
private static PetVocal getDefaultVocal(PetVocalsType type) {
|
||||
return switch (type) {
|
||||
case GENERIC_HAPPY -> new PetVocal("*wags tail happily*");
|
||||
case GENERIC_SAD -> new PetVocal("*whimpers*");
|
||||
case GENERIC_NEUTRAL -> new PetVocal("*looks around*");
|
||||
case HUNGRY -> new PetVocal("*stomach growls*");
|
||||
case THIRSTY -> new PetVocal("*pants*");
|
||||
case TIRED -> new PetVocal("*yawns*");
|
||||
case SLEEPING -> new PetVocal("*snores softly*");
|
||||
case PLAYFUL -> new PetVocal("*bounces excitedly*");
|
||||
case DISOBEY -> new PetVocal("*ignores command*");
|
||||
case EATING -> new PetVocal("*munches happily*");
|
||||
case DRINKING -> new PetVocal("*laps up water*");
|
||||
case LEVEL_UP -> new PetVocal("*jumps with joy*");
|
||||
case GREET_OWNER -> new PetVocal("*perks up excitedly*");
|
||||
case MUTED -> new PetVocal("*stays quiet*");
|
||||
case UNKNOWN_COMMAND -> new PetVocal("*tilts head confused*");
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.eu.habbo.habbohotel.items.interactions.pets.InteractionNest;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetDrink;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetFood;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetToy;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetTrampoline;
|
||||
import com.eu.habbo.habbohotel.pets.actions.*;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
@@ -52,6 +53,12 @@ public class PetManager {
|
||||
this.put(15, new ActionFollowLeft());
|
||||
this.put(16, new ActionFollowRight());
|
||||
this.put(17, new ActionPlayFootball());
|
||||
this.put(18, new ActionTeleport());
|
||||
this.put(19, new ActionBounce());
|
||||
this.put(20, new ActionFlatten());
|
||||
this.put(21, new ActionDance());
|
||||
this.put(22, new ActionSpin());
|
||||
this.put(23, new ActionSwitch());
|
||||
this.put(24, new ActionMoveForward());
|
||||
this.put(25, new ActionTurnLeft());
|
||||
this.put(26, new ActionTurnRight());
|
||||
@@ -59,10 +66,20 @@ public class PetManager {
|
||||
this.put(28, new ActionCroak());
|
||||
this.put(29, new ActionDip());
|
||||
this.put(30, new ActionWave());
|
||||
this.put(31, new ActionMambo());
|
||||
this.put(32, new ActionHighJump());
|
||||
this.put(33, new ActionChickenDance());
|
||||
this.put(34, new ActionTripleJump());
|
||||
this.put(35, new ActionWings());
|
||||
this.put(36, new ActionBreatheFire());
|
||||
this.put(37, new ActionHang());
|
||||
this.put(38, new ActionTorch());
|
||||
this.put(40, new ActionSwing());
|
||||
this.put(41, new ActionRoll());
|
||||
this.put(42, new ActionRingOfFire());
|
||||
this.put(43, new ActionEat());
|
||||
this.put(44, new ActionWagTail());
|
||||
this.put(45, new ActionCount());
|
||||
this.put(46, new ActionBreed());
|
||||
|
||||
}
|
||||
@@ -200,7 +217,7 @@ public class PetManager {
|
||||
PetData.generalFoodItems.add(baseItem);
|
||||
else if (baseItem.getInteractionType().getType() == InteractionPetDrink.class)
|
||||
PetData.generalDrinkItems.add(baseItem);
|
||||
else if (baseItem.getInteractionType().getType() == InteractionPetToy.class)
|
||||
else if (baseItem.getInteractionType().getType() == InteractionPetToy.class || baseItem.getInteractionType().getType() == InteractionPetTrampoline.class)
|
||||
PetData.generalToyItems.add(baseItem);
|
||||
} else {
|
||||
PetData data = this.getPetData(set.getInt("pet_id"));
|
||||
@@ -212,7 +229,7 @@ public class PetManager {
|
||||
data.addFoodItem(baseItem);
|
||||
else if (baseItem.getInteractionType().getType() == InteractionPetDrink.class)
|
||||
data.addDrinkItem(baseItem);
|
||||
else if (baseItem.getInteractionType().getType() == InteractionPetToy.class)
|
||||
else if (baseItem.getInteractionType().getType() == InteractionPetToy.class || baseItem.getInteractionType().getType() == InteractionPetTrampoline.class)
|
||||
data.addToyItem(baseItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.eu.habbo.habbohotel.pets;
|
||||
|
||||
/**
|
||||
* Represents the various mood states a pet can be in based on its stats.
|
||||
*/
|
||||
public enum PetMood {
|
||||
EXHAUSTED("exhausted", 0),
|
||||
STARVING("starving", 1),
|
||||
PARCHED("parched", 2),
|
||||
DEPRESSED("depressed", 3),
|
||||
NEUTRAL("neutral", 4),
|
||||
HAPPY("happy", 5),
|
||||
ECSTATIC("ecstatic", 6);
|
||||
|
||||
private final String key;
|
||||
private final int priority;
|
||||
|
||||
PetMood(String key, int priority) {
|
||||
this.key = key;
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the priority of this mood. Lower values indicate more urgent moods.
|
||||
* @return The priority value
|
||||
*/
|
||||
public int getPriority() {
|
||||
return this.priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this mood is a negative/urgent mood that needs addressing.
|
||||
* @return true if this is a negative mood
|
||||
*/
|
||||
public boolean isNegative() {
|
||||
return this.priority <= 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this mood is a positive mood.
|
||||
* @return true if this is a positive mood
|
||||
*/
|
||||
public boolean isPositive() {
|
||||
return this.priority >= 5;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package com.eu.habbo.habbohotel.pets;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
|
||||
/**
|
||||
* Manages all stat-related logic for pets including decay rates, recovery rates,
|
||||
* and mood calculations. This centralizes stat management for better maintainability.
|
||||
*/
|
||||
public class PetStatsManager {
|
||||
private final Pet pet;
|
||||
|
||||
// Configurable decay rates
|
||||
private int hungerDecayRate;
|
||||
private int thirstDecayRate;
|
||||
private int energyDecayRate;
|
||||
private int happinessDecayRate;
|
||||
|
||||
// Configurable recovery rates
|
||||
private int energyRecoveryRate;
|
||||
private int happinessRecoveryRate;
|
||||
|
||||
// Configurable thresholds
|
||||
private int hungryThreshold;
|
||||
private int thirstyThreshold;
|
||||
private int tiredThreshold;
|
||||
private int sadThreshold;
|
||||
|
||||
public PetStatsManager(Pet pet) {
|
||||
this.pet = pet;
|
||||
this.loadConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads configuration values from the emulator config.
|
||||
*/
|
||||
private void loadConfig() {
|
||||
this.hungerDecayRate = Emulator.getConfig().getInt("pet.stats.hunger_decay", 1);
|
||||
this.thirstDecayRate = Emulator.getConfig().getInt("pet.stats.thirst_decay", 1);
|
||||
this.energyDecayRate = Emulator.getConfig().getInt("pet.stats.energy_decay", 1);
|
||||
this.happinessDecayRate = Emulator.getConfig().getInt("pet.stats.happiness_decay", 1);
|
||||
this.energyRecoveryRate = Emulator.getConfig().getInt("pet.stats.energy_recovery", 5);
|
||||
this.happinessRecoveryRate = Emulator.getConfig().getInt("pet.stats.happiness_recovery", 1);
|
||||
|
||||
this.hungryThreshold = Emulator.getConfig().getInt("pet.threshold.hungry", 50);
|
||||
this.thirstyThreshold = Emulator.getConfig().getInt("pet.threshold.thirsty", 50);
|
||||
this.tiredThreshold = Emulator.getConfig().getInt("pet.threshold.tired", 30);
|
||||
this.sadThreshold = Emulator.getConfig().getInt("pet.threshold.sad", 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process stat changes when pet is walking/active.
|
||||
*/
|
||||
public void processActiveTick() {
|
||||
this.pet.addHunger(this.hungerDecayRate);
|
||||
this.pet.addThirst(this.thirstDecayRate);
|
||||
this.pet.addEnergy(-this.energyDecayRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process stat changes when pet is in nest/down (resting).
|
||||
*/
|
||||
public void processRestingTick() {
|
||||
this.pet.addHunger(-1);
|
||||
this.pet.addThirst(-1);
|
||||
this.pet.addEnergy(this.energyRecoveryRate);
|
||||
this.pet.addHappiness(this.happinessRecoveryRate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process stat changes when pet is standing still/idle.
|
||||
*/
|
||||
public void processIdleTick() {
|
||||
this.pet.addHunger(this.hungerDecayRate / 2);
|
||||
this.pet.addThirst(this.thirstDecayRate / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current mood of the pet based on its stats.
|
||||
* @return The current PetMood
|
||||
*/
|
||||
public PetMood getCurrentMood() {
|
||||
if (this.pet.getEnergy() < 20) return PetMood.EXHAUSTED;
|
||||
if (this.pet.getLevelHunger() > 80) return PetMood.STARVING;
|
||||
if (this.pet.getLevelThirst() > 80) return PetMood.PARCHED;
|
||||
if (this.pet.getHappiness() < 20) return PetMood.DEPRESSED;
|
||||
if (this.pet.getHappiness() > 80 && this.pet.getEnergy() > 60) return PetMood.ECSTATIC;
|
||||
if (this.pet.getHappiness() > 50) return PetMood.HAPPY;
|
||||
return PetMood.NEUTRAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the pet needs food.
|
||||
* @return true if hunger level exceeds the hungry threshold
|
||||
*/
|
||||
public boolean needsFood() {
|
||||
return this.pet.getLevelHunger() > this.hungryThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the pet needs water.
|
||||
* @return true if thirst level exceeds the thirsty threshold
|
||||
*/
|
||||
public boolean needsWater() {
|
||||
return this.pet.getLevelThirst() > this.thirstyThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the pet needs rest.
|
||||
* @return true if energy level is below the tired threshold
|
||||
*/
|
||||
public boolean needsRest() {
|
||||
return this.pet.getEnergy() < this.tiredThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the pet needs attention/play.
|
||||
* @return true if happiness level is below the sad threshold
|
||||
*/
|
||||
public boolean needsAttention() {
|
||||
return this.pet.getHappiness() < this.sadThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall health score of the pet (0-100).
|
||||
* @return An integer representing overall pet health
|
||||
*/
|
||||
public int getOverallHealth() {
|
||||
int maxEnergy = PetManager.maxEnergy(this.pet.getLevel());
|
||||
int energyPercent = (this.pet.getEnergy() * 100) / maxEnergy;
|
||||
int hungerPercent = 100 - this.pet.getLevelHunger();
|
||||
int thirstPercent = 100 - this.pet.getLevelThirst();
|
||||
int happinessPercent = this.pet.getHappiness();
|
||||
|
||||
return (energyPercent + hungerPercent + thirstPercent + happinessPercent) / 4;
|
||||
}
|
||||
|
||||
// Getters for decay/recovery rates
|
||||
public int getHungerDecayRate() { return hungerDecayRate; }
|
||||
public int getThirstDecayRate() { return thirstDecayRate; }
|
||||
public int getEnergyDecayRate() { return energyDecayRate; }
|
||||
public int getHappinessDecayRate() { return happinessDecayRate; }
|
||||
public int getEnergyRecoveryRate() { return energyRecoveryRate; }
|
||||
public int getHappinessRecoveryRate() { return happinessRecoveryRate; }
|
||||
|
||||
// Getters for thresholds
|
||||
public int getHungryThreshold() { return hungryThreshold; }
|
||||
public int getThirstyThreshold() { return thirstyThreshold; }
|
||||
public int getTiredThreshold() { return tiredThreshold; }
|
||||
public int getSadThreshold() { return sadThreshold; }
|
||||
}
|
||||
@@ -17,6 +17,9 @@ public class ActionBeg extends PetAction {
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
|
||||
// Begging is fun interaction with owner
|
||||
pet.addHappiness(5);
|
||||
|
||||
if (pet.getHappiness() > 90)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionBounce extends PetAction {
|
||||
public ActionBounce() {
|
||||
super(PetTasks.JUMP, true);
|
||||
this.minimumActionDuration = 3000;
|
||||
this.statusToSet.add(RoomUnitStatus.JUMP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.JUMP, null, false), 3000);
|
||||
|
||||
// Bouncing is fun!
|
||||
pet.addHappiness(8);
|
||||
|
||||
if (pet.getHappiness() > 60)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetBreedingNes
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.messages.outgoing.rooms.pets.breeding.PetBreedingStartFailedComposer;
|
||||
@@ -28,6 +29,7 @@ public class ActionBreed extends PetAction {
|
||||
|
||||
if (nest != null) {
|
||||
pet.getRoomUnit().setGoalLocation(pet.getRoom().getLayout().getTile(nest.getX(), nest.getY()));
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_HAPPY));
|
||||
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionChickenDance extends PetAction {
|
||||
public ActionChickenDance() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 4000;
|
||||
this.statusToSet.add(RoomUnitStatus.DANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.DANCE, "");
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.DANCE, null, false), 4000);
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
public class ActionCount extends PetAction {
|
||||
public ActionCount() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 3000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
|
||||
// Count by speaking
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ public class ActionCroak extends PetAction {
|
||||
|
||||
if (pet.getHappiness() > 80)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionDance extends PetAction {
|
||||
public ActionDance() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 5000;
|
||||
this.statusToSet.add(RoomUnitStatus.DANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.DANCE, "");
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.DANCE, null, false), 5000);
|
||||
|
||||
// Dancing is fun!
|
||||
pet.addHappiness(10);
|
||||
|
||||
if (pet.getHappiness() > 60)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionWater;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
@@ -23,6 +24,8 @@ public class ActionDip extends PetAction {
|
||||
HabboItem waterPatch = (HabboItem) waterItems.toArray()[Emulator.getRandom().nextInt(waterItems.size())];
|
||||
|
||||
pet.getRoomUnit().setGoalLocation(pet.getRoom().getLayout().getTile(waterPatch.getX(), waterPatch.getY()));
|
||||
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
@@ -10,18 +11,33 @@ import com.eu.habbo.habbohotel.users.Habbo;
|
||||
public class ActionDown extends PetAction {
|
||||
public ActionDown() {
|
||||
super(PetTasks.DOWN, true);
|
||||
this.minimumActionDuration = 4000;
|
||||
this.statusToRemove.add(RoomUnitStatus.BEG);
|
||||
this.statusToRemove.add(RoomUnitStatus.MOVE);
|
||||
this.statusToRemove.add(RoomUnitStatus.SIT);
|
||||
this.statusToRemove.add(RoomUnitStatus.DEAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.LAY, pet.getRoom().getStackHeight(pet.getRoomUnit().getX(), pet.getRoomUnit().getY(), false) + "");
|
||||
if (pet.getTask() != PetTasks.DOWN && !pet.getRoomUnit().hasStatus(RoomUnitStatus.LAY)) {
|
||||
pet.getRoomUnit().cmdLay = true;
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.LAY, pet.getRoomUnit().getCurrentLocation().getStackHeight() + "");
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
// Lying down is a bit boring but restful
|
||||
pet.addHappiness(-2);
|
||||
|
||||
Emulator.getThreading().run(() -> {
|
||||
pet.getRoomUnit().cmdLay = false;
|
||||
pet.clearPosture();
|
||||
}, this.minimumActionDuration);
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
@@ -12,17 +13,30 @@ public class ActionDrink extends PetAction {
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
if (pet.getLevelThirst() > 40) {
|
||||
pet.drink();
|
||||
|
||||
if (pet.getLevelThirst() > 65)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.THIRSTY));
|
||||
|
||||
return true;
|
||||
// Check if pet is thirsty enough to want water (threshold: 35 to match InteractionPetDrink)
|
||||
if (pet.getLevelThirst() >= 35) {
|
||||
// Check if there's water available in the room before sending pet to drink
|
||||
if (pet.getRoom() != null && pet.getRoom().getRoomSpecialTypes() != null) {
|
||||
Item drinkItem = pet.findDrink();
|
||||
|
||||
if (drinkItem != null) {
|
||||
// Water exists - pet goes to drink
|
||||
if (pet.getLevelThirst() > 65) {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.THIRSTY));
|
||||
}
|
||||
pet.drink();
|
||||
return true;
|
||||
} else {
|
||||
// No suitable water in room - pet complains
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.THIRSTY));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// Pet is not thirsty - disobeys command
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,42 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionEat extends PetAction {
|
||||
public ActionEat() {
|
||||
super(null, true);
|
||||
|
||||
this.statusToSet.add(RoomUnitStatus.EAT);
|
||||
// stopsPetWalking=false so pet can walk to food
|
||||
// Don't set EAT status here - let InteractionPetFood.onWalkOn() handle it when pet arrives
|
||||
super(null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
//Eat
|
||||
if (pet.getLevelHunger() > 40) {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.HUNGRY));
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.EAT, null, false), 500);
|
||||
pet.eat();
|
||||
|
||||
return true;
|
||||
// Check if pet is hungry enough to want food (threshold: 35 to match InteractionPetFood)
|
||||
if (pet.getLevelHunger() >= 35) {
|
||||
// Check if there's food available in the room before sending pet to eat
|
||||
if (pet.getRoom() != null && pet.getRoom().getRoomSpecialTypes() != null) {
|
||||
Item foodItem = pet.findFood();
|
||||
|
||||
if (foodItem != null) {
|
||||
// Food exists - pet goes to eat
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.HUNGRY));
|
||||
pet.eat();
|
||||
return true;
|
||||
} else {
|
||||
// No suitable food in room - pet complains
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.HUNGRY));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// Pet is not hungry - disobeys command
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionFlatten extends PetAction {
|
||||
public ActionFlatten() {
|
||||
super(PetTasks.DOWN, true);
|
||||
this.minimumActionDuration = 3000;
|
||||
this.statusToSet.add(RoomUnitStatus.FLAT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.FLAT, pet.getRoomUnit().getCurrentLocation().getStackHeight() + "");
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.FLAT, null, false), 3000);
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,9 @@ public class ActionFollow extends PetAction {
|
||||
|
||||
Emulator.getThreading().run(new PetFollowHabbo(pet, habbo, 0));
|
||||
|
||||
// Following owner is enjoyable
|
||||
pet.addHappiness(5);
|
||||
|
||||
if (pet.getHappiness() > 75)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.eu.habbo.threading.runnables.PetFollowHabbo;
|
||||
|
||||
public class ActionFollowLeft extends PetAction {
|
||||
public ActionFollowLeft() {
|
||||
super(PetTasks.FOLLOW, true);
|
||||
super(PetTasks.FOLLOW_LEFT, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -18,7 +18,10 @@ public class ActionFollowLeft extends PetAction {
|
||||
//Follow left.
|
||||
pet.clearPosture();
|
||||
|
||||
Emulator.getThreading().run(new PetFollowHabbo(pet, habbo, -2));
|
||||
Emulator.getThreading().run(new PetFollowHabbo(pet, habbo, +2));
|
||||
|
||||
// Following owner is enjoyable
|
||||
pet.addHappiness(5);
|
||||
|
||||
if (pet.getHappiness() > 75)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.eu.habbo.threading.runnables.PetFollowHabbo;
|
||||
|
||||
public class ActionFollowRight extends PetAction {
|
||||
public ActionFollowRight() {
|
||||
super(PetTasks.FOLLOW, true);
|
||||
super(PetTasks.FOLLOW_RIGHT, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -18,7 +18,10 @@ public class ActionFollowRight extends PetAction {
|
||||
//Follow right.
|
||||
pet.clearPosture();
|
||||
|
||||
Emulator.getThreading().run(new PetFollowHabbo(pet, habbo, +2));
|
||||
Emulator.getThreading().run(new PetFollowHabbo(pet, habbo, -2));
|
||||
|
||||
// Following owner is enjoyable
|
||||
pet.addHappiness(5);
|
||||
|
||||
if (pet.getHappiness() > 75)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.pets.actions;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
public class ActionFree extends PetAction {
|
||||
@@ -13,6 +14,9 @@ public class ActionFree extends PetAction {
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.freeCommand();
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_HAPPY));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetTree;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionHang extends PetAction {
|
||||
public ActionHang() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 4000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
// Hang requires pet to be on a pet tree (dragon/monkey tree)
|
||||
if (pet.getRoom() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HabboItem itemBelow = pet.getRoom().getTopItemAt(pet.getRoomUnit().getX(), pet.getRoomUnit().getY());
|
||||
if (!(itemBelow instanceof InteractionPetTree)) {
|
||||
// Pet must go to tree first
|
||||
pet.findTree();
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
return false;
|
||||
}
|
||||
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.HANG, "");
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.HANG, null, false), 4000);
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
@@ -16,8 +17,27 @@ public class ActionHere extends PetAction {
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.getRoomUnit().setGoalLocation(pet.getRoom().getLayout().getTileInFront(habbo.getRoomUnit().getCurrentLocation(), habbo.getRoomUnit().getBodyRotation().getValue()));
|
||||
pet.getRoomUnit().setCanWalk(true);
|
||||
if (pet.getRoom() == null || habbo.getRoomUnit() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pet.clearPosture();
|
||||
|
||||
// Try tile in front of habbo first
|
||||
RoomTile target = pet.getRoom().getLayout().getTileInFront(
|
||||
habbo.getRoomUnit().getCurrentLocation(),
|
||||
habbo.getRoomUnit().getBodyRotation().getValue()
|
||||
);
|
||||
|
||||
// If not walkable, try habbo's current tile
|
||||
if (target == null || !pet.getRoom().getLayout().tileWalkable(target.x, target.y)) {
|
||||
target = habbo.getRoomUnit().getCurrentLocation();
|
||||
}
|
||||
|
||||
if (target != null) {
|
||||
pet.getRoomUnit().setGoalLocation(target);
|
||||
pet.getRoomUnit().setCanWalk(true);
|
||||
}
|
||||
|
||||
if (pet.getHappiness() > 75)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionHighJump extends PetAction {
|
||||
public ActionHighJump() {
|
||||
super(PetTasks.JUMP, true);
|
||||
this.minimumActionDuration = 3000;
|
||||
this.statusToSet.add(RoomUnitStatus.JUMP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.JUMP, null, false), 3000);
|
||||
|
||||
if (pet.getHappiness() > 70)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,9 @@ public class ActionJump extends PetAction {
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.JUMP, null, false), 2000);
|
||||
|
||||
// Jumping is fun!
|
||||
pet.addHappiness(8);
|
||||
|
||||
if (pet.getHappiness() > 60)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionMambo extends PetAction {
|
||||
public ActionMambo() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 5000;
|
||||
this.statusToSet.add(RoomUnitStatus.DANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.DANCE, "");
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.DANCE, null, false), 5000);
|
||||
|
||||
if (pet.getHappiness() > 60)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.eu.habbo.habbohotel.pets.actions;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
public class ActionMoveForward extends PetAction {
|
||||
@@ -12,12 +13,23 @@ public class ActionMoveForward extends PetAction {
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
|
||||
pet.getRoomUnit().setGoalLocation(pet.getRoom().getLayout().getTileInFront(pet.getRoomUnit().getCurrentLocation(), pet.getRoomUnit().getBodyRotation().getValue()));
|
||||
pet.getRoomUnit().setCanWalk(true);
|
||||
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
if (pet.getRoom() == null || pet.getRoomUnit() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RoomTile targetTile = pet.getRoom().getLayout().getTileInFront(
|
||||
pet.getRoomUnit().getCurrentLocation(),
|
||||
pet.getRoomUnit().getBodyRotation().getValue()
|
||||
);
|
||||
|
||||
if (targetTile != null && pet.getRoom().getLayout().tileWalkable(targetTile.x, targetTile.y)) {
|
||||
pet.getRoomUnit().setGoalLocation(targetTile);
|
||||
pet.getRoomUnit().setCanWalk(true);
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
return true;
|
||||
}
|
||||
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,17 +12,14 @@ public class ActionNest extends PetAction {
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
if (pet.getEnergy() < 65) {
|
||||
pet.findNest();
|
||||
// Pet always obeys nest command - will go to nest or lay down if no nest available
|
||||
pet.findNest();
|
||||
|
||||
if (pet.getEnergy() < 30)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.TIRED));
|
||||
if (pet.getEnergy() < 30)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.TIRED));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
} else {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,133 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetToy;
|
||||
import com.eu.habbo.habbohotel.pets.*;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ActionPlay extends PetAction {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ActionPlay.class);
|
||||
|
||||
public ActionPlay() {
|
||||
super(null, false);
|
||||
super(PetTasks.PLAY, false);
|
||||
this.minimumActionDuration = 4000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
//Play
|
||||
//TODO Implement playing for pets. For example; go to ball, toy etc.
|
||||
if (pet.getHappiness() > 75)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
LOGGER.info("[ActionPlay] apply() called for pet: {}", pet.getName());
|
||||
|
||||
// Check if pet has enough energy to play
|
||||
if (pet.getEnergy() < 25) {
|
||||
LOGGER.info("[ActionPlay] Pet too tired, energy: {}", pet.getEnergy());
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.TIRED));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (pet.getRoom() == null || pet.getRoom().getRoomSpecialTypes() == null) {
|
||||
LOGGER.info("[ActionPlay] Room or RoomSpecialTypes is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all pet toys in the room
|
||||
THashSet<InteractionPetToy> toys = pet.getRoom().getRoomSpecialTypes().getPetToys();
|
||||
LOGGER.info("[ActionPlay] Found {} pet toys in room", toys.size());
|
||||
|
||||
// Find a toy to play with
|
||||
HabboItem toy = pet.getPetData().randomToyItem(toys);
|
||||
LOGGER.info("[ActionPlay] randomToyItem returned: {}", toy != null ? toy.getId() : "null");
|
||||
|
||||
// If no compatible toy, just pick any toy in the room
|
||||
if (toy == null && !toys.isEmpty()) {
|
||||
for (InteractionPetToy t : toys) {
|
||||
toy = t;
|
||||
LOGGER.info("[ActionPlay] Using any toy: {}", toy.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (toy != null) {
|
||||
RoomTile toyTile = pet.getRoom().getLayout().getTile(toy.getX(), toy.getY());
|
||||
LOGGER.info("[ActionPlay] Toy at tile: ({}, {}), tile found: {}", toy.getX(), toy.getY(), toyTile != null);
|
||||
|
||||
if (toyTile != null) {
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setCanWalk(true);
|
||||
pet.setTask(PetTasks.PLAY);
|
||||
|
||||
double distance = pet.getRoomUnit().getCurrentLocation().distance(toyTile);
|
||||
LOGGER.info("[ActionPlay] Distance to toy: {}", distance);
|
||||
|
||||
// Check if already at the toy
|
||||
if (distance == 0) {
|
||||
// Already at toy - start playing immediately
|
||||
LOGGER.info("[ActionPlay] Already at toy, starting play");
|
||||
this.startPlaying(pet, toy);
|
||||
} else {
|
||||
// Walk to toy first
|
||||
LOGGER.info("[ActionPlay] Setting goal location to toy");
|
||||
pet.getRoomUnit().setGoalLocation(toyTile);
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
// The InteractionPetToy.onWalkOn will handle the actual play when pet arrives
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("[ActionPlay] No toy found, doing solo play");
|
||||
// No toy found - play solo animation
|
||||
pet.clearPosture();
|
||||
pet.setTask(PetTasks.PLAY);
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.PLAY, "0");
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
pet.packetUpdate = true;
|
||||
|
||||
// Give smaller rewards for solo play
|
||||
pet.addHappiness(10);
|
||||
pet.addEnergy(-5);
|
||||
pet.addExperience(3);
|
||||
|
||||
Emulator.getThreading().run(() -> {
|
||||
if (pet.getRoomUnit() != null) {
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.PLAY);
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
pet.setTask(PetTasks.FREE);
|
||||
}, this.minimumActionDuration);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void startPlaying(Pet pet, HabboItem toy) {
|
||||
pet.getRoomUnit().clearStatus();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.PLAY, pet.getRoomUnit().getCurrentLocation().getStackHeight() + "");
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
pet.packetUpdate = true;
|
||||
|
||||
// Playing with toy gives better rewards
|
||||
pet.addHappiness(25);
|
||||
pet.addEnergy(-10);
|
||||
pet.addExperience(10);
|
||||
|
||||
// Update toy state
|
||||
toy.setExtradata("1");
|
||||
pet.getRoom().updateItemState(toy);
|
||||
|
||||
int playDuration = 2500 + (Emulator.getRandom().nextInt(20) * 500);
|
||||
Emulator.getThreading().run(() -> {
|
||||
toy.setExtradata("0");
|
||||
pet.getRoom().updateItem(toy);
|
||||
if (pet.getRoomUnit() != null) {
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.PLAY);
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
pet.setTask(PetTasks.FREE);
|
||||
}, playDuration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ public class ActionPlayDead extends PetAction {
|
||||
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.DEAD, pet.getRoom().getStackHeight(pet.getRoomUnit().getX(), pet.getRoomUnit().getY(), false) + "");
|
||||
|
||||
// Playing dead is not very fun
|
||||
pet.addHappiness(-3);
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
|
||||
+38
-11
@@ -3,41 +3,68 @@ package com.eu.habbo.habbohotel.pets.actions;
|
||||
import com.eu.habbo.habbohotel.items.interactions.InteractionPushable;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.Room;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
|
||||
public class ActionPlayFootball extends PetAction {
|
||||
public ActionPlayFootball() {
|
||||
super(null, false);
|
||||
super(PetTasks.PLAY_FOOTBALL, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
|
||||
Room room = pet.getRoom();
|
||||
|
||||
if(room == null || room.getLayout() == null)
|
||||
if (room == null || room.getLayout() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pet.getRoomUnit() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HabboItem foundBall = null;
|
||||
// Find the nearest ball to the pet
|
||||
HabboItem nearestBall = null;
|
||||
double nearestDistance = Double.MAX_VALUE;
|
||||
RoomTile petTile = pet.getRoomUnit().getCurrentLocation();
|
||||
|
||||
for(HabboItem item : room.getFloorItems()) {
|
||||
if(item instanceof InteractionPushable) {
|
||||
foundBall = item;
|
||||
if (petTile == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (HabboItem item : room.getFloorItems()) {
|
||||
if (item instanceof InteractionPushable) {
|
||||
RoomTile ballTile = room.getLayout().getTile(item.getX(), item.getY());
|
||||
if (ballTile != null) {
|
||||
double distance = petTile.distance(ballTile);
|
||||
if (distance < nearestDistance) {
|
||||
nearestDistance = distance;
|
||||
nearestBall = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(foundBall == null)
|
||||
if (nearestBall == null) {
|
||||
// No ball in room - disobey
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
return false;
|
||||
}
|
||||
|
||||
pet.getRoomUnit().setGoalLocation(room.getLayout().getTile(foundBall.getX(), foundBall.getY()));
|
||||
// Set task and pathfind to the ball
|
||||
pet.setTask(PetTasks.PLAY_FOOTBALL);
|
||||
pet.getRoomUnit().setCanWalk(true);
|
||||
pet.getRoomUnit().setGoalLocation(room.getLayout().getTile(nearestBall.getX(), nearestBall.getY()));
|
||||
|
||||
if (pet.getHappiness() > 75)
|
||||
if (pet.getHappiness() > 75) {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
} else {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
public class ActionRingOfFire extends PetAction {
|
||||
public ActionRingOfFire() {
|
||||
super(null, true);
|
||||
this.minimumActionDuration = 4000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
if (pet.getRoom() == null || pet.getRoomUnit() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ring of Fire can only be performed while hanging on a tree
|
||||
if (!pet.getRoomUnit().hasStatus(RoomUnitStatus.HANG)) {
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Transition from HANG to RINGOFFIRE
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.HANG);
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.RINGOFFIRE, pet.getRoomUnit().getCurrentLocation().getStackHeight() + "");
|
||||
pet.packetUpdate = true;
|
||||
|
||||
// After ring of fire, go back to hanging
|
||||
Emulator.getThreading().run(() -> {
|
||||
pet.getRoomUnit().removeStatus(RoomUnitStatus.RINGOFFIRE);
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.HANG, "");
|
||||
pet.packetUpdate = true;
|
||||
}, minimumActionDuration);
|
||||
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionRoll extends PetAction {
|
||||
public ActionRoll() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 3000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.LAY, pet.getRoomUnit().getCurrentLocation().getStackHeight() + "");
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.LAY, null, false), 3000);
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
@@ -10,12 +11,26 @@ import com.eu.habbo.habbohotel.users.Habbo;
|
||||
public class ActionSit extends PetAction {
|
||||
public ActionSit() {
|
||||
super(PetTasks.SIT, true);
|
||||
this.minimumActionDuration = 4000;
|
||||
this.statusToRemove.add(RoomUnitStatus.BEG);
|
||||
this.statusToRemove.add(RoomUnitStatus.MOVE);
|
||||
this.statusToRemove.add(RoomUnitStatus.LAY);
|
||||
this.statusToRemove.add(RoomUnitStatus.DEAD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
if (pet.getTask() != PetTasks.SIT && !pet.getRoomUnit().hasStatus(RoomUnitStatus.SIT)) {
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.SIT, pet.getRoom().getStackHeight(pet.getRoomUnit().getX(), pet.getRoomUnit().getY(), false) - 0.50 + "");
|
||||
pet.getRoomUnit().cmdSit = true;
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.SIT, pet.getRoomUnit().getCurrentLocation().getStackHeight() + "");
|
||||
|
||||
// Sitting is a bit boring
|
||||
pet.addHappiness(-2);
|
||||
|
||||
Emulator.getThreading().run(() -> {
|
||||
pet.getRoomUnit().cmdSit = false;
|
||||
pet.clearPosture();
|
||||
}, this.minimumActionDuration);
|
||||
|
||||
if (pet.getHappiness() > 75)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
@@ -25,6 +40,6 @@ public class ActionSit extends PetAction {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ public class ActionSpeak extends PetAction {
|
||||
pet.setMuted(false);
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.SPEAK, null, false), 2000);
|
||||
|
||||
// Speaking/expressing itself makes pet happy
|
||||
pet.addHappiness(3);
|
||||
|
||||
if (pet.getHappiness() > 70)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_HAPPY));
|
||||
else if (pet.getHappiness() < 30)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUserRotation;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
public class ActionSpin extends PetAction {
|
||||
public ActionSpin() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 2000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
|
||||
// Spin animation - rotate through all directions
|
||||
for (int i = 0; i < 8; i++) {
|
||||
final int rotation = i;
|
||||
Emulator.getThreading().run(() -> {
|
||||
pet.getRoomUnit().setRotation(RoomUserRotation.values()[rotation]);
|
||||
pet.packetUpdate = true;
|
||||
}, i * 250);
|
||||
}
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,10 @@ public class ActionStay extends PetAction {
|
||||
|
||||
pet.getRoomUnit().setCanWalk(false);
|
||||
pet.setStayStartedAt(Emulator.getIntUnixTimestamp());
|
||||
|
||||
// Staying still is boring
|
||||
pet.addHappiness(-5);
|
||||
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetTree;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionSwing extends PetAction {
|
||||
public ActionSwing() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 4000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
// Swing requires pet to be on a pet tree (dragon/monkey tree)
|
||||
if (pet.getRoom() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HabboItem itemBelow = pet.getRoom().getTopItemAt(pet.getRoomUnit().getX(), pet.getRoomUnit().getY());
|
||||
if (!(itemBelow instanceof InteractionPetTree)) {
|
||||
// Pet must go to tree first
|
||||
pet.findTree();
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.DISOBEY));
|
||||
return false;
|
||||
}
|
||||
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.SWING, "");
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.SWING, null, false), 4000);
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
public class ActionSwitch extends PetAction {
|
||||
public ActionSwitch() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
|
||||
// Switch/toggle behavior - pet acknowledges command
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
public class ActionTeleport extends PetAction {
|
||||
public ActionTeleport() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
// Teleport pet to a random walkable tile near owner
|
||||
if (habbo != null && habbo.getRoomUnit() != null && pet.getRoom() != null) {
|
||||
RoomTile targetTile = pet.getRoom().getLayout().getTileInFront(
|
||||
habbo.getRoomUnit().getCurrentLocation(),
|
||||
habbo.getRoomUnit().getBodyRotation().getValue()
|
||||
);
|
||||
|
||||
if (targetTile != null && targetTile.isWalkable()) {
|
||||
pet.getRoomUnit().setLocation(targetTile);
|
||||
pet.getRoomUnit().setZ(targetTile.getStackHeight());
|
||||
pet.packetUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (pet.getHappiness() > 50)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ public class ActionTorch extends PetAction {
|
||||
return false;
|
||||
}
|
||||
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.EAT, null, false), this.minimumActionDuration);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionTripleJump extends PetAction {
|
||||
public ActionTripleJump() {
|
||||
super(PetTasks.JUMP, true);
|
||||
this.minimumActionDuration = 4000;
|
||||
this.statusToSet.add(RoomUnitStatus.JUMP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
|
||||
// Triple jump - three jump animations
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Emulator.getThreading().run(() -> {
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.JUMP, "");
|
||||
pet.packetUpdate = true;
|
||||
}, i * 1200);
|
||||
}
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.JUMP, null, false), 4000);
|
||||
|
||||
if (pet.getHappiness() > 70)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.eu.habbo.habbohotel.pets.actions;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
|
||||
public class ActionWagTail extends PetAction {
|
||||
public ActionWagTail() {
|
||||
super(PetTasks.FREE, true);
|
||||
this.minimumActionDuration = 2000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pet pet, Habbo habbo, String[] data) {
|
||||
pet.clearPosture();
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.WAG_TAIL, "");
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.WAG_TAIL, null, false), 2000);
|
||||
|
||||
if (pet.getHappiness() > 40)
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_HAPPY));
|
||||
else
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetAction;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.threading.runnables.PetClearPosture;
|
||||
@@ -22,9 +23,15 @@ public class ActionWave extends PetAction {
|
||||
pet.getRoomUnit().setStatus(RoomUnitStatus.WAVE, "0");
|
||||
|
||||
Emulator.getThreading().run(new PetClearPosture(pet, RoomUnitStatus.WAVE, null, false), 2000);
|
||||
|
||||
// Waving is a fun trick
|
||||
pet.addHappiness(5);
|
||||
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.PLAYFUL));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GENERIC_NEUTRAL));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
package com.eu.habbo.habbohotel.pets.breeding;
|
||||
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetBreedingNest;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Represents an active breeding session between two pets.
|
||||
* Manages the state and lifecycle of the breeding process.
|
||||
*/
|
||||
public class PetBreedingSession {
|
||||
private final InteractionPetBreedingNest nest;
|
||||
private final Pet petOne;
|
||||
private Pet petTwo;
|
||||
private final long startTime;
|
||||
private BreedingState state;
|
||||
private ScheduledFuture<?> timeoutTask;
|
||||
|
||||
/**
|
||||
* Represents the various states of a breeding session.
|
||||
*/
|
||||
public enum BreedingState {
|
||||
WAITING_FOR_SECOND_PET,
|
||||
WAITING_FOR_CONFIRMATION,
|
||||
BREEDING_IN_PROGRESS,
|
||||
COMPLETED,
|
||||
CANCELLED
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new breeding session with the first pet.
|
||||
* @param nest The breeding nest item
|
||||
* @param firstPet The first pet to enter the nest
|
||||
*/
|
||||
public PetBreedingSession(InteractionPetBreedingNest nest, Pet firstPet) {
|
||||
this.nest = nest;
|
||||
this.petOne = firstPet;
|
||||
this.petTwo = null;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.state = BreedingState.WAITING_FOR_SECOND_PET;
|
||||
|
||||
// Auto-cancel if second pet doesn't arrive within configured timeout
|
||||
int timeoutSeconds = Emulator.getConfig().getInt("pet.breeding.timeout_seconds", 120);
|
||||
this.timeoutTask = Emulator.getThreading().getService().schedule(() -> {
|
||||
if (this.state == BreedingState.WAITING_FOR_SECOND_PET) {
|
||||
this.cancel("Timeout waiting for second pet");
|
||||
}
|
||||
}, timeoutSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to add the second pet to the breeding session.
|
||||
* @param pet The second pet to add
|
||||
* @return true if the pet was successfully added
|
||||
*/
|
||||
public boolean addSecondPet(Pet pet) {
|
||||
if (this.state != BreedingState.WAITING_FOR_SECOND_PET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate compatibility - must be same pet type
|
||||
if (pet.getPetData().getType() != this.petOne.getPetData().getType()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if breeding is possible for this pet type
|
||||
if (pet.getPetData().getOffspringType() == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't allow breeding with self
|
||||
if (pet.getId() == this.petOne.getId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.petTwo = pet;
|
||||
this.state = BreedingState.WAITING_FOR_CONFIRMATION;
|
||||
|
||||
// Cancel the timeout task since we have both pets
|
||||
if (this.timeoutTask != null && !this.timeoutTask.isDone()) {
|
||||
this.timeoutTask.cancel(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirms the breeding and starts the process.
|
||||
* @param habbo The habbo confirming the breeding
|
||||
* @param offspringName The name for the offspring
|
||||
*/
|
||||
public void confirm(Habbo habbo, String offspringName) {
|
||||
if (this.state != BreedingState.WAITING_FOR_CONFIRMATION) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = BreedingState.BREEDING_IN_PROGRESS;
|
||||
this.nest.breed(habbo, offspringName, this.petOne.getId(), this.petTwo.getId());
|
||||
this.state = BreedingState.COMPLETED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the breeding session and releases the pets.
|
||||
* @param reason The reason for cancellation
|
||||
*/
|
||||
public void cancel(String reason) {
|
||||
if (this.state == BreedingState.COMPLETED || this.state == BreedingState.CANCELLED) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = BreedingState.CANCELLED;
|
||||
|
||||
// Release first pet
|
||||
if (this.petOne != null && this.petOne.getRoomUnit() != null) {
|
||||
this.petOne.getRoomUnit().setCanWalk(true);
|
||||
this.petOne.setTask(PetTasks.FREE);
|
||||
}
|
||||
|
||||
// Release second pet
|
||||
if (this.petTwo != null && this.petTwo.getRoomUnit() != null) {
|
||||
this.petTwo.getRoomUnit().setCanWalk(true);
|
||||
this.petTwo.setTask(PetTasks.FREE);
|
||||
}
|
||||
|
||||
// Reset nest state
|
||||
this.nest.setExtradata("0");
|
||||
if (this.nest.getRoomId() > 0) {
|
||||
com.eu.habbo.habbohotel.rooms.Room room = com.eu.habbo.Emulator.getGameEnvironment().getRoomManager().getRoom(this.nest.getRoomId());
|
||||
if (room != null) {
|
||||
room.updateItem(this.nest);
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel any pending timeout task
|
||||
if (this.timeoutTask != null && !this.timeoutTask.isDone()) {
|
||||
this.timeoutTask.cancel(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the breeding session is still valid.
|
||||
* @return true if both pets are still in the same room
|
||||
*/
|
||||
public boolean isValid() {
|
||||
if (this.petOne == null || this.petOne.getRoom() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.petTwo != null && this.petTwo.getRoom() != this.petOne.getRoom()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public InteractionPetBreedingNest getNest() { return nest; }
|
||||
public Pet getPetOne() { return petOne; }
|
||||
public Pet getPetTwo() { return petTwo; }
|
||||
public long getStartTime() { return startTime; }
|
||||
public BreedingState getState() { return state; }
|
||||
|
||||
/**
|
||||
* Gets how long the session has been active in milliseconds.
|
||||
* @return Duration in milliseconds
|
||||
*/
|
||||
public long getDuration() {
|
||||
return System.currentTimeMillis() - this.startTime;
|
||||
}
|
||||
}
|
||||
@@ -946,8 +946,20 @@ public class Room implements Comparable<Room>, ISerialize, Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
this.unitManager.clear();
|
||||
// Save ALL remaining pets (including owner's pets) BEFORE clearing
|
||||
TIntObjectIterator<Pet> petIterator = this.getCurrentPets().iterator();
|
||||
for (int i = this.getCurrentPets().size(); i-- > 0; ) {
|
||||
try {
|
||||
petIterator.advance();
|
||||
petIterator.value().needsUpdate = true;
|
||||
petIterator.value().run(); // Run synchronously to ensure DB is updated before room reload
|
||||
} catch (NoSuchElementException e) {
|
||||
LOGGER.error("Caught exception", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.unitManager.clear();
|
||||
this.unitManager.clearBots();
|
||||
this.unitManager.clearPets();
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -434,6 +434,12 @@ public class RoomCycleManager {
|
||||
}
|
||||
|
||||
if (!unit.isWalking() && !unit.cmdSit) {
|
||||
// Don't override special pet statuses with SIT
|
||||
boolean hasSpecialPetStatus = unit.hasStatus(RoomUnitStatus.HANG)
|
||||
|| unit.hasStatus(RoomUnitStatus.SWING)
|
||||
|| unit.hasStatus(RoomUnitStatus.FLAME)
|
||||
|| unit.hasStatus(RoomUnitStatus.PLAY);
|
||||
|
||||
RoomTile thisTile = this.room.getLayout().getTile(unit.getX(), unit.getY());
|
||||
HabboItem topItem = this.room.getTallestChair(thisTile);
|
||||
|
||||
@@ -442,7 +448,7 @@ public class RoomCycleManager {
|
||||
unit.removeStatus(RoomUnitStatus.SIT);
|
||||
update = true;
|
||||
}
|
||||
} else if (thisTile.state == RoomTileState.SIT && (!unit.hasStatus(RoomUnitStatus.SIT)
|
||||
} else if (!hasSpecialPetStatus && thisTile.state == RoomTileState.SIT && (!unit.hasStatus(RoomUnitStatus.SIT)
|
||||
|| unit.sitUpdate)) {
|
||||
this.room.dance(unit, DanceType.NONE);
|
||||
unit.setStatus(RoomUnitStatus.SIT, (Item.getCurrentHeight(topItem) * 1.0D) + "");
|
||||
|
||||
@@ -13,11 +13,9 @@ import com.eu.habbo.habbohotel.items.interactions.games.battlebanzai.Interaction
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.freeze.InteractionFreezeExitTile;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagField;
|
||||
import com.eu.habbo.habbohotel.items.interactions.games.tag.InteractionTagPole;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionNest;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetBreedingNest;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetDrink;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetFood;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.*;
|
||||
import com.eu.habbo.habbohotel.items.interactions.wired.extra.WiredBlob;
|
||||
import com.eu.habbo.habbohotel.permissions.Permission;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
import com.eu.habbo.habbohotel.users.HabboInfo;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
@@ -25,23 +23,10 @@ import com.eu.habbo.habbohotel.users.HabboManager;
|
||||
import com.eu.habbo.habbohotel.wired.core.WiredManager;
|
||||
import com.eu.habbo.habbohotel.wired.tick.WiredTickable;
|
||||
import com.eu.habbo.messages.outgoing.inventory.AddHabboItemComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.FloorItemUpdateComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.ItemStateComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.RemoveFloorItemComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.RemoveWallItemComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.WallItemUpdateComposer;
|
||||
import com.eu.habbo.habbohotel.permissions.Permission;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.AddFloorItemComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.AddWallItemComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.FloorItemOnRollerComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.*;
|
||||
import com.eu.habbo.plugin.Event;
|
||||
import com.eu.habbo.plugin.events.furniture.FurnitureBuildheightEvent;
|
||||
import com.eu.habbo.plugin.events.furniture.FurnitureMovedEvent;
|
||||
import com.eu.habbo.plugin.events.furniture.FurniturePickedUpEvent;
|
||||
import com.eu.habbo.plugin.events.furniture.FurniturePlacedEvent;
|
||||
import com.eu.habbo.plugin.events.furniture.FurnitureRotatedEvent;
|
||||
import com.eu.habbo.plugin.events.furniture.*;
|
||||
import gnu.trove.TCollections;
|
||||
import org.apache.commons.math3.util.Pair;
|
||||
import gnu.trove.iterator.TIntObjectIterator;
|
||||
import gnu.trove.map.TIntIntMap;
|
||||
import gnu.trove.map.TIntObjectMap;
|
||||
@@ -49,6 +34,7 @@ import gnu.trove.map.hash.THashMap;
|
||||
import gnu.trove.map.hash.TIntIntHashMap;
|
||||
import gnu.trove.map.hash.TIntObjectHashMap;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
import org.apache.commons.math3.util.Pair;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -661,6 +647,10 @@ public class RoomItemManager {
|
||||
specialTypes.addPetDrink((InteractionPetDrink) item);
|
||||
} else if (item instanceof InteractionPetFood) {
|
||||
specialTypes.addPetFood((InteractionPetFood) item);
|
||||
} else if (item instanceof InteractionPetToy) {
|
||||
specialTypes.addPetToy((InteractionPetToy) item);
|
||||
} else if (item instanceof InteractionPetTree) {
|
||||
specialTypes.addPetTree((InteractionPetTree) item);
|
||||
} else if (item instanceof InteractionMoodLight ||
|
||||
item instanceof InteractionPyramid ||
|
||||
item instanceof InteractionMusicDisc ||
|
||||
@@ -780,6 +770,10 @@ public class RoomItemManager {
|
||||
specialTypes.removePetDrink((InteractionPetDrink) item);
|
||||
} else if (item instanceof InteractionPetFood) {
|
||||
specialTypes.removePetFood((InteractionPetFood) item);
|
||||
} else if (item instanceof InteractionPetToy) {
|
||||
specialTypes.removePetToy((InteractionPetToy) item);
|
||||
} else if (item instanceof InteractionPetTree) {
|
||||
specialTypes.removePetTree((InteractionPetTree) item);
|
||||
} else if (item instanceof InteractionMoodLight ||
|
||||
item instanceof InteractionPyramid ||
|
||||
item instanceof InteractionMusicDisc ||
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.eu.habbo.habbohotel.items.interactions.pets.InteractionNest;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetDrink;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetFood;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetToy;
|
||||
import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetTree;
|
||||
import com.eu.habbo.habbohotel.users.HabboItem;
|
||||
import com.eu.habbo.habbohotel.wired.WiredConditionType;
|
||||
import com.eu.habbo.habbohotel.wired.WiredEffectType;
|
||||
@@ -45,6 +46,7 @@ public class RoomSpecialTypes {
|
||||
private final THashMap<Integer, InteractionPetDrink> petDrinks;
|
||||
private final THashMap<Integer, InteractionPetFood> petFoods;
|
||||
private final THashMap<Integer, InteractionPetToy> petToys;
|
||||
private final THashMap<Integer, InteractionPetTree> petTrees;
|
||||
private final THashMap<Integer, InteractionRoller> rollers;
|
||||
|
||||
// Thread-safe wired collections using ConcurrentHashMap for better concurrency
|
||||
@@ -73,6 +75,7 @@ public class RoomSpecialTypes {
|
||||
this.petDrinks = new THashMap<>(0);
|
||||
this.petFoods = new THashMap<>(0);
|
||||
this.petToys = new THashMap<>(0);
|
||||
this.petTrees = new THashMap<>(0);
|
||||
this.rollers = new THashMap<>(0);
|
||||
|
||||
this.wiredTriggers = new ConcurrentHashMap<>();
|
||||
@@ -232,6 +235,28 @@ public class RoomSpecialTypes {
|
||||
}
|
||||
|
||||
|
||||
public InteractionPetTree getPetTree(int itemId) {
|
||||
return this.petTrees.get(itemId);
|
||||
}
|
||||
|
||||
public void addPetTree(InteractionPetTree item) {
|
||||
this.petTrees.put(item.getId(), item);
|
||||
}
|
||||
|
||||
public void removePetTree(InteractionPetTree petTree) {
|
||||
this.petTrees.remove(petTree.getId());
|
||||
}
|
||||
|
||||
public THashSet<InteractionPetTree> getPetTrees() {
|
||||
synchronized (this.petTrees) {
|
||||
THashSet<InteractionPetTree> petTrees = new THashSet<>();
|
||||
petTrees.addAll(this.petTrees.values());
|
||||
|
||||
return petTrees;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public InteractionRoller getRoller(int itemId) {
|
||||
synchronized (this.rollers) {
|
||||
return this.rollers.get(itemId);
|
||||
@@ -913,6 +938,23 @@ public class RoomSpecialTypes {
|
||||
|
||||
public THashSet<HabboItem> getItemsOfType(Class<? extends HabboItem> type) {
|
||||
THashSet<HabboItem> items = new THashSet<>();
|
||||
|
||||
// Check pet trees collection for InteractionPetTree type
|
||||
if (type == InteractionPetTree.class) {
|
||||
synchronized (this.petTrees) {
|
||||
items.addAll(this.petTrees.values());
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
// Check pet toys collection for InteractionPetToy type
|
||||
if (type == InteractionPetToy.class) {
|
||||
synchronized (this.petToys) {
|
||||
items.addAll(this.petToys.values());
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
synchronized (this.undefined) {
|
||||
for (HabboItem item : this.undefined.values()) {
|
||||
if (item.getClass() == type)
|
||||
@@ -959,6 +1001,8 @@ public class RoomSpecialTypes {
|
||||
this.nests.clear();
|
||||
this.petDrinks.clear();
|
||||
this.petFoods.clear();
|
||||
this.petToys.clear();
|
||||
this.petTrees.clear();
|
||||
this.rollers.clear();
|
||||
|
||||
this.wiredTriggers.clear();
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.bots.VisitorBot;
|
||||
import com.eu.habbo.habbohotel.items.Item;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetManager;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.pets.RideablePet;
|
||||
import com.eu.habbo.habbohotel.users.DanceType;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
@@ -983,7 +984,7 @@ public class RoomUnitManager {
|
||||
((RideablePet) pet).setRider(null);
|
||||
}
|
||||
|
||||
Emulator.getThreading().run(pet);
|
||||
pet.run(); // Run synchronously to ensure DB is updated before returning pet to inventory
|
||||
habbo.getInventory().getPetsComponent().addPet(pet);
|
||||
habbo.getClient().sendResponse(new AddPetComposer(pet));
|
||||
this.currentPets.remove(pet.getId());
|
||||
@@ -1266,11 +1267,29 @@ public class RoomUnitManager {
|
||||
// ==================== VISITOR BOT HANDLING ====================
|
||||
|
||||
/**
|
||||
* Handles Habbo entering the room (visitor bot notification).
|
||||
* Handles Habbo entering the room (visitor bot notification and pet greeting).
|
||||
*/
|
||||
public void habboEntered(Habbo habbo) {
|
||||
habbo.getRoomUnit().animateWalk = false;
|
||||
|
||||
// Have pets greet their owner
|
||||
synchronized (this.currentPets) {
|
||||
TIntObjectIterator<Pet> petIterator = this.currentPets.iterator();
|
||||
for (int i = this.currentPets.size(); i-- > 0; ) {
|
||||
try {
|
||||
petIterator.advance();
|
||||
Pet pet = petIterator.value();
|
||||
if (pet.getUserId() == habbo.getHabboInfo().getId()) {
|
||||
// Pet sees its owner - greet them!
|
||||
pet.say(pet.getPetData().randomVocal(PetVocalsType.GREET_OWNER));
|
||||
pet.addHappiness(10);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (this.currentBots) {
|
||||
if (habbo.getHabboInfo().getId() != this.room.getOwnerId()) {
|
||||
return;
|
||||
|
||||
@@ -55,6 +55,11 @@ public enum RoomUnitStatus {
|
||||
KICK("kck"),
|
||||
WAG_TAIL("wag"),
|
||||
DANCE("dan"),
|
||||
RINGOFFIRE("rng"),
|
||||
SWING("swg"),
|
||||
HANG("hg"),
|
||||
ROLL("rll"),
|
||||
FLAT("flt"),
|
||||
AMS("ams"),
|
||||
SWIM("swm"),
|
||||
TURN("trn"),
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public class PetPickupEvent extends MessageHandler {
|
||||
}
|
||||
|
||||
pet.removeFromRoom();
|
||||
Emulator.getThreading().run(pet);
|
||||
pet.run(); // Run synchronously to ensure DB is updated before returning pet to inventory
|
||||
|
||||
if (this.client.getHabbo().getHabboInfo().getId() == pet.getUserId()) {
|
||||
this.client.sendResponse(new AddPetComposer(pet));
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.eu.habbo.habbohotel.items.interactions.pets.InteractionPetFood;
|
||||
import com.eu.habbo.habbohotel.pets.GnomePet;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomUnitStatus;
|
||||
import com.eu.habbo.messages.outgoing.rooms.items.RemoveFloorItemComposer;
|
||||
import com.eu.habbo.messages.outgoing.rooms.users.RoomUserStatusComposer;
|
||||
@@ -22,28 +23,45 @@ public class PetEatAction implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
if (this.pet.getRoomUnit() != null && this.pet.getRoom() != null) {
|
||||
if (this.pet.levelHunger >= 20 && this.food != null && Integer.parseInt(this.food.getExtradata()) < this.food.getBaseItem().getStateCount()) {
|
||||
this.pet.addHunger(-20);
|
||||
// Check if food still has portions left (state < stateCount means food remaining)
|
||||
int currentState = 0;
|
||||
try {
|
||||
currentState = Integer.parseInt(this.food.getExtradata());
|
||||
} catch (NumberFormatException e) {
|
||||
currentState = 0;
|
||||
}
|
||||
|
||||
if (this.pet.levelHunger >= 10 && this.food != null && currentState < this.food.getBaseItem().getStateCount()) {
|
||||
// Say eating vocal on first bite
|
||||
if (currentState == 0 || Emulator.getRandom().nextInt(3) == 0) {
|
||||
this.pet.say(this.pet.getPetData().randomVocal(PetVocalsType.EATING));
|
||||
}
|
||||
|
||||
// Faster eating: reduce 40 hunger per bite instead of 20
|
||||
this.pet.addHunger(-40);
|
||||
this.pet.setTask(PetTasks.EAT);
|
||||
this.pet.getRoomUnit().setCanWalk(false);
|
||||
|
||||
this.food.setExtradata(Integer.valueOf(this.food.getExtradata()) + 1 + "");
|
||||
// Advance food state (each bite uses up a portion)
|
||||
this.food.setExtradata((currentState + 1) + "");
|
||||
this.pet.getRoom().updateItem(this.food);
|
||||
|
||||
if (this.pet instanceof GnomePet) {
|
||||
if (this.pet.getPetData().getType() == 26) {
|
||||
AchievementManager.progressAchievement(Emulator.getGameEnvironment().getHabboManager().getHabbo(this.pet.getUserId()), Emulator.getGameEnvironment().getAchievementManager().getAchievement("GnomeFeeding"), 20);
|
||||
AchievementManager.progressAchievement(Emulator.getGameEnvironment().getHabboManager().getHabbo(this.pet.getUserId()), Emulator.getGameEnvironment().getAchievementManager().getAchievement("GnomeFeeding"), 40);
|
||||
} else {
|
||||
AchievementManager.progressAchievement(Emulator.getGameEnvironment().getHabboManager().getHabbo(this.pet.getUserId()), Emulator.getGameEnvironment().getAchievementManager().getAchievement("LeprechaunFeeding"), 20);
|
||||
AchievementManager.progressAchievement(Emulator.getGameEnvironment().getHabboManager().getHabbo(this.pet.getUserId()), Emulator.getGameEnvironment().getAchievementManager().getAchievement("LeprechaunFeeding"), 40);
|
||||
}
|
||||
} else {
|
||||
AchievementManager.progressAchievement(Emulator.getGameEnvironment().getHabboManager().getHabbo(this.pet.getUserId()), Emulator.getGameEnvironment().getAchievementManager().getAchievement("PetFeeding"), 20);
|
||||
AchievementManager.progressAchievement(Emulator.getGameEnvironment().getHabboManager().getHabbo(this.pet.getUserId()), Emulator.getGameEnvironment().getAchievementManager().getAchievement("PetFeeding"), 40);
|
||||
}
|
||||
|
||||
Emulator.getThreading().run(this, 1000);
|
||||
// Faster eating: 500ms between bites instead of 1000ms
|
||||
Emulator.getThreading().run(this, 500);
|
||||
} else {
|
||||
if (this.food != null && Integer.parseInt(this.food.getExtradata()) == this.food.getBaseItem().getStateCount()) {
|
||||
Emulator.getThreading().run(new QueryDeleteHabboItem(this.food.getId()), 500);
|
||||
// Food is empty - remove it
|
||||
if (this.food != null && currentState >= this.food.getBaseItem().getStateCount()) {
|
||||
Emulator.getThreading().run(new QueryDeleteHabboItem(this.food.getId()), 250);
|
||||
if (this.pet.getRoom() != null) {
|
||||
this.pet.getRoom().removeHabboItem(this.food);
|
||||
this.pet.getRoom().sendComposer(new RemoveFloorItemComposer(this.food, true).compose());
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.eu.habbo.threading.runnables;
|
||||
import com.eu.habbo.Emulator;
|
||||
import com.eu.habbo.habbohotel.pets.Pet;
|
||||
import com.eu.habbo.habbohotel.pets.PetTasks;
|
||||
import com.eu.habbo.habbohotel.pets.PetVocalsType;
|
||||
import com.eu.habbo.habbohotel.rooms.RoomTile;
|
||||
import com.eu.habbo.habbohotel.users.Habbo;
|
||||
|
||||
@@ -19,31 +20,81 @@ public class PetFollowHabbo implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (this.pet != null) {
|
||||
if (this.pet.getTask() != PetTasks.FOLLOW)
|
||||
return;
|
||||
|
||||
if (this.habbo != null) {
|
||||
if (this.habbo.getRoomUnit() != null) {
|
||||
if (this.pet.getRoomUnit() != null) {
|
||||
RoomTile target = this.habbo.getHabboInfo().getCurrentRoom().getLayout().getTileInFront(this.habbo.getRoomUnit().getCurrentLocation(), Math.abs((this.habbo.getRoomUnit().getBodyRotation().getValue() + this.directionOffset + 4) % 8));
|
||||
|
||||
if (target != null) {
|
||||
if (target.x < 0 || target.y < 0)
|
||||
target = this.habbo.getHabboInfo().getCurrentRoom().getLayout().getTileInFront(this.habbo.getRoomUnit().getCurrentLocation(), this.habbo.getRoomUnit().getBodyRotation().getValue());
|
||||
|
||||
if (target.x >= 0 && target.y >= 0) {
|
||||
if (this.pet.getRoom().getLayout().tileWalkable(target.x, target.y)) {
|
||||
this.pet.getRoomUnit().setGoalLocation(target);
|
||||
this.pet.getRoomUnit().setCanWalk(true);
|
||||
this.pet.setTask(PetTasks.FOLLOW);
|
||||
}
|
||||
}
|
||||
Emulator.getThreading().run(this, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Comprehensive null checks
|
||||
if (this.pet == null || this.pet.getRoom() == null || this.pet.getRoomUnit() == null) {
|
||||
return; // Stop following - pet or room is gone
|
||||
}
|
||||
|
||||
// Check if task is any follow type
|
||||
PetTasks task = this.pet.getTask();
|
||||
if (task != PetTasks.FOLLOW && task != PetTasks.FOLLOW_LEFT && task != PetTasks.FOLLOW_RIGHT) {
|
||||
return; // Task was changed, stop
|
||||
}
|
||||
|
||||
// Check if habbo is still valid
|
||||
if (this.habbo == null || this.habbo.getRoomUnit() == null) {
|
||||
this.pet.setTask(PetTasks.FREE);
|
||||
return; // Owner gone, stop following
|
||||
}
|
||||
|
||||
// Check if habbo is still in the same room as the pet
|
||||
if (this.habbo.getHabboInfo().getCurrentRoom() != this.pet.getRoom()) {
|
||||
this.pet.setTask(PetTasks.FREE);
|
||||
this.pet.say(this.pet.getPetData().randomVocal(PetVocalsType.GENERIC_SAD));
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate target position
|
||||
RoomTile habboTile = this.habbo.getRoomUnit().getCurrentLocation();
|
||||
if (habboTile == null) {
|
||||
Emulator.getThreading().run(this, 500);
|
||||
return;
|
||||
}
|
||||
|
||||
int targetRotation = Math.abs((this.habbo.getRoomUnit().getBodyRotation().getValue()
|
||||
+ this.directionOffset + 4) % 8);
|
||||
|
||||
RoomTile target = this.pet.getRoom().getLayout().getTileInFront(habboTile, targetRotation);
|
||||
|
||||
// Validate target tile - try alternative positions if needed
|
||||
if (target == null || target.x < 0 || target.y < 0
|
||||
|| !this.pet.getRoom().getLayout().tileWalkable(target.x, target.y)) {
|
||||
// Try directly behind habbo
|
||||
target = this.pet.getRoom().getLayout().getTileInFront(
|
||||
habboTile,
|
||||
(this.habbo.getRoomUnit().getBodyRotation().getValue() + 4) % 8
|
||||
);
|
||||
}
|
||||
|
||||
// Try other adjacent positions if still invalid
|
||||
if (target == null || target.x < 0 || target.y < 0
|
||||
|| !this.pet.getRoom().getLayout().tileWalkable(target.x, target.y)) {
|
||||
// Try to the left
|
||||
target = this.pet.getRoom().getLayout().getTileInFront(
|
||||
habboTile,
|
||||
(this.habbo.getRoomUnit().getBodyRotation().getValue() + 2) % 8
|
||||
);
|
||||
}
|
||||
|
||||
if (target == null || target.x < 0 || target.y < 0
|
||||
|| !this.pet.getRoom().getLayout().tileWalkable(target.x, target.y)) {
|
||||
// Try to the right
|
||||
target = this.pet.getRoom().getLayout().getTileInFront(
|
||||
habboTile,
|
||||
(this.habbo.getRoomUnit().getBodyRotation().getValue() + 6) % 8
|
||||
);
|
||||
}
|
||||
|
||||
// If we found a valid target, move there
|
||||
if (target != null && target.x >= 0 && target.y >= 0) {
|
||||
if (this.pet.getRoom().getLayout().tileWalkable(target.x, target.y)) {
|
||||
this.pet.getRoomUnit().setGoalLocation(target);
|
||||
this.pet.getRoomUnit().setCanWalk(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Continue following with slight randomization for natural behavior
|
||||
int nextDelay = 400 + Emulator.getRandom().nextInt(200);
|
||||
Emulator.getThreading().run(this, nextDelay);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -75,7 +75,8 @@ class FreezeHandleSnowballExplosion implements Runnable {
|
||||
habbos.addAll(this.thrownData.room.getHabbosAt(freezeTile.getX(), freezeTile.getY()));
|
||||
|
||||
for (Habbo habbo : habbos) {
|
||||
if (habbo.getHabboInfo().getGamePlayer() != null && habbo.getHabboInfo().getGamePlayer() instanceof FreezeGamePlayer hPlayer) {
|
||||
if (habbo.getHabboInfo().getGamePlayer() != null && habbo.getHabboInfo().getGamePlayer() instanceof FreezeGamePlayer) {
|
||||
FreezeGamePlayer hPlayer = (FreezeGamePlayer) habbo.getHabboInfo().getGamePlayer();
|
||||
if (!hPlayer.canGetFrozen())
|
||||
continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user