Initial commit

This commit is contained in:
WatermelonModders
2022-05-31 12:35:46 -04:00
commit fc5cb0c32c
4097 changed files with 447075 additions and 0 deletions
+323
View File
@@ -0,0 +1,323 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
/*
static void summon_obelisk(struct powerhistory_data_s **data, struct deck_s *deck, struct card_s *new_card)
{
struct powerhistory_tag_s *card_tags;
struct powerhistory_entity_s *show;
add_powerstart(data, 3, -1, new_card->id, 0, NULL, 0);
int pos = cards_board_last(deck, new_card);
card_tags = default_tags(new_card, new_card->entity, 0);
add_tag(&card_tags, CONTROLLER, deck->controller);
add_tag(&card_tags, ENTITY_ID, new_card->id);
add_full_entity(&show, card_tags, new_card->id, new_card->entity->name, new_card->entity->nname);
add_ph_data_full(data, show);
add_tagchange(data, ZONE_POSITION, pos, new_card->id);
add_tagchange(data, ZONE, 1, new_card->id);
add_powerend(data);
}
*/
static int get_card_start_play(int entity_id, struct deck_s *deck, char *output, const int noutput, int *drawn_card, struct deck_s *opponent, struct card_s ***obelisk, struct hs_holder_s *h)
{
// FIXME: send this to both players??
struct card_s *new_card;
struct powerhistory_tag_s *card_tags;
struct powerhistory_entity_s *show;
struct powerhistory_data_s *data = NULL;
struct powerhistory_s *ph = NULL;
struct packet_s *p = NULL;
char *ptr;
add_tagchange(&data, STEP, 6, 1);
add_powerstart(&data, 5, 1, entity_id, 0, NULL, 0);
//add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 66); // hero
//add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 67); // hero power
add_tagchange(&data, RESOURCES, 1, entity_id);
add_tagchange(&data, 399, 0, entity_id);
add_tagchange(&data, NEXT_STEP, 17, 1);
add_powerend(&data);
add_tagchange(&data, STEP, 17, 1);
add_powerstart(&data, 5, 8, entity_id, 0, NULL, 0);
add_tagchange(&data, NEXT_STEP, 9, 1);
add_powerend(&data);
add_tagchange(&data, STEP, 9, 1);
/*
if((*obelisk)[0] == NULL && (*obelisk)[1] == NULL) {
(*obelisk)[0] = add_new_card(h->game, deck, -1, "EX1_614", -1);
(*obelisk)[1] = add_new_card(h->game, opponent, -1, "EX1_614", -1);
flag(&((*obelisk)[0])->state, CARD_BOARD, FLAG_SET);
flag(&((*obelisk)[1])->state, CARD_BOARD, FLAG_SET);
deck->board_position[0] = (*obelisk)[0]->id;
opponent->board_position[0] = (*obelisk)[1]->id;
summon_obelisk(&data, deck, (*obelisk)[0]);
summon_obelisk(&data, opponent, (*obelisk)[1]);
} else {
summon_obelisk(&data, opponent, (*obelisk)[0]);
summon_obelisk(&data, deck, (*obelisk)[1]);
}
assert((*obelisk)[0] && (*obelisk)[1]);
*/
add_powerstart(&data, 5, 0, entity_id, 0, NULL, 0);
if(*drawn_card != 0) {
add_tagchange(&data, ZONE_POSITION, 4, *drawn_card);
add_tagchange(&data, ZONE, ZONE_HAND, *drawn_card);
} else {
hm_log(LOG_DEBUG, lg, "about to draw card player %d", entity_id);
new_card = draw_random_card(deck, entity_id, -1);
card_tags = default_tags(new_card, new_card->entity, 0);
add_full_entity(&show, card_tags, new_card->id, new_card->entity->name, new_card->entity->nname);
add_ph_data_show(&data, show);
add_tagchange(&data, ZONE, ZONE_HAND, new_card->id);
add_tagchange(&data, ZONE_POSITION, new_card->zone_position, new_card->id);
*drawn_card = new_card->id;
hm_log(LOG_DEBUG, lg, "p2: zone position: %d card: %d", new_card->zone_position, new_card->id);
}
add_tagchange(&data, 399, 1, entity_id);
add_tagchange(&data, NEXT_STEP, 10, 1);
add_powerend(&data);
add_tagchange(&data, STEP, 10, 1);
add_powerstart(&data, 5, 2, entity_id, 0, NULL, 0);
add_tagchange(&data, NEXT_STEP, 12, 1);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&p, ph, P_POWERHISTORY);
powerhistory_dump(ph);
ptr = output;
int n = serialize(p, &ptr, ptr + noutput);
packet_free(p);
int o = 0;
// only player needs options
if(entity_id == 3) {
o = set_options(deck, opponent, output + n, ptr + noutput - n, 1);
}
return n + o;
}
void choose_one_entity(struct conn_client_s *c, struct chooseentities_s *e)
{
int id = 0;
struct chooseentities_ent_s *ent;
for(ent = e->entity; ent != NULL; ent = ent->next) {
id = ent->entity;
break;
}
assert(id > 0);
//card = card_get();
//flag(&card->state, CARD_DECK, FLAG_UNSET);
//flag(&card->state, CARD_HAND, FLAG_SET);
//card->zone_position = ++deck->handposition;
}
void choose_entities(struct conn_client_s *c, struct chooseentities_s *e)
{
struct chooseentities_ent_s *ent;
struct hs_holder_s *h;
//struct card_s *unwanted[4];
int nunwanted = 0;
//struct card_s *new_card;
//struct powerhistory_tag_s *card_tags;
//struct powerhistory_entity_s *show;
struct powerhistory_data_s *data = NULL, *data1 = NULL;
struct powerhistory_s *ph = NULL, *ph1 = NULL;
struct packet_s *p = NULL, *p1 = NULL;
char out[2048], *ptr, out1[2048], *ptr1;
int i, cw;
h = c->data;
assert(h);
if(h->id == 1) {
//max = 4; // p1 4 cards
assert(e->nentity <= 4);
} else {
//max = 3; // p2 3 cards
assert(e->nentity <= 3);
}
hm_log(LOG_EMERG, lg, "Unwanted cards");
for(i = 0; i < h->deck->ncards; i++) {
if(flag(&h->deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) {
hm_log(LOG_ALERT, c->log, "player %d hand card: %d zone_position: %d", h->entity_id, h->deck->cards[i]->id, h->deck->cards[i]->zone_position);
cw = 0;
for(ent = e->entity; ent != NULL; ent = ent->next) {
if(ent->entity == h->deck->cards[i]->id) {
hm_log(LOG_ALERT, c->log, "breaking with card: %d", h->deck->cards[i]->id);
cw = 1;
break;
}
}
if(cw == 0 && h->deck->cards[i]->id != 68) {
//unwanted[nunwanted++] = h->deck->cards[i];
hm_log(LOG_EMERG, c->log, "player %d unwanted card: %d zone_position: %d", h->entity_id, h->deck->cards[i]->id, h->deck->cards[i]->zone_position);
}
}
}
add_tagchange(&data, MULLIGAN_STATE, 2, h->entity_id);
add_tagchange(&data1, MULLIGAN_STATE, 2, h->entity_id);
add_powerstart(&data, 5, 6, h->entity_id, 0, NULL, 0);
add_powerstart(&data1, 5, 6, h->entity_id, 0, NULL, 0);
for(i = 0; i < nunwanted; i++) {
/*
new_card = draw_random_card(h->deck, h->entity_id, unwanted[i]->zone_position);
hm_log(LOG_DEBUG, c->log, "playerID: %d new card: %d position: %d", h->entity_id, new_card->id, new_card->zone_position);
card_tags = default_tags(new_card, new_card->entity, 0);
add_full_entity(&show, card_tags, new_card->id, new_card->entity->name, new_card->entity->nname);
add_ph_data_show(&data, show);
add_tagchange(&data1, ZONE, 3, new_card->id);
add_tagchange(&data, ZONE_POSITION, new_card->zone_position, new_card->id);
add_tagchange(&data1, ZONE_POSITION, new_card->zone_position, new_card->id);
add_hide(&data, unwanted[i]->id, 2);
add_tagchange(&data, ZONE, 2, unwanted[i]->id);
add_tagchange(&data1, ZONE, 2, unwanted[i]->id);
add_tagchange(&data, ZONE_POSITION, 0, unwanted[i]->id);
add_tagchange(&data1, ZONE_POSITION, 0, unwanted[i]->id);
flag(&unwanted[i]->state, CARD_HAND, FLAG_UNSET);
flag(&unwanted[i]->state, CARD_DECK, FLAG_SET);
*/
}
add_tagchange(&data, MULLIGAN_STATE, 3, h->entity_id);
add_tagchange(&data1, MULLIGAN_STATE, 3, h->entity_id);
add_powerend(&data);
add_powerend(&data1);
add_powerstart(&data, 5, 7, h->entity_id, 0, NULL, 0);
add_powerstart(&data1, 5, 7, h->entity_id, 0, NULL, 0);
add_tagchange(&data, MULLIGAN_STATE, 4, h->entity_id);
add_tagchange(&data1, MULLIGAN_STATE, 4, h->entity_id);
if(h->id == 1) {
h->game->flags |= G_P1_CARDS_CHOSEN;
} else {
h->game->flags |= G_P2_CARDS_CHOSEN;
}
if(EQFLAG(h->game->flags, (G_P1_CARDS_CHOSEN|G_P2_CARDS_CHOSEN))) {
add_tagchange(&data, NEXT_STEP, 6, 1);
add_tagchange(&data1, NEXT_STEP, 6, 1);
}
add_powerend(&data);
add_powerend(&data1);
add_ph(&ph, data);
add_packet(&p, ph, P_POWERHISTORY);
add_ph(&ph1, data1);
add_packet(&p1, ph1, P_POWERHISTORY);
powerhistory_dump(ph);
powerhistory_dump(ph1);
ptr = out;
int n = serialize(p, &ptr, ptr + sizeof(out));
packet_free(p);
ptr1 = out1;
int n1 = serialize(p1, &ptr1, ptr1 + sizeof(out1));
packet_free(p1);
//powerhistory_dump(ph);
//powerhistory_dump(ph1);
// p2 draws a card and notifies p1
if(EQFLAG(h->game->flags, (G_P1_CARDS_CHOSEN|G_P2_CARDS_CHOSEN))) {
char out2[2048], out3[2048];
int new_card_id = 0;
int enc, enc3;
struct card_s **obelisk;
obelisk = malloc(sizeof(void *) * 2);
memset(obelisk, 0, sizeof(void *) * 2);
if(h->entity_id == 3) {
enc = get_card_start_play(3, h->deck, out2, sizeof(out2), &new_card_id, h->opponent.deck, &obelisk, h);
enc3 = get_card_start_play(2, h->opponent.deck, out3, sizeof(out3), &new_card_id, h->deck, &obelisk, h);
} else {
enc3 = get_card_start_play(3, h->opponent.deck, out3, sizeof(out3), &new_card_id, h->deck, &obelisk, h);
enc = get_card_start_play(2, h->deck, out2, sizeof(out2), &new_card_id, h->opponent.deck, &obelisk, h);
}
memcpy(out + n, out2, enc);
memcpy(out1 + n1, out3, enc3);
hm_send(c, out, n + enc);
hm_send(h->opponent.client, out1, n1 + enc3);
register_turntimer(c);
} else {
hm_send(c, out, n);
hm_send(h->opponent.client, out1, n1);
}
}
+917
View File
@@ -0,0 +1,917 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
enum metatype_e {
METATYPE_DAMAGE = 1,
METATYPE_HEAL = 2,
};
void cards_reorder(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, u64 position, int summoned)
{
if(summoned == 0) {
cards_reorder_hand_owner(deck, attacker->id);
}
// spell card is never placed on board
if(!flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) {
cards_reorder_board_owner(deck, attacker->id, position);
}
}
struct packet_s *choose_option_player1(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
//struct deck_s *deck;
p = c->data;
//deck = p->deck;
add_powerstart(&data, 7, 0, p->held_card, opt->target, NULL, 0);
add_tagchange(&data, TEMP_RESOURCES, 0, p->entity_id);
add_tagchange(&data, RESOURCES_USED, p->deck->mana_used, p->entity_id);
add_tagchange(&data, 418, 3, p->entity_id);
add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id);
add_tagchange(&data, NUM_MINIONS_PLAYED_THIS_TURN, 1, p->entity_id);
//cards_reorder(deck, &data, attacker, opt, player);
/*
// set new zone positions for owner
if(player == 1) {
cards_reorder_hand_owner(p->deck, p->held_card);
cards_reorder_board_owner(&data, p->deck, p->held_card, opt->position);
for(i = 0; i < deck->ncards; i++) {
if(EQFLAG(deck->cards[i]->state, CARD_HAND)) {
hm_log(LOG_DEBUG, lg, "new position %d for card: %d", deck->cards[i]->zone_position, deck->cards[i]->id);
add_tagchange(&data, ZONE_POSITION, deck->cards[i]->zone_position, deck->cards[i]->id);
}
}
}
if(player == 2) {
cards_reorder_hand_opponent(&data, p->deck);
cards_reorder_board_opponent(&data, p->deck);
for(i = 0; i < deck->ncards; i++) {
if(deck->cards[i]->id == p->held_card) {
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i]->entity);
add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname);
add_ph_data_show(&data, show);
break;
}
}
}
*/
add_tagchange(&data, ZONE, 1, p->held_card);
add_tagchange(&data, JUST_PLAYED, 1, p->held_card);
add_tagchange(&data, ZONE_POSITION, opt->position, p->held_card);
add_tagchange(&data, 397, p->held_card, p->entity_id);
hm_log(LOG_DEBUG, lg, "board zone position %lld for card: %d", opt->position, p->held_card);
add_powerstart(&data, 3, -1, p->held_card, opt->target, NULL, 0);
add_powerend(&data);
add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
//powerhistory_dump(ph);
return packet;
}
struct packet_s *nontarget(struct conn_client_s *c, struct card_s *attacker)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
p = c->data;
add_powerstart(&data, 7, 0, attacker->id, 0, NULL, 0);
add_tagchange(&data, TEMP_RESOURCES, 0, p->entity_id);
add_tagchange(&data, RESOURCES_USED, 1, p->entity_id);
add_tagchange(&data, 418, 2, p->entity_id);
add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0);
struct powerhistory_entity_s *full = NULL;
struct card_s *card = NULL;
if(flag(&attacker->state, CARD_HP_REINFORCE, FLAG_ISSET)) {
card = add_new_card(p->game, p->deck, -1, "CS2_101t", -1);
struct powerhistory_tag_s *card_tags = default_tags(card, card->entity, 0);
int zone_position = zone_position_last(p->deck);
add_tag(&card_tags, ZONE_POSITION, zone_position);
add_tag(&card_tags, CONTROLLER, p->id);
add_tag(&card_tags, ENTITY_ID, card->id);
add_tag(&card_tags, CREATOR, attacker->id);
add_full_entity(&full, card_tags, card->id, card->entity->name, card->entity->nname);
add_ph_data_full(&data, full);
card->zone_position = zone_position;
//card->state |= (CARD_BOARD|CARD_EXHAUSTED);
flag(&card->state, CARD_BOARD, FLAG_SET);
flag(&card->state, CARD_EXHAUSTED, FLAG_SET);
} else if(flag(&attacker->state, CARD_HP_DAGGERMASTERY, FLAG_ISSET)) {
card = add_new_card(p->game, p->deck, -1, "CS2_082", -1);
struct powerhistory_tag_s *card_tags = default_tags(card, card->entity, 0);
add_tag(&card_tags, CONTROLLER, p->id);
add_tag(&card_tags, ENTITY_ID, card->id);
add_tag(&card_tags, CREATOR, attacker->id);
add_full_entity(&full, card_tags, card->id, card->entity->name, card->entity->nname);
add_ph_data_full(&data, full);
add_tagchange(&data, 334, attacker->id, p->entity_id);
p->deck->heroweapon = card;
//card->state |= CARD_EXHAUSTED;
flag(&card->state, CARD_EXHAUSTED, FLAG_SET);
} else if(flag(&attacker->state, CARD_HP_SHAPESHIFT, FLAG_ISSET)) {
p->deck->hero->armor += attacker->attack;
p->deck->hero->attack = attacker->attack;
add_tagchange(&data, ARMOR, p->deck->hero->armor, p->deck->hero->id);
add_tagchange(&data, ATK, attacker->attack, p->deck->hero->id);
} else if(flag(&attacker->state, CARD_HP_ARMORUP, FLAG_ISSET)) {
p->deck->hero->armor += attacker->attack;
add_tagchange(&data, ARMOR, p->deck->hero->armor, p->deck->hero->id);
} else if(flag(&attacker->state, CARD_HP_LIFETAP, FLAG_ISSET)) {
// FIXME: don't let enemy know what card we have
struct powerhistory_entity_s *show = NULL;
struct card_s *drawn_card = draw_random_card(p->deck, p->entity_id, -1);
struct powerhistory_tag_s *card_tags = default_tags(drawn_card, drawn_card->entity, 0);
p->deck->hero->health -= attacker->attack;
add_meta(&data, 1, attacker->attack, p->deck->hero->id);
add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, p->deck->hero->id);
add_tagchange(&data, DAMAGE, p->deck->hero->total_health - p->deck->hero->health, p->deck->hero->id);
hm_log(LOG_DEBUG, lg, "drawn card zone position %d for card: %d", drawn_card->zone_position, drawn_card->id);
add_full_entity(&show, card_tags, drawn_card->id, drawn_card->entity->name, drawn_card->entity->nname);
add_tagchange(&data, ZONE_POSITION, drawn_card->zone_position, drawn_card->id);
add_ph_data_show(&data, show);
}
add_powerend(&data);
add_tagchange(&data, 406, 1, p->entity_id);
add_tagchange(&data, EXHAUSTED, 1, attacker->id);
if(flag(&attacker->state, CARD_HP_DAGGERMASTERY, FLAG_ISSET)) {
add_tagchange(&data, ATK, card->attack, p->deck->hero->id);
p->deck->hero->attack = card->attack;
}
add_powerstart(&data, 5, -1, p->entity_id, 0, NULL, 0);
add_tagchange(&data, 394, 1, p->entity_id);
add_powerend(&data);
add_tagchange(&data, 358, 2, p->entity_id);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
//card_set_exhausted(attacker);
powerhistory_dump(ph);
return packet;
}
struct packet_s *spell_hp_damage(struct conn_client_s *c, struct card_s *defender, struct card_s *attacker)
{
/*
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
p = c->data;
game_attack(p, attacker, defender);
add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0);
add_tagchange(&data, RESOURCES_USED, p->deck->mana_used, p->entity_id);
add_tagchange(&data, 418, 36, p->entity_id);
add_tagchange(&data, CARD_TARGET, defender->id, attacker->id);
add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0);
add_meta(&data, 0, 0, defender->id);
add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id);
add_tagchange(&data, PREDAMAGE, 0, defender->id);
add_meta(&data, METATYPE_DAMAGE, attacker->attack, defender->id);
add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id);
add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id);
add_powerend(&data);
add_tagchange(&data, 406, 1, p->entity_id);
add_tagchange(&data, EXHAUSTED, 1, attacker->id);
check_remove_divine_shield(&data, defender);
if(defender->health == 0) {
add_tagchange(&data, EXHAUSTED, 0, defender->id); // 43
add_tagchange(&data, DAMAGE, 0, defender->id);
add_tagchange(&data, ZONE, 4, defender->id); // 49
add_tagchange(&data, ZONE_POSITION, 0, defender->id);
if(flag(&defender->state, CARD_HERO, FLAG_ISSET)) {
add_tagchange(&data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, PLAYSTATE, 4, p->entity_id);
} else {
cards_board_destroyed_reorder(&data, p->opponent.deck, defender->zone_position);
}
}
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
card_set_exhausted(attacker);
return packet;
*/
return NULL;
}
struct packet_s *heal(struct conn_client_s *c, struct card_s *defender, struct card_s *attacker)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
if(defender->total_health - defender->health > attacker->attack) {
hm_log(LOG_DEBUG, lg, "card: %d healed for %d", defender->id, attacker->attack);
defender->health += attacker->attack;
} else {
hm_log(LOG_DEBUG, lg, "card: %d hp fully restored", defender->id);
defender->health = defender->total_health;
}
p = c->data;
add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0);
add_tagchange(&data, RESOURCES_USED, p->deck->mana_used, p->entity_id);
add_tagchange(&data, CARD_TARGET, defender->id, attacker->id);
add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0);
add_meta(&data, 0, 0, defender->id);
add_tagchange(&data, 425, attacker->attack, defender->id);
add_tagchange(&data, 425, 0, defender->id);
add_meta(&data, 0, attacker->attack, defender->id);
add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id);
add_powerend(&data);
add_tagchange(&data, 406, 1, defender->id);
add_tagchange(&data, EXHAUSTED, 1, attacker->id);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
//card_set_exhausted(attacker);
return packet;
}
struct packet_s *attack(struct conn_client_s *c, struct chooseoption_s *opt)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
struct card_s *attacker, *defender;
//struct deck_s *deck;
p = c->data;
//deck = p->deck;
attacker = card_get(p->deck, NULL, p->arroworigin);
defender = card_get(p->opponent.deck, p->deck, opt->target);
assert(attacker && defender);
//game_attack(p, attacker, defender);
add_powerstart(&data, 1, -1, attacker->id, defender->id, NULL, 0);
add_tagchange(&data, 417, 1, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, PROPOSED_ATTACKER, attacker->id, 1);
add_tagchange(&data, PROPOSED_DEFENDER, opt->target, 1);
add_tagchange(&data, ATTACKING, 1, p->arroworigin);
add_tagchange(&data, NEXT_STEP, 10, 1);
add_tagchange(&data, STEP, 11, 1);
add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, DEFENDING, 1, opt->target);
add_tagchange(&data, PREDAMAGE, attacker->attack, opt->target);
add_tagchange(&data, PREDAMAGE, 0, opt->target);
add_meta(&data, 1, attacker->attack, opt->target);
add_tagchange(&data, LAST_AFFECTED_BY, p->arroworigin, opt->target);
add_tagchange(&data, DAMAGE, defender->total_health - defender->health, opt->target); // total damaged caused from beginning
add_tagchange(&data, PREDAMAGE, 1, p->arroworigin);
add_tagchange(&data, PREDAMAGE, 0, p->arroworigin);
add_meta(&data, 1, defender->attack, p->arroworigin);
add_tagchange(&data, NUM_ATTACKS_THIS_TURN, 1, p->arroworigin);
/*
if(--(attacker->actions_number) == 0) {
hm_log(LOG_DEBUG, lg, "setting card %d to EXHAUSTED", attacker->id);
add_tagchange(&data, EXHAUSTED, 1, p->arroworigin);
}
*/
add_tagchange(&data, PROPOSED_ATTACKER, 0, 1);
add_tagchange(&data, PROPOSED_DEFENDER, 0, 1);
add_tagchange(&data, ATTACKING, 0, p->arroworigin);
add_tagchange(&data, DEFENDING, 0, opt->target);
//check_remove_divine_shield(&data, defender);
add_powerend(&data);
add_powerstart(&data, 6, 0, 1, 0, NULL, 0);
//add_tagchange(&data, NUM_MINIONS_PLAYER_KILLED_THIS_TURN, 1, p->entity_id); // 368
//add_tagchange(&data, NUM_MINIONS_KILLED_THIS_TURN, 1, 1); // 369
add_tagchange(&data, 398, 1, p->entity_id);
add_tagchange(&data, 412, 1, p->entity_id);
//damage_done(p, attacker, defender);
/*
if(attacker->health == 0) {
cards_board_destroyed_reorder(&data, p->deck, attacker->zone_position);
add_tagchange(&data, EXHAUSTED, 0, attacker->id); // 43
add_tagchange(&data, DAMAGE, 0, attacker->id);
add_tagchange(&data, ZONE, 4, attacker->id); // 49
add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
} else {
add_tagchange(&data, DAMAGE, attacker->total_health - attacker->health, attacker->id); // total damaged caused from beginning
card_set_exhausted(attacker);
}
add_tagchange(&data, ARMOR, defender->armor, defender->id);
add_tagchange(&data, ARMOR, attacker->armor, attacker->id);
if(defender->health == 0) {
add_tagchange(&data, EXHAUSTED, 0, defender->id); // 43
add_tagchange(&data, DAMAGE, 0, defender->id);
add_tagchange(&data, ZONE, 4, defender->id); // 49
add_tagchange(&data, ZONE_POSITION, 0, defender->id);
if(EQFLAG(defender->state, CARD_HERO)) {
add_tagchange(&data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, PLAYSTATE, 4, p->entity_id);
} else {
cards_board_destroyed_reorder(&data, p->opponent.deck, defender->zone_position);
}
}
*/
/** destroy both */
/*
add_tagchange(&data, ZONE, 4, attacker->id); // 49
add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
add_tagchange(&data, ZONE, 4, defender->id); // 49
add_tagchange(&data, ZONE_POSITION, 0, defender->id);
attacker->state = CARD_DESTROYED;
defender->state = CARD_DESTROYED;
*/
add_powerend(&data);
add_tagchange(&data, STEP, 10, 1);
add_powerstart(&data, 5, 2, p->entity_id, 0, NULL, 0);
if(flag(&attacker->state, CARD_HERO, FLAG_ISSET) && p->deck->heroweapon) {
p->deck->heroweapon->durability--;
add_meta(&data, 1, p->deck->heroweapon->attack, p->deck->heroweapon->id);
add_tagchange(&data, LAST_AFFECTED_BY, p->deck->hero->id, p->deck->heroweapon->id);
add_tagchange(&data, DAMAGE, p->deck->heroweapon->maxdurability - p->deck->heroweapon->durability, p->deck->heroweapon->id);
add_tagchange(&data, EXHAUSTED, 1, p->deck->heroweapon->id);
if(p->deck->heroweapon->durability == 0) {
add_tagchange(&data, ZONE, 4, p->deck->heroweapon->id);
add_tagchange(&data, ATK, 0, attacker->id);
//p->deck->heroweapon->state |= CARD_DESTROYED;
flag(&p->deck->heroweapon->state, CARD_DESTROYED, FLAG_SET);
p->deck->hero->attack = 0;
hm_log(LOG_DEBUG, lg, "heroweapon destroyed %d", p->deck->heroweapon->id);
p->deck->heroweapon = NULL;
}
}
add_tagchange(&data, NEXT_STEP, 12, 1);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
return packet;
}
struct packet_s *buff(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_s *defender)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
struct deck_s *deck;
int i;
p = c->data;
deck = p->deck;
add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0);
add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost
add_tagchange(&data, 418, 26, p->entity_id);
add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id);
add_tagchange(&data, 430, 1, p->entity_id);
add_tagchange(&data, ZONE, 1, attacker->id);
add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
add_tagchange(&data, JUST_PLAYED, 1, attacker->id);
add_tagchange(&data, 397, attacker->id, p->entity_id);
add_tagchange(&data, CARD_TARGET, defender->id, attacker->id);
//cards_reorder(deck, &data, attacker, opt, player);
if(player == 2) {
for(i = 0; i < deck->ncards; i++) {
if(deck->cards[i]->id == p->held_card) {
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0);
add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname);
add_ph_data_show(&data, show);
break;
}
}
}
add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0);
add_meta(&data, 0, 0, defender->id);
//add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id);
//add_tagchange(&data, PREDAMAGE, 0, opt->target);
add_meta(&data, 3, 0, opt->target);
add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id);
//add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id);
add_powerend(&data);
add_tagchange(&data, ZONE, 4, attacker->id);
add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id);
add_tagchange(&data, WINDFURY, 1, defender->id);
//damage_done(&data, p, attacker, defender);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
return packet;
}
/*
static void defender_attacked(struct hs_holder_s *p, struct powerhistory_data_s **data, struct card_s *attacker, struct card_s *defender, struct chooseoption_s *opt)
{
add_meta(data, 0, 0, defender->id);
add_tagchange(data, PREDAMAGE, attacker->attack, defender->id);
add_tagchange(data, PREDAMAGE, 0, opt->target);
add_meta(data, 1, attacker->attack, opt->target);
add_tagchange(data, LAST_AFFECTED_BY, attacker->id, defender->id);
add_tagchange(data, DAMAGE, defender->total_health - defender->health, defender->id);
add_powerend(data);
add_tagchange(data, ZONE, 4, attacker->id);
add_tagchange(data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id);
//damage_done(p, attacker, defender);
}
*/
struct packet_s *spell_damage_aoe(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
struct deck_s *deck;
struct card_list_s *def;
p = c->data;
deck = p->deck;
add_powerstart(&data, 7, 0, attacker->id, 0, NULL, 0);
add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost
add_tagchange(&data, 418, 26, p->entity_id);
add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id);
add_tagchange(&data, 430, 1, p->entity_id);
add_tagchange(&data, ZONE, 1, attacker->id);
add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
add_tagchange(&data, JUST_PLAYED, 1, attacker->id);
add_tagchange(&data, 397, attacker->id, p->entity_id);
//cards_reorder(deck, &data, attacker, opt, player);
/*
if(player == 2) {
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(attacker->entity);
add_full_entity(&show, card_tags, attacker->id, attacker->entity->name, attacker->entity->nname);
add_ph_data_show(&data, show);
}
*/
if(defenders != NULL) {
add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0);
struct powerhistory_info_s *info = NULL;
for(def = defenders; def != NULL; def = def->next) {
add_info(&info, def->card->id);
}
add_meta_info(&data, 0, 0, info);
}
for(def = defenders; def != NULL; def = def->next) {
hm_log(LOG_DEBUG, lg, "AOE spell %d attacking %d", attacker->id, def->card->id);
add_tagchange(&data, PREDAMAGE, attacker->attack, def->card->id);
add_tagchange(&data, PREDAMAGE, 0, def->card->id);
add_meta(&data, 1, attacker->attack, def->card->id);
//check_remove_divine_shield(&data, def);
add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, def->card->id);
add_tagchange(&data, DAMAGE, def->card->total_health - def->card->health, def->card->id);
//damage_done(p, attacker, def->card);
}
if(defenders != NULL) {
add_powerend(&data);
}
add_tagchange(&data, ZONE, 4, attacker->id);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
flag(&attacker->state, CARD_BOARD, FLAG_UNSET);
return packet;
}
struct packet_s *spell_damage(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_s *defender)
{
/*
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
struct deck_s *deck;
p = c->data;
deck = p->deck;
add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0);
add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost
add_tagchange(&data, 418, 26, p->entity_id);
add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id);
add_tagchange(&data, 430, 1, p->entity_id);
add_tagchange(&data, ZONE, 1, attacker->id);
add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
add_tagchange(&data, JUST_PLAYED, 1, attacker->id);
add_tagchange(&data, 397, attacker->id, p->entity_id);
add_tagchange(&data, CARD_TARGET, defender->id, attacker->id);
//cards_reorder(deck, &data, attacker, opt, player);
//check_remove_divine_shield(&data, defender);
if(player == 2) {
for(i = 0; i < deck->ncards; i++) {
if(deck->cards[i]->id == p->held_card) {
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i]->entity);
add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname);
add_ph_data_show(&data, show);
break;
}
}
}
if(EQFLAG(attacker->state, CARD_NONTARGET)) {
struct deck_s *opp = p->opponent.deck;
for(i = 0; i < opp->ncards; i++) {
if(EQFLAG(opp->cards[i]->state, CARD_BOARD)) {
add_powerstart(&data, 3, -1, attacker->id, opp->cards[i]->id, NULL, 0);
defender_attacked(p, &data, attacker, opp->cards[i], opt);
add_powerend(&data);
}
}
} else {
add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0);
defender_attacked(p, &data, attacker, defender, opt);
add_powerend(&data);
}
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
return packet;
*/
return NULL;
}
int choose_option(struct conn_client_s *c, struct chooseoption_s *opt)
{
//struct packet_s *p1 = NULL, *p2 = NULL;
//struct hs_holder_s *p;
//char output[1024 * 8], *ptr;
//int n;
//const char opt1[14] = { 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x08, 0x12, 0x02, 0x08, 0x02, };
game(c, opt);
/*
chooseoption_dump(opt, p->held_card);
// aoe spell
if(p->held_card > 0) {
struct card_s *attacker = card_get(p->deck, NULL, p->held_card);
if(attacker && flag(&attacker->state, CARD_AOE_ENEMY_MINIONS, FLAG_ISSET)) {
struct card_list_s *defenders = NULL;
//attacker->state &= ~CARD_DECK;
flag(&attacker->state, CARD_DECK, FLAG_UNSET);
///< get opponent's board cards
defenders = cards_get_board(NULL, p->opponent.deck);
hm_log(LOG_INFO, c->log, "Casting AOE %d against enemy minions", p->held_card);
assert(attacker);
game_attack_aoe(p, attacker, defenders);
p1 = spell_damage_aoe(c, opt, 1, attacker, defenders);
p2 = spell_damage_aoe(c, opt, 2, attacker, defenders);
ptr = output;
n = serialize(p1, &ptr, ptr + sizeof(output));
hm_log(LOG_INFO, c->log, "Serialized %d bytes", n);
hm_send(c, output, n);
if(p2) {
ptr = output;
n = serialize(p2, &ptr, ptr + sizeof(output));
}
hm_send(p->opponent.client, output, n);
int so = set_options(p->deck, p->opponent.deck, output, output + sizeof(output), p->game->turn);
hm_send(c, output, so);
goto skip;
}
}
// play nontarget hero power
if(p->held_card > 0 && p->held_card == p->deck->heropower->id &&
flag(&p->deck->heropower->state, CARD_NONTARGET, FLAG_ISSET)) {
hm_log(LOG_ERR, c->log, "playing nontarget hero power %d", p->held_card);
struct card_s *attacker = p->deck->heropower;
assert(attacker);
p1 = nontarget(c, attacker);
ptr = output;
n = serialize(p1, &ptr, ptr + sizeof(output));
hm_send(c, output, n);
hm_send(p->opponent.client, output, n);
int so = set_options(p->deck, p->opponent.deck, output, output + sizeof(output), p->game->turn);
hm_send(c, output, so);
// next turn
} else if(opt->index == 0) {
struct card_s *drawn_card = NULL;
int zone = 0;
if(p->game->turn % 2 == 0 && p->deck->mana < 10) {
p->deck->mana++;
p->opponent.deck->mana++;
}
p->game->turn++;
cards_unset_flag(p->opponent.deck, CARD_EXHAUSTED);
hm_log(LOG_INFO, c->log, "Next turn: %d", p->game->turn);
p1 = next_turn(c, opt, &drawn_card, &zone);
p2 = next_turn(c, opt, &drawn_card, &zone);
ptr = output;
n = serialize(p1, &ptr, ptr + sizeof(output));
hm_send(c, output, n);
ptr = output;
n = serialize(p2, &ptr, ptr + sizeof(output));
int so = set_options(p->opponent.deck, p->deck, output + n, output + sizeof(output) - n, p->game->turn);
//memcpy(output + n + so, opt1, sizeof(opt1));
hm_send(p->opponent.client, output, n + so);
// attack or spell damage
} else if((opt->target != 0 && p->arroworigin != 0)) {
struct card_s *attacker = card_get(p->deck, NULL, p->arroworigin);
struct card_s *defender;
hm_log(LOG_ERR, c->log, "origin: %d target: %lld id %d", p->arroworigin, opt->target, attacker->id);
defender = card_get(p->deck, p->opponent.deck, opt->target);
assert(attacker && defender);
if(flag(&attacker->state, (CARD_SPELL_DAMAGE), FLAG_ISSET)) {
hm_log(LOG_INFO, c->log, "Casting spell damage %d > %lld", p->arroworigin, opt->target);
assert(attacker && defender);
game_attack(p, attacker, defender);
//attacker->state &= ~CARD_DECK;
flag(&attacker->state, CARD_DECK, FLAG_UNSET);
p1 = spell_damage(c, opt, 1, attacker, defender);
p2 = spell_damage(c, opt, 2, attacker, defender);
} else if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && flag(&attacker->state, CARD_SPELL_HEAL, FLAG_ISSET)) {
hm_log(LOG_INFO, c->log, "Healing %d > %lld", p->arroworigin, opt->target);
p1 = heal(c, defender, attacker);
} else if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && flag(&attacker->state, CARD_HP_SPELL_DAMAGE, FLAG_ISSET)) {
hm_log(LOG_INFO, c->log, "Casting HP spell %d > %lld", p->arroworigin, opt->target);
p1 = spell_hp_damage(c, defender, attacker);
} else if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && flag(&attacker->state, CARD_WINDFURY, FLAG_ISSET)) {
hm_log(LOG_INFO, c->log, "Casting windfury spell %d > %lld", p->arroworigin, opt->target);
p1 = buff(c, opt, 1, attacker, defender);
p2 = buff(c, opt, 2, attacker, defender);
} else {
hm_log(LOG_INFO, c->log, "Attacking %d > %lld", p->arroworigin, opt->target);
p1 = attack(c, opt);
}
ptr = output;
n = serialize(p1, &ptr, ptr + sizeof(output));
hm_log(LOG_INFO, c->log, "Serialized %d bytes", n);
hm_send(c, output, n);
if(p2) {
ptr = output;
n = serialize(p2, &ptr, ptr + sizeof(output));
}
hm_send(p->opponent.client, output, n);
int so = set_options(p->deck, p->opponent.deck, output, output + sizeof(output), p->game->turn);
hm_send(c, output, so);
// put card on board
} else if(p->held_card > 0) {
struct card_s *attacker = card_get(p->deck, NULL, p->held_card);
assert(attacker);
hm_log(LOG_INFO, lg, "Putting card %d on board", attacker->id);
flag(&attacker->state, CARD_HAND, FLAG_UNSET);
flag(&attacker->state, CARD_BOARD, FLAG_SET);
if(!flag(&attacker->state, CARD_CHARGE, FLAG_ISSET)) {
flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET);
}
hm_log(LOG_INFO, lg, "Flags for card %d:", attacker->id);
flag(&attacker->state, -1, FLAG_DUMP);
p1 = choose_option_player(c, opt, 1, attacker);
p2 = choose_option_player(c, opt, 2, attacker);
ptr = output;
n = serialize(p1, &ptr, ptr + sizeof(output));
int so = set_options(p->deck, p->opponent.deck, output + n, output + sizeof(output) - n, p->game->turn);
//hm_log(LOG_DEBUG, lg, "sending %d bytes to initiator", n + so);
hm_send(c, output, (int)(n + so));
char output2[2048];
ptr = output2;
int n2 = serialize(p2, &ptr, ptr + sizeof(output2));
//hm_log(LOG_DEBUG, lg, "sending %d bytes to initiator's opponent", n);
hm_send(p->opponent.client, output2, n2);
}
skip:
// unset origin
p->arroworigin = 0;
// unset
p->held_card = 0;
hm_log(LOG_INFO, c->log, "Unsetting held card %d arroworigin %d", p->held_card, p->arroworigin);
*/
return 0;
}
+464
View File
@@ -0,0 +1,464 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
const struct ent_s *find_entity(const char *name, const int nname)
{
int i;
for(i = 0; i < MAX_ENTITIES; i++) {
if(nname == entities[i].nname && memcmp(entities[i].name, name, nname) == 0) {
return &entities[i];
}
}
hm_log(LOG_EMERG, lg, "Entity [%.*s] not found", nname, name);
return NULL;
}
struct powerhistory_tag_s *add_tag(struct powerhistory_tag_s **dst, const int key, const int value)
{
struct powerhistory_tag_s *t;
t = malloc(sizeof(*t));
if(t == NULL) {
return NULL;
}
t->name = key;
t->value = value;
t->next = *dst;
*dst = t;
return t;
}
struct powerhistory_game_entity_s *add_game_entity(struct powerhistory_game_entity_s **dst, struct powerhistory_tag_s *tag, const int id)
{
struct powerhistory_game_entity_s *g;
g = malloc(sizeof(*g));
if(g == NULL) {
return NULL;
}
g->id = id;
g->tag = g->tag_tail = tag;
*dst = g;
return g;
}
struct powerhistory_tag_s *default_tags(struct card_s *card, const struct ent_s *ent, int zone_override)
{
int i;
struct powerhistory_tag_s *tag = NULL;
for(i = 0; i < ent->nprop; i++) {
//#define TEST_COST_
#undef TEST_COST_
#ifdef TEST_COST_
if(ent->p[i].key == COST) {
add_tag(&tag, COST, 0);
continue;
}
#endif
// buffed summoned unit
if(ent->p[i].key == HEALTH && card->health != ent->p[i].value) {
add_tag(&tag, ent->p[i].key, card->health);
continue;
}
// buffed summoned unit
if(ent->p[i].key == ATK && card->attack != ent->p[i].value) {
add_tag(&tag, ent->p[i].key, card->attack);
continue;
}
// don't add default zone 3
if(ent->p[i].key == ZONE && zone_override > 0) {
add_tag(&tag, ent->p[i].key, zone_override);
} else {
add_tag(&tag, ent->p[i].key, ent->p[i].value);
}
}
if(card) {
int *f = NULL;
int c;
c = flag_get(&card->state, &f);
for(i = 0; i < c; i++) {
switch(f[i]) {
case CARD_TAUNT:
add_tag(&tag, TAUNT, 1);
break;
case CARD_WINDFURY:
add_tag(&tag, WINDFURY, 1);
break;
case CARD_DIVINE_SHIELD:
add_tag(&tag, DIVINE_SHIELD, 1);
break;
case CARD_STEALTH:
add_tag(&tag, STEALTH, 1);
break;
case CARD_FREEZE:
add_tag(&tag, FREEZE, 1);
break;
case CARD_SPELLPOWER:
add_tag(&tag, SPELLPOWER, 1);
break;
}
}
if(flag(&card->state, CARD_HEROPOWER, FLAG_ISSET) || flag(&card->state, CARD_HEROPOWER, FLAG_ISSET)) {
add_tag(&tag, ZONE, 1);
}
// add Premium
//add_tag(&tag, PREMIUM, 1);
if(f) free(f);
}
return tag;
}
void add_hide(struct powerhistory_data_s **dst, u64 entity, u64 zone)
{
struct powerhistory_data_s *data;
struct powerhistory_hide_s *hide = NULL;
hide = malloc(sizeof(*hide));
hide->entity = entity;
hide->zone = zone;
data = malloc(sizeof(*data));
memset(data, 0, sizeof(*data));
data->hide = hide;
if(*dst && (*dst)->tail) {
(*dst)->tail->next = data;
(*dst)->tail = data;
} else {
*dst = data;
(*dst)->tail = (*dst)->next = data;
}
/*
data->next = *dst;
*dst = data;
*/
}
void add_info(struct powerhistory_info_s **dst, u64 infoid)
{
struct powerhistory_info_s *info = NULL;
info = malloc(sizeof(*info));
info->id = infoid;
info->next = *dst;
if(dst) *dst = info;
}
void add_meta_info(struct powerhistory_data_s **dst, u64 type, u64 d, struct powerhistory_info_s *info)
{
struct powerhistory_data_s *data;
struct powerhistory_meta_s *meta = NULL;
meta = malloc(sizeof(*meta));
meta->type = type;
meta->data = d;
meta->info = info;
data = malloc(sizeof(*data));
memset(data, 0, sizeof(*data));
data->meta = meta;
if(*dst && (*dst)->tail) {
(*dst)->tail->next = data;
(*dst)->tail = data;
} else {
*dst = data;
(*dst)->tail = (*dst)->next = data;
}
}
void add_meta(struct powerhistory_data_s **dst, u64 type, u64 d, u64 infoid)
{
struct powerhistory_data_s *data;
struct powerhistory_meta_s *meta = NULL;
struct powerhistory_info_s *info = NULL;
meta = malloc(sizeof(*meta));
meta->type = type;
meta->data = d;
info = malloc(sizeof(*info));
memset(info, 0, sizeof(*info));
info->id = infoid;
meta->info = info;
data = malloc(sizeof(*data));
memset(data, 0, sizeof(*data));
data->meta = meta;
if(*dst && (*dst)->tail) {
(*dst)->tail->next = data;
(*dst)->tail = data;
} else {
*dst = data;
(*dst)->tail = (*dst)->next = data;
}
}
void add_tagchange(struct powerhistory_data_s **dst, u64 key, u64 value, u64 id)
{
struct powerhistory_data_s *data;
struct powerhistory_tagchange_s *tag = NULL;
tag = malloc(sizeof(*tag));
tag->entity = id;
tag->tag = key;
tag->value = value;
data = malloc(sizeof(*data));
memset(data, 0, sizeof(*data));
data->tagchange = tag;
if(*dst && (*dst)->tail) {
(*dst)->tail->next = data;
(*dst)->tail = data;
} else {
*dst = data;
(*dst)->tail = (*dst)->next = data;
}
/*
data->next = *dst;
*dst = data;
*/
}
void add_powerend(struct powerhistory_data_s **dst)
{
struct powerhistory_data_s *data;
struct powerhistory_powerend_s *ps = NULL;
ps = malloc(sizeof(*ps));
memset(ps, 0, sizeof(*ps));
data = malloc(sizeof(*data));
memset(data, 0, sizeof(*data));
data->powerend = ps;
if(*dst && (*dst)->tail) {
(*dst)->tail->next = data;
(*dst)->tail = data;
} else {
*dst = data;
(*dst)->tail = (*dst)->next = data;
}
/*
data->next = *dst;
*dst = data;
*/
}
void add_powerstart(struct powerhistory_data_s **dst, u64 type, u64 index, u64 source, u64 target, char *card_id, int ncard_id)
{
struct powerhistory_data_s *data;
struct powerhistory_powerstart_s *ps = NULL;
ps = malloc(sizeof(*ps));
ps->type = type;
ps->index = index;
ps->source = source;
ps->target = target;
ps->ncard_id = ncard_id;
ps->card_id = card_id;
data = malloc(sizeof(*data));
memset(data, 0, sizeof(*data));
data->powerstart = ps;
if(*dst && (*dst)->tail) {
(*dst)->tail->next = data;
(*dst)->tail = data;
} else {
*dst = data;
(*dst)->tail = (*dst)->next = data;
}
/*
data->next = *dst;
*dst = data;
*/
}
void add_tagschange(struct powerhistory_data_s **dst, const struct ent_s *ent, u64 id)
{
int i;
for(i = 0; i < ent->nprop; i++) {
add_tagchange(dst, ent->p[i].key, ent->p[i].value, id);
}
add_tagchange(dst, ENTITY_ID, id, id);
}
void add_player(struct powerhistory_player_s **dst, u64 id, u64 bhi, u64 blo, u64 cardback, struct powerhistory_game_entity_s *ent)
{
struct powerhistory_player_s *p;
p = malloc(sizeof(*p));
p->id = id;
p->bnet_hi = bhi;
p->bnet_lo = blo;
p->cardback = cardback;
p->entity = ent;
p->next = *dst;
*dst = p;
}
void add_game_start(struct powerhistory_creategame_s **dst, struct powerhistory_game_entity_s *ge, struct powerhistory_player_s *p)
{
*dst = malloc(sizeof(**dst));
(*dst)->game_entity = ge;
(*dst)->player = p;
}
void add_ph_data_full(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full)
{
struct powerhistory_data_s *p;
p = malloc(sizeof(*p));
memset(p, 0, sizeof(*p));
if(full) {
p->full = full;
}
if(*dst && (*dst)->tail) {
(*dst)->tail->next = p;
(*dst)->tail = p;
} else {
*dst = p;
(*dst)->tail = (*dst)->next = p;
}
}
void add_ph_data_show(struct powerhistory_data_s **dst, struct powerhistory_entity_s *show)
{
struct powerhistory_data_s *p;
p = malloc(sizeof(*p));
memset(p, 0, sizeof(*p));
if(show) {
p->show = show;
}
if(*dst && (*dst)->tail) {
(*dst)->tail->next = p;
(*dst)->tail = p;
} else {
*dst = p;
(*dst)->tail = (*dst)->next = p;
}
}
void add_ph_data(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full, struct powerhistory_creategame_s *cg)
{
struct powerhistory_data_s *p;
p = malloc(sizeof(*p));
memset(p, 0, sizeof(*p));
if(cg) {
p->creategame = cg;
}
if(full) {
p->full = full;
}
if(*dst && (*dst)->tail) {
(*dst)->tail->next = p;
(*dst)->tail = p;
} else {
*dst = p;
(*dst)->tail = (*dst)->next = p;
}
/*
*dst->tail = p;
p->next = *dst;
*dst = p;
*/
}
void add_full_entity(struct powerhistory_entity_s **full, struct powerhistory_tag_s *tags, u64 id, const char *name, const int nname)
{
*full = malloc(sizeof(**full));
memset(*full, 0, sizeof(**full));
(*full)->entity = id;
(*full)->tag = tags;
(*full)->nname = nname;
(*full)->name = (char *)name;
}
void add_ph(struct powerhistory_s **dst, struct powerhistory_data_s *data)
{
*dst = malloc(sizeof(**dst));
memset(*dst, 0, sizeof(**dst));
(*dst)->data = data;
}
void add_packet(struct packet_s **dst, void *ph, enum packet_e n)
{
*dst = malloc(sizeof(**dst));
memset(*dst, 0, sizeof(**dst));
(*dst)->data = ph;
(*dst)->id = n;
}
void bin_dump(char *buf, const int len)
{
int i;
printf("binary dump of %d:\n", len);
for(i = 0; i < len; i++) {
printf("%x|", (unsigned char)buf[i]);
}
printf("\n");
}
+75
View File
@@ -0,0 +1,75 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
struct entitychoices_s *chooseone_choices(struct card_list_s *defenders, int player_id, int attacker_id)
{
struct entitychoices_s *ec;
struct entitychoices_entities_s *etmp;
struct card_list_s *def;
ec = malloc(sizeof(*ec));
ec->id = 3;
ec->type = 2;
ec->countmin = 1;
ec->countmax = 1;
ec->source = attacker_id;
ec->player_id = player_id;
ec->entities = NULL;
for(def = defenders; def != NULL; def = def->next) {
etmp = malloc(sizeof(*etmp));
etmp->entity = def->card->id;
etmp->next = ec->entities;
ec->entities = etmp;
}
return ec;
}
struct entitychoices_s *prepare_choices(struct deck_s *deck, int player_id)
{
struct entitychoices_s *ec;
struct entitychoices_entities_s *etmp;
int i, drawn = 0;
ec = malloc(sizeof(*ec));
ec->id = 1;
ec->type = 1;
ec->countmin = 0;
ec->source = 1;
ec->player_id = player_id;
ec->entities = NULL;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) {
etmp = malloc(sizeof(*etmp));
etmp->entity = deck->cards[i]->id;
etmp->next = ec->entities;
ec->entities = etmp;
drawn++;
}
}
ec->countmax = drawn;
return ec;
}
+998
View File
@@ -0,0 +1,998 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void card_to_deck(struct card_s *card)
{
flag(&card->state, CARD_HAND, FLAG_UNSET);
}
struct card_s *card_get_levelup_boss(struct deck_s *deck, struct card_s *card)
{
const char *bossname = NULL;
int i;
for(i = 0; i < MAX_LEVELUP; i++) {
hm_log(LOG_DEBUG, lg, "Levelup boss: [%s] [%s]", card->entity->name, levelup[i].src);
if(strcmp(card->entity->name, levelup[i].src) == 0) {
bossname = levelup[i].dst;
break;
}
}
if(bossname == NULL) {
return NULL;
}
for(i = 0; deck != NULL && i < deck->ncards; i++) {
if((flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET)) &&
flag(&deck->cards[i]->state, CARD_BOSS, FLAG_ISSET)) {
return deck->cards[i];
}
}
return NULL;
}
struct card_s *card_get_hero(struct deck_s *deck)
{
int i;
for(i = 0; deck != NULL && i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET)) {
return deck->cards[i];
}
}
return NULL;
}
struct card_s *card_get(struct deck_s *deck, struct deck_s *opponent, const int id)
{
int i;
#define FCARD(m__d)\
for(i = 0; m__d != NULL && i < m__d->ncards; i++) {\
if(id == m__d->cards[i]->id) {\
hm_log(LOG_DEBUG, lg, "card [%s](%d) found in deck %d", m__d->cards[i]->entity->desc, m__d->cards[i]->id, m__d->controller);\
assert(m__d->cards[i]->parent);\
return m__d->cards[i];\
}\
}
FCARD(deck)
FCARD(opponent)
hm_log(LOG_DEBUG, lg, "card (%d) not found in any deck (%d %d)", id, (deck ? deck->ncards : -1), (opponent ? opponent->ncards : -1));\
return NULL;
}
struct card_list_s *cards_get_board_boss(struct deck_s *deck)
{
int i;
struct card_list_s *list = NULL, *item;
for(i = 0; deck != NULL && i < deck->ncards; i++) {
if((flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET)) &&
flag(&deck->cards[i]->state, CARD_BOSS, FLAG_ISSET)) {
LIST_ADD(list, item, deck->cards[i]);
}
}
return list;
}
struct card_list_s *cards_get_hand(struct deck_s *deck)
{
int i;
struct card_list_s *list = NULL, *item;
for(i = 0; deck != NULL && i < deck->ncards; i++) {
if((flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET))) {
LIST_ADD(list, item, deck->cards[i]);
}
}
return list;
}
struct card_list_s *cards_get_board(struct deck_s *deck, struct deck_s *opponent, int hero, int exclude, int magic_immunity, int boss)
{
int i;
struct card_list_s *list = NULL, *item;
#define CBOARD(d)\
for(i = 0; d != NULL && i < d->ncards; i++) {\
if(d->cards[i]->id == exclude) continue;\
if((flag(&d->cards[i]->state, CARD_DIVINE_SHIELD, FLAG_ISSET)) && magic_immunity == 0) continue;\
if((flag(&d->cards[i]->state, CARD_BOSS, FLAG_ISSET)) && boss == 0) continue;\
if((flag(&d->cards[i]->state, CARD_BOARD, FLAG_ISSET) && !flag(&d->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) && !flag(&d->cards[i]->state, CARD_HEROWEAPON, FLAG_ISSET)) || \
(flag(&d->cards[i]->state, CARD_HERO, FLAG_ISSET) && hero == 1)\
) {\
hm_log(LOG_DEBUG, lg, "Card [%s](%d) found in deck %d", d->cards[i]->entity->desc, d->cards[i]->id, d->controller);\
LIST_ADD(list, item, d->cards[i]);\
}\
}
CBOARD(deck)
CBOARD(opponent)
return list;
}
int cards_get_board_count(struct deck_s *deck, struct deck_s *opponent, int hero, int exclude)
{
int i;
int total = 0;
#define CBOARD1(d)\
for(i = 0; d != NULL && i < d->ncards; i++) {\
if(d->cards[i]->id == exclude) continue;\
if((flag(&d->cards[i]->state, CARD_BOARD, FLAG_ISSET) && !flag(&d->cards[i]->state, CARD_DESTROYED, FLAG_ISSET)) || \
(flag(&d->cards[i]->state, CARD_HERO, FLAG_ISSET) && hero == 1)\
) {\
total++;\
/*hm_log(LOG_DEBUG, lg, "Card [%s](%d) found in deck %d", d->cards[i]->entity->desc, d->cards[i]->id, d->controller);*/\
\
}\
}
CBOARD1(deck)
CBOARD1(opponent)
return total;
}
struct card_s *card_random(struct card_list_s *l)
{
struct card_list_s *c;
int count;
for(count = 0, c = l; c != NULL; c = c->next, count++);
if(count < 1) {
return NULL;
}
int r = random_number(count);
for(count = 0, c = l; c != NULL && count != r; c = c->next, count++);
return c ? c->card : NULL;
}
int cards_count(struct card_list_s *l)
{
struct card_list_s *c;
int count;
for(count = 0, c = l; c != NULL; c = c->next, count++);
return count;
}
void cards_board_destroyed_reorder(struct deck_s *deck, int position)
{
int i;
hm_log(LOG_DEBUG, lg, "Destroying zone position %d from deck %d", position, deck->controller);
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) &&
deck->cards[i]->zone_position > position) {
--(deck->cards[i]->zone_position);
hm_log(LOG_DEBUG, lg, "Decreased board zone position %d for card: %d", deck->cards[i]->zone_position, deck->cards[i]->id);
}
}
}
void card_free(struct card_s *card, unsigned int flags)
{
struct card_link_s *children, *del;
struct card_list_s *t, *tdel;
struct card_expire_s *ce, *ced;
if(EQFLAG(flags, FREE_CARD_CHILDREN)) {
for(children = card->attached_children; children != NULL; ) {
del = children;
children = children->next;
free(del);
}
}
if(EQFLAG(flags, FREE_CARD_EXPIRE)) {
for(ce = card->expire; ce != NULL; ) {
ced = ce;
ce = ce->next;
free(ced);
}
}
for(t = card->target.card; t != NULL; ) {
tdel = t;
t = t->next;
free(tdel);
}
free(card);
}
int deck_get_taunts(struct deck_s *deck)
{
int i, c = 0;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_TAUNT, FLAG_ISSET) && flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET)) {
c++;
}
}
hm_log(LOG_DEBUG, lg, "Deck %d taunt cards: %d", deck->controller, c);
return c;
}
void cards_unset_flag(struct deck_s *deck, enum flags_e flags)
{
int i;
for(i = 0; i < deck->ncards; i++) {
flag(&deck->cards[i]->state, flags, FLAG_UNSET);
}
}
void reset_turn_plays(struct deck_s *deck)
{
int i;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET)) {
deck->cards[i]->turn_plays = 0;
}
}
}
void unset_mechanics_flags(struct hs_holder_s *p)
{
struct deck_s *deck;
int i;
#define clr\
for(i = 0; i < deck->ncards; i++) {\
flag(&deck->cards[i]->state, MECHANICS_ATTACK, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_DAMAGE, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_HEALTH, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_ATTACK_HEAL, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_ATTACK_DAMAGE, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_HEROPOWER, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_BATTLECRY_TRIGGER, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_CHANGESIDES, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_ARMOR, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_DURABILITY, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_DETACH, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_SELECTED, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_DESTROY_WEAPON, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_TURN_TRIGGER, FLAG_UNSET);\
flag(&deck->cards[i]->state, MECHANICS_COST, FLAG_UNSET);\
}
deck = p->deck;
clr
deck = p->opponent.deck;
clr
}
int zone_position_last(struct deck_s *deck)
{
int i, position = 0;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
deck->cards[i]->zone_position > position) {
position = deck->cards[i]->zone_position;
}
}
return ++position;
}
int cards_get_board_count_flag(struct deck_s *deck, struct card_s *card, int f)
{
int i;
int count = 0;
for(i = 0; i < deck->ncards; i++) {
if(deck->cards[i]->id == card->id) {
continue;
}
if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
flag(&deck->cards[i]->state, f, FLAG_ISSET)) {
count++;
}
}
hm_log(LOG_DEBUG, lg, "Found %d cards for flag %d", count, f);
return count;
}
int cards_board_last(struct deck_s *deck)
{
int i;
int position = 1;
for(i = 0; i < deck->ncards; i++) {
/*
if(deck->cards[i]->id == card->id) {
continue;
}
*/
if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) &&
deck->cards[i]->zone_position >= position) {
hm_log(LOG_DEBUG, lg, "Zone position increased with card %d position %d", deck->cards[i]->id, deck->cards[i]->zone_position);
position = deck->cards[i]->zone_position + 1;
}
}
return position;
}
static void add_child_link(struct card_s *dst, int id, const char *name)
{
struct card_link_s *a;
a = malloc(sizeof(*a));
a->id = id;
a->name = name;
a->next = dst->attached_children;
dst->attached_children = a;
}
void cards_dump(struct deck_s *deck, struct deck_s *opponent)
{
int i;
hm_log(LOG_DEBUG, lg, "Cards dump started");
#define dump(d)\
hm_log(LOG_DEBUG, lg, "Cards dump for deck %d:", d->controller);\
for(i = 0; i < d->ncards; i++) {\
if(flag(&d->cards[i]->state, CARD_BOARD, FLAG_ISSET) || \
flag(&d->cards[i]->state, CARD_HAND, FLAG_ISSET) \
) {\
hm_log(LOG_DEBUG, lg, "\t\tName[%s](%d) zone position[%d] attack[%d] health[%d] totalhealth[%d]", d->cards[i]->entity->desc, d->cards[i]->id, d->cards[i]->zone_position, d->cards[i]->attack, d->cards[i]->health, d->cards[i]->total_health);\
flag(&d->cards[i]->state, -1, FLAG_DUMP);\
}\
}
dump(deck)
dump(opponent)
hm_log(LOG_DEBUG, lg, "Cards dump finished");
}
void cards_reorder_board_owner(struct deck_s *deck, u64 held, u64 position)
{
int i;
if(position - 1 >= MAX_BOARD) {
position = MAX_BOARD;
}
for(i = 0; i < deck->ncards; i++) {
if(deck->cards[i]->id == held) {
deck->cards[i]->zone_position = position;
deck->board_position[position - 1] = deck->cards[i]->id;
continue;
}
// when card on board is positioned equally or higher than new card
if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) &&
deck->cards[i]->zone_position >= position) {
++(deck->cards[i]->zone_position);
deck->board_position[ (deck->cards[i]->zone_position - 1) ] = deck->cards[i]->id;
}
}
}
void cards_reorder_hand_owner(struct deck_s *deck, u64 id)
{
int i, pos = 0;
struct card_s *card;
card = card_get(deck, NULL, id);
pos = card->zone_position - 1;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) && deck->cards[i]->id != id) {
if(deck->cards[i]->zone_position > card->zone_position) {
hm_log(LOG_DEBUG, lg, "Hand card position %d board card position %d", deck->cards[i]->zone_position, card->zone_position);
deck->cards[i]->zone_position--;
if(deck->cards[i]->zone_position > pos) {
pos = deck->cards[i]->zone_position;
}
}
}
}
card->zone_position = 0;
hm_log(LOG_DEBUG, lg, "Reordering zone positions %d", pos);
deck->handposition = pos;
}
int cards_get_board_flag(struct deck_s *deck, int f, int exclude)
{
int i;
int count = 0;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
flag(&deck->cards[i]->state, f, FLAG_ISSET) &&
deck->cards[i]->id != exclude )
{
count++;
}
}
hm_log(LOG_DEBUG, lg, "Found %d entities of flag %d while excluded %d", count, f, exclude);
return count;
}
struct card_s *card_get_board_zoneposition(struct deck_s *deck, u64 position)
{
int i;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
deck->cards[i]->zone_position == position)
{
hm_log(LOG_DEBUG, lg, "Card zone positon %lld card [%s](%d) found", position, deck->cards[i]->entity->desc, deck->cards[i]->id);
return deck->cards[i];
}
}
return NULL;
}
void card_discard_by_name(struct hs_holder_s *p, struct card_s *card, const char *name)
{
int i;
struct deck_s *deck;
hm_log(LOG_DEBUG, lg, "Discarding attacker's [%s](%d) associates: name %s", card->entity->desc, card->id, name);
deck = card->controller == p->deck_copy->controller ? p->deck_copy : p->opponent.deck_copy;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
strcmp(name, deck->cards[i]->entity->name) == 0) {
flag(&deck->cards[i]->state, CARD_DISCARD, FLAG_SET);\
cards_reorder_hand_owner(deck, deck->cards[i]->id);\
}
}
}
int board_count_by_name(struct deck_s *deck, const char *name)
{
int i, count = 0;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
strcmp(name, deck->cards[i]->entity->name) == 0) {
count++;
}
}
return count;
}
struct card_list_s *cards_by_name(struct hs_holder_s *p, struct deck_s *deck, const char *name, int f)
{
int i;
struct card_list_s *list = NULL, *item;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, f, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
strcmp(name, deck->cards[i]->entity->name) == 0) {
LIST_ADD(list, item, deck->cards[i]);
}
}
return list;
}
struct card_s *card_by_name(struct hs_holder_s *p, struct deck_s *deck, const char *name, int f)
{
int i;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, f, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
strcmp(name, deck->cards[i]->entity->name) == 0) {
return deck->cards[i];
}
}
return NULL;
}
struct card_list_s *cards_get_random(struct deck_s *deck, int number, struct card_s *attacker, int zone)
{
int count = 0, r, r1, i, total;
struct card_list_s *list = NULL, *item, *i1;
struct card_list_s *output = NULL;
hm_log(LOG_DEBUG, lg, "Getting %d random cards", number);
for(i = 0; i < deck->ncards; i++) {
if( (zone == 1 &&
(
(
flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET)
) ||
flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET)
)
)
||
(zone == 6 &&
(
flag(&deck->cards[i]->state, CARD_DECK, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET)
)
)
) {
LIST_ADD(list, item, deck->cards[i]);
count++;
}
}
assert(count > 0);
if(count <= number && !flag(&attacker->state, CARD_ARCANE_MISSILES, FLAG_ISSET)) {
return list;
}
total = 0;
r1 = -1;
again:
r = random_number(count);
// arcane missiles can hit the same target multiple times
if(r1 == r && !flag(&attacker->state, CARD_ARCANE_MISSILES, FLAG_ISSET)) goto again;
for(i = 0, item = list; item != NULL; item = item->next, i++) {
if(i == r) {
hm_log(LOG_DEBUG, lg, "Random card [%s](%d) added", item->card->entity->desc, item->card->id);
LIST_ADD(output, i1, item->card);
r1 = r;
if(number == ++total) break;
else goto again;
}
}
// TODO: free list
return output;
}
struct card_s *cards_get_hand_random(struct deck_s *deck)
{
int count = 0, r, i, count_all;
struct card_list_s *list = NULL, *item;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_DESTROYED, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET)) {
LIST_ADD(list, item, deck->cards[i]);
hm_log(LOG_DEBUG, lg, "\tGetting random inhand card %d", deck->cards[i]->id);
count++;
}
}
hm_log(LOG_DEBUG, lg, "Getting random card from total count of %d", count);
if(count == 0) {
return NULL;
}
count_all = count;
r = random_number(count);
count = 0;
for(item = list; item != NULL; item = item->next, count++) {
if(count == r) {
hm_log(LOG_DEBUG, lg, "Returning random card [%s](%d) from %d cards", item->card->entity->desc, item->card->id, count_all);
return item->card;
}
}
return NULL;
}
int card_deck_count(struct deck_s *deck)
{
int count = 0, i;
for(i = 0; i < deck->ncards; i++) {
assert(deck);
assert(deck->cards);
assert(deck->cards[i]);
if(flag(&deck->cards[i]->state, CARD_DECK, FLAG_ISSET)
) {
count++;
}
}
hm_log(LOG_DEBUG, lg, "Found %d cards in deck %d", count, deck->controller);
return count;
}
struct card_s *draw_first_boss(struct deck_s *deck)
{
int i, r, count = 0;
r = random_number(MAX_BOSS);
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_BOSS, FLAG_ISSET)) {
if((count++) == r) {
hm_log(LOG_DEBUG, lg, "Start Hand Random Boss %d", r);
flag(&deck->cards[i]->state, CARD_DECK, FLAG_UNSET);
flag(&deck->cards[i]->state, CARD_HAND, FLAG_SET);
deck->cards[i]->zone_position = ++deck->handposition;
deck->cards[i]->cost = 0; // first boss costs 0
return deck->cards[i];
}
}
}
return NULL;
}
struct card_s *draw_random_card(struct deck_s *deck, int entity_id, int zone_position)
{
int r;
if(card_deck_count(deck) == 0) {
return NULL;
}
again:
r = random_number(deck->ncards);
// exclude drawn, board and mana card
if(!flag(&deck->cards[r]->state, CARD_DECK, FLAG_ISSET) ||
deck->cards[r]->id == 68) {
goto again;
}
flag(&deck->cards[r]->state, CARD_DECK, FLAG_UNSET);
flag(&deck->cards[r]->state, CARD_HAND, FLAG_SET);
deck->cards[r]->zone_position = zone_position >= 1 ? zone_position : ++deck->handposition;
hm_log(LOG_DEBUG, lg, "Drawn random card %d [%s], hand zone position %d player entity: %d", deck->cards[r]->id, deck->cards[r]->entity->desc, deck->handposition, entity_id);
return deck->cards[r];
}
struct card_s *new_card(const int id, const char *name, int controller)
{
struct card_s *card;
int i;
#ifdef SPELL_ZERO_MANA
int cardtype = 0;
#endif
card = malloc(sizeof(*card));
memset(card, 0, sizeof(*card));
card->id = id;
card->entity = find_entity(name, strlen(name));
assert(card->entity);
for(i = 0; i < card->entity->nprop; i++) {
if(card->entity->p[i].key == HEALTH) {
card->health = card->total_health = card->default_health = card->entity->p[i].value;
} else if(card->entity->p[i].key == COST) {
card->cost = card->default_cost = card->entity->p[i].value;
} else if(card->entity->p[i].key == ATK) {
card->attack = card->default_attack = card->entity->p[i].value;
} else if(card->entity->p[i].key == CARDTYPE) {
#ifdef SPELL_ZERO_MANA
card->cardtype = card->entity->p[i].value;
cardtype = card->entity->p[i].value;
#endif
} else if(card->entity->p[i].key == DURABILITY) {
card->durability = card->maxdurability = card->entity->p[i].value;
} else if(card->entity->p[i].key == SPELLPOWER) {
card->spellpower = card->entity->p[i].value;
}
}
#ifdef MANA_ZERO
card->cost = 0;
#endif
#ifdef SPELL_ZERO_MANA
if(cardtype == 5) {
card->cost = 0;
}
#endif
if(card->entity->attachment) {
card->attachment = card->entity->attachment;
}
card->controller = controller;
flags_copy(&card->state, &card->entity->flags);
return card;
}
void deck_add_attachment(struct deck_s *deck, const char *name, enum flags_e f)
{
struct attachment_list_s *a;
abort();
a = malloc(sizeof(*a));
a->name = name;
a->group = f;
a->next = deck->attachments;
deck->attachments = a;
}
int card_count_attachment(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, const char *name)
{
struct card_link_s *child;
struct card_s *child_card;
int count;
for(count = 0, child = card->attached_children; child != NULL; child = child->next, count++);
hm_log(LOG_DEBUG, lg, "Total attachments on card [%s](%d) is %d", card->entity->desc, card->id, count);
for(count = 0, child = card->attached_children; child != NULL; child = child->next) {
child_card = card_get(deck, opponent, child->id);
assert(child_card);
if(strcmp(child_card->entity->name, name) == 0) {
count++;
} else {
hm_log(LOG_DEBUG, lg, "Comparisson [%s] to [%s] failed", child_card->entity->name, name);
}
}
hm_log(LOG_DEBUG, lg, "Total of %d attachments %s on card [%s](%d)", count, name, card->entity->name, card->id);
return count;
}
void card_remove_attachment(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, const char *name)
{
struct card_link_s *child, *prev_child;
struct card_s *child_card;
hm_log(LOG_DEBUG, lg, "Removing attachments on card [%s](%d)", card->entity->name, card->id);
for(prev_child = NULL, child = card->attached_children; child != NULL; prev_child = child, child = child->next) {
child_card = card_get(deck, opponent, child->id);
assert(child_card);
hm_log(LOG_DEBUG, lg, "\t\t - checking attachment [%s] [%s](%d)", name, child_card->entity->name, child_card->id);
if(name == NULL || strcmp(child_card->entity->name, name) == 0) {
if(prev_child == NULL) {
card->attached_children = child->next;
} else {
prev_child->next = child->next;
}
flag(&(child_card->state), MECHANICS_DETACH, FLAG_SET);
flag(&(child_card->state), CARD_DESTROYED, FLAG_SET);
hm_log(LOG_DEBUG, lg, "Removing attachment [%s](%d) for card [%s](%d)", child_card->entity->desc, child_card->id, card->entity->desc, card->id);
flag(&(child_card->state), -1, FLAG_DUMP);
free(child);
break;
}
}
}
void deck_remove_attachment(struct deck_s *deck, struct deck_s *opponent, const char *name)
{
struct attachment_list_s *a, *prev;
struct card_list_s *cards, *card;
cards = cards_get_board(deck, NULL, -1, 0, -1, 1);
hm_log(LOG_DEBUG, lg, "Starting attachments removal");
for(prev = NULL, a = deck->attachments; a != NULL; prev = a, a = a->next) {
if(strcmp(name, a->name) == 0) {
if(prev == NULL) {
deck->attachments = a->next;
} else {
prev->next = a->next;
}
hm_log(LOG_DEBUG, lg, "Removing attachment [%s] from deck %p", a->name, deck);
free(a);
break;
}
}
for(card = cards; card != NULL; card = card->next) {
card_remove_attachment(deck, opponent, card->card, name);
}
}
void add_single_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, struct card_s *defender)
{
if(attacker && attacker->attachment) {
// FIXME: deck might be opponent's too
struct card_s *att = add_new_card(p->game, deck, -1, attacker->attachment, -1);
att->attached_to = defender->id;
add_child_link(defender, att->id, att->entity->name);
hm_log(LOG_DEBUG, lg, "Adding attachment [%s](%d) to card [%s]%d", att->entity->desc, att->id, defender->entity->desc, defender->id);
} else {
hm_log(LOG_ALERT, lg, "Attacker [%s](%d) has no attachment", attacker->entity->desc, attacker->id);
abort();
}
}
void card_apply_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *dst, const char *attachment)
{
struct card_s *card;
card = add_new_card(p->game, deck, -1, attachment, -1);
card->attached_to = dst->id;
add_child_link(dst, card->id, card->entity->name);
hm_log(LOG_DEBUG, lg, "Adding attachment [%s](%d) to card [%s]%d", card->entity->desc, card->id, dst->entity->desc, dst->id);
}
void card_apply_attachments(struct hs_holder_s *p, struct deck_s *deck, struct card_s *dst)
{
struct attachment_list_s *c;
assert(deck);
assert(dst);
// applying current attachments to card
for(c = deck->attachments; c != NULL; c = c->next) {
//cards_dump_board(deck);
abort();
if(c->group > 0 && !flag(&dst->state, c->group, FLAG_ISSET)) {
continue;
}
card_apply_attachment(p, deck, dst, c->name);
}
}
void cards_apply_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, enum flags_e f)
{
struct card_list_s *c, *cards;
struct card_s *att;
cards = cards_get_board(deck, NULL, -1, attacker->id, -1, 1);
for(c = cards; c != NULL; c = c->next) {
if(f > 0 && !flag(&c->card->state, f, FLAG_ISSET)) {
continue;
}
att = add_new_card(p->game, deck, -1, attacker->attachment, -1);
att->attached_to = c->card->id;
add_child_link(c->card, att->id, att->entity->name);
hm_log(LOG_DEBUG, lg, "Adding attachment [%s](%d) to card [%s]%d", att->entity->desc, att->id, c->card->entity->desc, c->card->id);
}
}
void card_destroy(struct card_s *card, struct deck_s *deck, int to_hand)
{
struct hs_holder_s *p = deck->parent;
struct conn_client_s *c = p->client;
if(flag(&card->state, CARD_BOARD, FLAG_ISSET)) {
flag(&card->state, CARD_BOARD, FLAG_UNSET);
}
if(flag(&card->state, CARD_SPELLPOWER, FLAG_ISSET)) {
//deck->spellpower -= card->spellpower;
deck->spellpower--;
}
if(!to_hand) {
flag(&card->state, CARD_DESTROYED, FLAG_SET);
}
cards_board_destroyed_reorder(deck, card->zone_position);
{
struct card_s *__fake_defender = card;
__SECTION_DESTROYED
}
}
void card_dump(struct card_s *card)
{
hm_log(LOG_DEBUG, lg, "Dumping card %d:\
\n\tParent: %p\n\
\tController: %d\n\
\tID: %d\n\
\tHealth: %d\n", card->id, card->parent, card->controller, card->id, card->health);\
}
+441
View File
@@ -0,0 +1,441 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
#define TEST_DECK_MAX 2
const char *test_deck[TEST_DECK_MAX] = { "EX1_581", "EX1_306" };
struct card_s *add_new_card(struct game_s *game, struct deck_s *deck, int index, const char *card, enum flags_e flags)
{
int n;
struct card_s *c;
n = ++(deck->ncards);
deck->cards = realloc(deck->cards, sizeof(void *) * deck->ncards);
game->maxentity_id++;
if(index == -1) {
c = new_card(game->maxentity_id, card, deck->controller);
} else {
c = new_card(index, card, deck->controller);
}
if(flags != -1) {
//c->state |= flags;
flag(&c->state, flags, FLAG_SET);
}
assert(deck);
assert(deck->parent);
c->parent = deck->parent;
deck->cards[n - 1] = c;
hm_log(LOG_DEBUG, lg, "Added new card to deck: %p controller: %d card: %d properties: %d total cards: %d game maxentity_id: %d", deck, deck->controller, c->id, c->entity->nprop, deck->ncards, game->maxentity_id);
return c;
}
static struct deck_s *create_deck(struct conn_client_s *c, const int controller, int *counter)
{
struct deck_s *deck;
int i, j;
struct hs_holder_s *p;
struct game_s *game;
p = c->data;
game = p->game;
deck = malloc(sizeof(*deck));
if(deck == NULL) {
return NULL;
}
memset(deck, 0, sizeof(*deck));
deck->controller = controller;
assert(p);
deck->parent = p;
#ifdef TEST_DECK
#define DEFAULT_DECK_MAX 30
int id;
deck->ncards = DEFAULT_DECK_MAX;
deck->cards = malloc(sizeof(void *) * deck->ncards);
for(j = 0, i = 0, j = 0; i < deck->ncards; i++, j++ ) {
if(controller == 1) {
id = i + 4;
} else {
id = i + 4 + DEFAULT_DECK_MAX;
}
if(j == TEST_DECK_MAX) j = 0;
//j = (controller == 1 ? 0 : 1);
deck->cards[i] = new_card(id, test_deck[j], controller);
assert(deck);
deck->cards[i]->parent = deck->parent;
//deck->cards[i]->state |= CARD_DECK;
flag(&deck->cards[i]->state, CARD_DECK, FLAG_SET);
game->maxentity_id++;
}
#else
struct player_deck_s *pdc;
deck->ncards = c->ncards;
deck->cards = malloc(sizeof(void *) * deck->ncards);
for(j = 0, pdc = c->cards; pdc != NULL; pdc = pdc->next) {
for(i = 0; i < pdc->count; i++) {
deck->cards[j] = new_card((*counter)++, pdc->code, controller);
deck->cards[j]->parent = deck->parent;
flag(&deck->cards[j]->state, CARD_DECK, FLAG_SET);
hm_log(LOG_DEBUG, lg, "Added card (%d)[%s]", deck->cards[j]->id, deck->cards[j]->entity->desc);
game->maxentity_id++;
j++;
}
}
assert(j == deck->ncards);
#endif
hm_log(LOG_DEBUG, lg, "Created deck: %p controller: %d ncards: %d", deck, controller, deck->ncards);
return deck;
}
void prepare_decks(struct conn_client_s *c)
{
struct hs_holder_s *p1;
struct deck_s *p2_deck;
int i;
p1 = c->data;
assert(p1);
if(p1->opponent.accessible == 1) {
p2_deck = p1->opponent.deck;
}
assert(p2_deck);
if(EQFLAG(p1->deck->flags, DECK_INIT)) {
return;
}
p1->deck->flags |= DECK_INIT;
p2_deck->flags |= DECK_INIT;
// randomly select 4 cards for p1 - 2nd turn
// randomly select 3 cards for p2 - 1st turn
// put one random boss
draw_first_boss(p1->deck);
for(i = 0; i < 3; i++) {
draw_random_card(p1->deck, p1->entity_id, -1);
}
for(i = 0; i < p1->deck->ncards; i++) {
if(p1->deck->cards[i]->entity->nname == strlen("GAME_005") &&
memcmp(p1->deck->cards[i]->entity->name, "GAME_005", strlen("GAME_005")) == 0) {
flag(&p1->deck->cards[i]->state, CARD_HAND, FLAG_SET);
p1->deck->cards[i]->zone_position = ++p1->deck->handposition;
}
}
hm_log(LOG_DEBUG, lg, "P1 deck default zone position: %d", p1->deck->handposition);
// put one random boss
draw_first_boss(p2_deck);
for(i = 0; i < 2; i++) {
draw_random_card(p2_deck, 3, -1);
}
hm_log(LOG_DEBUG, lg, "P2 deck default zone position: %d", p2_deck->handposition);
}
void holder_free(struct hs_holder_s *h)
{
deck_free(h->deck, (FREE_DECK_ATTACHMENT | FREE_CARD_CHILDREN | FREE_CARD_EXPIRE));
deck_free(h->deck_copy, (FREE_DECK_ATTACHMENT | FREE_CARD_CHILDREN | FREE_CARD_EXPIRE));
free(h);
}
int append_decks(struct conn_client_s *p1, struct conn_client_s *p2)
{
struct hs_holder_s *p1_holder, *p2_holder;
struct game_s *g;
p1_holder = malloc(sizeof(*p1));
p2_holder = malloc(sizeof(*p2));
memset(p1_holder, 0, sizeof(*p1_holder));
memset(p2_holder, 0, sizeof(*p2_holder));
p1->data = p1_holder;
p2->data = p2_holder;
p1_holder->client = p1;
p2_holder->client = p2;
g = malloc(sizeof(*g));
memset(g, 0, sizeof(*g));
g->entity_id = 1;
g->flags = 0;
g->turn = 1;
g->maxentity_id = 3; ///< start with offset 4, as 1 - game entity, 2/3 - players
p1_holder->game = p2_holder->game = g;
assert(p1_holder->game && p2_holder->game);
int counter = 4;
p1_holder->deck = create_deck(p1, 1, &counter);
p2_holder->deck = create_deck(p2, 2, &counter);
p1_holder->opponent.accessible = 1;
p2_holder->opponent.accessible = 1;
p1_holder->opponent.deck = p2_holder->deck;
p2_holder->opponent.deck = p1_holder->deck;
p1_holder->deck->bnet_hi = 0x4ab3967;
p2_holder->deck->bnet_hi = 0x49E8Eb5;
p1_holder->id = 1;
p2_holder->id = 2;
p1_holder->entity_id = 2;
p2_holder->entity_id = 3;
p1_holder->opponent.client = p2;
p2_holder->opponent.client = p1;
p1_holder->deck->mana = p2_holder->deck->mana = 1;
p1_holder->deck->hero = add_new_card(p1_holder->game, p1_holder->deck, -1, "TB_SPT_Boss" /*p1->hero*/, -1);
p1_holder->deck->heropower = add_new_card(p1_holder->game, p1_holder->deck, -1, p1->hp, -1);
p2_holder->deck->hero = add_new_card(p1_holder->game, p2_holder->deck, -1, "LOEA04_01"/*p2->hero*/, -1);
p2_holder->deck->heropower = add_new_card(p1_holder->game, p2_holder->deck, -1, p2->hp, -1);
(void)add_new_card(p1_holder->game, p1_holder->deck, -1, "GAME_005", CARD_HAND);
prepare_decks(p1);
return 0;
}
void game_free(struct game_s *g)
{
ev_timer_stop(loop, &g->turntimer);
ev_timer_stop(loop, &g->force_next_turn);
free(g);
}
void copy_card(struct card_s **dst, struct card_s *src)
{
if(src == NULL) {
*dst = NULL;
return;
}
*dst = malloc(sizeof(**dst));
memset(*dst, 0, sizeof(**dst));
#define cpyc(m_ele)\
(*dst)->m_ele = src->m_ele;
cpyc(parent);
cpyc(id);
cpyc(controller);
memcpy(&(*dst)->state, &src->state, sizeof(src->state));
cpyc(attachment);
cpyc(attached_to);
cpyc(attached_children);
cpyc(entity);
cpyc(zone_position);
cpyc(total_health);
cpyc(health);
cpyc(default_health);
cpyc(buff_health);
cpyc(attack);
cpyc(default_attack);
cpyc(cost);
cpyc(default_cost);
cpyc(cardtype);
cpyc(durability);
cpyc(maxdurability);
cpyc(armor);
cpyc(actions_number);
cpyc(spellpower);
// do not copy 'target' and 'receive'
memcpy(&(*dst)->boss, &src->boss, sizeof(src->boss));
cpyc(linked);
cpyc(expire);
cpyc(total_plays);
cpyc(turn_plays);
}
void deck_free(struct deck_s *deck, unsigned int flags)
{
int i;
struct attachment_list_s *a, *del;
if(deck == NULL) {
return;
}
if(EQFLAG(flags, FREE_DECK_ATTACHMENT)) {
for(a = deck->attachments; a != NULL; ) {
del = a;
a = a->next;
free(del);
}
}
for(i = 0; i < deck->ncards; i++) {
card_free(deck->cards[i], flags);
}
free(deck);
}
struct deck_s *copy_deck(struct deck_s *src)
{
struct deck_s *dst;
int i;
dst = malloc(sizeof(*dst));
dst->hero = dst->heropower = dst->heroweapon = NULL;
#define cpy(m_ele)\
dst->m_ele = src->m_ele;
assert(src->parent);
cpy(parent);
cpy(bnet_hi);
cpy(controller);
cpy(mana);
cpy(mana_used);
cpy(spellpower);
cpy(handposition);
cpy(ncards);
memcpy(&dst->modifiers, &src->modifiers, sizeof(src->modifiers));
dst->cards = malloc(sizeof(void *) * dst->ncards);
for(i = 0; i < dst->ncards; i++) {
copy_card(&dst->cards[i], src->cards[i]);
if(flag(&dst->cards[i]->state, CARD_HERO, FLAG_ISSET)) {
dst->hero = dst->cards[i];
} else if(flag(&dst->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) {
dst->heropower = dst->cards[i];
} else if(flag(&dst->cards[i]->state, CARD_HEROWEAPON, FLAG_ISSET)) {
dst->heroweapon = dst->cards[i];
}
}
memcpy(&dst->board_position, &src->board_position, sizeof(src->board_position));
cpy(attachments);
cpy(fatigue);
cpy(gameover);
cpy(flags);
return dst;
}
void decks_copy(struct hs_holder_s *p)
{
struct hs_holder_s *opponent;
opponent = p->opponent.client->data;
assert(p->deck_copy == NULL);
assert(p->opponent.deck_copy == NULL);
assert(opponent->deck_copy == NULL);
assert(opponent->opponent.deck_copy == NULL);
///< make copies of our and opponent's deck
p->deck_copy = copy_deck(p->deck);
opponent->opponent.deck_copy = p->deck_copy;
p->opponent.deck_copy = copy_deck(p->opponent.deck);
opponent->deck_copy = p->opponent.deck_copy;
hm_log(LOG_DEBUG, lg, "Deck old %p new %p Opponeng old %p new %p", p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy);
}
void decks_swap(struct hs_holder_s *p)
{
struct hs_holder_s *o;
o = p->opponent.client->data;
hm_log(LOG_DEBUG, lg, "Freeing decks %p %p", p->deck, p->opponent.deck);
hm_log(LOG_DEBUG, lg, "Decks copies to swap %p %p", p->deck_copy, p->opponent.deck_copy);
// free old decks
deck_free(p->deck, 0);
deck_free(p->opponent.deck, 0);
o->deck = NULL;
o->opponent.deck = NULL;
// swap current player
p->deck = p->deck_copy;
p->opponent.deck = p->opponent.deck_copy;
p->deck_copy = NULL;
p->opponent.deck_copy = NULL;
// swap opponent
o->deck = p->opponent.deck;
o->opponent.deck = p->deck;
o->deck_copy = NULL;
o->opponent.deck_copy = NULL;
}
@@ -0,0 +1,63 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void next_turn(struct conn_client_s *c, struct hs_holder_s *p/*, struct chooseoption_s *opt*/)
{
struct packet_s *p1;
struct packet_s *p2;
struct card_s *drawn_card = NULL;
int zone = 0;
decks_copy(p);
// refresh resources
update_resources(p->opponent.deck_copy, NULL, 1);
mechanics_next_turn(c, p);
hm_log(LOG_INFO, c->log, "Next turn: %d", p->game->turn);
p1 = net_next_turn(c, &drawn_card, &zone);
p2 = net_next_turn(c, &drawn_card, &zone);
decks_swap(p);
net_send(c, p1);
net_send(p->opponent.client, p2);
net_send_options(p->opponent.client, p->opponent.deck, p->deck, p->game->turn);
packet_free(p1);
packet_free(p2);
/*
ptr = output;
n = serialize(p1, &ptr, ptr + sizeof(output));
hm_send(c, output, n);
ptr = output;
n = serialize(p2, &ptr, ptr + sizeof(output));
int so = set_options(p->opponent.deck, p->deck, output + n, output + sizeof(output) - n, p->game->turn);
//memcpy(output + n + so, opt1, sizeof(opt1));
hm_send(p->opponent.client, output, n + so);
*/
}
+262
View File
@@ -0,0 +1,262 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void power_attack(struct conn_client_s *c, struct hs_holder_s *p, struct chooseoption_s *opt)
{
struct card_s *attacker = NULL, *defender;
struct deck_s *deck, *opponent;
struct packet_s *p1 = NULL, *p2 = NULL, *extra = NULL;
struct card_list_s *defenders = NULL, *clitem, *def;
decks_copy(p);
deck = p->deck_copy;
opponent = p->opponent.deck_copy;
attacker = card_get(deck, NULL, p->arroworigin);
if(!attacker) attacker = card_get(deck, NULL, p->held_card);
assert(attacker);
if(flag(&attacker->state, CARD_HAND, FLAG_ISSET)) {
flag(&attacker->state, CARD_HAND, FLAG_UNSET);
}
if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) {
// update resources
update_resources(deck, attacker, 0);
// put spell on board
if(!flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) {
flag(&attacker->state, CARD_BOARD, FLAG_SET);
}
}
defender = card_get(deck, opponent, opt->target);
// there can only be none or one defender here
if(defender) {
LIST_ADD(defenders, clitem, defender);
}
hm_log(LOG_ERR, c->log, "Power attack: origin: %d target: %lld held: %d attacker: [%s](%d) defenders: %p", p->arroworigin, opt->target, p->held_card, attacker->entity->desc, attacker->id, defenders);
if(/*p->held_card > 0 && */flag(&attacker->state, CARD_AOE, FLAG_ISSET)) {
hm_log(LOG_INFO, c->log, "Attacker AOE [%s](%d)", attacker->entity->desc, attacker->id);
/*
///< get opponent's board cards
if(flag(&attacker_aoe->state, CARD_AOE_ENEMY_MINIONS, FLAG_ISSET)) {
defenders = cards_get_board(NULL, p->opponent.deck_copy, 0, -1);
} else if(flag(&attacker_aoe->state, CARD_AOE_ALLENEMY, FLAG_ISSET)) {
defenders = cards_get_board(NULL, p->opponent.deck_copy, 1, -1);
} else if(flag(&attacker_aoe->state, CARD_AOE_TARGET_ALL, FLAG_ISSET)) {
defenders = cards_get_board(p->deck_copy, p->opponent.deck_copy, 1, -1);
} else if(flag(&attacker_aoe->state, CARD_AOE_MINIONS, FLAG_ISSET)) {
defenders = cards_get_board(p->deck_copy, p->opponent.deck_copy, 0, -1);
} else if(flag(&attacker_aoe->state, CARD_AOE_CLEAVE, FLAG_ISSET) || flag(&attacker_aoe->state, CARD_AOE_MULTISHOT, FLAG_ISSET)) {
defenders = cards_get_random(p->opponent.deck_copy, 2, attacker, 1);
} else if(flag(&attacker_aoe->state, CARD_TRACKING, FLAG_ISSET)) {
defenders = cards_get_random(p->deck_copy, 3, attacker_aoe, 6);
flag(&attacker_aoe->state, MECHANICS_SELECTED, FLAG_SET);
} else if(flag(&attacker_aoe->state, CARD_ARCANE_MISSILES, FLAG_ISSET)) {
int tsp = attacker_aoe->attack + p->deck_copy->spellpower;
defenders = cards_get_random(p->opponent.deck_copy, tsp, attacker_aoe, 1);
} else if(flag(&attacker_aoe->state, CARD_SINISTER_STRIKE, FLAG_ISSET) ||
flag(&attacker_aoe->state, CARD_MIND_BLAST, FLAG_ISSET)) {
LIST_ADD(defenders, clitem, opponent->hero);
}
hm_log(LOG_INFO, c->log, "Casting AOE card [%s](%d) against:", attacker_aoe->entity->desc, attacker_aoe->id);
for(def = defenders; def != NULL; def = def->next) {
hm_log(LOG_INFO, c->log, "\t[%s](%d)", def->card->entity->desc, def->card->id);
}
mechanics_attack_aoe(c, opt->position, attacker_aoe, &defenders);
*/
{
struct card_s *__fake_levelup = NULL;
__SECTION_SPELL_AOE
}
{
struct card_s *__fake_defender = attacker;
__SECTION_DESTROYED
}
p1 = net_spell_aoe(c, opt, deck->controller, attacker);
p2 = net_spell_aoe(c, opt, opponent->controller, attacker);
if(flag(&attacker->state, CARD_TRACKING, FLAG_ISSET)) {
struct entitychoices_s *ec;
ec = chooseone_choices(defenders, p->id, attacker->id);
add_packet(&extra, ec, P_ENTITYCHOICES);
entitychoices_dump(ec);
// set client to choose one
p->choose_one = 1;
}
} else if(
attacker && flag(&attacker->state, CARD_BUFF, FLAG_ISSET) && flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) {
/*
if(flag(&attacker->state, CARD_BLOODLUST, FLAG_ISSET)) {
defenders = cards_get_board(p->deck_copy, NULL, 0, attacker->id);
} else if(flag(&attacker->state, CARD_VANISH, FLAG_ISSET)) {
defenders = cards_get_board(p->deck_copy, p->opponent.deck_copy, 0, attacker->id);
} else if(flag(&attacker->state, CARD_SAVAGE_ROAR, FLAG_ISSET)) {
defenders = cards_get_board(p->deck_copy, NULL, 1, attacker->id);
} else if(flag(&attacker->state, CARD_CLAW, FLAG_ISSET) ||
flag(&attacker->state, CARD_HEROIC_STRIKE, FLAG_ISSET)) {
LIST_ADD(defenders, clitem, deck->hero);
} else if(flag(&attacker->state, CARD_MIND_VISION, FLAG_ISSET)) {
defenders = NULL;
} else {
LIST_ADD(defenders, clitem, defender);
}
*/
hm_log(LOG_INFO, c->log, "Buff [%s)(%d)", attacker->entity->desc, attacker->id);
mechanics_buff(c, opt, attacker, &defenders);
for(def = defenders; def != NULL; def = def->next) {
hm_log(LOG_INFO, c->log, "Buffing [%s)(%d) > [%s](%d)", attacker->entity->desc, attacker->id, def->card->entity->desc, def->card->id);
}
p1 = net_buff(c, opt, deck->controller, attacker, defenders);
p2 = net_buff(c, opt, opponent->controller, attacker, defenders);
/*
} else if(attacker && flag(&attacker->state, CARD_BATTLECRY_TARGET, FLAG_ISSET) && (
(attacker->total_plays == 0 && flag(&attacker->state, CARD_BATTLECRY_HEAL2_TARGET, FLAG_ISSET)) ||
(attacker->total_plays == 0 && flag(&attacker->state, CARD_BATTLECRY_DAMAGE1_TARGET, FLAG_ISSET)) ||
(attacker->total_plays == 0 && flag(&attacker->state, CARD_BATTLECRY_DAMAGE2_TARGET, FLAG_ISSET)) ||
(attacker->total_plays == 0 && flag(&attacker->state, CARD_BATTLECRY_DAMAGE3_TARGET, FLAG_ISSET)))
) {
flag(&attacker->state, MECHANICS_BATTLECRY_TRIGGER, FLAG_SET);
LIST_ADD(defenders, clitem, defender);
hm_log(LOG_INFO, c->log, "Battlecry target %d > %lld, total plays %d", p->arroworigin, opt->target, attacker->total_plays);
mechanics_attack(c, opt, attacker, defenders);
p1 = net_spell(c, opt, 1, attacker, defenders);
*/
} else if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && flag(&attacker->state, CARD_HP_SPELL_DAMAGE, FLAG_ISSET)) {
//LIST_ADD(defenders, clitem, defender);
//mechanics_attack(c, opt, attacker, defenders);
hm_log(LOG_INFO, c->log, "Casting HP spell %d > %lld", p->arroworigin, opt->target);
p1 = net_spell_hp_damage(c, defenders, attacker);
} else if(flag(&attacker->state, (CARD_SPELL), FLAG_ISSET)) {
hm_log(LOG_INFO, c->log, "Casting spell %d > %lld", p->arroworigin, opt->target);
assert(attacker);
/*
LIST_ADD(defenders, clitem, defender);
if(flag(&attacker->state, CARD_SWIPE, FLAG_ISSET)) {
mechanics_attack_swipe(c, opt->position, attacker, &defenders);
} else {
mechanics_attack(c, opt, attacker, defenders);
}
*/
struct card_s *__fake_levelup = NULL;
__SECTION_SPELL
{
struct card_s *__fake_defender = attacker;
__SECTION_DESTROYED
}
p1 = net_spell(c, opt, deck->controller, attacker, defenders, __fake_levelup);
if(!flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) {
p2 = net_spell(c, opt, opponent->controller, attacker, defenders, __fake_levelup);
}
} else {
hm_log(LOG_INFO, c->log, "Attacking %d > %lld", p->arroworigin, opt->target);
struct card_s *__fake_levelup = NULL;
__SECTION_ATTACK
p1 = net_attack(c, opt, attacker, defender, deck->controller);
p2 = net_attack(c, opt, attacker, defender, opponent->controller);
}
decks_swap(p);
net_send(c, p1);
if(p2) {
net_send(p->opponent.client, p2);
} else {
net_send(p->opponent.client, p1);
}
if(extra) {
net_send(c, extra);
//net_send(p->opponent.client, extra);
} else {
net_send_options(c, p->deck, p->opponent.deck, p->game->turn);
}
packet_free(p1);
if(p2) packet_free(p2);
if(extra) packet_free(extra);
/*
if(p->em)
em_fire(p);
if(player2->em)
em_fire(player2);
*/
/*
ptr = output;
n = serialize(p1, &ptr, ptr + sizeof(output));
hm_log(LOG_INFO, c->log, "Serialized %d bytes", n);
hm_send(c, output, n);
if(p2) {
ptr = output;
n = serialize(p2, &ptr, ptr + sizeof(output));
}
hm_send(p->opponent.client, output, n);
int so = set_options(p->deck, p->opponent.deck, output, output + sizeof(output), p->game->turn);
hm_send(c, output, so);
*/
}
@@ -0,0 +1,69 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void put_card_onboard(struct conn_client_s *c, struct hs_holder_s *p, struct chooseoption_s *opt)
{
struct packet_s *p1;
struct packet_s *p2;
struct card_s *attacker;
decks_copy(p);
///< get attacker from copied deck
attacker = card_get(p->deck_copy, NULL, p->held_card);
assert(attacker);
update_resources(p->deck_copy, attacker, 0);
hm_log(LOG_INFO, lg, "Putting card %d on board", attacker->id);
mechanics_put_card_onboard(c, opt->position, attacker, 0, NULL, opt, p->deck_copy);
p1 = net_card_onboard(p, opt, attacker, p->deck_copy->controller);
p2 = net_card_onboard(p, opt, attacker, p->opponent.deck_copy->controller);
decks_swap(p);
net_send(c, p1);
net_send_options(c, p->deck, p->opponent.deck, p->game->turn);
net_send(p->opponent.client, p2);
packet_free(p1);
packet_free(p2);
/*
int n;
char output[8192];
char *ptr = output;
n = serialize(p1, &ptr, ptr + sizeof(output));
int so = set_options(p->deck, p->opponent.deck, output + n, output + sizeof(output) - n, p->game->turn);
//hm_log(LOG_DEBUG, lg, "sending %d bytes to initiator", n + so);
hm_send(c, output, (int)(n + so));
char output2[2048];
ptr = output2;
int n2 = serialize(p2, &ptr, ptr + sizeof(output2));
//hm_log(LOG_DEBUG, lg, "sending %d bytes to initiator's opponent", n);
hm_send(p->opponent.client, output2, n2);
*/
}
@@ -0,0 +1,74 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
int game(struct conn_client_s *c, struct chooseoption_s *opt)
{
struct hs_holder_s *p;
struct card_s *attacker = NULL;
p = c->data;
if(p->held_card > 0) {
attacker = card_get(p->deck, NULL, p->held_card);
}
if(opt->index == 0) {
next_turn(c, p);
} else if(
(!(attacker && flag(&attacker->state, CARD_BATTLECRY, FLAG_ISSET))) &&
(!(attacker && flag(&attacker->state, CARD_WEAPON, FLAG_ISSET))) &&
(
(opt->target != 0 && p->arroworigin != 0) ||
(p->held_card > 0 && flag(&attacker->state, CARD_SPELL, FLAG_ISSET)))
/*
(p->held_card > 0 && flag(&attacker->state, CARD_BUFF_AOE, FLAG_ISSET)) ||
(p->held_card > 0 && flag(&attacker->state, CARD_VANISH, FLAG_ISSET)) ||
(p->held_card > 0 && flag(&attacker->state, CARD_SUMMON, FLAG_ISSET)) ||
(p->held_card > 0 && flag(&attacker->state, CARD_DRAW_CARD, FLAG_ISSET)) ||
(p->held_card > 0 && flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET))
*/
) {
// attack or spell damage
hm_log(LOG_INFO, c->log, "Power attack held: %d, attacker: %p, target: %lld, arroworigin: %d", p->held_card, attacker, opt->target, p->arroworigin);
power_attack(c, p, opt);
} else if(p->held_card > 0) {
// put card on board
put_card_onboard(c, p, opt);
}
//skip:
// unset origin
p->arroworigin = 0;
// unset
p->held_card = 0;
cards_dump(p->deck, p->opponent.deck);
unset_mechanics_flags(p);
hm_log(LOG_INFO, c->log, "Unsetting held card %d arroworigin %d", p->held_card, p->arroworigin);
return 0;
}
@@ -0,0 +1,52 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void mechanics_attack_aoe(struct conn_client_s *c, u64 position, struct card_s *attacker, struct card_list_s **defenders, struct card_s **fake_levelup)
{
struct hs_holder_s *p;
struct deck_s *deck;
struct card_list_s *item;
p = c->data;
deck = p->deck_copy;
assert(deck);
hm_log(LOG_DEBUG, c->log, "Attack %d > defenders", attacker->id);
if(!flag(&attacker->state, CARD_TRACKING, FLAG_ISSET)) {
game_attack_aoe(p, attacker, *defenders, fake_levelup);
} else {
if(defenders) attacker->target.card = *defenders;
}
if(flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) {
flag(&attacker->state, MECHANICS_HEROPOWER, FLAG_SET);
flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET);
hm_log(LOG_DEBUG, c->log, "Card [%s](%d) heropower triggered", attacker->entity->desc, attacker->id);
} else {
hm_log(LOG_DEBUG, c->log, "Card [%s](%d) heropower not triggered", attacker->entity->desc, attacker->id);
}
if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && !flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) {
flag(&attacker->state, CARD_DESTROYED, FLAG_SET);
cards_reorder(p, deck, attacker, position, 0);
}
}
+53
View File
@@ -0,0 +1,53 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void mechanics_buff(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s **d)
{
struct hs_holder_s *p;
struct deck_s *deck;
struct card_list_s *def;
p = c->data;
deck = p->deck_copy;
#define defender ((*d != NULL) ? (*d)->card : NULL)
#define defenders (*d)
if(defender) {
hm_log(LOG_DEBUG, c->log, "Buff [%s](%d) to [%s](%d)", attacker->entity->desc, attacker->id, defender->entity->desc, defender->id);
}
// set destroyed if spell
if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) {
{
struct card_s *__fake_defender = attacker;
__SECTION_DESTROYED
}
flag(&attacker->state, CARD_DESTROYED, FLAG_SET);
cards_reorder(p, deck, attacker, opt->position, 0);
}
__SECTION_BUFF
// set exhausted if minion
if(flag(&attacker->state, CARD_MINION, FLAG_ISSET)) {
flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET);
}
}
@@ -0,0 +1,48 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void mechanics_draw_card(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, int cards, struct card_list_s **defenders)
{
struct hs_holder_s *p;
struct deck_s *deck;
int i;
struct card_s *card;
struct card_list_s *clitem;
p = c->data;
deck = p->deck_copy;
assert(deck);
hm_log(LOG_DEBUG, c->log, "%s Drawing %d cards:", LOG_MECHANICS, cards);
for(i = 0; i < cards; i++) {
card = draw_random_card(deck, p->entity_id, -1);
flag(&card->state, CARD_HAND, FLAG_SET);
LIST_ADD(*defenders, clitem, card);
hm_log(LOG_DEBUG, c->log, "%s Drawing card %d from deck %d", LOG_MECHANICS, card->id, card->parent->deck_copy->controller);
}
if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && !flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) {
flag(&attacker->state, CARD_DESTROYED, FLAG_SET);
cards_reorder(p, deck, attacker, opt->position, 0);
}
}
@@ -0,0 +1,139 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
#ifdef TEST_DECK
#define LEVEL3_EXP 2
#define LEVEL2_EXP 1
#else
//#define LEVEL3_EXP 10
//#define LEVEL2_EXP 5
#define LEVEL3_EXP 2
#define LEVEL2_EXP 1
#endif
#define LEVEL2 2
#define LEVEL3 3
static void level_up(struct hs_holder_s *p, struct deck_s *deck, struct card_s *dst, struct card_s *target)
{
assert(dst && target);
dst->boss.experience += target->cost;
if(dst->boss.experience >= LEVEL3_EXP && dst->boss.level < LEVEL3) {
card_remove_attachment(deck, NULL, dst, LEVEL_1);
card_remove_attachment(deck, NULL, dst, LEVEL_2);
card_apply_attachment(p, deck, dst, LEVEL_3);
if(dst->entity->level3) {
hsl_add_new_card_hand(deck, dst->entity->level3, holder);
}
// when we bypass level 2
if(dst->boss.level == 0 && dst->entity->level2) {
hsl_add_new_card_hand(deck, dst->entity->level2, holder);
}
dst->boss.level = LEVEL3;
hm_log(LOG_DEBUG, lg, "Boss [%s](%d) reached level 3", dst->entity->desc, dst->id);
} else if(dst->boss.experience >= LEVEL2_EXP && dst->boss.level < LEVEL2) {
dst->boss.level = LEVEL2;
card_remove_attachment(deck, NULL, dst, LEVEL_1);
card_apply_attachment(p, deck, dst, LEVEL_2);
if(dst->entity->level2) {
hsl_add_new_card_hand(deck, dst->entity->level2, holder);
}
hm_log(LOG_DEBUG, lg, "Boss [%s](%d) reached level 2", dst->entity->desc, dst->id);
} else {
hm_log(LOG_DEBUG, lg, "No leveling up for boss [%s](%d) exp %d", dst->entity->desc, dst->id, dst->boss.experience);
}
}
int game_attack_aoe(struct hs_holder_s *p, struct card_s *attacker, struct card_list_s *defenders, struct card_s **fake_levelup)
{
struct card_list_s *def;
#define WEAPON_ATTACK(m_attacker, m_deck)\
if(flag(&m_attacker->state, CARD_BOSS, FLAG_ISSET)) {\
{\
struct card_s *__fake_weapon = m_deck->heroweapon;\
struct deck_s *__fake_deck = m_deck;\
__SECTION_WEAPON_ATTACK\
}\
}
#define ATTACHMENT_ATTACK(m_attacker, m_deck)\
{\
struct card_s *__fake_attacker = m_attacker;\
struct deck_s *__fake_deck = m_deck;\
\
if(flag(&attacker->state, CARD_BOSS, FLAG_ISSET) ||\
flag(&attacker->state, CARD_MINION, FLAG_ISSET)) {\
\
__SECTION_ATTACHMENT_ATTACK\
\
}\
}
for(def = defenders; def != NULL; def = def->next) {
entity_attack(p, attacker, def->card);
ATTACHMENT_ATTACK(def->card, p->opponent.deck_copy);
// add experience
if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) &&
flag(&attacker->state, CARD_LEVELUP, FLAG_ISSET) &&
flag(&def->card->state, CARD_DESTROYED, FLAG_ISSET)) {
// spell experience association
struct card_s *boss = card_get_levelup_boss(p->deck_copy, attacker);
if(boss) {
level_up(p, p->deck_copy, boss, def->card);
} else {
hm_log(LOG_DEBUG, lg, "CARD_LEVELUP specified for card %d but boss not found", attacker->id);
abort();
}
} else if(flag(&attacker->state, CARD_BOSS, FLAG_ISSET) &&
!flag(&attacker->state, CARD_DESTROYED, FLAG_ISSET) &&
flag(&def->card->state, CARD_DESTROYED, FLAG_ISSET)) {
level_up(p, p->deck_copy, attacker, def->card);
} else if(flag(&def->card->state, CARD_BOSS, FLAG_ISSET) &&
!flag(&def->card->state, CARD_DESTROYED, FLAG_ISSET) &&
flag(&attacker->state, CARD_DESTROYED, FLAG_ISSET)) {
level_up(p, p->opponent.deck_copy, def->card, attacker);
} else {
hm_log(LOG_DEBUG, lg, "No boss involved or destroyed: Attacker [%s](%d) > Defender [%s](%d) %d %d %d", attacker->entity->desc, attacker->id, def->card->entity->desc, def->card->id, flag(&attacker->state, CARD_SPELL, FLAG_ISSET), flag(&attacker->state, CARD_LEVELUP, FLAG_ISSET), flag(&def->card->state, CARD_DESTROYED, FLAG_ISSET));
}
}
WEAPON_ATTACK(attacker, p->deck_copy);
ATTACHMENT_ATTACK(attacker, p->deck_copy);
return 0;
}
@@ -0,0 +1,210 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
#define F_ENRAGED 0x1
static void consider_attachments(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, int *heal, int *damage)
{
// check buffs
struct card_link_s *child;
struct card_s *child_card;
int flag = 0;
for(child = card->attached_children; child != NULL; child = child->next) {
child_card = card_get(deck, opponent, child->id);
assert(child_card);
// Enraged - 80% damage reduction
if(!EQFLAG(flag, F_ENRAGED) && strcmp(child_card->entity->name, "CS2_011o") == 0 && *damage > 0) {
flag |= F_ENRAGED;
int d = *damage;
if((*damage *= .2) < 1) *damage = 1;
hm_log(LOG_DEBUG, lg, "Defender [%s](%d) incoming damage reduced from %d to %d", card->entity->desc, card->id, d, *damage);
}
}
}
static int tags_change(struct hs_holder_s *p, struct card_s *attacker, struct card_s *defender)
{
int attack = 0, heal = 0;
int defender_health;
int defender_armor;
/*
int a_side;
int d_side;
a_side = attacker->controller;
d_side = defender->controller;
*/
defender_health = defender->health;
defender_armor = defender->armor;
if(defender->receive.damage > 0) {
attack = defender->receive.damage;
if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) && p->deck_copy->spellpower > 0) {
attack += p->deck_copy->spellpower;
}
} else if(defender->receive.heal > 0) {
heal = defender->receive.heal;
}
consider_attachments(p->deck_copy, p->opponent.deck_copy, defender, &heal, &attack);
__SECTION_ATTACK_EFFECT
// heal
if(heal > 0) {
hm_log(LOG_DEBUG, lg, "Attacker [%s](%d) healing [%s](%d) healpower: %d", attacker->entity->desc, attacker->id, defender->entity->desc, defender->id, heal);
if(defender->health + heal > defender->total_health) {
defender->health = defender->total_health;
} else {
defender->health += heal;
}
defender->receive.heal = heal;
// attack
} else {
if(attack == 0) {
attack = attacker->attack;
}
__SECTION_ATTACK_EFFECT_ATTACHMENT
hm_log(LOG_DEBUG, lg, "Attacker [%s](%d) attacking [%s](%d) power: %d", attacker->entity->desc, attacker->id, defender->entity->desc, defender->id, attack);
defender->receive.damage = attack;
if(attack >= (defender->health + defender->armor)) {
defender->health = 0;
defender->armor = 0;
flag(&defender->state, CARD_DESTROYED, FLAG_SET);
} else {
defender->armor -= attack;
if(defender->armor < 0) {
defender->health += defender->armor;
defender->armor = 0;
}
}
}
if(defender_health != defender->health) {
flag(&defender->state, MECHANICS_DAMAGE, FLAG_SET);
if(defender_health > defender->health) {
flag(&defender->state, MECHANICS_ATTACK_DAMAGE, FLAG_SET);
if(flag(&defender->state, CARD_GURU_BERSERKER, FLAG_ISSET) && defender->health != 0) {
defender->attack += 3;
flag(&defender->state, MECHANICS_ATTACK, FLAG_SET);
add_single_attachment(p, p->deck_copy, defender, defender);
}
hm_log(LOG_DEBUG, lg, "Defender: %d set to be damaged", defender->id);
} else {
flag(&defender->state, MECHANICS_ATTACK_HEAL, FLAG_SET);
hm_log(LOG_DEBUG, lg, "Defender: %d set to be healed", defender->id);
//attacker->target.heal = attacker->attack;
//defender->receive.heal = attacker->attack;
}
} else {
hm_log(LOG_DEBUG, lg, "Defender: %d health unchanged", defender->id);
}
if(defender->armor != defender_armor) {
flag(&defender->state, MECHANICS_ARMOR, FLAG_SET);
}
return 0;
}
int entity_attack(struct hs_holder_s *p, struct card_s *attacker, struct card_s *defender)
{
struct card_list_s *item;
hm_log(LOG_DEBUG, lg, "Attack");
hm_log(LOG_DEBUG, lg, "Attacker: %d Health: %d Attack: %d Deck: %d", attacker->id, attacker->health, attacker->attack, attacker->controller);
hm_log(LOG_DEBUG, lg, "Defender: %d Health: %d Attack: %d Deck: %d", defender->id, defender->health, defender->attack, defender->controller);
LIST_ADD(attacker->target.card, item, defender);
// increase total plays of attacker
attacker->total_plays++;
attacker->turn_plays++;
tags_change(p, attacker, defender);
///< defender strikes back
if(!flag(&attacker->state, CARD_SPELL, FLAG_ISSET) &&
!flag(&attacker->state, MECHANICS_BATTLECRY_TRIGGER, FLAG_ISSET) &&
// FIXME: !!! do friendly minions ever attack each other physically?
attacker->parent->deck_copy->controller != defender->parent->deck_copy->controller
) {
tags_change(p, defender, attacker);
}
if(!flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) {
if(attacker->health == 0) {
hm_log(LOG_DEBUG, lg, "Destroying attacker %d from deck %d", attacker->id, p->deck_copy->controller);
card_destroy(attacker, p->deck_copy, 0);
} else {
if(!(attacker->turn_plays == 1 && flag(&attacker->state, CARD_WINDFURY, FLAG_ISSET))) {
flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET);
}
}
}
if(defender->health == 0) {
if(flag(&defender->state, CARD_HERO, FLAG_ISSET)) {
// TODO: game over
hm_log(LOG_DEBUG, lg, "Game over");
} else {
hm_log(LOG_DEBUG, lg, "Destroying defender %d from deck %d", defender->id, p->opponent.deck_copy->controller);
card_destroy(defender, p->opponent.deck_copy, 0);
}
}
{
struct card_s *__fake_defender = attacker;
struct card_s *__fake_attacker = defender;
if(__fake_attacker->attack > 0) {
__SECTION_DEFENDER
}
}
{
struct card_s *__fake_defender = defender;
struct card_s *__fake_attacker = attacker;
if(__fake_attacker->attack > 0) {
__SECTION_DEFENDER
}
}
hm_log(LOG_DEBUG, lg, "Post Attacker: [%s](%d) Health: %d", attacker->entity->desc, attacker->id, attacker->health);
hm_log(LOG_DEBUG, lg, "Post Defender: [%s](%d) Health: %d", defender->entity->desc, defender->id, defender->health);
return 0;
}
@@ -0,0 +1,35 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
int update_resources(struct deck_s *deck, struct card_s *attacker, int refresh)
{
// refresh resources
if(refresh == 1) {
hm_log(LOG_DEBUG, lg, "Mana refreshed to %d", deck->mana);
deck->mana_used = 0;
return 0;
}
deck->mana_used += attacker->cost;
hm_log(LOG_DEBUG, lg, "Card cost: %d", attacker->cost);
hm_log(LOG_DEBUG, lg, "Mana used: %d Mana total: %d", deck->mana_used, deck->mana);
return 0;
}
+131
View File
@@ -0,0 +1,131 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void mechanics_expire(int game_turn, struct card_s *card, enum expire_e key, int value, const char *attachment)
{
struct card_expire_s *ce;
ce = malloc(sizeof(*ce));
memset(ce, 0, sizeof(*ce));
ce->turn = game_turn;
switch(key) {
case EXPIRE_ATTACK:
ce->attack = value;
break;
case EXPIRE_FROZEN:
ce->frozen = value;
break;
case EXPIRE_MAGIC_IMMUNITY:
ce->magic_immunity = value;
break;
case EXPIRE_DESTROY:
ce->destroy = value;
break;
case EXPIRE_ATTACHMENT:
ce->attachment = attachment;
break;
default:
abort();
break;
}
ce->next = card->expire;
card->expire = ce;
}
static void expiration_list(struct hs_holder_s *p, struct deck_s *deck, struct deck_s *deck_opponent, struct card_s *card, int *unfreeze, int *mimmunity)
{
struct card_expire_s *ce;
for(ce = card->expire; ce != NULL; ce = ce->next) {
if(ce->frozen > 0 && *unfreeze < ce->turn) {
*unfreeze = ce->turn; // get the highest unfreeze turn
}
if(ce->magic_immunity > 0 && *mimmunity < ce->turn) {
*mimmunity = ce->turn; // get the highest magic immunity turn
}
if(ce->turn == p->game->turn) {
if(ce->attack != 0) {
card->attack += ce->attack;
hm_log(LOG_DEBUG, lg, "%s Changed attack of card %d to %d", LOG_MECHANICS, card->id, card->attack);
flag(&card->state, MECHANICS_ATTACK, FLAG_SET);
} else if(ce->destroy == 1) {
hm_log(LOG_DEBUG, lg, "%s Card %d set to be destroyed", LOG_MECHANICS, card->id);
flag(&card->state, CARD_DESTROYED, FLAG_SET);
}
if(ce->attachment != NULL) {
card_remove_attachment(deck, p->opponent.deck_copy, card, ce->attachment);
ce->attachment = NULL;
}
}
}
}
void mechanics_expired(struct hs_holder_s *p, struct deck_s *deck)
{
int i;
int unfreeze_turn, magic_immunity_turn;
for(i = 0; i < deck->ncards; i++) {
unfreeze_turn = magic_immunity_turn = 0;
expiration_list(p, deck, p->opponent.deck_copy, deck->cards[i], &unfreeze_turn, &magic_immunity_turn);
if(p->game->turn == unfreeze_turn) {
hm_log(LOG_DEBUG, lg, "%s Unfreezing card: %d", LOG_MECHANICS, deck->cards[i]->id);
flag(&deck->cards[i]->state, CARD_FROZEN, FLAG_UNSET);
}
if(p->game->turn == magic_immunity_turn) {
hm_log(LOG_DEBUG, lg, "%s Removing magic immunity from card: %d", LOG_MECHANICS, deck->cards[i]->id);
flag(&deck->cards[i]->state, CARD_DIVINE_SHIELD, FLAG_UNSET);
}
}
}
void force_expire(struct hs_holder_s *p, struct deck_s *deck, struct card_s *card)
{
struct card_expire_s *ce;
struct deck_s *deck_opponent = p->opponent.deck_copy;
#define ATT\
if(ce->attachment != NULL) {\
card_remove_attachment(deck, deck_opponent, card, ce->attachment);\
}
for(ce = card->expire; ce != NULL; ce = ce->next) {
if(ce->frozen == 1) {
ATT
flag(&card->state, CARD_FROZEN, FLAG_UNSET);
}
}
}
@@ -0,0 +1,70 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
static void summon_npc(struct conn_client_s *c, struct hs_holder_s *p, struct deck_s *opponent)
{
hsl_summon_card(opponent, "EX1_158t", holder);
}
void mechanics_next_turn(struct conn_client_s *c, struct hs_holder_s *p)
{
struct deck_s *opponent, *deck;
deck = p->deck_copy;
opponent = p->opponent.deck_copy;
if(p->game->turn % 2 == 0 && p->deck->mana < 10) {
deck->mana++;
opponent->mana++;
}
p->game->turn++;
reset_turn_plays(opponent);
summon_npc(c, p, opponent);
mechanics_expired(p, deck);
mechanics_expired(p, opponent);
cards_unset_flag(opponent, CARD_EXHAUSTED);
register_turntimer(p->opponent.client);
// fatigue?
if(card_deck_count(opponent) == 0) {
struct card_s *card = p->opponent.deck_copy->hero;
assert(card);
hm_log(LOG_DEBUG, lg, "Opponent's deck empty: Fatigue %d to hero [%s](%d)", p->opponent.deck_copy->fatigue, card->entity->desc, card->id);
++(opponent->fatigue);
card->health -= opponent->fatigue;
if(card->health <= 0) {
opponent->gameover = 1;
}
}
{
struct deck_s *__fake_deck = deck;
__SECTION_ENDTURN
}
}
@@ -0,0 +1,76 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void mechanics_put_card_onboard(struct conn_client_s *c, u64 position, struct card_s *attacker, int summoned, struct card_list_s **d, struct chooseoption_s *opt, struct deck_s *deck)
{
struct hs_holder_s *p;
struct card_s *card;
struct card_list_s *defenders = NULL;
p = c->data;
assert(deck);
hm_log(LOG_DEBUG, c->log, "%s Putting card %d onboard summoned %d defenders %p", LOG_MECHANICS, attacker->id, summoned, defenders);
flag(&attacker->state, CARD_HAND, FLAG_UNSET);
// if charge or battlecry target
if(!flag(&attacker->state, CARD_CHARGE, FLAG_ISSET) &&
!flag(&attacker->state, CARD_BATTLECRY_TARGET, FLAG_ISSET) &&
!flag(&attacker->state, CARD_WEAPON, FLAG_ISSET)
) {
flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET);
}
// spellpower
if(flag(&attacker->state, CARD_SPELLPOWER, FLAG_ISSET)) {
deck->spellpower++; //attacker->spellpower;
hm_log(LOG_DEBUG, c->log, "%s Player %d spellpower %d", LOG_MECHANICS, p->entity_id, deck->spellpower);
}
// regular minion or weapon
if(flag(&attacker->state, CARD_WEAPON, FLAG_ISSET)) {
__SECTION_WEAPON
} else {
flag(&attacker->state, CARD_BOARD, FLAG_SET);
}
cards_reorder(p, deck, attacker, position, summoned);
// battlecries
if(flag(&attacker->state, CARD_BATTLECRY, FLAG_ISSET) &&
!flag(&attacker->state, MECHANICS_CHANGESIDES, FLAG_ISSET) // captured minions do not trigger BC
) {
flag(&attacker->state, MECHANICS_BATTLECRY_TRIGGER, FLAG_SET);
{
struct card_s *__fake_levelup = NULL;
__SECTION_BATTLECRY
}
}
{
struct card_s *__fake_attacker = attacker;
__SECTION_IDLE
}
{
__SECTION_ONBOARD
}
}
+40
View File
@@ -0,0 +1,40 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void mechanics_summon(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s **defenders)
{
struct hs_holder_s *p;
struct deck_s *deck;
p = c->data;
deck = p->deck_copy;
assert(deck);
assert(attacker);
if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET)) {
if(!flag(&attacker->state, CARD_HEROPOWER, FLAG_ISSET)) {
flag(&attacker->state, CARD_DESTROYED, FLAG_SET);
cards_reorder(p, deck, attacker, opt->position, 0);
} else {
flag(&attacker->state, CARD_EXHAUSTED, FLAG_SET);
}
}
}
+173
View File
@@ -0,0 +1,173 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
struct packet_s *net_attack(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_s *defender, int target_player)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
//struct card_s *attacker, *defender;
//struct deck_s *deck;
p = c->data;
//deck = p->deck;
//attacker = card_get(p->deck, NULL, p->arroworigin);
//defender = card_get(p->opponent.deck, p->deck, opt->target);
//assert(attacker && defender);
//game_attack(p, attacker, defender);
add_powerstart(&data, 1, -1, attacker->id, defender->id, NULL, 0);
//add_tagchange(&data, 417, 1, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, PROPOSED_ATTACKER, attacker->id, 1);
add_tagchange(&data, PROPOSED_DEFENDER, opt->target, 1);
add_tagchange(&data, ATTACKING, 1, p->arroworigin);
add_tagchange(&data, NEXT_STEP, 10, 1);
add_tagchange(&data, STEP, 11, 1);
add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, DEFENDING, 1, opt->target);
add_tagchange(&data, PREDAMAGE, defender->receive.damage, opt->target);
add_tagchange(&data, PREDAMAGE, 0, opt->target);
add_meta(&data, 1, defender->receive.damage, opt->target);
add_tagchange(&data, LAST_AFFECTED_BY, p->arroworigin, opt->target);
//add_tagchange(&data, DAMAGE, defender->total_health - defender->health, opt->target); // total damaged caused from beginning
add_tagchange(&data, PREDAMAGE, attacker->receive.damage, p->arroworigin);
add_tagchange(&data, PREDAMAGE, 0, p->arroworigin);
add_meta(&data, 1, attacker->receive.damage, p->arroworigin);
add_tagchange(&data, NUM_ATTACKS_THIS_TURN, 1, p->arroworigin);
/*
if(--(attacker->actions_number) == 0) {
hm_log(LOG_DEBUG, lg, "setting card %d to EXHAUSTED", attacker->id);
add_tagchange(&data, EXHAUSTED, 1, p->arroworigin);
}
*/
add_tagchange(&data, PROPOSED_ATTACKER, 0, 1);
add_tagchange(&data, PROPOSED_DEFENDER, 0, 1);
add_tagchange(&data, ATTACKING, 0, p->arroworigin);
add_tagchange(&data, DEFENDING, 0, opt->target);
// pass old deck
//LIST_ADD(cl, clitem, attacker);
//LIST_ADD(cl, clitem, defender);
net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, target_player, NET_ATTACK);
add_powerend(&data);
//add_powerstart(&data, 6, 0, 1, 0, NULL, 0);
//add_tagchange(&data, NUM_MINIONS_PLAYER_KILLED_THIS_TURN, 1, p->entity_id); // 368
//add_tagchange(&data, NUM_MINIONS_KILLED_THIS_TURN, 1, 1); // 369
//add_tagchange(&data, 398, 1, p->entity_id);
//add_tagchange(&data, 412, 1, p->entity_id);
//damage_done(&data, p, attacker, defender);
//update_zone_position_attack(&data, p);
/*
if(attacker->health == 0) {
cards_board_destroyed_reorder(&data, p->deck, attacker->zone_position);
add_tagchange(&data, EXHAUSTED, 0, attacker->id); // 43
add_tagchange(&data, DAMAGE, 0, attacker->id);
add_tagchange(&data, ZONE, 4, attacker->id); // 49
add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
} else {
add_tagchange(&data, DAMAGE, attacker->total_health - attacker->health, attacker->id); // total damaged caused from beginning
card_set_exhausted(attacker);
}
add_tagchange(&data, ARMOR, defender->armor, defender->id);
add_tagchange(&data, ARMOR, attacker->armor, attacker->id);
if(defender->health == 0) {
add_tagchange(&data, EXHAUSTED, 0, defender->id); // 43
add_tagchange(&data, DAMAGE, 0, defender->id);
add_tagchange(&data, ZONE, 4, defender->id); // 49
add_tagchange(&data, ZONE_POSITION, 0, defender->id);
if(EQFLAG(defender->state, CARD_HERO)) {
add_tagchange(&data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2);
add_tagchange(&data, PLAYSTATE, 4, p->entity_id);
} else {
cards_board_destroyed_reorder(&data, p->opponent.deck, defender->zone_position);
}
}
*/
/** destroy both */
/*
add_tagchange(&data, ZONE, 4, attacker->id); // 49
add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
add_tagchange(&data, ZONE, 4, defender->id); // 49
add_tagchange(&data, ZONE_POSITION, 0, defender->id);
attacker->state = CARD_DESTROYED;
defender->state = CARD_DESTROYED;
*/
//add_powerend(&data);
//add_tagchange(&data, STEP, 10, 1);
//add_powerstart(&data, 5, 2, p->entity_id, 0, NULL, 0);
/*
if(flag(&attacker->state, CARD_HERO, FLAG_ISSET) && p->deck->heroweapon) {
p->deck->heroweapon->durability--;
add_meta(&data, 1, p->deck->heroweapon->attack, p->deck->heroweapon->id);
add_tagchange(&data, LAST_AFFECTED_BY, p->deck->hero->id, p->deck->heroweapon->id);
add_tagchange(&data, DAMAGE, p->deck->heroweapon->maxdurability - p->deck->heroweapon->durability, p->deck->heroweapon->id);
add_tagchange(&data, EXHAUSTED, 1, p->deck->heroweapon->id);
if(p->deck->heroweapon->durability == 0) {
add_tagchange(&data, ZONE, 4, p->deck->heroweapon->id);
add_tagchange(&data, ATK, 0, attacker->id);
//p->deck->heroweapon->state |= CARD_DESTROYED;
flag(&p->deck->heroweapon->state, CARD_DESTROYED, FLAG_SET);
p->deck->hero->attack = 0;
hm_log(LOG_DEBUG, lg, "heroweapon destroyed %d", p->deck->heroweapon->id);
p->deck->heroweapon = NULL;
}
}
*/
//add_tagchange(&data, NEXT_STEP, 12, 1);
//add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
return packet;
}
+109
View File
@@ -0,0 +1,109 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
struct packet_s *net_buff(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
struct deck_s *deck;
int i;
struct card_list_s *def;
int count = 0;
p = c->data;
deck = p->deck;
for(count = 0, def = defenders; def != NULL; def = def->next, count++);
if(defenders && count == 1) {
add_powerstart(&data, 7, 0, attacker->id, defenders->card->id, NULL, 0);
} else {
add_powerstart(&data, 7, 0, attacker->id, 0, NULL, 0);
}
add_tagchange(&data, 418, 26, p->entity_id);
add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id);
add_tagchange(&data, 430, 1, p->entity_id);
add_tagchange(&data, ZONE, 1, attacker->id);
add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
add_tagchange(&data, JUST_PLAYED, 1, attacker->id);
add_tagchange(&data, 397, attacker->id, p->entity_id);
//add_tagchange(&data, CARD_TARGET, defender->id, attacker->id);
//cards_reorder(deck, &data, attacker, opt, player);
if(attacker->controller != player) {
for(i = 0; i < deck->ncards; i++) {
if(deck->cards[i]->id == p->held_card) {
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0);
add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname);
add_ph_data_show(&data, show);
break;
}
}
}
if(defenders) {
if(count == 1) {
add_powerstart(&data, 3, -1, attacker->id, defenders->card->id, NULL, 0);
} else {
add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0);
}
struct powerhistory_info_s *info = NULL;
for(def = defenders; def != NULL; def = def->next) {
add_info(&info, def->card->id);
}
assert(info);
add_meta_info(&data, 0, 0, info);
//add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id);
//add_tagchange(&data, PREDAMAGE, 0, opt->target);
//add_meta(&data, 3, 0, opt->target);
//add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id);
//add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id);
add_powerend(&data);
}
if(count == 1) {
net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_BUFF);
} else {
net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_BUFFAOE);
}
//add_tagchange(&data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id);
//add_tagchange(&data, WINDFURY, 1, defender->id);
//damage_done(&data, p, attacker, defender);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
return packet;
}
+603
View File
@@ -0,0 +1,603 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
static void net_card_summon_entity(struct powerhistory_data_s **data, struct card_s *card, int id, int zone, int target_player)
{
struct powerhistory_entity_s *full = NULL;
// if summon to hand, only show it to owner
if(zone == 1 || (zone == 3 && target_player == card->parent->deck_copy->controller) || zone == 6) {
struct powerhistory_tag_s *card_tags = default_tags(card, card->entity, 0);
add_tag(&card_tags, CONTROLLER, card->parent->deck_copy->controller);
add_tag(&card_tags, ENTITY_ID, card->id);
if(id != 0) {
add_tag(&card_tags, CREATOR, id);
}
add_full_entity(&full, card_tags, card->id, card->entity->name, card->entity->nname);
add_ph_data_full(data, full);
hm_log(LOG_ALERT, lg, "Generating full entity zone %d for card [%s](%d) player %d card parent %d", zone, card->entity->desc, card->id, target_player, card->parent->deck_copy->controller);
} else {
struct powerhistory_tag_s *card_tags = NULL;
add_tag(&card_tags, CONTROLLER, card->parent->deck_copy->controller);
add_tag(&card_tags, ENTITY_ID, card->id);
if(id != 0) {
add_tag(&card_tags, CREATOR, id);
}
add_full_entity(&full, card_tags, card->id, NULL, 0);
add_ph_data_full(data, full);
hm_log(LOG_ALERT, lg, "Generating full enemy entity zone %d for card [%s](%d) player %d card parent %d", zone, card->entity->desc, card->id, target_player, card->parent->deck_copy->controller);
}
// if card is attached to any other
/*
for(att = card->attachments; att != NULL; att = att->next) {
add_tagchange(data, ATTACHED, att->id, card->id);
}
*/
if(card->attached_to > 0) {
add_tagchange(data, ATTACHED, card->attached_to, card->id);
}
add_tagchange(data, ZONE_POSITION, card->zone_position, card->id);
add_tagchange(data, ZONE, zone, card->id);
if(id != 0) {
add_tagchange(data, 334, id, card->parent->deck_copy->controller);
}
}
static void net_card_to_hand(struct powerhistory_data_s **data, struct card_s *card, int target_player, struct hs_holder_s *p)
{
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(card, card->entity, 0);
assert(card);
assert(card->parent);
assert(card->parent->deck_copy);
assert(card->parent->deck_copy->controller);
hm_log(LOG_ALERT, lg, "Card to hand deck controller %d target %d p->id %d", card->parent->deck_copy->controller, target_player, p->id);
if(target_player == card->controller) {
add_full_entity(&show, card_tags, card->id, card->entity->name, card->entity->nname);
add_ph_data_show(data, show);
}
}
static void net_spell_tracking(struct powerhistory_data_s **data, struct card_s *card, int target_player)
{
struct card_list_s *t;
if(card->target.card != NULL) {
add_powerstart(data, 3, -1, card->id, 0, NULL, 0);
}
if(card->target.card != NULL) {
add_meta(data, 0, 0, card->id);
}
if(target_player != 1) {
for(t = card->target.card; t != NULL; t = t->next) {
/*
struct powerhistory_entity_s *full = NULL;
struct powerhistory_tag_s *card_tags = NULL;
add_tag(&card_tags, CONTROLLER, t->card->parent->controller);
add_tag(&card_tags, ENTITY_ID, t->card->id);
add_tag(&card_tags, ZONE, 6);
add_full_entity(&full, card_tags, t->card->id, NULL, 0);
add_ph_data_full(data, full);
*/
add_tagchange(data, ZONE, 6, t->card->id);
}
} else {
for(t = card->target.card; t != NULL; t = t->next) {
struct powerhistory_entity_s *full = NULL;
struct powerhistory_tag_s *card_tags = default_tags(t->card, t->card->entity, 6);
add_tag(&card_tags, CONTROLLER, t->card->parent->deck_copy->controller);
add_tag(&card_tags, ENTITY_ID, t->card->id);
add_full_entity(&full, card_tags, t->card->id, t->card->entity->name, t->card->entity->nname);
add_ph_data_show(data, full);
}
}
if(card->target.card != NULL) {
// add_powerend(data);
}
}
static void net_spell_type(struct powerhistory_data_s **data, struct card_s *card)
{
struct card_list_s *t;
if(card->target.card && card->target.card->next == NULL) {
add_powerstart(data, 3, -1, card->id, card->target.card->card->id, NULL, 0);
} else {
add_powerstart(data, 3, -1, card->id, 0, NULL, 0);
}
if(card->target.card != NULL) {
struct powerhistory_info_s *info = NULL;
for(t = card->target.card; t != NULL; t = t->next) {
add_info(&info, t->card->id);
}
assert(info);
add_meta_info(data, 0, 0, info);
}
for(t = card->target.card; t != NULL; t = t->next) {
if(flag(&t->card->state, MECHANICS_ATTACK_HEAL, FLAG_ISSET)) {
add_tagchange(data, 425, t->card->receive.heal, t->card->id);
add_tagchange(data, 425, 0, t->card->id);
add_meta(data, 2, t->card->receive.heal, t->card->id);
add_tagchange(data, LAST_AFFECTED_BY, card->id, t->card->id);
} else if(flag(&t->card->state, MECHANICS_ATTACK_DAMAGE, FLAG_ISSET)) {
add_tagchange(data, PREDAMAGE, t->card->receive.damage, t->card->id);
add_tagchange(data, PREDAMAGE, 0, t->card->id);
add_meta(data, 1, t->card->receive.damage, t->card->id);
add_tagchange(data, LAST_AFFECTED_BY, card->id, t->card->id);
} else if(flag(&t->card->state, MECHANICS_DESTROY_WEAPON, FLAG_ISSET)) {
add_tagchange(data, DURABILITY, 0, t->card->id);
add_tagchange(data, LAST_AFFECTED_BY, card->id, t->card->id);
add_tagchange(data, EXHAUSTED, 0, t->card->id);
add_tagchange(data, ZONE, 4, t->card->id);
}
}
add_powerend(data);
}
static int qscb(const struct flag_pr_s **src, const struct flag_pr_s **dst)
{
return ((*src)->priority - (*dst)->priority);
}
static int merge(struct flag_pr_s ***dst, int ndst, struct flag_pr_s **src, int nsrc)
{
int i;
if(src == NULL && *dst != NULL) {
return ndst;
} else if(src != NULL && *dst == NULL) {
*dst = src;
return nsrc;
} else {
assert(dst && src);
}
*dst = realloc(*dst, (ndst + nsrc) * sizeof(void *));
for(i = 0; i < nsrc; i++) {
(*dst)[i + ndst] = src[i];
}
free(src);
return (ndst + nsrc);
}
static void net_card_flags_iter(struct powerhistory_data_s **data, struct flag_pr_s **src, int nsrc, int target_player, struct hs_holder_s *p)
{
int i;
#define TAG(m_id, m_num)\
add_tagchange(data, m_id, m_num, src[i]->parent_card->id);
for(i = 0; i < nsrc; i++) {
switch(src[i]->flag) {
case MECHANICS_DAMAGE:
if(src[i]->type == F_ADDED) {
TAG(DAMAGE, src[i]->parent_card->total_health - src[i]->parent_card->health)
}
break;
case MECHANICS_HEALTH:
if(src[i]->type == F_ADDED) {
TAG(HEALTH, src[i]->parent_card->total_health)
TAG(DAMAGE, src[i]->parent_card->total_health - src[i]->parent_card->health);
}
break;
case MECHANICS_ATTACK:
if(src[i]->type == F_ADDED) {
TAG(ATK, src[i]->parent_card->attack)
}
break;
case MECHANICS_ARMOR:
if(src[i]->type == F_ADDED) {
TAG(ARMOR, src[i]->parent_card->armor)
}
break;
case MECHANICS_DETACH:
if(src[i]->type == F_ADDED) {
TAG(ATTACHED, 0)
//TAG(314, 0)
//TAG(323, 0)
//TAG(324, 0)
}
break;
case MECHANICS_DURABILITY:
if(src[i]->type == F_ADDED) {
TAG(DAMAGE, src[i]->parent_card->maxdurability - src[i]->parent_card->durability)
}
break;
case MECHANICS_CHANGESIDES:
if(src[i]->type == F_ADDED) {
TAG(CONTROLLER, src[i]->parent_card->controller)
}
break;
case MECHANICS_COST:
if(src[i]->type == F_ADDED) {
TAG(COST, src[i]->parent_card->cost)
}
break;
case MECHANICS_SELECTED:
if(src[i]->type == F_ADDED) {
net_spell_tracking(data, src[i]->parent_card, target_player);
}
break;
case CARD_WINDFURY:
if(src[i]->type == F_ADDED) {
TAG(WINDFURY, 1)
} else {
TAG(WINDFURY, 0)
}
break;
case CARD_DIVINE_SHIELD:
if(src[i]->type == F_REMOVED) {
TAG(DIVINE_SHIELD, 0)
} else {
TAG(DIVINE_SHIELD, 1)
}
break;
case CARD_TAUNT:
if(src[i]->type == F_REMOVED) {
TAG(TAUNT, 0)
} else {
TAG(TAUNT, 1)
}
break;
case CARD_EXHAUSTED:
if(src[i]->type == F_REMOVED) {
TAG(EXHAUSTED, 0)
} else {
TAG(EXHAUSTED, 1)
}
break;
case CARD_FROZEN:
if(src[i]->type == F_REMOVED) {
TAG(FROZEN, 0)
} else {
TAG(FROZEN, 1)
}
break;
case CARD_HIDE:
if(src[i]->type == F_ADDED) {
add_hide(data, src[i]->parent_card->id, 6);
}
break;
case CARD_LINKED:
if(src[i]->type == F_ADDED) {
TAG(LINKEDCARD, src[i]->parent_card->linked)
}
break;
case CARD_DESTROYED:
if(src[i]->type == F_ADDED) {
add_powerstart(data, 6, 0, 1, 0, NULL, 0);
TAG(ZONE, 4)
TAG(ZONE_POSITION, 0)
TAG(DAMAGE, 0)
add_powerend(data);
}
break;
case CARD_DISCARD:
if(src[i]->type == F_ADDED) {
TAG(ZONE, 4)
}
break;
case CARD_HAND:
if(src[i]->type == F_ADDED) {
net_card_to_hand(data, src[i]->parent_card, target_player, p);
TAG(ZONE, 3)
TAG(ZONE_POSITION, src[i]->parent_card->zone_position) // force new position as well
}
break;
case CARD_BOARD:
if(src[i]->type == F_ADDED) {
TAG(ZONE, 1)
TAG(ZONE_POSITION, src[i]->parent_card->zone_position) // force new position as well
if(flag(&src[i]->parent_card->state, CARD_SPELL, FLAG_ISSET) &&
!flag(&src[i]->parent_card->state, CARD_BUFF, FLAG_ISSET) &&
!flag(&src[i]->parent_card->state, CARD_WEAPON, FLAG_ISSET)
/*
!flag(&src[i]->parent_card->state, CARD_SUMMON_CS2_MIRROR, FLAG_ISSET) && // FIXME: tmp
!flag(&src[i]->parent_card->state, CARD_DRAW_CARD, FLAG_ISSET) && // FIXME: tmp
!flag(&src[i]->parent_card->state, CARD_TRACKING, FLAG_ISSET) // FIXME: tmp
*/
) {
net_spell_type(data, src[i]->parent_card);
}
}
break;
case MECHANICS_BATTLECRY_TRIGGER:
if(src[i]->type == F_ADDED) {
/*
if(
// non-target
flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE3_ENEMY_HERO, FLAG_ISSET) ||
flag(&src[i]->parent_card->state, CARD_BATTLECRY_DESTROY_ENEMY_WEAPON, FLAG_ISSET) ||
flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE1_ALL, FLAG_ISSET) ||
flag(&src[i]->parent_card->state, CARD_BATTLECRY_HEAL2_ALIES, FLAG_ISSET) ||
flag(&src[i]->parent_card->state, CARD_BATTLECRY_HEAL6_ALLY_HERO, FLAG_ISSET) ||
// targetable
flag(&src[i]->parent_card->state, CARD_BATTLECRY_HEAL2_TARGET, FLAG_ISSET) ||
flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE1_TARGET, FLAG_ISSET) ||
flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE2_TARGET, FLAG_ISSET) ||
flag(&src[i]->parent_card->state, CARD_BATTLECRY_DAMAGE3_TARGET, FLAG_ISSET)
) {
*/
net_spell_type(data, src[i]->parent_card);
//}
}
break;
case MECHANICS_TURN_TRIGGER:
if(src[i]->type == F_ADDED) {
// TODO; fix this
/*
if(
// non-target
flag(&src[i]->parent_card->state, CARD_TURN_HEAL1_MINIONS, FLAG_ISSET)
) {
net_spell_type(data, src[i]->parent_card);
}
*/
net_spell_type(data, src[i]->parent_card);
}
break;
case MECHANICS_HEROPOWER:
if(src[i]->type == F_ADDED) {
net_spell_type(data, src[i]->parent_card);
}
break;
default:
hm_log(LOG_DEBUG, lg, "Flag %d not supported", src[i]->flag);
break;
}
}
}
static void change_zone_positions(struct powerhistory_data_s **data, struct deck_s *old, struct deck_s *new)
{
int i;
for(i = 0; i < old->ncards && i < new->ncards; i++) {
if(old->cards[i]->zone_position != new->cards[i]->zone_position) {
add_tagchange(data, ZONE_POSITION, new->cards[i]->zone_position, new->cards[i]->id);
}
}
}
static void net_card_flags_step(struct powerhistory_data_s **data, struct card_s *old_card, struct card_s *new_card, struct hs_holder_s *p, struct flag_pr_s ***dst, int *ndst)
{
struct flag_pr_s **old = NULL;
struct flag_pr_s **new = NULL;
int nold = 0, nnew = 0;
int n;
//flag(&new_card->state, -1, FLAG_DUMP);
flags_diff(&old_card->state, &new_card->state, &new, &nnew, &old, &nold, new_card);
if(nnew != 0 || nold != 0) {
hm_log(LOG_DEBUG, lg, "Considering card [%s](%d)", new_card->entity->desc, new_card->id);
n = merge(&new, nnew, old, nold);
*ndst = merge(dst, *ndst, new, n);
assert(new);
}
// game over FIXME: wrong position
if(flag(&new_card->state, CARD_HERO, FLAG_ISSET) && new_card->health == 0) {
add_tagchange(data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2); // needed
add_tagchange(data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2); // needed
add_tagchange(data, PLAYSTATE, 4, p->entity_id); // needed
}
}
static void net_card_summon(struct powerhistory_data_s **data, struct deck_s *deck_old, struct deck_s *deck_new, struct card_list_s *attacker, int target_player, int nettype)
{
int i;
int att;
hm_log(LOG_DEBUG, lg, "Attempt to summon from deck %p:%p", deck_old, deck_new);
if(!(deck_old && deck_new && deck_new->ncards != deck_old->ncards)) {
if(deck_new && deck_old) {
hm_log(LOG_DEBUG, lg, "Not summoning from deck %p:%p:%d new: %d old: %d", deck_new, deck_old, deck_new->controller, deck_new->ncards, deck_old->ncards);
}
return;
}
hm_log(LOG_DEBUG, lg, "Summoning as deck new %p:%d and deck old %p:%d", deck_new, deck_new->ncards, deck_old, deck_old->ncards);
if(attacker && attacker->card) {
att = attacker->card->id;
} else {
att = 0;
}
// it's very important to set this when various user actions summon units
if(nettype == NET_PUTONBOARD || nettype == NET_BUFFAOE) {
add_powerstart(data, 3, -1, att, 0, NULL, 0);
} else if(nettype == NET_SPELL || nettype == NET_SPELLAOE) {
add_powerstart(data, 6, 0, att, 0, NULL, 0);
}
// NET_BUFF, NET_SPELLAOE - no power start
// we never remove cards, so diff is always up
for(i = deck_old->ncards; i < deck_new->ncards; i++) {
// if card just changed sides, ignore it
if(flag(&deck_new->cards[i]->state, MECHANICS_CHANGESIDES, FLAG_ISSET)) {
continue;
}
// summon attachment
if(flag(&deck_new->cards[i]->state, CARD_ATTACHMENT, FLAG_ISSET)) {
//hm_log(LOG_DEBUG, lg, "Summoning attachment card [%s](%d)", deck_new->cards[i]->entity->name, deck_new->cards[i]->id);
//net_card_summon_entity(data, deck_new->cards[i], att, 6, target_player);
// summon cards on board
} else if(flag(&deck_new->cards[i]->state, CARD_BOARD, FLAG_ISSET)) {
hm_log(LOG_DEBUG, lg, "Summoning card [%s](%d) to board", deck_new->cards[i]->entity->name, deck_new->cards[i]->id);
net_card_summon_entity(data, deck_new->cards[i], att, 1, target_player);
// summon cards in hand
} else if(flag(&deck_new->cards[i]->state, CARD_HAND, FLAG_ISSET)
) {
hm_log(LOG_DEBUG, lg, "Summoning card [%s](%d) to hand", deck_new->cards[i]->entity->name, deck_new->cards[i]->id);
net_card_summon_entity(data, deck_new->cards[i], att, 3, target_player);
} else {
hm_log(LOG_DEBUG, lg, "Card [%s](%d) set to be summoned, but no destination set, aborting", deck_new->cards[i]->entity->name, deck_new->cards[i]->id);
abort();
}
}
if(nettype == NET_PUTONBOARD || nettype == NET_SPELL || nettype == NET_BUFFAOE || nettype == NET_SPELLAOE) {
add_powerend(data);
}
for(i = deck_old->ncards; i < deck_new->ncards; i++) {
// if card just changed sides, ignore it
if(flag(&deck_new->cards[i]->state, MECHANICS_CHANGESIDES, FLAG_ISSET)) {
continue;
}
// summon attachment
if(flag(&deck_new->cards[i]->state, CARD_ATTACHMENT, FLAG_ISSET)) {
hm_log(LOG_DEBUG, lg, "Summoning attachment card [%s](%d)", deck_new->cards[i]->entity->name, deck_new->cards[i]->id);
net_card_summon_entity(data, deck_new->cards[i], att, 6, target_player);
}
}
// NET_BUFF, NET_SPELLAOE - no power end
}
void net_card_flags(struct powerhistory_data_s **data, struct deck_s *deck_old, struct deck_s *deck_new,
struct deck_s *opp_old, struct deck_s *opp_new, struct card_list_s *src, struct hs_holder_s *p, int target_player, int nettype)
{
struct card_s *old_card = NULL;
struct card_list_s *c;
int i;
struct flag_pr_s **summary = NULL;
int nsummary = 0;
//add_tagchange(&data, TEMP_RESOURCES, 0, p->entity_id);
#define d1 (p->deck)
#define c1 (p->deck_copy)
#define d2 (p->opponent.deck)
#define c2 (p->opponent.deck_copy)
assert(p);
assert(deck_old && deck_new);
change_zone_positions(data, d1, c1);
change_zone_positions(data, d2, c2);
if(deck_old->mana_used != deck_new->mana_used) {
add_tagchange(data, RESOURCES_USED, deck_new->mana_used, p->entity_id);
}
if(deck_old->spellpower != deck_new->spellpower) {
add_tagchange(data, CURRENT_SPELLPOWER, deck_new->spellpower, p->entity_id);
}
if(opp_old && opp_new && opp_old->spellpower != opp_new->spellpower) {
add_tagchange(data, CURRENT_SPELLPOWER, opp_new->spellpower, p->entity_id == 3 ? 2 : 3);
}
if(src != NULL) {
for(c = src; c != NULL; c = c->next) {
old_card = card_get(deck_old, opp_old, c->card->id);
assert(old_card);
net_card_flags_step(data, old_card, c->card, p, &summary, &nsummary);
}
net_card_summon(data, deck_old, deck_new, src, target_player, nettype);
net_card_summon(data, opp_old, opp_new, src, target_player, nettype);
} else {
for(i = 0; i < deck_old->ncards && i < deck_new->ncards; i++) {
net_card_flags_step(data, deck_old->cards[i], deck_new->cards[i], p, &summary, &nsummary);
}
for(i = 0; i < opp_old->ncards && i < opp_new->ncards; i++) {
net_card_flags_step(data, opp_old->cards[i], opp_new->cards[i], p, &summary, &nsummary);
}
net_card_summon(data, deck_old, deck_new, NULL, target_player, nettype);
net_card_summon(data, opp_old, opp_new, NULL, target_player, nettype);
}
if(summary) {
qsort(summary, nsummary, sizeof(*summary), (int (*)(const void *, const void *))qscb);
net_card_flags_iter(data, summary, nsummary, target_player, p);
}
if(nsummary > 0) {
for(i = 0; i < nsummary; i++) {
free(summary[i]);
}
free(summary);
}
}
+64
View File
@@ -0,0 +1,64 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
struct packet_s *net_card_onboard(struct hs_holder_s *p, struct chooseoption_s *opt, struct card_s *attacker, int player)
{
//struct deck_s *deck;
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
assert(p);
add_powerstart(&data, 7, 0, p->held_card, opt->target, NULL, 0);
//add_tagchange(&data, TEMP_RESOURCES, 0, p->entity_id);
//add_tagchange(&data, RESOURCES_USED, p->deck_copy->mana_used, p->entity_id);
if(!flag(&attacker->state, CARD_CHARGE, FLAG_ISSET)) {
add_tagchange(&data, EXHAUSTED, 1, p->held_card);
}
if(player != attacker->controller) {
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(attacker, attacker->entity, 0);
add_full_entity(&show, card_tags, attacker->id, attacker->entity->name, attacker->entity->nname);
add_ph_data_show(&data, show);
/*
if(flag(&attacker->state, CARD_BATTLECRY_DRAW1_CARD, FLAG_ISSET)) {
add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0);
add_meta(&data, 0, 0, attacker->id);
add_powerend(&data);
}
*/
}
net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_PUTONBOARD);
hm_log(LOG_DEBUG, lg, "board zone position %lld for card: %d", opt->position, p->held_card);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
hm_log(LOG_DEBUG, lg, "Card onboard for player: %d", player);
powerhistory_dump(ph);
return packet;
}
+40
View File
@@ -0,0 +1,40 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
struct packet_s *net_game_over(struct hs_holder_s *p, int loser)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
add_powerstart(&data, 5, 0, 2, 0, NULL, 0);
add_tagchange(&data, PLAYSTATE, 3, loser == 2 ? 3 : 2); // needed
add_tagchange(&data, PLAYSTATE, 5, loser == 2 ? 3 : 2); // needed
add_tagchange(&data, PLAYSTATE, 4, loser); // needed
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
return packet;
}
+166
View File
@@ -0,0 +1,166 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
struct packet_s *net_next_turn(struct conn_client_s *c, struct card_s **drawn_card, int *zoneposition)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
p = c->data;
add_tagchange(&data, STEP, 12, 1);
add_powerstart(&data, 5, 4, 3, 0, NULL, 0);
add_tagchange(&data, NEXT_STEP, 16, 1);
add_powerend(&data);
add_tagchange(&data, STEP, 16, 1);
add_powerstart(&data, 5, 5, 3, 0, NULL, 0);
add_tagchange(&data, NEXT_STEP, 13, 1);
add_powerend(&data);
add_tagchange(&data, STEP, 13, 1);
add_powerstart(&data, 5, -1, 1, 0, NULL, 0);
add_tagchange(&data, NUM_TURNS_LEFT, 0, p->entity_id);
add_tagchange(&data, NUM_TURNS_LEFT, 1, p->entity_id);
add_tagchange(&data, CURRENT_PLAYER, 0, p->entity_id);
add_tagchange(&data, CURRENT_PLAYER, 1, (p->entity_id == 2 ? 3 : 2));
add_tagchange(&data, TURN, p->game->turn, 1);
add_tagchange(&data, NEXT_STEP, 6, 1);
add_powerend(&data);
add_tagchange(&data, STEP, 6, 1);
add_powerstart(&data, 5, 1, 2, 0, NULL, 0);
/*
if(p->entity_id == 3) {
add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 64);
add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 65);
} else {
add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 66);
add_tagchange(&data, NUM_TURNS_IN_PLAY, 1, 67);
}
*/
add_tagchange(&data, RESOURCES_USED, 0, (p->entity_id == 2 ? 3 : 2));
add_tagchange(&data, RESOURCES, p->deck_copy->mana, (p->entity_id == 2 ? 3 : 2));
add_tagchange(&data, 399, 0, (p->entity_id == 2 ? 3 : 2));
add_tagchange(&data, NEXT_STEP, 17, 1);
add_powerend(&data);
add_tagchange(&data, STEP, 17, 1);
add_powerstart(&data, 5, 8, 2, 0, NULL, 0);
add_tagchange(&data, NEXT_STEP, 9, 1);
add_powerend(&data);
add_tagchange(&data, STEP, 9, 1);
add_powerstart(&data, 5, 0, 2, 0, NULL, 0);
//card_used_reorder(p->deck, p->held_card);
if(*drawn_card == NULL) {
// player who just finished his move
struct deck_s *deck = p->opponent.deck_copy;
*drawn_card = draw_random_card(deck, p->entity_id == 2 ? 3 : 2, -1);
if(*drawn_card) {
*zoneposition = (*drawn_card)->zone_position;
hm_log(LOG_DEBUG, lg, "drawn card zone position %d for card: %d", (*drawn_card)->zone_position, (*drawn_card)->id);
add_tagchange(&data, ZONE, 3, (*drawn_card)->id);
add_tagchange(&data, ZONE_POSITION, *zoneposition, (*drawn_card)->id);
} else {
struct card_s *card = p->opponent.deck_copy->hero;
assert(card);
add_powerstart(&data, 8, 0, card->id, 0, NULL, 0);
add_tagchange(&data, FATIGUE, p->opponent.deck_copy->fatigue, p->entity_id);
add_tagchange(&data, PREDAMAGE, p->opponent.deck_copy->fatigue, p->entity_id);
add_tagchange(&data, PREDAMAGE, 0, p->entity_id);
add_meta(&data, 1, p->opponent.deck_copy->fatigue, card->id);
add_tagchange(&data, LAST_AFFECTED_BY, 0, card->id);
add_tagchange(&data, DAMAGE, card->total_health - card->health, card->id);
add_powerend(&data);
}
} else {
// next player to move
if(*drawn_card) {
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(*drawn_card, (*drawn_card)->entity, 0);
add_full_entity(&show, card_tags, (*drawn_card)->id, (*drawn_card)->entity->name, (*drawn_card)->entity->nname);
add_tagchange(&data, ZONE_POSITION, *zoneposition, (*drawn_card)->id);
add_ph_data_show(&data, show);
}
}
if(p->deck_copy->gameover == 1 || p->opponent.deck_copy->gameover == 1) {
add_tagchange(&data, PLAYSTATE, 3, p->entity_id == 2 ? 3 : 2); // needed
add_tagchange(&data, PLAYSTATE, 5, p->entity_id == 2 ? 3 : 2); // needed
add_tagchange(&data, PLAYSTATE, 4, p->entity_id); // needed
}
//net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, p->id);
add_tagchange(&data, EXHAUSTED, 0, p->opponent.deck_copy->heropower->id);
if(p->opponent.deck_copy->heroweapon) {
add_tagchange(&data, EXHAUSTED, 0, p->opponent.deck_copy->heroweapon->id);
}
add_tagchange(&data, 399, 1, (p->entity_id == 2 ? 3 : 2));
add_tagchange(&data, 198, 10, 1);
add_powerend(&data);
/*
struct powerhistory_entity_s *show = NULL;
struct ent_s *ent = find_entity("CS2_119", 7);
add_full_entity(&show, card_tags, p->entity_id == 2 ? 24 + 30 : 24, "CS2_119", 7);
add_ph_data_show(&data, show);
add_tagchange(&data, 263, (p->entity_id == 2 ? 5 : 6), p->entity_id == 2 ? 24 + 30 : 24);
add_tagchange(&data, 399, 1, (p->entity_id == 2 ? 3 : 2));
add_tagchange(&data, 198, 10, 1);
add_powerend(&data);
*/
add_tagchange(&data, STEP, 10, 1);
add_powerstart(&data, 5, 2, 2, 0, NULL, 0);
add_tagchange(&data, NEXT_STEP, 12, 1);
net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, p->id, NET_NEXTTURN);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
hm_log(LOG_DEBUG, lg, "Next turn %d dump", p->game->turn);
powerhistory_dump(ph);
return packet;
}
+82
View File
@@ -0,0 +1,82 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void net_send_turntimer(struct conn_client_s *c, int seconds, int turn, int show)
{
int n;
char output[8192];
char *ptr = output;
struct turntimer_s *all;
struct packet_s *packet;
struct hs_holder_s *p;
p = c->data;
all = malloc(sizeof(*all));
all->seconds = seconds;
all->turn = turn;
all->show = show;
add_packet(&packet, all, P_TURNTIMER);
ptr = output;
n = serialize(packet, &ptr, output + sizeof(output));
turntimer_dump(all);
hm_send(c, output, n);
hm_send(p->opponent.client, output, n);
}
int net_send(struct conn_client_s *c, struct packet_s *packet)
{
int n;
char output[8192];
char *ptr = output;
n = serialize(packet, &ptr, ptr + sizeof(output));
hm_send(c, output, n);
return 0;
}
int net_send_options(struct conn_client_s *c, struct deck_s *deck, struct deck_s *opponent, int turn)
{
int n;
char output[8192];
n = set_options(deck, opponent, output, output + sizeof(output), turn);
hm_send(c, output, n);
return 0;
}
int net_send_cl_options(struct conn_client_s *c, struct card_list_s *cl, int turn)
{
int n;
char output[8192];
n = set_options_cards(cl, output, output + sizeof(output), turn);
hm_send(c, output, n);
return 0;
}
+125
View File
@@ -0,0 +1,125 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
static void net_defender_attacked(struct hs_holder_s *p, struct powerhistory_data_s **data, struct card_s *attacker, struct card_s *defender, struct chooseoption_s *opt)
{
add_meta(data, 0, 0, defender->id);
add_tagchange(data, PREDAMAGE, attacker->attack, defender->id);
add_tagchange(data, PREDAMAGE, 0, opt->target);
add_meta(data, 1, attacker->attack, opt->target);
add_tagchange(data, LAST_AFFECTED_BY, attacker->id, defender->id);
add_tagchange(data, DAMAGE, defender->total_health - defender->health, defender->id);
add_powerend(data);
//add_tagchange(data, ZONE, 4, attacker->id);
//add_tagchange(data, NUM_OPTIONS_PLAYED_THIS_TURN, 1, p->entity_id);
}
struct packet_s *net_spell(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders, struct card_s *fake_levelup)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
struct deck_s *deck;
int i;
struct card_list_s *cl = NULL, *clitem, *def;
struct card_s *defender;
p = c->data;
deck = p->deck_copy;
defender = defenders->card;
add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0);
//add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost
//add_tagchange(&data, 418, 26, p->entity_id);
//add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id);
//add_tagchange(&data, 430, 1, p->entity_id);
//add_tagchange(&data, ZONE, 1, attacker->id);
//add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
//add_tagchange(&data, JUST_PLAYED, 1, attacker->id);
//add_tagchange(&data, 397, attacker->id, p->entity_id);
add_tagchange(&data, CARD_TARGET, defender->id, attacker->id);
if(player != attacker->controller) {
for(i = 0; i < deck->ncards; i++) {
if(deck->cards[i]->id == p->held_card) {
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0);
add_full_entity(&show, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname);
add_ph_data_show(&data, show);
break;
}
}
}
if(flag(&attacker->state, CARD_NONTARGET, FLAG_ISSET)) {
struct deck_s *opp = p->opponent.deck_copy;
for(i = 0; i < opp->ncards; i++) {
if(flag(&opp->cards[i]->state, CARD_BOARD, FLAG_ISSET)) {
add_powerstart(&data, 3, -1, attacker->id, opp->cards[i]->id, NULL, 0);
net_defender_attacked(p, &data, attacker, opp->cards[i], opt);
add_powerend(&data);
}
}
} else {
/*
add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0);
//net_defender_attacked(p, &data, attacker, defender, opt);
add_meta(&data, 0, 0, defender->id);
add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id);
add_tagchange(&data, PREDAMAGE, 0, opt->target);
add_meta(&data, 1, attacker->attack, opt->target);
add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id);
//add_tagchange(&data, DAMAGE, defender->total_health - defender->health, defender->id);
add_powerend(&data);
*/
//damage_done(&data, p, attacker, defender);
//update_zone_position_attack(&data, p);
// pass old deck
LIST_ADD(cl, clitem, attacker);
for(def = defenders; def != NULL; def = def->next) {
LIST_ADD(cl, clitem, def->card);
}
net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_SPELL);
//net_card_flags(&data, p->deck, NULL, attacker, p);
//net_card_flags(&data, p->opponent.deck, NULL, defender, p);
add_powerend(&data);
}
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
return packet;
}
+109
View File
@@ -0,0 +1,109 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
struct packet_s *net_spell_aoe(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
struct card_list_s *def;
struct card_list_s *cl = NULL, *clitem;
struct card_list_s *defenders;
p = c->data;
defenders = attacker->target.card;
LIST_ADD(cl, clitem, attacker);
for(def = defenders; def != NULL; def = def->next) {
LIST_ADD(cl, clitem, def->card);
}
add_powerstart(&data, 7, 0, attacker->id, 0, NULL, 0);
if(flag(&attacker->state, CARD_TRACKING, FLAG_ISSET)) {
if(player == 2) {
add_tagchange(&data, 418, 41, p->entity_id);
add_tagchange(&data, 269, 1, p->entity_id);
add_tagchange(&data, 430, 1, p->entity_id);
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(attacker, attacker->entity, 1);
add_full_entity(&show, card_tags, attacker->id, attacker->entity->name, attacker->entity->nname);
add_ph_data_show(&data, show);
add_tagchange(&data, 397, attacker->id, p->entity_id);
}
net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_SPELLAOE);
} else {
/*
add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id); ///< total cost
add_tagchange(&data, 418, 26, p->entity_id);
add_tagchange(&data, NUM_CARDS_PLAYED_THIS_TURN, 1, p->entity_id);
add_tagchange(&data, 430, 1, p->entity_id);
//add_tagchange(&data, ZONE, 1, attacker->id);
//add_tagchange(&data, ZONE_POSITION, 0, attacker->id);
//add_tagchange(&data, JUST_PLAYED, 1, attacker->id);
//add_tagchange(&data, 397, attacker->id, p->entity_id);
//cards_reorder(deck, &data, attacker, opt, player);
*/
if(player != attacker->controller) {
hm_log(LOG_DEBUG, lg, "Spell aoe attacker [%s](%d) showing full entity player %d controller %d", attacker->entity->desc, attacker->id, player, attacker->controller);
struct powerhistory_entity_s *show = NULL;
struct powerhistory_tag_s *card_tags = default_tags(attacker, attacker->entity, 0);
add_full_entity(&show, card_tags, attacker->id, attacker->entity->name, attacker->entity->nname);
add_ph_data_show(&data, show);
}
// draw cards
/*
if(player == 1 && defenders != NULL) {
add_powerstart(&data, 3, -1, attacker->id, 0, NULL, 0);
add_meta(&data, 0, 0, attacker->id);
}
*/
net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, NULL, p, player, NET_SPELLAOE);
// draw cards
/*
if(player == 1 && defenders != NULL) {
add_powerend(&data);
}
*/
add_powerend(&data);
}
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
return packet;
}
@@ -0,0 +1,65 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
struct packet_s *net_spell_hp_damage(struct conn_client_s *c, struct card_list_s *defenders, struct card_s *attacker)
{
struct packet_s *packet = NULL;
struct powerhistory_s *ph = NULL;
struct powerhistory_data_s *data = NULL;
struct hs_holder_s *p;
struct card_list_s *cl = NULL, *clitem, *def;
struct card_s *defender;
p = c->data;
defender = defenders->card;
add_powerstart(&data, 7, 0, attacker->id, defender->id, NULL, 0);
//add_tagchange(&data, RESOURCES_USED, deck->mana_used, p->entity_id);
//add_tagchange(&data, 418, 36, p->entity_id);
/*
add_tagchange(&data, CARD_TARGET, defender->id, attacker->id);
add_powerstart(&data, 3, -1, attacker->id, defender->id, NULL, 0);
add_meta(&data, 0, 0, defender->id);
add_tagchange(&data, PREDAMAGE, attacker->attack, defender->id);
add_tagchange(&data, PREDAMAGE, 0, defender->id);
add_meta(&data, 1, attacker->attack, defender->id);
add_tagchange(&data, LAST_AFFECTED_BY, attacker->id, defender->id);
*/
// pass old deck
LIST_ADD(cl, clitem, attacker);
for(def = defenders; def != NULL; def = def->next) {
LIST_ADD(cl, clitem, def->card);
}
net_card_flags(&data, p->deck, p->deck_copy, p->opponent.deck, p->opponent.deck_copy, cl, p, p->id, NET_SPELLHP_DAMAGE);
add_powerend(&data);
//add_tagchange(&data, 406, 1, p->entity_id);
add_powerend(&data);
add_ph(&ph, data);
add_packet(&packet, ph, P_POWERHISTORY);
powerhistory_dump(ph);
return packet;
}
+277
View File
@@ -0,0 +1,277 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
int game_start(struct conn_client_s *c)
{
struct powerhistory_entity_s *full, *mana_card = NULL;
struct powerhistory_game_entity_s *ge1, *ge2, *ge_main;
struct powerhistory_tag_s *p1_tags, *p2_tags, *game_tags, *card_tags;
struct powerhistory_player_s *players = NULL;
struct powerhistory_creategame_s *game_start;
struct powerhistory_data_s *data = NULL;
struct powerhistory_s *ph;
struct packet_s *p, *p1;
const struct ent_s *ent1, *ent2, *ent_game, *ent_nocard;
char out[8192], *ptr;
int i;
ent1 = find_entity("PLAYER1", 7);
ent2 = find_entity("PLAYER2", 7);
if(ent1 == NULL || ent2 == NULL) {
return -1;
}
p1_tags = default_tags(NULL, ent1, 0);
p2_tags = default_tags(NULL, ent2, 0);
add_tag(&p1_tags, ENTITY_ID, 2);
add_tag(&p2_tags, ENTITY_ID, 3);
add_tag(&p1_tags, CONTROLLER, 1);
add_tag(&p2_tags, CONTROLLER, 2);
add_game_entity(&ge1, p1_tags, 2);
add_game_entity(&ge2, p2_tags, 3);
struct hs_holder_s *holder;
struct deck_s *deck;
holder = c->data;
add_player(&players, 1, 0x200000257544347, holder->deck->bnet_hi, 0, ge1);
add_player(&players, 2, 0x200000257544347, holder->opponent.deck->bnet_hi, 0, ge2);
//add_player(&players, 1, 0x200000257544347, 0x4ab3967, 0, ge1);
//add_player(&players, 2, 0x200000257544347, 0x49E8Eb5, 0, ge2);
ent_game = find_entity("GAME_ENTITY", 11);
game_tags = default_tags(NULL, ent_game, 0);
add_tag(&game_tags, ENTITY_ID, 1);
add_game_entity(&ge_main, game_tags, 1);
add_game_start(&game_start, ge_main, players);
add_ph_data(&data, NULL, game_start);
//prepare_decks(c);
//setup_cards(c);
assert(holder->deck != holder->opponent.deck);
ent_nocard = find_entity("NO_CARD", 7);
assert(ent_nocard);
deck = holder->deck;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) {
continue;
}
if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) {
assert(deck->cards[i]->entity);
card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0);
add_tag(&card_tags, ZONE, ZONE_HAND);
add_tag(&card_tags, ZONE_POSITION, deck->cards[i]->zone_position);
} else {
card_tags = default_tags(NULL, ent_nocard, 0);
}
add_tag(&card_tags, CONTROLLER, deck->controller);
add_tag(&card_tags, ENTITY_ID, deck->cards[i]->id);
if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) {
add_full_entity(&full, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname);
} else {
add_full_entity(&full, card_tags, deck->cards[i]->id, NULL, 0);
}
if(deck->cards[i]->id == 68) {
mana_card = full;
} else {
add_ph_data(&data, full, NULL);
}
}
deck = holder->opponent.deck;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) {
continue;
}
card_tags = NULL;
if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET)) {
add_tag(&card_tags, ZONE, ZONE_HAND);
add_tag(&card_tags, ZONE_POSITION, deck->cards[i]->zone_position);
} else {
add_tag(&card_tags, ZONE, ZONE_DECK);
}
add_tag(&card_tags, CONTROLLER, deck->controller);
add_tag(&card_tags, ENTITY_ID, deck->cards[i]->id);
add_full_entity(&full, card_tags, deck->cards[i]->id, NULL, 0);
if(deck->cards[i]->id == 68) {
mana_card = full;
} else {
add_ph_data(&data, full, NULL);
}
}
deck = holder->deck;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) {
card_tags = NULL;
card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0);
add_tag(&card_tags, CONTROLLER, deck->controller);
add_tag(&card_tags, ENTITY_ID, deck->cards[i]->id);
add_tag(&card_tags, ZONE, 1);
if(flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) add_tag(&card_tags, CREATOR, deck->hero->id);
add_full_entity(&full, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname);
add_ph_data(&data, full, NULL);
}
}
deck = holder->opponent.deck;
for(i = 0; i < deck->ncards; i++) {
if(flag(&deck->cards[i]->state, CARD_HERO, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) {
card_tags = NULL;
card_tags = default_tags(deck->cards[i], deck->cards[i]->entity, 0);
add_tag(&card_tags, CONTROLLER, deck->controller);
add_tag(&card_tags, ENTITY_ID, deck->cards[i]->id);
add_tag(&card_tags, ZONE, 1);
if(flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) add_tag(&card_tags, CREATOR, deck->hero->id);
add_full_entity(&full, card_tags, deck->cards[i]->id, deck->cards[i]->entity->name, deck->cards[i]->entity->nname);
add_ph_data(&data, full, NULL);
}
}
/*
ent_nocard = find_entity("HERO_08", 7);
card_tags = default_tags(ent_nocard);
add_tag(&card_tags, CONTROLLER, 1);
add_tag(&card_tags, ENTITY_ID, 64);
add_full_entity(&full, card_tags, 64, "TU4e_001", 8);
add_ph_data(&data, full, NULL);
ent_nocard = find_entity("HERO_09", 7);
card_tags = default_tags(ent_nocard);
add_tag(&card_tags, CONTROLLER, 2);
add_tag(&card_tags, ENTITY_ID, 66);
add_full_entity(&full, card_tags, 66, "HERO_09", 7);
add_ph_data(&data, full, NULL);
*/
/*
ent_nocard = find_entity("CS2_034", 7);
card_tags = default_tags(ent_nocard);
add_tag(&card_tags, CONTROLLER, 1);
add_tag(&card_tags, ENTITY_ID, 65);
add_full_entity(&full, card_tags, 65, "CS2_034", 7);
add_ph_data(&data, full, NULL);
ent_nocard = find_entity("CS1h_001", 8);
card_tags = default_tags(ent_nocard);
add_tag(&card_tags, CONTROLLER, 2);
add_tag(&card_tags, ENTITY_ID, 67);
add_full_entity(&full, card_tags, 67, "CS1h_001", 8);
add_ph_data(&data, full, NULL);
*/
/*
ent_nocard = find_entity("GAME_005", 8);
card_tags = default_tags(ent_nocard);
add_tag(&card_tags, CONTROLLER, 1);
add_tag(&card_tags, ENTITY_ID, 68);
if(holder->id == 1) {
add_tag(&card_tags, CREATOR, 1);
add_tag(&card_tags, CARDTYPE, 5);
add_full_entity(&full, card_tags, 68, "GAME_005", 8);
} else {
add_full_entity(&full, card_tags, 68, NULL, 0);
}
add_ph_data(&data, full, NULL);
*/
add_ph_data(&data, mana_card, NULL);
add_ph(&ph, data);
add_packet(&p, ph, P_POWERHISTORY);
powerhistory_dump(ph);
ptr = out;
int n = serialize(p, &ptr, ptr + sizeof(out));
packet_free(p);
data = NULL;
ph = NULL;
add_tagschange(&data, ent_game, 1);
add_tagchange(&data, STEP, 4, 1);
add_tagschange(&data, ent1, 2);
add_tagchange(&data, CONTROLLER, 1, 2);
add_tagchange(&data, MULLIGAN_STATE, 1, 2);
add_tagschange(&data, ent2, 3);
add_tagchange(&data, CONTROLLER, 2, 3);
add_powerstart(&data, 5, -1, 1, 0, NULL, 0);
add_ph(&ph, data);
add_packet(&p1, ph, P_POWERHISTORY);
ptr = out + n;
int n1 = serialize(p1, &ptr, ptr + sizeof(out) - n);
packet_free(p1);
struct entitychoices_s *ec;
ec = prepare_choices(holder->deck, holder->id);
add_packet(&p1, ec, P_ENTITYCHOICES);
ptr = out + n + n1;
int n2 = serialize(p1, &ptr, ptr + sizeof(out) - n - n1);
packet_free(p1);
//bin_dump(ptr - n2, n2);
if(holder->id == 1) {
ec = prepare_choices(holder->opponent.deck, 2);
} else {
ec = prepare_choices(holder->opponent.deck, 1);
}
add_packet(&p1, ec, P_ENTITYCHOICES);
ptr = out + n + n1 + n2;
int n3 = serialize(p1, &ptr, ptr + sizeof(out) - n - n1 - n2);
packet_free(p1);
//bin_dump(ptr - n3, n3);
const char common[19] = { 0x13, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x09, 0x22, 0x07, 0x08, 0x03, 0x10, 0xb1, 0x02, 0x18, 0x01 };
memcpy(out + n + n1 + n2 + n3, common, sizeof(common));
hm_send(c, out, (int)(n + n1 + n2 + n3 + sizeof(common)));
return 0;
}
+346
View File
@@ -0,0 +1,346 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mods.h>
#include <game.h>
enum board_e {
BOARD_RANDOM = 0x0c,
};
extern struct ht_s **games;
int ping(struct conn_client_s *c)
{
struct packet_s *p;
char output[512], *ptr;
int len;
ptr = output;
p = packet_init(P_PONG, NULL);
len = serialize(p, &ptr, ptr + sizeof(output));
packet_free(p);
hm_send(c, output, len);
return 0;
}
int game_setup(struct conn_client_s *p1, struct conn_client_s *p2, const int id)
{
struct gamesetup_s *g;
struct packet_s *p;
char output[512], *ptr;
int len;
ptr = output;
g = malloc(sizeof(*g));
int rand = random_number(12);
// board indexes 0 and 9 not supported
g->board = (rand == 0 || rand == 9) ? 1 : rand;
g->maxsecrets = 5;
g->maxfriendlyminions = 7;
g->keepalive = 900;
g->stuckdisconnect = 25;
p = packet_init(P_GAMESETUP, g);
len = serialize(p, &ptr, ptr + sizeof(output));
packet_free(p);
hm_log(LOG_DEBUG, p1->log, "starting game %d", id);
assert(p1->data == NULL && p2->data == NULL);
append_decks(p1, p2);
hm_send(p1, output, len);
hm_send(p2, output, len);
return 0;
}
static void retrieve_deck_cb(struct cbop_s *cbop)
{
struct watcher_s *w = cbop->data;
int cards_count = 0;
const char *hp = NULL;
if(cbop->lcb_error == LCB_SUCCESS) {
json_tokener *tok;
struct json_object *obj;
int i;
struct player_deck_s *pd = NULL;
tok = json_tokener_new();
obj = json_tokener_parse_ex(tok, CBGR(bytes), CBGR(nbytes));
json_object_object_foreach(obj, key, val) {
if(strcmp(key, "hero") == 0) {
int type = json_object_get_type(val);
if(type == json_type_string) {
}
} else if(strcmp(key, "hp") == 0) {
int type = json_object_get_type(val);
if(type == json_type_string) {
hp = json_object_get_string(val);
}
} else if(strcmp(key, "cards") == 0) {
int type = json_object_get_type(val);
if(type == json_type_array) {
int l = json_object_array_length(val);
for(i = 0; i < l; i++) {
struct player_deck_s *pdc = malloc(sizeof(*pdc));
pdc->next = pd;
pd = pdc;
json_object *o = json_object_array_get_idx(val, i);
int subtype = json_object_get_type(o);
if(subtype == json_type_object) {
json_object *code;
json_object_object_get_ex(o, "code", &code);
if(json_object_get_type(code) == json_type_string) {
snprintf(pdc->code, sizeof(pdc->code), "%s", json_object_get_string(code));
}
json_object *count;
json_object_object_get_ex(o, "count", &count);
if(json_object_get_type(count) == json_type_int) {
pdc->count = json_object_get_int(count);
cards_count += pdc->count;
}
}
}
}
}
}
char key1[128], key2[128];
snprintf(key1, sizeof(key1), "u:deck_%s_%s", MOD_URL, w->p1->hbs_id);
snprintf(key2, sizeof(key2), "u:deck_%s_%s", MOD_URL, w->p2->hbs_id);
assert(hp);
if(CBGR(nkey) == strlen(key1) && memcmp(key1, CBGR(key), strlen(key1)) == 0 && !(w->p1->cards)) {
hm_log(LOG_DEBUG, lg, "Player1 deck: %d", cards_count);
w->p1->cards = pd;
w->p1->ncards = cards_count;
snprintf(w->p1->hp, sizeof(w->p1->hp), "%s", hp);
//snprintf(w->p1->hero, sizeof(w->p1->hero), "%s", hero);
} else if(CBGR(nkey) == strlen(key2) && memcmp(key2, CBGR(key), strlen(key2)) == 0 && !(w->p2->cards)) {
hm_log(LOG_DEBUG, lg, "Player2 deck: %d", cards_count);
w->p2->cards = pd;
w->p2->ncards = cards_count;
snprintf(w->p2->hp, sizeof(w->p2->hp), "%s", hp);
//snprintf(w->p2->hero, sizeof(w->p2->hero), "%s", hero);
} else {
abort();
}
json_object_put(obj);
json_tokener_free(tok);
} else {
hm_log(LOG_DEBUG, lg, "Couchbase key [%.*s] failed with error 0x%x", (int)CBGR(nkey), (char *)CBGR(key), cbop->lcb_error);
}
if(++(w->counter) == 2) {
//assert(w->p1->cards && w->p2->cards);
//assert(w->p1->ncards != 0);
//assert(w->p2->ncards != 0);
if(w->p1->cards == NULL || w->p2->cards == NULL ||
w->p1->ncards != 30 || w->p2->ncards != 30) {
hm_log(LOG_DEBUG, lg, "Droping both players as deck1: %p:%d deck2: %p:%d", w->p1->cards, w->p1->ncards, w->p2->cards, w->p2->ncards);
async_shutdown_client(w->p1);
async_shutdown_client(w->p2);
//FIXME: memory leak if any of the players has deck allocated
} else {
hm_log(LOG_DEBUG, lg, "Retrieved deck(30 cards) for both players");
game_setup(w->p1, w->p2, 0);
}
free(w);
}
free(cbop);
}
void retrieve_deck(struct watcher_s *w, int player)
{
struct cbop_s *cbop;
char key[128];
char *k;
cbop = malloc(sizeof(*cbop));
memset(cbop, 0, sizeof(*cbop));
cbop->data = w;
if(player == 0) {
k = w->p1->hbs_id;
} else {
k = w->p2->hbs_id;
}
snprintf(key, sizeof(key), "u:deck_%s_%s", MOD_URL, k);
hm_log(LOG_DEBUG, lg, "Retrieving deck for player: %d", player);
CBGQ_V0(0, key, strlen(key), retrieve_deck_cb, 0, 0)
}
void get_decks(struct conn_client_s *p1, struct conn_client_s *p2, const int id)
{
struct watcher_s *watcher;
int i;
watcher = malloc(sizeof(*watcher));
watcher->p1 = p1;
watcher->p2 = p2;
watcher->counter = 0;
watcher->target = 2;
for(i = 0; i < 2; i++) {
retrieve_deck(watcher, i);
}
}
void find_game(struct conn_client_s *p1, struct handshake_s *h)
{
char key[32];
struct ht_s *opponent;
struct conn_client_s *p2;
int n, k;
handshake_dump(h);
// client id
snprintf(p1->hbs_id, sizeof(p1->hbs_id), "%.*s", h->nversion, h->version);
k = *(int *)h->password;
n = snprintf(key, sizeof(key), "%d", k);
opponent = ht_get(games, key, strlen(key));
if(opponent == NULL) {
HT_ADD_WA(games, key, n, p1, sizeof(p1), p1->pool);
} else {
p2 = (struct conn_client_s *)(opponent->s);
HT_REM(games, key, n, p1->pool);
// bind clients
snprintf(p1->foreign_client_index, sizeof(p1->foreign_client_index), "%s", p2->client_index);
snprintf(p2->foreign_client_index, sizeof(p2->foreign_client_index), "%s", p1->client_index);
get_decks(p1, p2, k);
}
}
void hs(struct conn_client_s *c, const char *buf, const int len)
{
int l = 8;
struct packet_s *p;
char *ptr, *next = NULL;
int player = 0;
struct hs_holder_s *pd;
struct ht_s *opponent;
ptr = (char *)buf;
if(len > 8) {
l += *(int *)(buf + 4);
}
if(l < len) {
next = (char *)buf + l;
}
p = deserialize(&ptr, ptr + l);
if(p == NULL) {
hm_log(LOG_DEBUG, lg, "Parsing %d bytes from fd %d failed, removing client", len, c->fd);
async_shutdown_client(c);
return;
}
if(c->data) {
pd = c->data;
player = pd->entity_id;
}
if(strlen(c->foreign_client_index) > 0) {
opponent = ht_get(async_clients, c->foreign_client_index, strlen(c->foreign_client_index));
if(opponent) {
hm_log(LOG_DEBUG, lg, "Opponent found for fd %d", c->fd);
if(opponent->n != sizeof(void *) || (void *)opponent->s != pd->opponent.client) {
abort();
}
} else {
hm_log(LOG_DEBUG, lg, "Opponent not found for fd %d, exitting", c->fd);
packet_free(p);
memset(&pd->opponent, 0, sizeof(pd->opponent));
async_shutdown_client(c);
return;
}
} else {
hm_log(LOG_DEBUG, lg, "Foreign client not specified for client fd %d", c->fd);
//async_shutdown_client(c);
//return;
}
if(p->id == P_PING) {
ping(c);
} else if(p->id == P_HANDSHAKE) {
find_game(c, p->data);
} else if(p->id == P_GETGAMESTATE) {
hm_log(LOG_DEBUG, lg, "Client command: gamestate player entity: %d", player);
game_start(c);
} else if(p->id == P_USERUI) {
hm_log(LOG_DEBUG, lg, "Client command: userui player entity: %d", player);
user_ui(c, p->data);
} else if(p->id == P_CHOOSEENTITIES) {
hm_log(LOG_ALERT, lg, "Client command: choose entities player entity: %d", player);
if(pd && pd->choose_one == 1) {
pd->choose_one = 0;
choose_one_entity(c, p->data);
} else {
choose_entities(c, p->data);
}
} else if(p->id == P_CHOOSEOPTION) {
chooseoption_dump(p->data, ((struct hs_holder_s *)(c->data))->held_card);
hm_log(LOG_DEBUG, lg, "Client command: choose option player entity: %d", player);
choose_option(c, p->data);
} else {
hm_log(LOG_DEBUG, lg, "Client command: unsupported command");
async_shutdown_client(c);
return;
}
if(p->id != P_USERUI) packet_free(p);
if(next) {
hs(c, next, len - l);
}
}
@@ -0,0 +1,24 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CHOOSE_ENTITIES_H_
#define CHOOSE_ENTITIES_H_
void choose_one_entity(struct conn_client_s *c, struct chooseentities_s *e);
void choose_entities(struct conn_client_s *c, struct chooseentities_s *e);
#endif
+23
View File
@@ -0,0 +1,23 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CHOOSE_OPTION_H_
#define CHOOSE_OPTION_H_
int choose_option(struct conn_client_s *c, struct chooseoption_s *opt);
#endif
+50
View File
@@ -0,0 +1,50 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COMMON_H_
#define COMMON_H_
const struct ent_s *find_entity(const char *name, const int nname);
struct powerhistory_tag_s *add_tag(struct powerhistory_tag_s **dst, const int key, const int value);
struct powerhistory_game_entity_s *add_game_entity(struct powerhistory_game_entity_s **dst, struct powerhistory_tag_s *tag, const int id);
struct powerhistory_tag_s *default_tags(struct card_s *card, const struct ent_s *ent, int zone_override);
void add_tagchange(struct powerhistory_data_s **dst, u64 key, u64 value, u64 id);
void add_powerstart(struct powerhistory_data_s **dst, u64 type, u64 index, u64 source, u64 target, char *card_id, int ncard_id);
void add_tagschange(struct powerhistory_data_s **dst, const struct ent_s *ent, u64 id);
void add_player(struct powerhistory_player_s **dst, u64 id, u64 bhi, u64 blo, u64 cardback, struct powerhistory_game_entity_s *ent);
void add_game_start(struct powerhistory_creategame_s **dst, struct powerhistory_game_entity_s *ge, struct powerhistory_player_s *p);
void add_ph_data(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full, struct powerhistory_creategame_s *cg);
void add_ph_data(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full, struct powerhistory_creategame_s *cg);
void add_ph(struct powerhistory_s **dst, struct powerhistory_data_s *data);
void add_packet(struct packet_s **dst, void *ph, enum packet_e n);
void add_hide(struct powerhistory_data_s **dst, u64 entity, u64 zone);
void add_powerend(struct powerhistory_data_s **dst);
void add_full_entity(struct powerhistory_entity_s **full, struct powerhistory_tag_s *tags, u64 id, const char *name, const int nname);
void add_ph_data_show(struct powerhistory_data_s **dst, struct powerhistory_entity_s *show);
void add_meta(struct powerhistory_data_s **dst, u64 type, u64 d, u64 infoid);
void add_info(struct powerhistory_info_s **dst, u64 infoid);
void add_meta_info(struct powerhistory_data_s **dst, u64 type, u64 d, struct powerhistory_info_s *info);
void add_ph_data_full(struct powerhistory_data_s **dst, struct powerhistory_entity_s *full);
void bin_dump(char *buf, const int len);
int random_number(int max);
void register_turntimer(struct conn_client_s *c);
extern struct ht_s **clients;
extern struct ev_loop *loop;
#endif
+270
View File
@@ -0,0 +1,270 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DECK_H_
#define DECK_H_
#define DECK_INIT 0x1
#define G_P1_CARDS_CHOSEN 0x1
#define G_P2_CARDS_CHOSEN 0x2
#define MAX_BOSS 2
#define MAX_BOARD 7
#define LIST_ADD(list__, item__, src__)\
item__ = malloc(sizeof(*item__));\
item__->card = src__;\
item__->next = NULL;\
if(list__ != NULL && (list__)->tail) {\
(list__)->tail->next = item__;\
(list__)->tail = item__;\
} else {\
(list__) = item__;\
(list__)->tail = item__;\
}
#define LIST_ADD_LINK(list__, src__)\
list__ = src__;
enum deck_mod_e {
DECK_MODIFIER_ATTACK = 1,
DECK_MODIFIER_HEALTH,
DECK_MODIFIER_ATTACK_CHARGE,
DECK_MODIFIER_ATTACK_BEAST,
};
enum deck_free_e {
FREE_DECK_ATTACHMENT = (1<<1),
FREE_CARD_CHILDREN = (1<<2),
FREE_CARD_EXPIRE = (1<<3),
};
struct card_expire_s {
int turn;
int attack;
int frozen;
int destroy;
int magic_immunity;
const char *attachment;
struct card_expire_s *next;
};
struct attachment_list_s {
const char *name;
enum flags_e group;
struct attachment_list_s *next;
};
struct card_link_s {
int id;
const char *name;
struct card_link_s *next, *tail;
};
struct card_s {
struct hs_holder_s *parent;
int controller;
int id;
struct flags_s state;
const char *attachment; // name of CARD_ATTACHMENT
int attached_to; // only for CARD_ATTACHMENT
struct card_link_s *attached_children; // children
const struct ent_s *entity;
int zone_position;
int total_health;
int health;
int default_health;
int buff_health;
int attack;
int default_attack;
int cost;
int default_cost;
int cardtype;
int durability;
int maxdurability;
int armor;
int actions_number;
int spellpower;
struct {
unsigned int flags;
struct card_list_s *card;
} target;
struct {
int damage;
int heal;
} receive;
struct {
char level;
int experience;
} boss;
int linked;
struct card_expire_s *expire;
int priority_override;
int total_plays; // total number of plays with this card, zero'd when returned to hand
int turn_plays; // total number of plays since turn started
};
struct deck_s {
struct hs_holder_s *parent;
u64 bnet_hi;
int controller;
int mana;
int mana_used;
int spellpower;
int handposition;
int ncards;
struct card_s **cards;
struct {
int attack;
int attack_charge;
int attack_beast;
int health;
} modifiers;
struct card_s *hero;
struct card_s *heropower;
struct card_s *heroweapon;
int board_position[MAX_BOARD];
struct attachment_list_s *attachments;
int fatigue;
int gameover;
unsigned int flags;
};
struct card_list_s {
struct card_s *card;
struct card_list_s *tail, *next;
};
struct game_s {
int entity_id;
unsigned int flags;
int turn;
int maxentity_id;
struct ev_timer turntimer, force_next_turn;
};
struct hs_holder_s {
struct conn_client_s *client;
struct deck_s *deck;
struct deck_s *deck_copy;
int id;
int entity_id;
int held_card;
int arroworigin;
int choose_one;
struct {
int accessible;
struct deck_s *deck;
struct deck_s *deck_copy;
struct conn_client_s *client;
} opponent;
struct game_s *game;
unsigned int flags;
};
void holder_free(struct hs_holder_s *h);
int append_decks(struct conn_client_s *p1, struct conn_client_s *p2);
int append_game(struct conn_client_s *p1, struct conn_client_s *p2);
void card_to_deck(struct card_s *card);
struct card_s *draw_random_card(struct deck_s *deck, int entity_id, int zone_position);
struct card_s *new_card(const int id, const char *name, int controller);
void card_used_reorder(struct deck_s *deck, u64 id);
void cards_reorder_board_opponent(struct powerhistory_data_s **data, struct deck_s *deck);
void cards_reorder_board_owner(struct deck_s *deck, u64 held, u64 position);
struct card_s *card_get(struct deck_s *deck, struct deck_s *opponent, const int id);
struct card_list_s *cards_get_board(struct deck_s *deck, struct deck_s *opponent, int hero, int exclude, int magic_immunity, int boss);
struct card_s *card_get_hero(struct deck_s *deck);
void cards_reorder_hand_owner(struct deck_s *deck, u64 id);
void cards_reorder_hand_opponent(struct powerhistory_data_s **data, struct deck_s *deck);
void cards_board_destroyed_reorder(struct deck_s *deck, int position);
int game_attack(struct hs_holder_s *p, struct card_s *attacker, struct card_s *defender);
int update_resources(struct deck_s *deck, struct card_s *attacker, int refresh);
void cards_unset_flag(struct deck_s *deck, enum flags_e flags);
void card_set_exhausted(struct card_s *card);
int cards_board_last(struct deck_s *deck);
struct card_s *add_new_card(struct game_s *game, struct deck_s *deck, int index, const char *card, unsigned int flags);
int zone_position_last(struct deck_s *deck);
void unset_mechanics_flags(struct hs_holder_s *p);
void cards_reorder(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, u64 position, int summoned);
int cards_get_board_count(struct deck_s *deck, struct deck_s *opponent, int hero, int exclude);
void decks_copy(struct hs_holder_s *p);
void decks_swap(struct hs_holder_s *p);
void deck_modifier(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, enum deck_mod_e key, int value);
void deck_apply_modifiers(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, u64 position);
void card_destroy(struct card_s *card, struct deck_s *deck, int to_hand);
void deck_destroy_modifier(struct deck_s *deck, struct card_s *defender);
struct card_s *cards_get_hand_random(struct deck_s *deck);
void copy_card(struct card_s **dst, struct card_s *src);
struct card_list_s *cards_get_random(struct deck_s *deck, int number, struct card_s *attacker, int zone);
int cards_get_board_count_flag(struct deck_s *deck, struct card_s *card, int f);
int cards_get_board_flag(struct deck_s *deck, int f, int exclude);
void card_apply_attachments(struct hs_holder_s *p, struct deck_s *deck, struct card_s *card);
void deck_add_attachment(struct deck_s *deck, const char *attachment, enum flags_e f);
void cards_apply_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, enum flags_e f);
int card_count_attachment(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, const char *name);
void add_single_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *attacker, struct card_s *defender);
void card_remove_attachment(struct deck_s *deck, struct deck_s *opponent, struct card_s *card, const char *name);
struct card_s *card_get_board_zoneposition(struct deck_s *deck, u64 position);
void card_apply_attachment(struct hs_holder_s *p, struct deck_s *deck, struct card_s *dst, const char *attachment);
void cards_adjacent(struct hs_holder_s *p, struct deck_s *deck);
int deck_get_taunts(struct deck_s *deck);
void card_discard_by_name(struct hs_holder_s *p, struct card_s *card, const char *name);
struct card_s *card_by_name(struct hs_holder_s *p, struct deck_s *deck, const char *name, int f);
struct card_list_s *cards_get_board_boss(struct deck_s *deck);
void reset_turn_plays(struct deck_s *deck);
void card_free(struct card_s *card, unsigned int flags);
int card_deck_count(struct deck_s *deck);
void deck_free(struct deck_s *deck, unsigned int flags);
struct card_s *card_get_levelup_boss(struct deck_s *deck, struct card_s *card);
int cards_count(struct card_list_s *l);
struct card_s *card_random(struct card_list_s *l);
struct card_s *draw_first_boss(struct deck_s *deck);
struct card_list_s *cards_get_hand(struct deck_s *deck);
int board_count_by_name(struct deck_s *deck, const char *name);
void cards_dump(struct deck_s *deck, struct deck_s *opponent);
struct card_list_s *cards_by_name(struct hs_holder_s *p, struct deck_s *deck, const char *name, int f);
#endif
@@ -0,0 +1,24 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITY_CHOICES_H_
#define ENTITY_CHOICES_H_
struct entitychoices_s *prepare_choices(struct deck_s *deck, int player_id);
struct entitychoices_s *chooseone_choices(struct card_list_s *defenders, int player_id, int attacker_id);
#endif
+56
View File
@@ -0,0 +1,56 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FLAGS_H_
#define FLAGS_H_
#define MAX_FLAGS_ARRAY 16
#define LL_BITS 64
enum flag_type_e {
F_ADDED = 1,
F_REMOVED = 2,
};
struct flag_pr_s {
enum flags_e flag;
int priority;
enum flag_type_e type;
struct card_s *parent_card;
};
// 64 * MAX_FLAGS_ARRAY flags
struct flags_s {
unsigned long long nibble[MAX_FLAGS_ARRAY];
};
enum flags_action_e {
FLAG_SET = 0,
FLAG_UNSET = 1,
FLAG_ISSET = 2,
FLAG_DUMP = 3,
};
int flag(struct flags_s *flags, enum flags_e src, enum flags_action_e action);
int flags_copy(struct flags_s *dst, const struct flags_s *src);
void flags_diff(struct flags_s *old, struct flags_s *new,
struct flag_pr_s ***src_added, int *nsrc_added,
struct flag_pr_s ***src_removed, int *nsrc_removed,
struct card_s *parent_card);
int flag_get(struct flags_s *flags, int **f);
#endif
+67
View File
@@ -0,0 +1,67 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GAME_H_
#define GAME_H_
#define LOG_MECHANICS "{Mechanics}: "
#define HM_GAMESERVER
#include <hsl_cardname.h>
#include <levelup.h>
#include <sections.h>
#include <json.h>
#include <hmbase.h>
#include <async_client.h>
#include <flag_def.h>
#include <proto.h>
#include <common.h>
#include <hs.h>
#include <deck.h>
#include <choose_entities.h>
#include <entity_choices.h>
#include <choose_option.h>
#include <game_options.h>
#include <mechanics.h>
#include <net.h>
#include <level.h>
struct packet_s *game_reply(struct hs_holder_s *p, struct chooseoption_s *opt, struct card_s *attacker, int player);
int game_attack_aoe(struct hs_holder_s *p, struct card_s *attacker, struct card_list_s *defenders, struct card_s **fake_levelup);
void user_ui(struct conn_client_s *c, struct userui_s *u);
int game(struct conn_client_s *c, struct chooseoption_s *opt);
void game_free(struct game_s *g);
void next_turn(struct conn_client_s *c, struct hs_holder_s *p/*, struct chooseoption_s *opt*/);
void mechanics_attack(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s *defenders);
void mechanics_next_turn(struct conn_client_s *c, struct hs_holder_s *p);
void mechanics_put_card_onboard(struct conn_client_s *c, u64 position, struct card_s *attacker, int summoned, struct card_list_s **defenders, struct chooseoption_s *opt, struct deck_s *deck);
void mechanics_attack_aoe(struct conn_client_s *c, u64 position, struct card_s *attacker, struct card_list_s **defenders, struct card_s **fake_levelup);
void mechanics_buff(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s **defenders);
void mechanics_summon(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_list_s **defenders);
void mechanics_draw_card(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, int cards, struct card_list_s **defenders);
void mechanics_expire(int game_turn, struct card_s *card, enum expire_e key, int value, const char *name);
void force_expire(struct hs_holder_s *p, struct deck_s *deck, struct card_s *card);
void mechanics_attack_swipe(struct conn_client_s *c, u64 position, struct card_s *attacker, struct card_list_s **defenders);
int entity_attack(struct hs_holder_s *p, struct card_s *attacker, struct card_s *defender);
void put_card_onboard(struct conn_client_s *c, struct hs_holder_s *p, struct chooseoption_s *opt);
void power_attack(struct conn_client_s *c, struct hs_holder_s *p, struct chooseoption_s *opt);
extern struct hm_log_s *lg;
#endif
+24
View File
@@ -0,0 +1,24 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GAME_OPTIONS_H_
#define GAME_OPTIONS_H_
int set_options(struct deck_s *deck, struct deck_s *opponent, char *buffer, char *endbuffer, int turn);
int set_options_cards(struct card_list_s *cl, char *buffer, char *endbuffer, int turn);
#endif
+25
View File
@@ -0,0 +1,25 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HS_H_
#define HS_H_
void hs(struct conn_client_s *c, const char *buf, const int len);
int game_start(struct conn_client_s *c);
void handshake_dump(struct handshake_s *h);
#endif
+57
View File
@@ -0,0 +1,57 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CARDNAME_H_
#define CARDNAME_H_
#define CN_BOAR "CS2_boar"
#define CN_VULTURE "CS2_237"
#define CN_BLACK_HOLE "EX1_312"
#define CN_DEMONIC_CONVERSION "OG_101"
#define CN_EIDOLON "AT_023"
#define CN_COUNTER_HELIX "EX1_400"
#define CN_CULLING_BLADE "CS2_108"
#define CN_WARCRY "NEW1_036"
#define CN_GODS_WRATH "EX1_259"
#define CN_FORKED_LIGHTNING "EX1_251"
#define CN_DRAGONS_BREATH "BRM_003"
#define CN_ENRAGE "CS2_011"
#define CN_REQUIEM_OF_SOULS "EX1_303"
#define CN_SHADOW_FIEND "CS2_118"
#define CN_NECROMASTERY "EX1_596e"
#define CN_LAGUNA_BLADE "AT_001"
#define CN_WOUNDED "AT_039e"
#define CN_SWIPES "CS2_012"
#define CN_GODS_STRENGTH "OG_223"
#define CN_URSA "EX1_165t2"
#define CN_SVEN "EX1_383"
#define CN_ECHO_SABRE "LOE_118"
#define CN_DIVINE_RAPIER "CS2_097"
#define CN_DIVINE_RAPIER_BONUS "FP1_020e"
#define CN_LINA "AT_018"
#define CN_ZEUS "EX1_559"
#define CN_ENIGMA "CS2_065"
#define CN_AXE "NEW1_011"
#define CN_STORMWIND_CHAMP "CS2_222"
#define CN_STORMWIND_CHAMP_BONUS "CS2_222o"
#define CN_SKELETON "NAX4_03H"
#define CN_TINY "EX1_105"
#define CN_WISP_BONUS "NAX12_04e"
#define CN_WISP "CS2_231"
#define CN_DESOLATOR_BONUS "LOEA06_03e"
#endif
+25
View File
@@ -0,0 +1,25 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LEVEL_H_
#define LEVEL_H_
#define LEVEL_1 "CS2_103e2"
#define LEVEL_2 "EX1_178ae"
#define LEVEL_3 "CS1_129e"
#endif
+32
View File
@@ -0,0 +1,32 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MECHANICS_H_
#define MECHANICS_H_
enum expire_e {
EXPIRE_ATTACK = 1,
EXPIRE_FROZEN = 2,
EXPIRE_DESTROY = 3,
EXPIRE_ATTACHMENT = 4,
EXPIRE_MAGIC_IMMUNITY = 5,
};
void mechanics_expire(int game_turn, struct card_s *card, enum expire_e key, int value, const char *attachment);
void mechanics_expired(struct hs_holder_s *p, struct deck_s *deck);
#endif
+47
View File
@@ -0,0 +1,47 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef NET_H_
#define NET_H_
enum nettype_e {
NET_BUFF = 1,
NET_BUFFAOE,
NET_PUTONBOARD,
NET_ATTACK,
NET_SPELL,
NET_SPELLAOE,
NET_NEXTTURN,
NET_SPELLHP_DAMAGE,
};
void net_card_flags(struct powerhistory_data_s **data, struct deck_s *deck_old, struct deck_s *deck_new,
struct deck_s *opp_old, struct deck_s *opp_new, struct card_list_s *src, struct hs_holder_s *p, int target_player, int nettype);
struct packet_s *net_attack(struct conn_client_s *c, struct chooseoption_s *opt, struct card_s *attacker, struct card_s *defender, int target_player);
int net_send(struct conn_client_s *c, struct packet_s *packet);
int net_send_options(struct conn_client_s *c, struct deck_s *deck, struct deck_s *opponent, int turn);
int net_send_cl_options(struct conn_client_s *c, struct card_list_s *cl, int turn);
struct packet_s *net_next_turn(struct conn_client_s *c, struct card_s **drawn_card, int *zoneposition);
struct packet_s *net_card_onboard(struct hs_holder_s *p, struct chooseoption_s *opt, struct card_s *attacker, int player);
struct packet_s *net_spell_aoe(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker);
struct packet_s *net_buff(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders);
struct packet_s *net_spell(struct conn_client_s *c, struct chooseoption_s *opt, int player, struct card_s *attacker, struct card_list_s *defenders, struct card_s *fake_levelup);
struct packet_s *net_spell_hp_damage(struct conn_client_s *c, struct card_list_s *defenders, struct card_s *attacker);
void net_send_turntimer(struct conn_client_s *c, int seconds, int turn, int show);
struct packet_s *net_game_over(struct hs_holder_s *p, int loser);
#endif
@@ -0,0 +1,35 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CHOOSEENTITIES_H_
#define CHOOSEENTITIES_H_
struct chooseentities_ent_s {
u64 entity;
struct chooseentities_ent_s *next;
};
struct chooseentities_s {
u64 id;
int nentity;
struct chooseentities_ent_s *entity;
};
void chooseentities_free(struct chooseentities_s *c);
void *chooseentities_deserialize(char **dst, const char *maxdst);
#endif
+50
View File
@@ -0,0 +1,50 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENT_S_
#define ENT_S_
#include <flag_def.h>
#include <flags.h>
#define MAX_PROPERTIES 16
struct ent_property_s {
int key;
int value;
};
struct ent_s {
const char *name;
int nname;
int nprop;
const char *level2;
const char *level3;
const char *desc;
struct flags_s flags;
const char *attachment;
struct ent_property_s p[MAX_PROPERTIES];
};
extern struct ent_s entities[MAX_ENTITIES];
void entities_init();
void entities_init2();
#endif
@@ -0,0 +1,42 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ENTITYCHOICES_H_
#define ENTITYCHOICES_H_
struct entitychoices_entities_s {
u64 entity;
struct entitychoices_entities_s *next;
};
struct entitychoices_s {
u64 id;
u64 type;
u64 countmin;
u64 countmax;
u64 source;
u64 player_id;
struct entitychoices_entities_s *entities;
};
void entitychoices_free(struct entitychoices_s *ec);
int entitychoices_serialize(void *ep, char **dst, const char *maxdst);
void entitychoices_dump(struct entitychoices_s *es);
#endif
+250
View File
@@ -0,0 +1,250 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TAG_H_
#define TAG_H_
enum gametag_e {
TAG_SCRIPT_DATA_NUM_1 = 2,
TAG_SCRIPT_DATA_NUM_2 = 3,
TAG_SCRIPT_DATA_ENT_1 = 4,
TAG_SCRIPT_DATA_ENT_2 = 5,
MISSION_EVENT = 6,
TIMEOUT = 7,
TURN_START = 8,
TURN_TIMER_SLUSH = 9,
PREMIUM = 12,
GOLD_REWARD_STATE = 13,
PLAYSTATE = 17,
LAST_AFFECTED_BY = 18,
STEP = 19,
TURN = 20,
FATIGUE = 22,
CURRENT_PLAYER = 23,
FIRST_PLAYER = 24,
RESOURCES_USED = 25,
RESOURCES = 26,
HERO_ENTITY = 27,
MAXHANDSIZE = 28,
STARTHANDSIZE = 29,
PLAYER_ID = 30,
TEAM_ID = 31,
TRIGGER_VISUAL = 32,
RECENTLY_ARRIVED = 33,
PROTECTING = 34,
PROTECTED = 35,
DEFENDING = 36,
PROPOSED_DEFENDER = 37,
ATTACKING = 38,
PROPOSED_ATTACKER = 39,
ATTACHED = 40,
EXHAUSTED = 43,
DAMAGE = 44,
HEALTH = 45,
ATK = 47,
COST = 48,
ZONE = 49,
CONTROLLER = 50,
OWNER = 51,
DEFINITION = 52,
ENTITY_ID = 53,
HISTORY_PROXY = 54,
COPY_DEATHRATTLE = 55,
ELITE = 114,
MAXRESOURCES = 176,
CARD_SET = 183,
CARDTEXT_INHAND = 184,
CARDNAME = 185,
CARD_ID = 186,
DURABILITY = 187,
SILENCED = 188,
WINDFURY = 189,
TAUNT = 190,
STEALTH = 191,
SPELLPOWER = 192,
DIVINE_SHIELD = 194,
CHARGE = 197,
NEXT_STEP = 198,
CLASS = 199,
CARDRACE = 200,
FACTION = 201,
CARDTYPE = 202,
RARITY = 203,
STATE = 204,
SUMMONED = 205,
FREEZE = 208,
ENRAGED = 212,
OVERLOAD = 215,
LOYALTY = 216,
DEATHRATTLE = 217,
BATTLECRY = 218,
SECRET = 219,
COMBO = 220,
CANT_HEAL = 221,
CANT_DAMAGE = 222,
CANT_SET_ASIDE = 223,
CANT_REMOVE_FROM_GAME = 224,
CANT_READY = 225,
CANT_EXHAUST = 226,
CANT_ATTACK = 227,
CANT_TARGET = 228,
CANT_DESTROY = 229,
CANT_DISCARD = 230,
CANT_PLAY = 231,
CANT_DRAW = 232,
INCOMING_HEALING_MULTIPLIER = 233,
INCOMING_HEALING_ADJUSTMENT = 234,
INCOMING_HEALING_CAP = 235,
INCOMING_DAMAGE_MULTIPLIER = 236,
INCOMING_DAMAGE_ADJUSTMENT = 237,
INCOMING_DAMAGE_CAP = 238,
CANT_BE_HEALED = 239,
CANT_BE_DAMAGED = 240,
CANT_BE_SET_ASIDE = 241,
CANT_BE_REMOVED_FROM_GAME = 242,
CANT_BE_READIED = 243,
CANT_BE_EXHAUSTED = 244,
CANT_BE_ATTACKED = 245,
CANT_BE_TARGETED = 246,
CANT_BE_DESTROYED = 247,
CANT_BE_SUMMONING_SICK = 253,
FROZEN = 260,
JUST_PLAYED = 261,
LINKEDCARD = 262,
ZONE_POSITION = 263,
CANT_BE_FROZEN = 264,
COMBO_ACTIVE = 266,
CARD_TARGET = 267,
NUM_CARDS_PLAYED_THIS_TURN = 269,
CANT_BE_TARGETED_BY_OPPONENTS = 270,
NUM_TURNS_IN_PLAY = 271,
NUM_TURNS_LEFT = 272,
OUTGOING_DAMAGE_CAP = 273,
OUTGOING_DAMAGE_ADJUSTMENT = 274,
OUTGOING_DAMAGE_MULTIPLIER = 275,
OUTGOING_HEALING_CAP = 276,
OUTGOING_HEALING_ADJUSTMENT = 277,
OUTGOING_HEALING_MULTIPLIER = 278,
INCOMING_ABILITY_DAMAGE_ADJUSTMENT = 279,
INCOMING_COMBAT_DAMAGE_ADJUSTMENT = 280,
OUTGOING_ABILITY_DAMAGE_ADJUSTMENT = 281,
OUTGOING_COMBAT_DAMAGE_ADJUSTMENT = 282,
OUTGOING_ABILITY_DAMAGE_MULTIPLIER = 283,
OUTGOING_ABILITY_DAMAGE_CAP = 284,
INCOMING_ABILITY_DAMAGE_MULTIPLIER = 285,
INCOMING_ABILITY_DAMAGE_CAP = 286,
OUTGOING_COMBAT_DAMAGE_MULTIPLIER = 287,
OUTGOING_COMBAT_DAMAGE_CAP = 288,
INCOMING_COMBAT_DAMAGE_MULTIPLIER = 289,
INCOMING_COMBAT_DAMAGE_CAP = 290,
CURRENT_SPELLPOWER = 291,
ARMOR = 292,
MORPH = 293,
IS_MORPHED = 294,
TEMP_RESOURCES = 295,
OVERLOAD_OWED = 296,
NUM_ATTACKS_THIS_TURN = 297,
NEXT_ALLY_BUFF = 302,
MAGNET = 303,
FIRST_CARD_PLAYED_THIS_TURN = 304,
MULLIGAN_STATE = 305,
TAUNT_READY = 306,
STEALTH_READY = 307,
CHARGE_READY = 308,
CANT_BE_TARGETED_BY_ABILITIES = 311,
SHOULDEXITCOMBAT = 312,
CREATOR = 313,
CANT_BE_DISPELLED = 314,
PARENT_CARD = 316,
NUM_MINIONS_PLAYED_THIS_TURN = 317,
PREDAMAGE = 318,
TARGETING_ARROW_TEXT = 325,
ENCHANTMENT_BIRTH_VISUAL = 330,
ENCHANTMENT_IDLE_VISUAL = 331,
CANT_BE_TARGETED_BY_HERO_POWERS = 332,
HEALTH_MINIMUM = 337,
TAG_ONE_TURN_EFFECT = 338,
SILENCE = 339,
COUNTER = 340,
ARTISTNAME = 342,
HAND_REVEALED = 348,
ADJACENT_BUFF = 350,
FLAVORTEXT = 351,
FORCED_PLAY = 352,
LOW_HEALTH_THRESHOLD = 353,
SPELLPOWER_DOUBLE = 356,
HEALING_DOUBLE = 357,
NUM_OPTIONS_PLAYED_THIS_TURN = 358,
TO_BE_DESTROYED = 360,
AURA = 362,
POISONOUS = 363,
HOW_TO_EARN = 364,
HOW_TO_EARN_GOLDEN = 365,
HERO_POWER_DOUBLE = 366,
AI_MUST_PLAY = 367,
NUM_MINIONS_PLAYER_KILLED_THIS_TURN = 368,
NUM_MINIONS_KILLED_THIS_TURN = 369,
AFFECTED_BY_SPELL_POWER = 370,
EXTRA_DEATHRATTLES = 371,
START_WITH_1_HEALTH = 372,
IMMUNE_WHILE_ATTACKING = 373,
MULTIPLY_HERO_DAMAGE = 374,
MULTIPLY_BUFF_VALUE = 375,
CUSTOM_KEYWORD_EFFECT = 376,
TOPDECK = 377,
CANT_BE_TARGETED_BY_BATTLECRIES = 379,
SHOWN_HERO_POWER = 380,
DEATHRATTLE_RETURN_ZONE = 382,
STEADY_SHOT_CAN_TARGET = 383,
DISPLAYED_CREATOR = 385,
POWERED_UP = 386,
SPARE_PART = 388,
FORGETFUL = 389,
CAN_SUMMON_MAXPLUSONE_MINION = 390,
OBFUSCATED = 391,
BURNING = 392,
OVERLOAD_LOCKED = 393,
NUM_TIMES_HERO_POWER_USED_THIS_GAME = 394,
CURRENT_HEROPOWER_DAMAGE_BONUS = 395,
HEROPOWER_DAMAGE = 396,
LAST_CARD_PLAYED = 397,
NUM_FRIENDLY_MINIONS_THAT_DIED_THIS_TURN = 398,
NUM_CARDS_DRAWN_THIS_TURN = 399,
AI_ONE_SHOT_KILL = 400,
EVIL_GLOW = 401,
HIDE_COST = 402,
INSPIRE = 403,
RECEIVES_DOUBLE_SPELLDAMAGE_BONUS = 404,
HEROPOWER_ADDITIONAL_ACTIVATIONS = 405,
HEROPOWER_ACTIVATIONS_THIS_TURN = 406,
REVEALED = 410,
NUM_FRIENDLY_MINIONS_THAT_DIED_THIS_GAME = 412,
CANNOT_ATTACK_HEROES = 413,
LOCK_AND_LOAD = 414,
TREASURE = 415,
SHADOWFORM = 416,
NUM_FRIENDLY_MINIONS_THAT_ATTACKED_THIS_TURN = 417,
NUM_RESOURCES_SPENT_THIS_GAME = 418,
CHOOSE_BOTH = 419,
ELECTRIC_CHARGE_LEVEL = 420,
HEAVILY_ARMORED = 421,
DONT_SHOW_IMMUNE = 422,
HISTORY_PROXY_NO_BIG_CARD = 432,
TRANSFORMED_FROM_CARD = 435,
};
#endif
+70
View File
@@ -0,0 +1,70 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MISC_H_
#define MISC_H_
struct gamesetup_s {
u64 board;
u64 maxsecrets;
u64 maxfriendlyminions;
u64 keepalive;
u64 stuckdisconnect;
};
struct handshake_s {
u64 gamehandle;
char *password;
int npassword;
u64 clienthandle;
u64 mission;
char *version;
int nversion;
struct platform_s *platform;
};
struct platform_s {
u64 os;
u64 screen;
int nname;
char *name;
u64 store;
};
struct chooseoption_s {
u64 id;
u64 index;
u64 target;
u64 suboption;
u64 position;
};
void gamesetup_free(struct gamesetup_s *g);
int gamesetup_serialize(void *data, char **dst, const char *maxdst);
void handshake_free(struct handshake_s *h);
void *handshake_deserialize(char **dst, const char *maxdst);
void platform_free(struct platform_s *p);
struct platform_s *platform_deserialize(char **dst, const char *maxdst);
void chooseoption_free(struct chooseoption_s *c);
void *chooseoption_deserialize(char **dst, const char *maxdst);
void chooseoption_dump(struct chooseoption_s *o, u64 local_held_card);
#endif
@@ -0,0 +1,34 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MOUSEINFO_H_
#define MOUSEINFO_H_
struct mouseinfo_s {
u64 arroworigin;
u64 heldcard;
u64 overcard;
u64 x;
u64 y;
};
void mouseinfo_free(struct mouseinfo_s *p);
void *mouseinfo_deserialize(char **dst, const char *maxdst);
int mouseinfo_serialize(void *ao, char **dst, const char *maxdst);
int mouseinfo_size(struct mouseinfo_s *p);
#endif
+60
View File
@@ -0,0 +1,60 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPTIONS_H_
#define OPTIONS_H_
struct suboption_target_s {
u64 value;
struct suboption_target_s *next;
};
struct suboption_s {
u64 id;
struct suboption_target_s *target;
struct suboption_s *next;
};
struct option_s {
u64 type;
struct suboption_s *mainoption;
struct suboption_s *suboptions;
struct option_s *next;
};
struct alloptions_s {
u64 id;
struct option_s *options;
};
void alloptions_free(struct alloptions_s *a);
int alloptions_serialize(void *s, char **dst, const char *maxdst);
int alloptions_size(struct alloptions_s *p);
void option_free(struct option_s *p);
int option_serialize(struct option_s *s, char **dst, const char *maxdst);
int option_size(struct option_s *p);
void suboption_free(struct suboption_s *p);
int suboption_serialize(struct suboption_s *s, char **dst, const char *maxdst);
int suboption_size(struct suboption_s *p);
void alloptions_dump(struct alloptions_s *a);
#endif
+56
View File
@@ -0,0 +1,56 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PACKET_H_
#define PACKET_H_
enum packet_e {
P_GETGAMESTATE = 0x01,
P_CHOOSEOPTION = 0x02,
P_CHOOSEENTITIES = 0x03,
P_TURNTIMER = 0x09,
P_ENTITIESCHOSEN = 0x0D,
P_ALLOPTIONS = 0x0E,
P_USERUI = 0x0F,
P_GAMESETUP = 0x10,
P_ENTITYCHOICES = 0x11,
P_POWERHISTORY = 0x13,
P_SPECTATORNOTIFY = 0x18,
P_PING = 0x73,
P_PONG = 0x74,
P_HANDSHAKE = 0xA8,
};
struct packet_s {
int id;
int len;
void *data;
};
struct packet_deserialize_s {
int id;
void *(*deserialize)(char **dst, const char *end);
int (*serialize)(void *p, char **dst, const char *end);
int (*free)(void *p);
};
void packet_free(struct packet_s *p);
struct packet_s *deserialize(char **dst, const char *maxdst);
int serialize(struct packet_s *p, char **dst, const char *maxdst);
struct packet_s *packet_init(enum packet_e id, void *data);
#endif
@@ -0,0 +1,178 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DEF_H_
#define DEF_H_
#define error()\
hm_log(LOG_EMERG, lg, "dst: %p end: %p n: %d", *dst, maxdst, n);\
abort();
struct powerhistory_tag_s {
u64 name;
u64 value;
struct powerhistory_tag_s *next;
};
struct powerhistory_hide_s {
u64 entity;
u64 zone;
};
struct powerhistory_tagchange_s {
u64 entity;
u64 tag;
u64 value;
};
struct powerhistory_entity_s {
u64 entity;
char *name;
int nname;
struct powerhistory_tag_s *tag, *tag_tail;
};
struct powerhistory_powerstart_s {
u64 type;
u64 index;
u64 source;
u64 target;
int ncard_id;
char *card_id;
};
struct powerhistory_powerend_s {
int i;
};
struct powerhistory_game_entity_s {
u64 id;
struct powerhistory_tag_s *tag, *tag_tail;
};
struct powerhistory_s {
struct powerhistory_data_s *data, *data_tail;
};
struct powerhistory_info_s {
u64 id;
struct powerhistory_info_s *next;
};
struct powerhistory_meta_s {
u64 type;
u64 data;
struct powerhistory_info_s *info, *info_tail;
};
struct powerhistory_player_s {
u64 id;
u64 bnet_hi;
u64 bnet_lo;
u64 cardback;
struct powerhistory_game_entity_s *entity;
struct powerhistory_player_s *next;
};
struct powerhistory_creategame_s {
struct powerhistory_game_entity_s *game_entity;
struct powerhistory_player_s *player, *player_tail;
};
struct powerhistory_data_s {
struct powerhistory_entity_s *full;
struct powerhistory_entity_s *show;
struct powerhistory_hide_s *hide;
struct powerhistory_tagchange_s *tagchange;
struct powerhistory_creategame_s *creategame;
struct powerhistory_powerstart_s *powerstart;
struct powerhistory_powerend_s *powerend;
struct powerhistory_entity_s *change_entity;
struct powerhistory_meta_s *meta;
struct powerhistory_data_s *next, *tail;
};
void powerhistory_free(struct powerhistory_s *p);
void *powerhistory_deserialize(char **dst, const char *maxdst);
int powerhistory_serialize(void *data, char **dst, const char *maxdst);
int powerhistory_size(struct powerhistory_s *ph);
struct powerhistory_data_s *powerhistory_data_deserialize(char **dst, const char *maxdst);
int powerhistorydata_serialize(struct powerhistory_data_s *ph, char **dst, const char *maxdst);
int powerhistorydata_size(struct powerhistory_data_s *ph);
void powerhistory_data_free(struct powerhistory_data_s *d);
struct powerhistory_meta_s *meta_deserialize(char **dst, const char *maxdst);
int meta_serialize(struct powerhistory_meta_s *ph, char **dst, const char *maxdst);
int meta_size(struct powerhistory_meta_s *ph);
void meta_free(struct powerhistory_meta_s *t);
struct powerhistory_powerend_s *powerend_deserialize(char **dst, const char *maxdst);
int powerend_serialize(struct powerhistory_powerend_s *ph, char **dst, const char *maxdst);
int powerend_size(struct powerhistory_powerend_s *ph);
void powerend_free(struct powerhistory_powerend_s *p);
struct powerhistory_powerstart_s *powerstart_deserialize(char **dst, const char *maxdst);
int powerstart_serialize(struct powerhistory_powerstart_s *ph, char **dst, const char *maxdst);
int powerstart_size(struct powerhistory_powerstart_s *ph);
void powerstart_free(struct powerhistory_powerstart_s *p);
struct powerhistory_creategame_s *creategame_deserialize(char **dst, const char *maxdst);
int creategame_serialize(struct powerhistory_creategame_s *ph, char **dst, const char *maxdst);
int creategame_size(struct powerhistory_creategame_s *ph);
void creategame_free(struct powerhistory_creategame_s *c);
struct powerhistory_tagchange_s *tagchange_deserialize(char **dst, const char *maxdst);
int tagchange_serialize(struct powerhistory_tagchange_s *ph, char **dst, const char *maxdst);
int tagchange_size(struct powerhistory_tagchange_s *ph);
void tagchange_free(struct powerhistory_tagchange_s *t);
struct powerhistory_hide_s *hide_deserialize(char **dst, const char *maxdst);
int hide_serialize(struct powerhistory_hide_s *ph, char **dst, const char *maxdst);
int hide_size(struct powerhistory_hide_s *ph);
void hide_free(struct powerhistory_hide_s *t);
struct powerhistory_game_entity_s *game_entity_deserialize(char **dst, const char *maxdst);
int game_entity_serialize(struct powerhistory_game_entity_s *ph, char **dst, const char *maxdst);
int game_entity_size(struct powerhistory_game_entity_s *ph);
void game_entity_free(struct powerhistory_game_entity_s *g);
struct powerhistory_entity_s *entity_deserialize(char **dst, const char *maxdst);
int entity_serialize(struct powerhistory_entity_s *ph, char **dst, const char *maxdst);
int entity_size(struct powerhistory_entity_s *ph);
void entity_free(struct powerhistory_entity_s *e);
struct powerhistory_tag_s *tag_deserialize(char **dst, const char *maxdst);
int tag_serialize(struct powerhistory_tag_s *ph, char **dst, const char *maxdst);
int tag_size(struct powerhistory_tag_s *ph);
void tag_free(struct powerhistory_tag_s *t);
void player_free(struct powerhistory_player_s *p);
struct powerhistory_player_s *player_deserialize(char **dst, const char *maxdst);
int player_serialize(struct powerhistory_player_s *ph, char **dst, const char *maxdst);
int player_size(struct powerhistory_player_s *ph);
int bnet_size(struct powerhistory_player_s *ph);
void powerhistory_dump(struct powerhistory_s *p);
#endif
+72
View File
@@ -0,0 +1,72 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PROTO_H_
#define PROTO_H_
#include <assert.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <memory.h>
#include <malloc.h>
#include <sys/time.h>
#include <time.h>
#include <ev.h>
#include <hmbase.h>
typedef unsigned long long u64;
int sizeofu64(u64 v);
int sizeofu32(int v);
int stream_write(const char **dst, const char *end, const void *src, const int nsrc);
int write_byte(char **dst, const char *end, const char src);
int write_bytes(char **dst, const char *end, const char *src, const int nsrc);
void write_uint(char **dst, const char *end, int src);
void write_uint64(char **dst, const char *end, u64 src);
int write_mem_int(char **dst, const char *end, const int src);
char read_byte(char **dst, const char *end);
int read_uint(char **dst, const char *end);
u64 read_uint64(char **dst, const char *end);
int read_mem_int(char **dst, const char *end);
char *read_bytes(char **dst, const char *end, int *ndst);
int skip(char **dst, const char *end, const int jump);
#include <ent_gen.h>
#include <flag_def.h>
#include <flags.h>
#include <zone.h>
#include <misc.h>
#include <powerhistory.h>
#include <packet.h>
#include <gametag.h>
#include <ent.h>
#include <entitychoices.h>
#include <chooseentities.h>
#include <options.h>
#include <mouseinfo.h>
#include <userui.h>
#include <turntimer.h>
extern struct hm_log_s *lg;
#endif
@@ -0,0 +1,31 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TURNTIMER_H_
#define TURNTIMER_H_
struct turntimer_s {
u64 seconds;
u64 turn;
char show;
};
void turntimer_free(struct turntimer_s *t);
int turntimer_serialize(void *ao, char **dst, const char *maxdst);
void turntimer_dump(struct turntimer_s *t);
#endif
+33
View File
@@ -0,0 +1,33 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef USERUI_H_
#define USERUI_H_
struct userui_s {
struct mouseinfo_s *mouseinfo;
u64 emote;
u64 player_id;
};
void userui_free(struct userui_s *u);
int userui_serialize(void *ao, char **dst, const char *maxdst);
void *userui_deserialize(char **dst, const char *maxdst);
int userui_size(struct userui_s *p);
void userui_dump(struct userui_s *u);
#endif
+33
View File
@@ -0,0 +1,33 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ZONE_H_
#define ZONE_H_
enum zone_e {
ZONE_INVALID = 0,
ZONE_PLAY = 1,
ZONE_DECK = 2,
ZONE_HAND = 3,
ZONE_GRAVEYARD = 4,
ZONE_REMOVEDFROMGAME = 5,
ZONE_SETASIDE = 6,
ZONE_SECRET = 7,
ZONE_DISCARD = -2,
};
#endif
+538
View File
@@ -0,0 +1,538 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SECTIONS_H_
#define SECTIONS_H_
#include <section_buff.h>
#include <section_battlecry.h>
#include <section_defender.h>
#include <section_spell.h>
#include <section_spell_aoe.h>
#include <section_attack.h>
#include <section_attack_effect.h>
#include <section_weapon.h>
#include <section_endturn.h>
#include <section_onboard.h>
#include <section_destroyed.h>
#include <section_weapon_destroyed.h>
#include <section_idle.h>
#include <section_weapon_attack.h>
#include <section_attachment_attack.h>
#include <section_attack_effect_attachment.h>
// built-in variables
#define HSL_attacker (attacker)
#define HSL_defender (defender)
#define HSL_defenders (defenders)
#define HSL_player (p)
#define HSL_opponent ((struct hs_holder_s *)(p->opponent.client->data))
#define HSL_deck_player (p->deck_copy)
#define HSL_deck_opponent (p->opponent.deck_copy)
#define HSL_target (opt->target)
#define HSL_ally_hero (p->deck_copy->hero)
#define HSL_enemy_hero (p->opponent.deck_copy->hero)
#define HSL_weapon_player (p->deck_copy->heroweapon)
#define HSL_weapon_opponent (p->opponent.deck_copy->heroweapon)
#define HSL_deck_defender (defender->parent)
#define HSL_fake_defender (__fake_defender)
#define HSL_fake_attacker (__fake_attacker)
#define HSL_fake_weapon (__fake_weapon)
#define HSL_fake_deck (__fake_deck)
#define HSL_fake_levelup (&__fake_levelup)
#define HSL_no_attacker (-1)
#define HSL_heroes_included 1
#define HSL_heroes_excluded 0
#define HSL_magic_immunity_included 1
#define HSL_magic_immunity_excluded 0
// generic macros
#define def(m_type, m_dst) struct m_type *m_dst = NULL;
#define is_spell(m_dst) (flag(&m_dst->state, CARD_SPELL, FLAG_ISSET))
#define cmp_cardname(m_card, m_src) (strcmp(m_card->entity->name, m_src) == 0)
#define hsl_set_windfury(m_dst)\
flag(&m_dst->state, CARD_WINDFURY, FLAG_SET)
#define hsl_set_taunt(m_dst)\
flag(&m_dst->state, CARD_TAUNT, FLAG_SET);
#define hsl_refresh_mana(m_deck, m_amount)\
deck->mana_used = (m_amount > deck->mana_used) ? 0 : deck->mana_used - m_amount ;
#define turn_plays(m_card) (m_card->turn_plays)
/**
* @brief Foreach
*
* @param m_alias iterator
* @param m_src source
*/
#define foreach(m_alias, m_src)\
for(m_alias = m_src; m_alias != NULL; m_alias = m_alias->next)
/**
* @brief Find out if controller is current player
*
* @param m_card played card
*/
#define is_controller_player(m_card)\
(p->id == m_card->parent->deck_copy->controller)
// hsl_* macros
// only works on friendly deck
#define hsl_set_magic_immunity(m_dst)\
force_expire(p, HSL_deck_player, m_dst);\
mechanics_expire(p->game->turn + 2, m_dst, EXPIRE_MAGIC_IMMUNITY, 1, NULL);\
flag(&m_dst->state, CARD_DIVINE_SHIELD, FLAG_SET);
#define hsl_set_fullhealth(m_dst)\
m_dst->health = m_dst->total_health;\
flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET);
#define hsl_swap_health(m_dst, m_src)\
int hp = m_dst->health;\
m_dst->health = m_dst->total_health = m_src->health - m_src->buff_health;\
m_src->health = m_src->total_health = hp + m_src->buff_health;\
flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET);\
flag(&m_src->state, MECHANICS_HEALTH, FLAG_SET);
#define hsl_set_health(m_dst, m_change)\
m_dst->health = m_dst->total_health = (m_change + m_dst->buff_health);\
flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET);
#define hsl_decrease_health(m_dst, m_change)\
m_dst->buff_health -= m_change;\
m_dst->total_health -= m_change;\
flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET);\
if(m_dst->health > m_dst->total_health) {\
m_dst->health = m_dst->total_health;\
}
#define hsl_increase_health(m_dst, m_change)\
m_dst->buff_health += m_change;\
m_dst->health += m_change;\
m_dst->total_health += m_change;\
flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET);
#define hsl_replenish_health(m_dst, m_change)\
if(m_dst->total_health >= (m_dst->health + m_change)) {\
m_dst->health += m_change;\
flag(&m_dst->state, MECHANICS_HEALTH, FLAG_SET);\
}
#define hsl_change_armor(m_dst, m_change)\
m_dst->armor += m_change;\
flag(&m_dst->state, MECHANICS_ARMOR, FLAG_SET);
#define hsl_change_attack(m_dst, m_change)\
m_dst->attack += m_change;\
flag(&m_dst->state, MECHANICS_ATTACK, FLAG_SET);
#define hsl_cards_by_name(m_deck, m_name) (cards_by_name(HSL_player, m_deck, m_name, CARD_BOARD))
#define hsl_board_count_by_name(m_deck, m_name) (board_count_by_name(m_deck, m_name))
#define hsl_board_minions_count(m_deck, m_attacker) cards_get_board_count(m_deck, NULL, 0, m_attacker->id)
#define hsl_add_single_attachment(m_player, m_deck, m_dst, m_src) add_single_attachment(m_player, m_deck, m_dst, m_src)
#define hsl_remove_attachment(m_deck, m_opponent, m_card, m_name) (card_remove_attachment(m_deck, m_opponent, m_card, m_name))
#define level(m_dst) (m_dst->boss.level)
#define is_destroyed(m_dst) (flag(&m_dst->state, CARD_DESTROYED, FLAG_ISSET))
#define is_boss(m_dst) (flag(&m_dst->state, CARD_BOSS, FLAG_ISSET))
#define hsl_apply_attachment(m_player, m_deck, m_dst, m_src) (card_apply_attachment(m_player, m_deck, m_dst, m_src))
#define hsl_cards_get_hand_random(m_deck) (cards_get_hand_random(m_deck))
#define hsl_cards_get_hand(m_deck) (cards_get_hand(m_deck))
#define hsl_receive_damage(m_dst, m_dmg)\
if(m_dst) { m_dst->receive.damage = m_dmg; }
#define hsl_receive_heal(m_dst, m_heal)\
if(m_dst) { m_dst->receive.heal = m_heal; }
#define hsl_freeze(m_src, m_dst)\
hm_log(LOG_DEBUG, lg, "Attacker [%s](%d) froze [%s](%d)", m_src->entity->desc, m_src->id, m_dst->entity->desc, m_dst->id);\
mechanics_expire(p->game->turn + 3, m_dst, EXPIRE_FROZEN, 1, NULL);\
flag(&m_dst->state, CARD_FROZEN, FLAG_SET);
#define hsl_add_defender(m_src, m_holder)\
struct card_list_s *m_holder;\
LIST_ADD(defenders, m_holder, m_src)
#define hsl_return_to_hand(m_card)\
flag(&m_card->state, CARD_BOARD, FLAG_UNSET);\
flag(&m_card->state, CARD_HAND, FLAG_SET);\
flag(&m_card->state, CARD_EXHAUSTED, FLAG_UNSET);\
m_card->health = m_card->total_health = m_card->default_health;\
flag(&m_card->state, MECHANICS_HEALTH, FLAG_SET);\
m_card->attack = m_card->default_attack;\
flag(&m_card->state, MECHANICS_ATTACK, FLAG_SET);\
card_remove_attachment(hsl_deck(m_card), NULL, m_card, NULL);\
card_destroy(m_card, hsl_deck(m_card), 1);\
/* order is importatnt here, new zone position must come after card is destroyed */\
if(m_card->controller == HSL_deck_player->controller) {\
m_card->zone_position = ++(HSL_deck_player->handposition);\
} else {\
m_card->zone_position = ++(HSL_deck_opponent->handposition);\
}\
#define hsl_cards_get_hand(m_deck) (cards_get_hand(m_deck))
#define hsl_add_new_card_hand(m_deck, m_card, m_holder)\
struct card_s *m_holder = add_new_card(m_deck->parent->game, m_deck, -1, m_card, -1);\
flag(&m_holder->state, CARD_HAND, FLAG_SET);\
m_holder->zone_position = ++(m_deck->handposition);
#define hsl_destroy(m_deck, m_dst)\
{\
struct card_s *__fake_defender = m_dst;\
__SECTION_DESTROYED\
}\
flag(&m_dst->state, CARD_DESTROYED, FLAG_SET);\
cards_board_destroyed_reorder(m_deck, m_dst->zone_position);
#define hsl_destroy_inhand(m_dst) card_discard_by_name(HSL_player, HSL_fake_defender, m_dst)
#define hsl_set_weapon_durability(m_dst, m_value)\
m_dst->durability += m_value;\
flag(&m_dst->state, MECHANICS_DURABILITY, FLAG_SET);
#define hsl_weapon_durability(m_dst) m_dst->durability
#define hsl_destroy_weapon(m_attacker, m_deck)\
if(m_deck->heroweapon) {\
/*struct card_list_s *itm;*/\
__SECTION_WEAPON_DESTROYED;\
flag(&m_deck->heroweapon->state, CARD_DESTROYED, FLAG_SET);\
flag(&m_deck->heroweapon->state, CARD_BOARD, FLAG_UNSET);\
flag(&m_deck->heroweapon->state, CARD_HEROWEAPON, FLAG_UNSET);\
flag(&m_deck->heroweapon->state, CARD_EXHAUSTED, FLAG_UNSET);\
\
/*LIST_ADD(m_attacker->target.card, itm, m_holder->deck_copy->heroweapon);*/\
\
flag(&m_deck->heroweapon->state, MECHANICS_DESTROY_WEAPON, FLAG_SET);\
m_deck->heroweapon = NULL;\
}
#define is_weapon(m_deck, m_src) (m_deck && m_deck->heroweapon && strcmp(m_deck->heroweapon->entity->name, m_src) == 0)
#define hsl_change_cost(m_card, m_change)\
(m_card->cost = (m_card->default_cost - m_change >= 0) ? (m_card->default_cost - m_change) : 0);\
flag(&(m_card->state), MECHANICS_COST, FLAG_SET);
#define hsl_card_spell_by_name(m_player, m_deck, m_name) (card_by_name(m_player, m_deck, m_name, CARD_SPELL))
#define hsl_card_board_by_name(m_player, m_deck, m_name) (card_by_name(m_player, m_deck, m_name, CARD_BOARD))
#define hsl_card_hand_by_name(m_player, m_deck, m_name) (card_by_name(m_player, m_deck, m_name, CARD_HAND))
#define hsl_count_attachments(m_deck, m_opponent, m_card, m_name) (card_count_attachment(m_deck, m_opponent, m_card, m_name))
#define hsl_discard_random_hand(m_deck, m_amount, m_holder)\
int m_holder;\
for(m_holder = 0; m_holder < m_amount; m_holder++) {\
struct card_s *m_card = cards_get_hand_random(m_deck);\
if(m_card) {\
flag(&m_card->state, CARD_DISCARD, FLAG_SET);\
flag(&m_card->state, CARD_HAND, FLAG_UNSET);\
cards_reorder_hand_owner(m_deck, m_card->id);\
}\
}
#define hsl_discard_hand(m_deck, m_all)\
struct card_list_s *m_holder;\
for(m_holder = m_all; m_holder != NULL; m_holder = m_holder->next) {\
flag(&m_holder->card->state, CARD_DISCARD, FLAG_SET);\
cards_reorder_hand_owner(m_deck, m_holder->card->id);\
}
#define card(m_list) (m_list->card)
#define hsl_card(m_target)\
card_get(HSL_deck_player, HSL_deck_opponent, m_target)
#define hsl_deck(m_card) ((m_card->controller == HSL_deck_player->controller) ? HSL_deck_player : HSL_deck_opponent)
#define default_health(m_card) (m_card->default_health)
#define default_attack(m_card) (m_card->default_attack)
#define hsl_board_all_cards(m_attacker, m_hero) cards_get_board(p->deck_copy, p->opponent.deck_copy, m_hero, m_attacker->id, HSL_magic_immunity_included, 1)
#define hsl_board_all_cards_no_boss(m_attacker, m_hero) (cards_get_board(p->deck_copy, p->opponent.deck_copy, m_hero, m_attacker->id, HSL_magic_immunity_included, 0))
#define hsl_board_friendly_cards(m_deck, m_attacker, m_hero) (cards_get_board(m_deck, NULL, m_hero, m_attacker, HSL_magic_immunity_included, 1))
#define hsl_board_friendly_cards_wattacker(m_hero) cards_get_board(p->deck_copy, NULL, m_hero, -1, HSL_magic_immunity_included, 1);
#define hsl_board_enemy_cards(m_attacker, m_hero, m_mi) cards_get_board(NULL, p->opponent.deck_copy, m_hero, m_attacker->id, m_mi, 1);
#define hsl_board_friendly_no_boss(m_attacker, m_hero, m_mi) cards_get_board(NULL, p->opponent.deck_copy, m_hero, m_attacker->id, m_mi, 0);
#define hsl_board_boss_cards(m_deck) (cards_get_board_boss(m_deck))
#define hsl_attack_aoe(m_dst, m_src, m_fake_levelup) mechanics_attack_aoe(c, opt->position, m_dst, &m_src, m_fake_levelup)
#define hsl_attack(m_dst, m_src, m_fake_levelup) hsl_attack_aoe(m_dst, m_src, m_fake_levelup)
/**
* @brief Summon card for deck
*
* @param m_deck deck to summon to
* @param m_name name of the card
* @param m_card card holder
**/
#define hsl_summon_card(m_deck, m_name, m_card)\
int m_card##pos = cards_board_last(m_deck);\
if(m_card##pos <= MAX_BOARD) {\
struct card_s *m_card = add_new_card(p->game, m_deck, -1, m_name, -1);\
mechanics_put_card_onboard(c, m_card##pos, m_card, 1, NULL, NULL, m_deck);\
}
/**
* @brief Count number of cards in list of cards
*
* @param m_cards list of cards
**/
#define hsl_count_cards(m_cards) (cards_count(m_cards))
/**
* @brief Get random card from list of cards
*
* @param m_cards list of cards
**/
#define hsl_random_card(m_cards) (card_random(m_cards))
/**
* @brief Draw number of cards from player's deck
*
* @param m_player deck owner
* @param m_deck deck to draw from
* @param m_card card's holder
* @param m_amount number of cards to draw
**/
#define hsl_draw_cards(m_player, m_deck, m_card, m_amount)\
int m_card##idx;\
struct card_s *m_card;\
for(m_card##idx = 0; m_card##idx < m_amount; m_card##idx++) {\
m_card = draw_random_card(m_deck, m_player->entity_id, 0);\
if(m_card) {\
flag(&m_card->state, CARD_HAND, FLAG_SET);\
struct card_list_s *m_card##itm;\
LIST_ADD(defenders, m_card##itm, m_card);\
}\
}
/**
* @brief Link card to another card's targets
*
* @param m_dst destination card
* @param m_src source card
**/
#define hsl_link_target(m_dst, m_src)\
LIST_ADD_LINK(m_dst->target.card, m_src)
/**
* @brief Add target to defenders
*
* @param m_src source card
* @param m_holder variable placeholder
**/
#define hsl_add_target(m_src, m_holder)\
struct card_list_s *m_holder##item;\
LIST_ADD(defenders, m_holder##item, m_src);\
/**
* @brief Attack as battlecry
*
* @param m_attacker attacking card
* @param m_defender defending card
* @param m_damage damage caused
**/
#define hsl_attack_bc(m_attacker, m_defender, m_damage)\
m_defender->receive.damage = m_damage;\
entity_attack(p, m_attacker, m_defender);
/**
* @brief Heal defender by certain amount (alias)
**/
#define hsl_heal_bc(m_attacker, m_defender, m_damage)\
hsl_heal(m_attacker, m_defender, m_damage);
/*
m_defender->receive.heal = m_damage;\
#entity_attack(p, m_attacker, m_defender);\
#struct card_list_s *item;\
LIST_ADD(m_attacker->target.card, item, m_defender);
*/
/**
* @brief Heal defender by certain amount
*
* @param m_attacker healer card
* @param m_defender receiver card
* @param m_damage amount of healing
**/
#define hsl_heal(m_attacker, m_defender, m_damage)\
m_defender->receive.heal = m_damage;\
entity_attack(p, m_attacker, m_defender);\
struct card_list_s *item;\
LIST_ADD(m_attacker->target.card, item, m_defender);
/**
* @brief Mark target as corrupted
*
* Corrupted target is destroyed after m_turn turns
*
* @param m_turn number of turns from current turn when card is destroyed
* @param m_defender destination card
*/
#define hsl_buff_corrupt_expire(m_turn, m_defender)\
flag(&(m_defender->state), CARD_CORRUPTED, FLAG_SET);\
mechanics_expire(p->game->turn + m_turn, m_defender, EXPIRE_DESTROY, 1, NULL)
/**
* @brief Change attack for m_turn turns
*
* @param m_turn expiration turn
* @param m_defender destination card
* @param m_attack value to change
*/
#define hsl_buff_attack_expire(m_turn, m_defender, m_attack)\
m_defender->attack += m_attack;\
flag(&(m_defender->state), MECHANICS_ATTACK, FLAG_SET);\
mechanics_expire(p->game->turn + m_turn, m_defender, EXPIRE_ATTACK, -(m_attack), NULL);
/**
* @brief Change health of card
*
* @param m_card destination card
* @param m_health health value
*/
#define hsl_add_attachment(m_player, m_attacker, m_defender, m_turn)\
add_single_attachment(m_player, hsl_deck(m_defender), m_attacker, m_defender);\
mechanics_expire(p->game->turn + m_turn, m_defender, EXPIRE_ATTACHMENT, 0, m_attacker->attachment);
/**
* @brief Change health of card
*
* @param m_card destination card
* @param m_health health value
*/
#define buff_health(m_card, m_health)\
defenders->card->health = m_health;\
flag(&(m_card->state), MECHANICS_HEALTH, FLAG_SET);
/**
* @brief Set divine shield to card
*
* @param m_card destination card
*/
#define hsl_divine_shield(m_card)\
flag(&(m_card->state), CARD_DIVINE_SHIELD, FLAG_SET);
/**
* @brief Set flag to card
*
* @param m_card destination card
* @param m_flag flag to set
*/
#define setflag(m_card, m_flag)\
flag(&(m_card->state), m_flag, FLAG_SET);
/**
* @brief Unset flag from card
*
* @param m_card destination card
* @param m_flag flag to unset
*/
#define unsetflag(m_card, m_flag)\
flag(&(m_card->state), m_flag, FLAG_UNSET);
/**
* @brief Unset windfury flag from card
*
* @param m_card destination card
*/
#define hsl_unset_windfury(m_card) (flag(&(m_card->state), CARD_WINDFURY, FLAG_UNSET))
/**
* @brief Set exhausted flag to card
*
* @param m_card destination card
*/
#define hsl_set_exhausted(m_card) (flag(&(m_card->state), CARD_EXHAUSTED, FLAG_SET))
/**
* @brief Unset exhausted flag from card
*
* @param m_card destination card
*/
#define hsl_unset_exhausted(m_card) (flag(&(m_card->state), CARD_EXHAUSTED, FLAG_UNSET))
/**
* @brief Transform defender to m_name
*
* Any mechanics like polymorph
*
* @param m_attacker card with ability to transform target
* @param m_defender card being attacked
* @param m_name card code name
*/
#define hsl_transform(m_attacker, m_defender,m_name)\
struct card_s *card;\
card = add_new_card(p->game, p->opponent.deck_copy, -1, m_name, -1);\
card->zone_position = m_defender->zone_position;\
mechanics_put_card_onboard(c, card->zone_position, card, 1, NULL, NULL);\
m_defender->linked = card->id;\
flag(&m_defender->state, CARD_LINKED, FLAG_SET);\
flag(&m_defender->state, CARD_HIDE, FLAG_SET);\
flag(&m_defender->state, CARD_BOARD, FLAG_UNSET);
/**
* @brief Give weapon to player
*
* Called only in '.section onboard'. There is no need to linked destroyed weapon to defenders
*
* @param m_dst hero card
*/
#define hsl_give_weapon(m_dst)\
if(m_dst->heroweapon != NULL) {\
/* destroy weapon first */\
{\
struct card_s *__fake_weapon = m_dst->heroweapon;\
__SECTION_WEAPON_DESTROYED;\
}\
\
m_dst->heroweapon->priority_override = 900;\
flag(&(m_dst->heroweapon->state), CARD_DESTROYED, FLAG_SET);\
flag(&(m_dst->heroweapon->state), CARD_BOARD, FLAG_UNSET);\
flag(&(m_dst->heroweapon->state), CARD_HEROWEAPON, FLAG_UNSET);\
}\
flag(&attacker->state, CARD_BOARD, FLAG_SET);\
flag(&attacker->state, CARD_HEROWEAPON, FLAG_SET);\
m_dst->heroweapon = attacker;
#endif
+269
View File
@@ -0,0 +1,269 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <unistd.h>
#include <game.h>
#include <errno.h>
struct ht_s **games = NULL;
struct conn_server_s *user_cs;
struct hm_log_s *lg;
struct ev_loop *loop = NULL;
static struct hm_log_s l;
static struct hm_pool_s *pool;
void set_result(const char *k, int r);
static void client_disconnected(void *data, const char *foreign_client_index, const char *hbs_id)
{
struct hs_holder_s *p = data;
struct game_s *g;
if(p == NULL) {
return;
}
struct packet_s *packet = net_game_over(p, p->entity_id == 2 ? 3 : 2);
struct ht_s *opponent = ht_get(async_clients, foreign_client_index, strlen(foreign_client_index));
if(opponent && opponent->n == sizeof(void *)) {
// loser
hm_log(LOG_DEBUG, lg, "Client disconnect callback, opponent exists");
net_send((void *)opponent->s, packet);
set_result(hbs_id, 0);
} else {
// winner
hm_log(LOG_DEBUG, lg, "Client disconnect callback, opponent doesn't exist, cleaning game");
set_result(hbs_id, 1);
g = p->game;
game_free(g);
}
packet_free(packet);
holder_free(p);
}
static void hm_recv(struct conn_client_s *cs, const char *buf, const int len)
{
hs(cs, buf, len);
}
static void server_shutdown()
{
shutdown_server(user_cs);
couchbase_deinit();
ht_free(games, pool);
ht_free(async_clients, pool);
}
int start_server()
{
struct conn_server_s *cs;
entities_init();
entities_init2();
lg = &l;
games = ht_init(pool);
async_clients = ht_init(pool);
cs = malloc(sizeof(*cs));
memset(cs, 0, sizeof(*cs));
cs->loop = loop;
cs->host = "0.0.0.0";
cs->port = "3724";
cs->log = &l;
cs->pool = pool;
cs->recv = hm_recv;
cs->client_dc = client_disconnected;
cs->shutdown = server_shutdown;
connector_server(cs);
user_cs = cs;
return 0;
}
void callback(struct instance_s *data)
{
struct instance_s *i;
if(data == NULL) {
couchbase_deinit();
hm_log(LOG_DEBUG, lg, "{Connector}: all destinations are offline");
return;
}
for(i = data; i != NULL; i = i->next) {
hm_log(LOG_DEBUG, lg, "{Connector}: connstr: [%s] online: %d group: %d bucket index: %d", i->connstr, i->status, i->group, i->index);
}
start_server();
}
static void sigh_terminate(int __attribute__ ((unused)) signo)
{
user_cs->shutdown();
}
static void initsignals()
{
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = SIG_IGN;
if(sigaction(SIGPIPE, &act, NULL) < 0) {
hm_log(LOG_CRIT, lg, "{Connector}: sigaction sigpipe");
}
/** We don't care if someone stops and starts a child process with kill (1) */
act.sa_flags = SA_NOCLDSTOP;
/* catch INT and TERM signals */
act.sa_flags = 0;
act.sa_handler = sigh_terminate;
if(sigaction(SIGINT, &act, NULL) < 0) {
hm_log(LOG_CRIT, lg, "{Connector}: Unable to register SIGINT signal handler: %s", strerror(errno));
exit(1);
}
if(sigaction(SIGTERM, &act, NULL) < 0) {
hm_log(LOG_CRIT, lg, "{Connector}: Unable to register SIGTERM signal handler: %s", strerror(errno));
exit(1);
}
}
void daemonize () {
if(chdir("/") != 0) {
hm_log(LOG_DEBUG, lg, "Unable change directory to /: %s", strerror(errno));
exit(1);
}
pid_t pid = fork();
if(pid < 0) {
hm_log(LOG_DEBUG, lg, "Unable to daemonize: fork failed: %s", strerror(errno));
exit(1);
}
if(pid != 0) {
hm_log(LOG_DEBUG, lg, "Daemonized as pid %d.", pid);
exit(0);
}
fclose(stdin);
fclose(stdout);
fclose(stderr);
#define NULL_DEV "/dev/null"
stdin = fopen(NULL_DEV, "r");
if(stdin == NULL) {
hm_log(LOG_EMERG, lg, "Unable to reopen stdin to %s: %s", NULL_DEV, strerror(errno));
exit(1);
}
stdout = fopen(NULL_DEV, "w");
if(stdout == NULL) {
hm_log(LOG_EMERG, lg, "Unable to reopen stdout to %s: %s", NULL_DEV, strerror(errno));
exit(1);
}
stderr = fopen(NULL_DEV, "w");
if(stderr == NULL) {
hm_log(LOG_EMERG, lg, "Unable to reopen stderr to %s: %s", NULL_DEV, strerror(errno));
exit(1);
}
pid_t s = setsid();
if(s < 0) {
hm_log(LOG_EMERG, lg, "Unable to create new session, setsid(2) failed: %s :: %d", strerror(errno), s);
exit(1);
}
hm_log(LOG_DEBUG, lg, "Successfully daemonized as pid %d.", getpid());
}
int main(int argc, char **argv)
{
struct couchbase_data_s cd;
const char *hosts[1] = { "localhost" };
const int groups[1] = { 0 }; // Must start with 0
const char *buckets[1] = { "hbs" };
const char *passwd[1] = { "aci" };
int i, daemon = 0;
memset(&l, 0, sizeof(l));
for(i = 1; i < argc; i++) {
if(strlen(argv[i]) > 6 && memcmp(argv[i], "--log=", 6) == 0) {
daemon = 1;
hm_log_open(&l, argv[i] + 6, LOG_DEBUG);
}
}
if(daemon == 0) {
hm_log_open(&l, NULL, LOG_DEBUG);
}
lg = &l;
loop = ev_default_loop(0);
pool = hm_create_pool(&l);
hm_log(LOG_DEBUG, lg, "\nhm_gameserver Copyright (C) 2016 Filip Pancik\n\
This program comes with ABSOLUTELY NO WARRANTY.\n\
This is free software, and you are welcome to redistribute it\n\
under certain conditions.");
initsignals();
if(daemon == 1) {
daemonize();
}
cd.loop = loop;
cd.log = &l;
cd.pool = pool;
cd.callback = callback;
cd.hosts = hosts;
cd.hgroups = groups;
cd.nhosts = 1;
cd.buckets = buckets;
cd.bpasswd = passwd;
cd.nbuckets = 1;
couchbase_init(&cd);
ev_run(loop, 0);
hm_destroy_pool(pool);
hm_log_close(&l);
ev_default_destroy();
return 0;
}
+487
View File
@@ -0,0 +1,487 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
static int log_enable = 1;
static struct option_s *fill_option(u64 type, u64 id, struct suboption_target_s *targets)
{
struct option_s *option;
option = malloc(sizeof(*option));
memset(option, 0, sizeof(*option));
option->type = type;
if(id != -1) {
option->mainoption = malloc(sizeof(*(option->mainoption)));
memset(option->mainoption, 0, sizeof(*(option->mainoption)));
option->mainoption->id = id;
option->mainoption->target = targets;
}
return option;
}
static void add_suboption_target(struct suboption_target_s **so, u64 id)
{
struct suboption_target_s *s;
s = malloc(sizeof(*s));
s->value = id;
s->next = *so;
*so = s;
}
int set_options_cards(struct card_list_s *cl, char *buffer, char *endbuffer, int turn)
{
struct packet_s *packet;
struct alloptions_s *all;
struct option_s *option = NULL, *o;
struct card_list_s *c;
for(c = cl; c != NULL; c = c->next) {
o = fill_option(6, c->card->id, NULL);
o->next = option;
option = o;
}
o = fill_option(2, -1, NULL);
o->next = option;
option = o;
all = malloc(sizeof(*all));
all->id = turn;
all->options = option;
alloptions_dump(all);
add_packet(&packet, all, P_ALLOPTIONS);
char *ptr = buffer;
int n = serialize(packet, &ptr, endbuffer);
//hm_log(LOG_NOTICE, lg, "set options:");
//bin_dump(buffer, n);
return n;
}
static void set_options_board(struct option_s **option, struct card_s *card, struct deck_s *opponent, const int taunt_count)
{
struct option_s *o;
int j;
struct suboption_target_s *so = NULL;
if(
(flag(&card->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&card->state, CARD_DESTROYED, FLAG_ISSET) &&
!flag(&card->state, CARD_SPELL, FLAG_ISSET) &&
!flag(&card->state, CARD_FROZEN, FLAG_ISSET) ) &&
/*( flag(&card->state, CARD_HERO, FLAG_ISSET) && card->attack > 0) */
card->attack > 0
) {
if(!flag(&card->state, CARD_TARGETING, FLAG_ISSET) && !flag(&card->state, CARD_TARGETING_BC, FLAG_ISSET)) {
goto add;
}
if(log_enable) hm_log(LOG_NOTICE, lg, "setting targets for card %d", card->id);
for(j = 0; j < opponent->ncards; j++) {
if((flag(&opponent->cards[j]->state, CARD_BOARD, FLAG_ISSET) ||
flag(&opponent->cards[j]->state, CARD_HERO, FLAG_ISSET) ) &&
!flag(&opponent->cards[j]->state, CARD_DESTROYED, FLAG_ISSET)
) {
// if taunt cards on board, does enemy have taunt
if(taunt_count > 0 && !flag(&card->state, CARD_HEROPOWER, FLAG_ISSET)) {
if(flag(&opponent->cards[j]->state, CARD_TAUNT, FLAG_ISSET)) {
hm_log(LOG_DEBUG, lg, "\tadding opponent taunt card %d as a target", opponent->cards[j]->id);
add_suboption_target(&so, opponent->cards[j]->id);
}
} else {
hm_log(LOG_DEBUG, lg, "\tadding opponent card %d as a target", opponent->cards[j]->id);
add_suboption_target(&so, opponent->cards[j]->id);
}
}
}
add:
o = fill_option(3, card->id, so);
o->next = *option;
*option = o;
} /*else {
hm_log(LOG_ALERT, lg, "Card %d: board %d desttroyed %d frozen %d spell %d", card->id,
flag(&card->state, CARD_BOARD, FLAG_ISSET),
flag(&card->state, CARD_DESTROYED, FLAG_ISSET),
flag(&card->state, CARD_FROZEN, FLAG_ISSET),
flag(&card->state, CARD_SPELL, FLAG_ISSET)
);
} */
}
enum side_e {
SIDE_PLAYER = 0,
SIDE_OPPONENT
};
static void calc_targets(struct deck_s *deck, struct card_s *attacker, enum side_e side, struct suboption_target_s **so)
{
int i;
struct card_s *defender;
int debug = 0;
for(i = 0; i < deck->ncards; i++) {
defender = deck->cards[i];
// ignore destroyed, spell, not board and not hero
if(flag(&defender->state, CARD_SPELL, FLAG_ISSET) ||
(!flag(&defender->state, CARD_BOARD, FLAG_ISSET) && !flag(&defender->state, CARD_HERO, FLAG_ISSET)) ||
flag(&defender->state, CARD_DESTROYED, FLAG_ISSET)
) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", defender->id);
continue;
}
// culling blade
if(flag(&attacker->state, CARD_TARGET_30PERCENT_LESS, FLAG_ISSET) &&
(defender->health * 3) > defender->total_health) {
continue;
}
// magic immunity
if(flag(&attacker->state, CARD_SPELL, FLAG_ISSET) &&
!flag(&attacker->state, CARD_PIERCE_MAGIC_IMMUNITY, FLAG_ISSET) &&
flag(&defender->state, CARD_DIVINE_SHIELD, FLAG_ISSET)) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// battlecry
/*
if(flag(&attacker->state, CARD_TARGET_BC_AUTO, FLAG_ISSET)) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
*/
// allies
if(flag(&attacker->state, CARD_TARGET_ALLY, FLAG_ISSET) && side == SIDE_OPPONENT ) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// enemies
if(flag(&attacker->state, CARD_TARGET_ENEMY, FLAG_ISSET) && side == SIDE_PLAYER) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// ally bosses
if(flag(&attacker->state, CARD_TARGET_ALLY_BOSSES, FLAG_ISSET) &&
(side == SIDE_OPPONENT || !flag(&defender->state, CARD_BOSS, FLAG_ISSET))
) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// enemy bosses
if(flag(&attacker->state, CARD_TARGET_ENEMY_BOSSES, FLAG_ISSET) &&
(side == SIDE_PLAYER || !flag(&defender->state, CARD_BOSS, FLAG_ISSET))
) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// bosses
if(flag(&attacker->state, CARD_TARGET_BOSSES, FLAG_ISSET) &&
(!flag(&defender->state, CARD_BOSS, FLAG_ISSET))
) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// board target (exc. heroes)
if(flag(&attacker->state, CARD_TARGET_BOARD, FLAG_ISSET) &&
(flag(&defender->state, CARD_HERO, FLAG_ISSET))) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// ally board target (exc. heroes)
if(flag(&attacker->state, CARD_TARGET_ALLY_BOARD, FLAG_ISSET) &&
(side == SIDE_OPPONENT || flag(&defender->state, CARD_HERO, FLAG_ISSET))) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// enemy board target (exc. heroes)
if(flag(&attacker->state, CARD_TARGET_ENEMY_BOARD, FLAG_ISSET) &&
(side == SIDE_PLAYER || flag(&defender->state, CARD_HERO, FLAG_ISSET))) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// skip non-hero targets if only heroes are valid targets
if(flag(&attacker->state, CARD_TARGET_HERO, FLAG_ISSET) &&
!flag(&defender->state, CARD_HERO, FLAG_ISSET)) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// enemy hero
if(flag(&attacker->state, CARD_TARGET_ENEMY_HERO, FLAG_ISSET) &&
(side == SIDE_PLAYER || !flag(&defender->state, CARD_HERO, FLAG_ISSET))
) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// ally hero
if(flag(&attacker->state, CARD_TARGET_ALLY_HERO, FLAG_ISSET) &&
(side == SIDE_OPPONENT || !flag(&defender->state, CARD_HERO, FLAG_ISSET))) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// minions
if(flag(&attacker->state, CARD_TARGET_MINIONS, FLAG_ISSET) &&
(flag(&defender->state, CARD_HERO, FLAG_ISSET) || flag(&defender->state, CARD_BOSS, FLAG_ISSET))) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// enemy minions
if(flag(&attacker->state, CARD_TARGET_ENEMY_MINIONS, FLAG_ISSET) &&
(side == SIDE_PLAYER || flag(&defender->state, CARD_HERO, FLAG_ISSET) || flag(&defender->state, CARD_BOSS, FLAG_ISSET))) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// ally minions
if(flag(&attacker->state, CARD_TARGET_ALLY_MINIONS, FLAG_ISSET) &&
(side == SIDE_OPPONENT || flag(&defender->state, CARD_HERO, FLAG_ISSET) || flag(&defender->state, CARD_BOSS, FLAG_ISSET))
) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// allies
if((flag(&attacker->state, CARD_TARGET_ALLY, FLAG_ISSET) && side == SIDE_OPPONENT)) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// undamaged minion eg. backstab
if(flag(&attacker->state, CARD_TARGET_UNDAMAGED_MINION, FLAG_ISSET)
&&
(defender->total_health != defender->health ||
flag(&defender->state, CARD_HERO, FLAG_ISSET)) ) {
continue;
}
// undamaged minion eg. execute
if(flag(&attacker->state, CARD_TARGET_DAMAGED_MINION, FLAG_ISSET)
&&
(defender->total_health == defender->health ||
flag(&defender->state, CARD_HERO, FLAG_ISSET))) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// shadow word: pain
if(flag(&attacker->state, CARD_TARGET_3ATTACK_LESS, FLAG_ISSET) &&
( defender->attack > 3 ||
flag(&defender->state, CARD_HERO, FLAG_ISSET) )) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// shadow word: death
if(flag(&attacker->state, CARD_TARGET_5ATTACK_MORE, FLAG_ISSET) &&
(defender->attack < 5 ||
flag(&defender->state, CARD_HERO, FLAG_ISSET))) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// Ursa
if(flag(&attacker->state, CARD_TARGET_URSA, FLAG_ISSET) &&
strcmp(defender->entity->name, CN_URSA) != 0) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// Sven
if(flag(&attacker->state, CARD_TARGET_SVEN, FLAG_ISSET) &&
strcmp(defender->entity->name, CN_SVEN) != 0) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
// sacr. pact
if(flag(&attacker->state, CARD_TARGET_DEMON, FLAG_ISSET) &&
( !flag(&defender->state, CARD_RACE_DEMON, FLAG_ISSET) ||
flag(&defender->state, CARD_HERO, FLAG_ISSET))) {
if(debug) hm_log(LOG_DEBUG, lg, "target exit for card %d", deck->cards[i]->id);
continue;
}
if(debug) hm_log(LOG_DEBUG, lg, "\tadding card %d as a target of [%s](%d)", defender->id, attacker->entity->desc, attacker->id);
add_suboption_target(so, defender->id);
}
}
int set_options(struct deck_s *deck, struct deck_s *opponent, char *buffer, char *endbuffer, int turn)
{
int i;
int taunt_count;
struct packet_s *packet;
struct alloptions_s *all;
struct option_s *option = NULL, *o = NULL;
assert(opponent);
// does enemy board contain taunt?
taunt_count = deck_get_taunts(opponent);
// find playable cards
for(i = 0; i < deck->ncards; i++) {
// exhausted or frozen
if(flag(&deck->cards[i]->state, CARD_EXHAUSTED, FLAG_ISSET) ||
flag(&deck->cards[i]->state, CARD_FROZEN, FLAG_ISSET)) {
if(log_enable) hm_log(LOG_DEBUG, lg, "skipping card %d as it's exhausted or frozen", deck->cards[i]->id);
continue;
}
// not on board, in hand, heropower or frozen
if(!flag(&deck->cards[i]->state, CARD_BOARD, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET)) {
if(log_enable) hm_log(LOG_DEBUG, lg, "skipping card %d as it's not: on board, in hand, heropower or hero with attack", deck->cards[i]->id);
continue;
}
// set options to cards placed on board
if(!flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)) {
set_options_board(&option, deck->cards[i], opponent, taunt_count);
}
int board_count = cards_get_board_count(deck, NULL, 0, -1);
// set playable in hand cards that are not spells/bc
if(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) &&
!flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET) &&
deck->cards[i]->cost <= (deck->mana - deck->mana_used) &&
board_count < MAX_BOARD
) {
o = fill_option(3, deck->cards[i]->id, NULL);
o->next = option;
option = o;
if(log_enable) hm_log(LOG_DEBUG, lg, "setting playable card [%s](%d) in hand and it's not a spell, board count %d", deck->cards[i]->entity->desc, deck->cards[i]->id, board_count);
continue;
}
// set in-hand spells, targeting battlecries
if((flag(&deck->cards[i]->state, CARD_SPELL, FLAG_ISSET) &&
flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET))
||
(flag(&deck->cards[i]->state, CARD_HAND, FLAG_ISSET) &&
flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET))
||
flag(&deck->cards[i]->state, CARD_WEAPON, FLAG_ISSET)
||
flag(&deck->cards[i]->state, CARD_HEROPOWER, FLAG_ISSET)
) {
if(log_enable) hm_log(LOG_DEBUG, lg, "Considering Spell/Battlecry card %d", deck->cards[i]->id);
if(flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET) && board_count >= MAX_BOARD) {
if(log_enable) hm_log(LOG_DEBUG, lg, "Battlecry card %d igrnoed as board is full", deck->cards[i]->id);
continue;
}
if(deck->cards[i]->cost > (deck->mana - deck->mana_used)) {
if(log_enable) hm_log(LOG_DEBUG, lg, "Spell card %d too expensive", deck->cards[i]->id);
continue;
}
if(log_enable) hm_log(LOG_DEBUG, lg, "Card [%s](%d) with cost %d accepted", deck->cards[i]->entity->desc, deck->cards[i]->id, deck->cards[i]->cost);
struct suboption_target_s *so = NULL;
if(flag(&deck->cards[i]->state, CARD_TARGETING, FLAG_ISSET) || flag(&deck->cards[i]->state, CARD_TARGETING_BC, FLAG_ISSET)) {
if(log_enable) hm_log(LOG_NOTICE, lg, "setting targets for card [%s](%d)", deck->cards[i]->entity->desc, deck->cards[i]->id);
calc_targets(deck, deck->cards[i], SIDE_PLAYER, &so);
calc_targets(opponent, deck->cards[i], SIDE_OPPONENT, &so);
}
if(so != NULL ||
flag(&deck->cards[i]->state, CARD_NONTARGET, FLAG_ISSET)
) {
o = fill_option(/*deck->cards[i]->cardtype*/ 3, deck->cards[i]->id, so);
o->next = option;
option = o;
}
}
}
o = fill_option(2, -1, NULL);
o->next = option;
option = o;
all = malloc(sizeof(*all));
all->id = turn;
all->options = option;
alloptions_dump(all);
add_packet(&packet, all, P_ALLOPTIONS);
char *ptr = buffer;
int n = serialize(packet, &ptr, endbuffer);
packet_free(packet);
//hm_log(LOG_NOTICE, lg, "set options:");
//bin_dump(buffer, n);
return n;
}
+87
View File
@@ -0,0 +1,87 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void alloptions_free(struct alloptions_s *a)
{
struct option_s *o, *del;
for(o = a->options; o != NULL; del = o, o = o->next, option_free(del));
free(a);
}
int alloptions_serialize(void *ao, char **dst, const char *maxdst)
{
int n = 0;
struct option_s *m;
struct alloptions_s *s;
char *start;
start = *dst;
s = ao;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, s->id);
for(m = s->options; m != NULL; m = m->next) {
write_byte(dst, maxdst, 18);
n = option_size(m);
write_uint(dst, maxdst, n);
option_serialize(m, dst, maxdst);
}
return (*dst - start);
}
int alloptions_size(struct alloptions_s *p)
{
int num = 0, n;
struct option_s *s;
num += 1;
num += sizeofu64(p->id);
for(s = p->options; s != NULL; s = s->next) {
num += 1;
n = option_size(s);
num += sizeofu32(n) + n;
}
return num;
}
void alloptions_dump(struct alloptions_s *a)
{
struct suboption_target_s *t;
struct suboption_s *m;
struct option_s *o;
hm_log(LOG_DEBUG, lg, "Dumping alloptions:");
hm_log(LOG_DEBUG, lg, "id: %lld", a->id);
for(o = a->options; o != NULL; o = o->next) {
hm_log(LOG_DEBUG, lg, "\tOption type: %lld", o->type);
for(m = o->mainoption; m != NULL; m = m->next) {
hm_log(LOG_DEBUG, lg, "\t\tMainoption id: %lld", m->id);
for(t = m->target; t != NULL; t = t->next) {
hm_log(LOG_DEBUG, lg, "\t\t\tTarget id: %lld", t->value);
}
}
assert(o->suboptions == NULL);
}
}
+31
View File
@@ -0,0 +1,31 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
int bnet_size(struct powerhistory_player_s *player)
{
int size = 0;
if(player) {
size += 2;
size += sizeofu64(player->bnet_hi);
size += sizeofu64(player->bnet_lo);
}
return size;
}
+65
View File
@@ -0,0 +1,65 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void chooseentities_free(struct chooseentities_s *c)
{
struct chooseentities_ent_s *e, *del;
for(e = c->entity; e != NULL; del = e, e = e->next, free(del));
free(c);
}
void *chooseentities_deserialize(char **dst, const char *maxdst)
{
int n, i;
struct chooseentities_s *c;
struct chooseentities_ent_s *e;
c = malloc(sizeof(*c));
memset(c, 0, sizeof(*c));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
c->id = read_uint64(dst, maxdst);
c->entity = NULL;
n = read_byte(dst, maxdst);
if(n != 18) {
return c;
}
c->nentity = read_uint(dst, maxdst);
if(c->nentity > 5 || c->nentity < 0) {
free(c);
return NULL;
}
for(i = 0; i < c->nentity && *dst < maxdst; i++) {
e = malloc(sizeof(*e));
e->entity = read_uint(dst, maxdst);
e->next = c->entity;
c->entity = e;
}
return c;
}
+69
View File
@@ -0,0 +1,69 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void chooseoption_free(struct chooseoption_s *c)
{
free(c);
}
void *chooseoption_deserialize(char **dst, const char *maxdst)
{
int n;
struct chooseoption_s *o;
o = malloc(sizeof(*o));
memset(o, 0, sizeof(*o));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
o->id = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 16) {
error();
}
o->index = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 24) {
error();
}
o->target = read_uint64(dst, maxdst);
while(*dst < maxdst) {
n = read_byte(dst, maxdst);
if(n == 32) {
o->suboption = read_uint64(dst, maxdst);
} else if(n == 40) {
o->position = read_uint64(dst, maxdst);
} else {
error();
}
}
return o;
}
void chooseoption_dump(struct chooseoption_s *o, u64 local_held_card)
{
hm_log(LOG_ALERT, lg, "Choose options dump: option id: %lld index: %lld target: %lld suboption: %lld position: %lld local held card: %lld", o->id, o->index, o->target, o->suboption, o->position, local_held_card);
}
+109
View File
@@ -0,0 +1,109 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void creategame_free(struct powerhistory_creategame_s *c)
{
struct powerhistory_player_s *player, *del;
for(player = c->player; player != NULL; del = player, player = player->next, player_free(del));
free(c);
}
struct powerhistory_creategame_s *creategame_deserialize(char **dst, const char *maxdst)
{
int n, len;
struct powerhistory_creategame_s *t;
struct powerhistory_player_s *player;
t = malloc(sizeof(*t));
t->player = t->player_tail = NULL;
n = read_byte(dst, maxdst);
if(n != 10) {
error();
}
len = read_uint(dst, maxdst);
t->game_entity = game_entity_deserialize(dst, *dst + len);
while(*dst < maxdst) {
n = read_byte(dst, maxdst);
if(n != 18) {
error();
}
len = read_uint(dst, maxdst);
player = player_deserialize(dst, *dst + len);
player->next = NULL;
if(t->player == NULL && t->player_tail == NULL) {
t->player = player;
t->player_tail = player;
} else {
t->player_tail->next = player;
t->player_tail = player;
}
}
return t;
}
int creategame_size(struct powerhistory_creategame_s *cg)
{
struct powerhistory_player_s *p;
int num = 0;
int n;
if(cg) {
num += 1;
n = game_entity_size(cg->game_entity);
num += sizeofu32(n) + n;
for(p = cg->player; p != NULL; p = p->next) {
num += 1;
n = player_size(p);
num += sizeofu32(n) + n;
}
}
return num;
}
int creategame_serialize(struct powerhistory_creategame_s *cg, char **dst, const char *maxdst)
{
int n;
struct powerhistory_player_s *p;
write_byte(dst, maxdst, 10);
n = game_entity_size(cg->game_entity);
write_uint(dst, maxdst, n);
game_entity_serialize(cg->game_entity, dst, maxdst);
for(p = cg->player; p != NULL; p = p->next) {
write_byte(dst, maxdst, 18);
n = player_size(p);
write_uint(dst, maxdst, n);
player_serialize(p, dst, maxdst);
}
return 0;
}
+120
View File
@@ -0,0 +1,120 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
#define MAP_PACKET_MAX 12
typedef int (*f)(void *c);
static struct packet_deserialize_s map_packet[MAP_PACKET_MAX] = {
{P_GETGAMESTATE, NULL, NULL, NULL},
{P_CHOOSEOPTION, chooseoption_deserialize, NULL, (f)chooseoption_free},
{P_TURNTIMER, NULL, turntimer_serialize, (f)turntimer_free},
{P_CHOOSEENTITIES, chooseentities_deserialize, NULL, (f)chooseentities_free},
{P_ALLOPTIONS, NULL, alloptions_serialize, (f)alloptions_free},
{P_ENTITYCHOICES, NULL, entitychoices_serialize, (f)entitychoices_free},
{P_GAMESETUP, NULL, gamesetup_serialize, (f)gamesetup_free},
{P_USERUI, userui_deserialize, userui_serialize, (f)userui_free},
{P_POWERHISTORY, powerhistory_deserialize, powerhistory_serialize, (f)powerhistory_free},
{P_HANDSHAKE, handshake_deserialize, NULL, (f)handshake_free},
{P_PING, NULL, NULL, NULL},
{P_PONG, NULL, NULL, NULL},
};
struct packet_s *deserialize(char **dst, const char *maxdst)
{
struct packet_s *p;
int i;
if(!(dst != NULL && *dst != NULL && *dst < maxdst)) {
return NULL;
}
p = malloc(sizeof(*p));
p->id = read_mem_int(dst, maxdst);
p->len = read_mem_int(dst, maxdst);
for(i = 0; i < MAP_PACKET_MAX; i++) {
if(map_packet[i].id == p->id) {
if(map_packet[i].deserialize) {
p->data = map_packet[i].deserialize(dst, maxdst);
assert(p->data);
}
return p;
}
}
free(p);
return NULL;
}
void packet_free(struct packet_s *p)
{
int i;
for(i = 0; i < MAP_PACKET_MAX; i++) {
if(map_packet[i].id == p->id) {
if(map_packet[i].free) {
map_packet[i].free(p->data);
}
free(p);
break;
}
}
}
int serialize(struct packet_s *p, char **dst, const char *maxdst)
{
int i, n = 0;
char *off_len;
write_mem_int(dst, maxdst, p->id);
off_len = *dst;
write_mem_int(dst, maxdst, 0); // make space for length
n += 2 * sizeof(int);
for(i = 0; i < MAP_PACKET_MAX; i++) {
if(map_packet[i].id == p->id) {
if(map_packet[i].serialize) {
n += map_packet[i].serialize(p->data, dst, maxdst);
}
write_mem_int(&off_len, maxdst, n - (2 * sizeof(int)));
return n;
}
}
return -1;
}
struct packet_s *packet_init(enum packet_e id, void *data)
{
struct packet_s *p;
p = malloc(sizeof(*p));
p->id = id;
p->data = data;
return p;
}
+119
View File
@@ -0,0 +1,119 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void entity_free(struct powerhistory_entity_s *e)
{
struct powerhistory_tag_s *tag, *del;
for(tag = e->tag; tag != NULL; del = tag, tag = tag->next, tag_free(del));
//free(e->name);
free(e);
}
struct powerhistory_entity_s *entity_deserialize(char **dst, const char *maxdst)
{
int n, len;
struct powerhistory_entity_s *p;
struct powerhistory_tag_s *t;
p = malloc(sizeof(*p));
p->tag = p->tag_tail = NULL;
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
p->entity = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 18) {
error();
}
p->name = read_bytes(dst, maxdst, &p->nname);
while(*dst < maxdst) {
n = read_byte(dst, maxdst);
len = read_uint(dst, maxdst);
if(n == 26) {
t = tag_deserialize(dst, *dst + len);
t->next = NULL;
if(p->tag == NULL && p->tag_tail == NULL) {
p->tag = t;
p->tag_tail = t;
} else {
p->tag_tail->next = t;
p->tag_tail = t;
}
} else {
error();
return NULL;
}
}
return p;
}
int entity_size(struct powerhistory_entity_s *ent)
{
int num = 0;
int ts;
struct powerhistory_tag_s *tag;
num += 2;
num += sizeofu64(ent->entity);
num += sizeofu32(ent->nname) + ent->nname;
for(tag = ent->tag; tag != NULL; tag = tag->next) {
num += 1;
ts = tag_size(tag);
num += sizeofu32(ts) + ts;
}
return num;
}
int entity_serialize(struct powerhistory_entity_s *ent, char **dst, const char *maxdst)
{
int ts;
struct powerhistory_tag_s *t;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, ent->entity);
write_byte(dst, maxdst, 18);
write_bytes(dst, maxdst, ent->name, ent->nname);
if(ent->tag) {
for(t = ent->tag; t != NULL; t = t->next) {
write_byte(dst, maxdst, 26);
ts = tag_size(t);
write_uint(dst, maxdst, ts);
tag_serialize(t, dst, maxdst);
}
}
return 0;
}
+89
View File
@@ -0,0 +1,89 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void entitychoices_free(struct entitychoices_s *ec)
{
struct entitychoices_entities_s *e, *del;
for(e = ec->entities; e != NULL; del = e, e = e->next, free(del));
free(ec);
}
int entitychoices_serialize(void *ep, char **dst, const char *maxdst)
{
int n = 0;
struct entitychoices_entities_s *es;
struct entitychoices_s *e = ep;
char *start;
start = *dst;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, e->id);
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, e->type);
write_byte(dst, maxdst, 32);
write_uint64(dst, maxdst, e->countmin);
write_byte(dst, maxdst, 40);
write_uint64(dst, maxdst, e->countmax);
if(e->entities) {
write_byte(dst, maxdst, 50);
for(es = e->entities; es != NULL; es = es->next) {
n += sizeofu64(es->entity);
}
write_uint(dst, maxdst, n);
for(es = e->entities; es != NULL; es = es->next) {
write_uint64(dst, maxdst, es->entity);
}
}
if(e->source > 0) {
write_byte(dst, maxdst, 56);
write_uint64(dst, maxdst, e->source);
}
write_byte(dst, maxdst, 64);
write_uint64(dst, maxdst, e->player_id);
return (*dst - start);
}
void entitychoices_dump(struct entitychoices_s *es)
{
struct entitychoices_entities_s *ent;
hm_log(LOG_DEBUG, lg, "Entity Choices dump:");
hm_log(LOG_DEBUG, lg, "\t\tID: %lld", es->id);
hm_log(LOG_DEBUG, lg, "\t\tType: %lld", es->type);
hm_log(LOG_DEBUG, lg, "\t\tCountMin: %lld", es->countmin);
hm_log(LOG_DEBUG, lg, "\t\tCountMax: %lld", es->countmax);
hm_log(LOG_DEBUG, lg, "\t\tSource: %lld", es->source);
hm_log(LOG_DEBUG, lg, "\t\tPlayer: %lld", es->player_id);
for(ent = es->entities; ent != NULL; ent = ent->next) {
hm_log(LOG_DEBUG, lg, "\t\t\tChild entity: %lld", ent->entity);
}
}
+105
View File
@@ -0,0 +1,105 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void game_entity_free(struct powerhistory_game_entity_s *g)
{
struct powerhistory_tag_s *tag, *del;
for(tag = g->tag; tag != NULL; del = tag, tag = tag->next, tag_free(del));
free(g);
}
struct powerhistory_game_entity_s *game_entity_deserialize(char **dst, const char *maxdst)
{
int n, len;
struct powerhistory_game_entity_s *t;
struct powerhistory_tag_s *tag;
t = malloc(sizeof(*t));
memset(t, 0, sizeof(*t));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
t->id = read_uint64(dst, maxdst);
while(*dst < maxdst) {
n = read_byte(dst, maxdst);
if(n != 18) {
error();
}
len = read_uint(dst, maxdst);
tag = tag_deserialize(dst, *dst + len);
tag->next = NULL;
if(t->tag == NULL && t->tag_tail == NULL) {
t->tag = tag;
t->tag_tail = tag;
} else {
t->tag_tail->next = tag;
t->tag_tail = tag;
}
}
return t;
}
int game_entity_serialize(struct powerhistory_game_entity_s *ent, char **dst, const char *maxdst)
{
int ts;
struct powerhistory_tag_s *t;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, ent->id);
if(ent->tag) {
for(t = ent->tag; t != NULL; t = t->next) {
write_byte(dst, maxdst, 18);
ts = tag_size(t);
write_uint(dst, maxdst, ts);
tag_serialize(t, dst, maxdst);
}
}
return 0;
}
int game_entity_size(struct powerhistory_game_entity_s *ent)
{
int ts;
struct powerhistory_tag_s *tag;
int num = 0;
num += 1;
num += sizeofu64(ent->id);
for(tag = ent->tag; tag != NULL; tag = tag->next) {
num += 1;
ts = tag_size(tag);
num += sizeofu32(ts) + ts;
}
return num;
}
+81
View File
@@ -0,0 +1,81 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void gamesetup_free(struct gamesetup_s *g)
{
free(g);
}
struct gamesetup_s *gamesetup_deserialize(char **dst, const char *maxdst)
{
abort();
return NULL;
}
int gamesetup_serialize(void *data, char **dst, const char *maxdst)
{
char *start;
struct gamesetup_s *g = data;
start = *dst;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, g->board);
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, g->maxsecrets);
write_byte(dst, maxdst, 24);
write_uint64(dst, maxdst, g->maxfriendlyminions);
if(g->keepalive > 0) {
write_byte(dst, maxdst, 32);
write_uint64(dst, maxdst, g->keepalive);
}
if(g->stuckdisconnect > 0) {
write_byte(dst, maxdst, 40);
write_uint64(dst, maxdst, g->stuckdisconnect);
}
return (*dst - start);
}
int gamesetup_size(struct gamesetup_s *g)
{
int num = 0;
num += 3;
num += sizeofu64(g->board);
num += sizeofu64(g->maxsecrets);
num += sizeofu64(g->maxfriendlyminions);
if(g->keepalive > 0) {
num += 1;
num += sizeofu64(g->keepalive);
}
if(g->stuckdisconnect > 0) {
num += 1;
num += sizeofu64(g->stuckdisconnect);
}
return num;
}
+83
View File
@@ -0,0 +1,83 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void handshake_free(struct handshake_s *h)
{
platform_free(h->platform);
free(h->version);
free(h->password);
free(h);
}
void *handshake_deserialize(char **dst, const char *maxdst)
{
int n, len;
struct handshake_s *h;
h = malloc(sizeof(*h));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
h->gamehandle = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 18) {
error();
}
h->password = read_bytes(dst, maxdst, &h->npassword);
n = read_byte(dst, maxdst);
if(n != 24) {
error();
}
h->clienthandle = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n == 32) {
h->mission = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
}
if(n != 42) {
error();
}
h->version = read_bytes(dst, maxdst, &h->nversion);
n = read_byte(dst, maxdst);
if(n != 58) {
error();
}
len = read_uint(dst, maxdst);
h->platform = platform_deserialize(dst, *dst + len);
return h;
}
void handshake_dump(struct handshake_s *h)
{
hm_log(LOG_DEBUG, lg, "Gamehandle: %lld password: [%.*s] clienthandle: %lld mission: %lld verion: [%.*s] ", h->gamehandle, h->npassword, h->password, h->clienthandle, h->mission, h->nversion, h->version);
if(h->platform) {
hm_log(LOG_DEBUG, lg, "Os: %lld screen: %lld name: [%.*s] store: %lld", h->platform->os, h->platform->screen, h->platform->nname, h->platform->name, h->platform->store);
}
}
+69
View File
@@ -0,0 +1,69 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void hide_free(struct powerhistory_hide_s *t)
{
free(t);
}
struct powerhistory_hide_s *hide_deserialize(char **dst, const char *maxdst)
{
int n;
struct powerhistory_hide_s *t;
t = malloc(sizeof(*t));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
t->entity = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 16) {
error();
}
t->zone = read_uint64(dst, maxdst);
return t;
}
int hide_serialize(struct powerhistory_hide_s *ent, char **dst, const char *maxdst)
{
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, ent->entity);
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, ent->zone);
return 0;
}
int hide_size(struct powerhistory_hide_s *hide)
{
int size = 0;
if(hide) {
size += 2;
size += sizeofu64(hide->entity);
size += sizeofu64(hide->zone);
}
return size;
}
+126
View File
@@ -0,0 +1,126 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void meta_free(struct powerhistory_meta_s *t)
{
struct powerhistory_info_s *info, *del;
for(info = t->info; info != NULL; del = info, info = info->next, free(del));
free(t);
}
struct powerhistory_meta_s *meta_deserialize(char **dst, const char *maxdst)
{
int n, len;
struct powerhistory_meta_s *t;
struct powerhistory_info_s *info;
int i;
t = malloc(sizeof(*t));
memset(t, 0, sizeof(*t));
while(*dst < maxdst) {
n = read_byte(dst, maxdst);
if(n == 18) {
len = read_uint(dst, maxdst);
for(i = 0; i < len; i++) {
info = malloc(sizeof(*info));
info->id = read_uint64(dst, maxdst);
info->next = NULL;
if(t->info == NULL && t->info_tail == NULL) {
t->info = info;
t->info_tail = info;
} else {
t->info_tail->next = info;
t->info_tail = info;
}
}
} else if(n == 24) {
t->type = read_uint64(dst, maxdst);
} else if(n == 32) {
t->data = read_uint64(dst, maxdst);
} else {
error();
}
}
return t;
}
int meta_size(struct powerhistory_meta_s *p)
{
int num = 0, num2;
struct powerhistory_info_s *m;
if(p->info) {
num += 1;
num2 = num;
for(m = p->info; m != NULL; m = m->next) {
num += sizeofu64(m->id);
}
num += sizeofu32(num - num2);
}
if(p->type != 0) {
num += 1;
num += sizeofu64(p->type);
}
if(p->data != 0) {
num += 1;
num += sizeofu64(p->data);
}
return num;
}
int meta_serialize(struct powerhistory_meta_s *p, char **dst, const char *maxdst)
{
int num = 0;
struct powerhistory_info_s *m;
if(p->info) {
write_byte(dst, maxdst, 18);
for(m = p->info; m != NULL; m = m->next) {
num += sizeofu64(m->id);
}
write_uint(dst, maxdst, num);
for(m = p->info; m != NULL; m = m->next) {
write_uint64(dst, maxdst, m->id);
}
}
if(p->type != 0) {
write_byte(dst, maxdst, 24);
write_uint64(dst, maxdst, p->type);
}
if(p->data != 0) {
write_byte(dst, maxdst, 32);
write_uint64(dst, maxdst, p->data);
}
return 0;
}
+104
View File
@@ -0,0 +1,104 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void mouseinfo_free(struct mouseinfo_s *m)
{
free(m);
}
void *mouseinfo_deserialize(char **dst, const char *maxdst)
{
int n;
struct mouseinfo_s *c;
c = malloc(sizeof(*c));
memset(c, 0, sizeof(*c));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
c->arroworigin = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 16) {
error();
}
c->heldcard = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 24) {
error();
}
c->overcard = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 32) {
error();
}
c->x = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 40) {
error();
}
c->y = read_uint64(dst, maxdst);
return c;
}
int mouseinfo_serialize(void *ao, char **dst, const char *maxdst)
{
struct mouseinfo_s *s;
char *start;
start = *dst;
s = ao;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, s->arroworigin);
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, s->heldcard);
write_byte(dst, maxdst, 24);
write_uint64(dst, maxdst, s->overcard);
write_byte(dst, maxdst, 32);
write_uint64(dst, maxdst, s->x);
write_byte(dst, maxdst, 40);
write_uint64(dst, maxdst, s->y);
return (*dst - start);
}
int mouseinfo_size(struct mouseinfo_s *p)
{
int num = 0;
num += 5;
num += sizeofu64(p->arroworigin);
num += sizeofu64(p->heldcard);
num += sizeofu64(p->overcard);
num += sizeofu64(p->x);
num += sizeofu64(p->y);
return num;
}
+84
View File
@@ -0,0 +1,84 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void option_free(struct option_s *o)
{
struct suboption_s *s, *del;
for(s = o->mainoption; s != NULL; del = s, s = s->next, suboption_free(del));
for(s = o->suboptions; s != NULL; del = s, s = s->next, suboption_free(del));
free(o);
}
int option_serialize(struct option_s *s, char **dst, const char *maxdst)
{
int n = 0;
struct suboption_s *m;
char *start;
start = *dst;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, s->type);
if(s->mainoption) {
write_byte(dst, maxdst, 18);
n = suboption_size(s->mainoption);
write_uint(dst, maxdst, n);
suboption_serialize(s->mainoption, dst, maxdst);
}
if(s->suboptions) {
for(m = s->suboptions; m != NULL; m = m->next) {
write_byte(dst, maxdst, 26);
n = suboption_size(m);
write_uint(dst, maxdst, n);
suboption_serialize(m, dst, maxdst);
}
}
return (*dst - start);
}
int option_size(struct option_s *p)
{
int num = 0, n;
struct suboption_s *s;
num += 1;
num += sizeofu64(p->type);
if(p->mainoption) {
num += 1;
n = suboption_size(p->mainoption);
num += sizeofu32(n) + n;
}
if(p->suboptions) {
for(s = p->suboptions; s != NULL; s = s->next) {
num += 1;
n = suboption_size(s);
num += sizeofu32(n) + n;
}
}
return num;
}
+61
View File
@@ -0,0 +1,61 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void platform_free(struct platform_s *p)
{
free(p->name);
free(p);
}
struct platform_s *platform_deserialize(char **dst, const char *maxdst)
{
int n;
struct platform_s *h;
h = malloc(sizeof(*h));
h->store = 0;
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
h->os = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 16) {
error();
}
h->screen = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 26) {
error();
}
h->name = read_bytes(dst, maxdst, &h->nname);
if(*dst < maxdst) {
n = read_byte(dst, maxdst);
if(n == 32) {
h->store = read_uint64(dst, maxdst);
}
}
return h;
}
+116
View File
@@ -0,0 +1,116 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void player_free(struct powerhistory_player_s *p)
{
game_entity_free(p->entity);
free(p);
}
struct powerhistory_player_s *player_deserialize(char **dst, const char *maxdst)
{
int n, len;
struct powerhistory_player_s *player;
player = malloc(sizeof(*player));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
player->id = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 18) {
error();
}
len = read_uint(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
player->bnet_hi = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 16) {
error();
}
player->bnet_lo = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 24) {
error();
}
player->cardback = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 34) {
error();
}
len = read_uint(dst, maxdst);
player->entity = game_entity_deserialize(dst, *dst + len);
return player;
}
int player_serialize(struct powerhistory_player_s *player, char **dst, const char *maxdst)
{
int n;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, player->id);
// bnet
write_byte(dst, maxdst, 18);
n = bnet_size(player);
write_uint(dst, maxdst, n);
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, player->bnet_hi);
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, player->bnet_lo);
write_byte(dst, maxdst, 24);
write_uint64(dst, maxdst, player->cardback);
write_byte(dst, maxdst, 34);
n = game_entity_size(player->entity);
write_uint(dst, maxdst, n);
game_entity_serialize(player->entity, dst, maxdst);
return 0;
}
int player_size(struct powerhistory_player_s *p)
{
int size = 0, ts;
if(p) {
size += 4;
size += sizeofu64(p->id);
ts = bnet_size(p);
size += sizeofu32(ts) + ts;
size += sizeofu64(p->cardback);
ts = game_entity_size(p->entity);
size += sizeofu32(ts) + ts;
}
return size;
}
+42
View File
@@ -0,0 +1,42 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void powerend_free(struct powerhistory_powerend_s *p)
{
free(p);
}
struct powerhistory_powerend_s *powerend_deserialize(char **dst, const char *maxdst)
{
struct powerhistory_powerend_s *t;
t = malloc(sizeof(*t));
return t;
}
int powerend_serialize(struct powerhistory_powerend_s *t, char **dst, const char *maxdst)
{
return 0;
}
int powerend_size(struct powerhistory_powerend_s *p)
{
return 0;
}
+183
View File
@@ -0,0 +1,183 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void powerhistory_free(struct powerhistory_s *p)
{
struct powerhistory_data_s *d, *del;
for(d = p->data; d != NULL; del = d, d = d->next, powerhistory_data_free(del));
free(p);
}
void *powerhistory_deserialize(char **dst, const char *maxdst)
{
struct powerhistory_s *p;
struct powerhistory_data_s *d;
int n, len;
p = malloc(sizeof(*p));
p->data = NULL;
p->data_tail = NULL;
while(*dst < maxdst) {
n = read_byte(dst, maxdst);
len = read_uint(dst, maxdst);
if(n == 10) {
d = powerhistory_data_deserialize(dst, *dst + len);
d->next = NULL;
if(p->data == NULL && p->data_tail == NULL) {
p->data = d;
p->data_tail = d;
} else {
p->data_tail->next = d;
p->data_tail = d;
}
} else {
error();
return NULL;
}
}
return p;
}
int powerhistory_serialize(void *data, char **dst, const char *maxdst)
{
int n, o = 0;
struct powerhistory_data_s *d;
struct powerhistory_s *ph = data;
if(ph->data) {
for(d = ph->data; d != NULL; d = d->next) {
write_byte(dst, maxdst, 10);
o += 1;
n = powerhistorydata_size(d);
write_uint(dst, maxdst, n);
o += sizeofu32(n) + n;
powerhistorydata_serialize(d, dst, maxdst);
}
}
return o;
}
int powerhistory_size(struct powerhistory_s *ph)
{
struct powerhistory_data_s *d;
int n, num = 0;
if(ph->data) {
for(d = ph->data; d != NULL; d = d->next) {
num += 1;
n = powerhistorydata_size(d);
num += n + sizeofu32(n);
}
}
return num;
}
void powerhistory_dump(struct powerhistory_s *p)
{
struct powerhistory_tag_s *t;
struct powerhistory_data_s *d;
struct powerhistory_game_entity_s *ge;
struct powerhistory_player_s *player;
struct powerhistory_info_s *i;
int it = 0;
assert(p);
for(d = p->data; d != NULL; d = d->next) {
hm_log(LOG_DEBUG, lg, "Data %d", it++);
if(d->full) {
hm_log(LOG_DEBUG, lg, "data->full:");
hm_log(LOG_DEBUG, lg, "\tentity: %lld name: [%.*s]", d->full->entity, d->full->nname, d->full->name);
for(t = d->full->tag; t != NULL; t = t->next) {
hm_log(LOG_DEBUG, lg, "\t\ttag name: %lld value: %lld", t->name, t->value);
}
}
if(d->show) {
hm_log(LOG_DEBUG, lg, "data->show:");
hm_log(LOG_DEBUG, lg, "\tentity: %lld name: [%.*s]", d->show->entity, d->show->nname, d->show->name);
for(t = d->show->tag; t != NULL; t = t->next) {
hm_log(LOG_DEBUG, lg, "\t\ttag name: %lld value: %lld", t->name, t->value);
}
}
if(d->hide) {
hm_log(LOG_DEBUG, lg, "data->hide:");
hm_log(LOG_DEBUG, lg, "\tentity: %lld zone: %lld", d->hide->entity, d->hide->zone);
}
if(d->tagchange) {
hm_log(LOG_DEBUG, lg, "data->tagchange:");
hm_log(LOG_DEBUG, lg, "\tentity: %lld tag: %lld value: %lld", d->tagchange->entity, d->tagchange->tag, d->tagchange->value);
}
if(d->creategame) {
ge = d->creategame->game_entity;
hm_log(LOG_DEBUG, lg, "game entity id: %lld", ge->id);
for(t = ge->tag; t != NULL; t = t->next) {
hm_log(LOG_DEBUG, lg, "\ttag name: %lld value: %lld", t->name, t->value);
}
for(player = d->creategame->player; player != NULL; player = player->next) {
hm_log(LOG_DEBUG, lg, "\t\tdata->creategame->player:");
hm_log(LOG_DEBUG, lg, "\t\t\tid: %lld bhi: %lld blo: %lld cardback: %lld", player->id, player->bnet_hi, player->bnet_lo, player->cardback);
ge = player->entity;
hm_log(LOG_DEBUG, lg, "\t\t\tplayer->entity: %lld", ge->id);
for(t = ge->tag; t != NULL; t = t->next) {
hm_log(LOG_DEBUG, lg, "\t\t\t\ttag name: %lld value: %lld", t->name, t->value);
}
}
}
if(d->powerstart) {
hm_log(LOG_DEBUG, lg, "data->powerstart");
hm_log(LOG_DEBUG, lg, "\ttype: %lld index: %lld source: %lld target: %lld card: [%.*s]", d->powerstart->type, d->powerstart->index, d->powerstart->source, d->powerstart->target, d->powerstart->ncard_id, d->powerstart->card_id);
}
if(d->powerend) {
hm_log(LOG_DEBUG, lg, "data->powerend");
}
if(d->change_entity) {
hm_log(LOG_DEBUG, lg, "data->change_entity:");
hm_log(LOG_DEBUG, lg, "\tentity: %lld name: [%.*s]", d->change_entity->entity, d->change_entity->nname, d->change_entity->name);
for(t = d->change_entity->tag; t != NULL; t = t->next) {
hm_log(LOG_DEBUG, lg, "\t\ttag name: %lld value: %lld", t->name, t->value);
}
}
if(d->meta) {
hm_log(LOG_DEBUG, lg, "data->meta:");
hm_log(LOG_DEBUG, lg, "\ttype: %lld data: %lld", d->meta->type, d->meta->data);
for(i = d->meta->info; i != NULL; i = i->next) {
hm_log(LOG_DEBUG, lg, "\t\t\tinfo id: %lld", i->id);
}
}
}
}
+200
View File
@@ -0,0 +1,200 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void powerhistory_data_free(struct powerhistory_data_s *d)
{
if(d->full) entity_free(d->full);
if(d->show) entity_free(d->show);
if(d->hide) hide_free(d->hide);
if(d->tagchange) tagchange_free(d->tagchange);
if(d->creategame) creategame_free(d->creategame);
if(d->powerstart) powerstart_free(d->powerstart);
if(d->powerend) powerend_free(d->powerend);
if(d->change_entity) entity_free(d->change_entity);
if(d->meta) meta_free(d->meta);
free(d);
}
struct powerhistory_data_s *powerhistory_data_deserialize(char **dst, const char *maxdst)
{
struct powerhistory_data_s *p;
int n, len;
p = malloc(sizeof(*p));
memset(p, 0, sizeof(*p));
while(*dst < maxdst) {
n = read_byte(dst, maxdst);
len = read_uint(dst, maxdst);
if(n == 10) {
p->full = entity_deserialize(dst, *dst + len);
} else if(n == 18) {
p->show = entity_deserialize(dst, *dst + len);
} else if(n == 26) {
p->hide = hide_deserialize(dst, *dst + len);
} else if(n == 34) {
p->tagchange = tagchange_deserialize(dst, *dst + len);
} else if(n == 42) {
p->creategame = creategame_deserialize(dst, *dst + len);
} else if(n == 50) {
p->powerstart = powerstart_deserialize(dst, *dst + len);
} else if(n == 58) {
p->powerend = powerend_deserialize(dst, *dst + len);
} else if(n == 66) {
p->meta = meta_deserialize(dst, *dst + len);
} else {
return NULL;
}
}
return p;
}
int powerhistorydata_serialize(struct powerhistory_data_s *phd, char **dst, const char *maxdst)
{
int n;
if(phd->full) {
write_byte(dst, maxdst, 10);
n = entity_size(phd->full);
write_uint(dst, maxdst, n);
entity_serialize(phd->full, dst, maxdst);
}
if(phd->show) {
write_byte(dst, maxdst, 18);
n = entity_size(phd->show);
write_uint(dst, maxdst, n);
entity_serialize(phd->show, dst, maxdst);
}
if(phd->hide) {
write_byte(dst, maxdst, 26);
n = hide_size(phd->hide);
write_uint(dst, maxdst, n);
hide_serialize(phd->hide, dst, maxdst);
}
if(phd->tagchange) {
write_byte(dst, maxdst, 34);
n = tagchange_size(phd->tagchange);
write_uint(dst, maxdst, n);
tagchange_serialize(phd->tagchange, dst, maxdst);
}
if(phd->creategame) {
write_byte(dst, maxdst, 42);
n = creategame_size(phd->creategame);
write_uint(dst, maxdst, n);
creategame_serialize(phd->creategame, dst, maxdst);
}
if(phd->powerstart) {
write_byte(dst, maxdst, 50);
n = powerstart_size(phd->powerstart);
write_uint(dst, maxdst, n);
powerstart_serialize(phd->powerstart, dst, maxdst);
}
if(phd->powerend) {
write_byte(dst, maxdst, 58);
n = powerend_size(phd->powerend);
write_uint(dst, maxdst, n);
powerend_serialize(phd->powerend, dst, maxdst);
}
if(phd->meta) {
write_byte(dst, maxdst, 66);
n = meta_size(phd->meta);
write_uint(dst, maxdst, n);
meta_serialize(phd->meta, dst, maxdst);
}
if(phd->change_entity) {
write_byte(dst, maxdst, 74);
n = entity_size(phd->change_entity);
write_uint(dst, maxdst, n);
entity_serialize(phd->change_entity, dst, maxdst);
}
return 0;
}
int powerhistorydata_size(struct powerhistory_data_s *phd)
{
int num = 0, n;
if(phd->full) {
num += 1;
n = entity_size(phd->full);
num += n + sizeofu32(n);
}
if(phd->show) {
num += 1;
n = entity_size(phd->show);
num += n + sizeofu32(n);
}
if(phd->hide) {
num += 1;
n = hide_size(phd->hide);
num += n + sizeofu32(n);
}
if(phd->tagchange) {
num += 1;
n = tagchange_size(phd->tagchange);
num += n + sizeofu32(n);
}
if(phd->creategame) {
num += 1;
n = creategame_size(phd->creategame);
num += n + sizeofu32(n);
}
if(phd->powerstart) {
num += 1;
n = powerstart_size(phd->powerstart);
num += n + sizeofu32(n);
}
if(phd->powerend) {
num += 1;
n = powerend_size(phd->powerend);
num += n + sizeofu32(n);
}
if(phd->meta) {
num += 1;
n = meta_size(phd->meta);
num += n + sizeofu32(n);
}
if(phd->change_entity) {
num += 1;
n = entity_size(phd->change_entity);
num += n + sizeofu32(n);
}
return num;
}
+112
View File
@@ -0,0 +1,112 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void powerstart_free(struct powerhistory_powerstart_s *p)
{
free(p->card_id);
free(p);
}
struct powerhistory_powerstart_s *powerstart_deserialize(char **dst, const char *maxdst)
{
int n;
struct powerhistory_powerstart_s *t;
t = malloc(sizeof(*t));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
t->type = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 16) {
error();
}
t->index = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 24) {
error();
}
t->source = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 32) {
error();
}
t->target = read_uint64(dst, maxdst);
t->ncard_id = 0;
t->card_id = NULL;
// optional
n = read_byte(dst, maxdst);
if(n != 42) {
return t;
}
t->card_id = read_bytes(dst, maxdst, &t->ncard_id);
return t;
}
int powerstart_serialize(struct powerhistory_powerstart_s *p, char **dst, const char *maxdst)
{
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, p->type);
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, p->index);
write_byte(dst, maxdst, 24);
write_uint64(dst, maxdst, p->source);
write_byte(dst, maxdst, 32);
write_uint64(dst, maxdst, p->target);
if(p->ncard_id > 0) {
write_byte(dst, maxdst, 42);
write_bytes(dst, maxdst, p->card_id, p->ncard_id);
}
return 0;
}
int powerstart_size(struct powerhistory_powerstart_s *p)
{
int size = 0;
int n;
if(p) {
size += 4;
size += sizeofu64(p->type);
size += sizeofu64(p->index);
size += sizeofu64(p->source);
size += sizeofu64(p->target);
if(p->ncard_id > 0) {
size += 1;
n = sizeofu64(p->ncard_id);
size += sizeofu32(n) + n;
}
}
return size;
}
+231
View File
@@ -0,0 +1,231 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
int sizeofu64(u64 val)
{
unsigned int num = 1u;
while(1 == 1) {
val >>= 7;
if(val == 0) {
break;
}
num++;
}
return num;
}
int sizeofu32(int val)
{
unsigned int num = 1u;
while(1 == 1) {
val >>= 7;
if(val == 0) {
break;
}
num++;
}
return num;
}
int read_mem_int(char **dst, const char *end)
{
int n;
if(*dst + sizeof(int) > end) {
return -1;
}
n = *(int *)(*dst);
(*dst) += sizeof(int);
return n;
}
int write_mem_int(char **dst, const char *end, const int src)
{
if(*dst + sizeof(src) > end) {
hm_log(LOG_EMERG, lg, "Cannot write %d %p %p", src, *dst, end);
abort();
}
memcpy(*dst, &src, sizeof(src));
(*dst) += sizeof(src);
return 0;
}
int write_byte(char **dst, const char *end, char src)
{
if(*dst + sizeof(src) > end) {
hm_log(LOG_EMERG, lg, "Cannot write %d %p %p", src, *dst, end);
abort();
}
memcpy(*dst, &src, sizeof(src));
(*dst)++;
return 0;
}
char read_byte(char **dst, const char *end)
{
char out;
if(*dst + sizeof(char) > end) {
return -1;
}
out = *((char *)(*dst));
(*dst)++;
return out;
}
int skip(char **dst, const char *end, const int jump)
{
if((*dst + jump) > end) {
hm_log(LOG_ALERT, lg, "Invalid skip %p %p %d", *dst, end, jump);
return -1;
}
*dst += jump;
return 0;
}
int read_uint(char **dst, const char *end)
{
int num = 0, num2;
int i;
for(i = 0; (i < 5 && *dst < end); i++) {
num2 = read_byte(dst, end);
if(i == 4 && (num2 & 240) != 0) {
hm_log(LOG_EMERG, lg, "Incorrect num size");
abort();
}
if((num2 & 128) == 0) {
return num | (unsigned int)((unsigned int)num2 << 7 * i);
}
num |= (unsigned int)((unsigned int)(num2 & 127) << 7 * i);
}
return num;
}
u64 read_uint64(char **dst, const char *end)
{
u64 num = 0;
int num2;
int i;
for(i = 0; (i < 10 && *dst < end); i++) {
num2 = read_byte(dst, end);
if(i == 9 && (num2 & 254) != 0) {
hm_log(LOG_EMERG, lg, "Incorrect num size");
abort();
}
if((num2 & 128) == 0) {
return num | (unsigned long long)((unsigned long long)num2 << 7 * i);
}
num |= (unsigned long long)((unsigned long long)(num2 & 127) << 7 * i);
}
return num;
}
void write_uint(char **dst, const char *end, int src)
{
char b;
while(1 == 1) {
b = (char)(src & 127);
src >>= 7;
if(src == 0) {
break;
}
b |= 128;
write_byte(dst, end, b);
}
write_byte(dst, end, b);
}
char *read_bytes(char **dst, const char *end, int *ndst)
{
char *out;
*ndst = read_uint(dst, end);
if(*dst + *ndst > end) {
hm_log(LOG_EMERG, lg, "Dst read bytes %p %p %d", end, *dst + *ndst, *ndst);
abort();
}
out = malloc(*ndst);
memcpy(out, *dst, *ndst);
*dst += *ndst;
return out;
}
int write_bytes(char **dst, const char *end, const char *src, const int nsrc)
{
if(*dst + nsrc > end) {
hm_log(LOG_EMERG, lg, "Cannot write %d %p %p", nsrc, *dst, end);
abort();
}
write_uint(dst, end, nsrc);
memcpy(*dst, src, nsrc);
(*dst) += nsrc;
return 0;
}
void write_uint64(char **dst, const char *end, u64 src)
{
char b;
while(1 == 1) {
b = (char)(src & 127);
src >>= 7;
if(src == 0) {
break;
}
b |= 128;
write_byte(dst, end, b);
}
write_byte(dst, end, b);
}
+75
View File
@@ -0,0 +1,75 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void suboption_free(struct suboption_s *s)
{
struct suboption_target_s *t, *del;
for(t = s->target; t != NULL; del = t, t = t->next, free(del));
free(s);
}
int suboption_size(struct suboption_s *p)
{
int num = 0, num2;
struct suboption_target_s *m;
num += sizeofu64(p->id);
if(p->target) {
num += 1;
num2 = num;
for(m = p->target; m != NULL; m = m->next) {
num += sizeofu64(m->value);
}
num += sizeofu32(num - num2);
}
num += 1;
return num;
}
int suboption_serialize(struct suboption_s *s, char **dst, const char *maxdst)
{
int num = 0;
struct suboption_target_s *m;
char *start;
start = *dst;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, s->id);
if(s->target) {
write_byte(dst, maxdst, 26);
for(m = s->target; m != NULL; m = m->next) {
num += sizeofu64(m->value);
}
write_uint(dst, maxdst, num);
for(m = s->target; m != NULL; m = m->next) {
write_uint64(dst, maxdst, m->value);
}
}
return (*dst - start);
}
+73
View File
@@ -0,0 +1,73 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void tag_free(struct powerhistory_tag_s *t)
{
free(t);
}
struct powerhistory_tag_s *tag_deserialize(char **dst, const char *maxdst)
{
int n;
struct powerhistory_tag_s *t;
t = malloc(sizeof(*t));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
t->name = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 16) {
error();
}
t->value = read_uint64(dst, maxdst);
return t;
}
int tag_size(struct powerhistory_tag_s *tag)
{
int size = 0;
if(tag) {
size += 2;
size += sizeofu64(tag->name);
size += sizeofu64(tag->value);
}
return size;
}
int tag_serialize(struct powerhistory_tag_s *t, char **dst, const char *maxdst)
{
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, t->name);
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, t->value);
return 0;
}
+79
View File
@@ -0,0 +1,79 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void tagchange_free(struct powerhistory_tagchange_s *t)
{
free(t);
}
struct powerhistory_tagchange_s *tagchange_deserialize(char **dst, const char *maxdst)
{
int n;
struct powerhistory_tagchange_s *t;
t = malloc(sizeof(*t));
n = read_byte(dst, maxdst);
if(n != 8) {
error();
}
t->entity = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 16) {
error();
}
t->tag = read_uint64(dst, maxdst);
n = read_byte(dst, maxdst);
if(n != 24) {
error();
}
t->value = read_uint64(dst, maxdst);
return t;
}
int tagchange_serialize(struct powerhistory_tagchange_s *ent, char **dst, const char *maxdst)
{
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, ent->entity);
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, ent->tag);
write_byte(dst, maxdst, 24);
write_uint64(dst, maxdst, ent->value);
return 0;
}
int tagchange_size(struct powerhistory_tagchange_s *t)
{
int size = 0;
if(t) {
size += 3;
size += sizeofu64(t->entity);
size += sizeofu64(t->tag);
size += sizeofu64(t->value);
}
return size;
}
+51
View File
@@ -0,0 +1,51 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void turntimer_free(struct turntimer_s *t)
{
free(t);
}
int turntimer_serialize(void *ao, char **dst, const char *maxdst)
{
struct turntimer_s *s;
char *start;
start = *dst;
s = ao;
write_byte(dst, maxdst, 8);
write_uint64(dst, maxdst, s->seconds);
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, s->turn);
write_byte(dst, maxdst, 24);
write_byte(dst, maxdst, s->show);
return (*dst - start);
}
void turntimer_dump(struct turntimer_s *t)
{
hm_log(LOG_DEBUG, lg, "Turn timer dump:");
hm_log(LOG_DEBUG, lg, "\t\tseconds: %lld", t->seconds);
hm_log(LOG_DEBUG, lg, "\t\tturn: %lld", t->turn);
hm_log(LOG_DEBUG, lg, "\t\tshow: %d", t->show);
}
+124
View File
@@ -0,0 +1,124 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <proto.h>
void userui_free(struct userui_s *u)
{
mouseinfo_free(u->mouseinfo);
free(u);
}
void *userui_deserialize(char **dst, const char *maxdst)
{
int n, len;
struct userui_s *c;
c = malloc(sizeof(*c));
memset(c, 0, sizeof(*c));
while(*dst < maxdst) {
n = read_byte(dst, maxdst);
if(n == 10) {
len = read_uint(dst, maxdst);
c->mouseinfo = mouseinfo_deserialize(dst, *dst + len);
}
else if(n == 16) {
c->emote = read_uint64(dst, maxdst);
}
else if(n == 24) {
c->player_id = read_uint64(dst, maxdst);
}
}
return c;
}
int userui_serialize(void *ao, char **dst, const char *maxdst)
{
struct userui_s *s;
char *start;
int n;
start = *dst;
s = ao;
if(s->mouseinfo) {
write_byte(dst, maxdst, 10);
n = mouseinfo_size(s->mouseinfo);
write_uint(dst, maxdst, n);
mouseinfo_serialize(s->mouseinfo, dst, maxdst);
}
if(s->emote != -1) {
write_byte(dst, maxdst, 16);
write_uint64(dst, maxdst, s->emote);
}
if(s->player_id != -1) {
write_byte(dst, maxdst, 24);
write_uint64(dst, maxdst, s->player_id);
}
return (*dst - start);
}
int userui_size(struct userui_s *p)
{
int num = 0, n;
if(p->mouseinfo) {
num += 1;
n = mouseinfo_size(p->mouseinfo);
num += n + sizeofu32(n);
}
if(p->emote != 0) {
num += 1;
num += sizeofu64(p->emote);
}
if(p->player_id != 0) {
num += 1;
num += sizeofu64(p->player_id);
}
return num;
}
void userui_dump(struct userui_s *u)
{
if(u) {
if(u->mouseinfo) {
hm_log(LOG_DEBUG, lg, "arrow origin: %lld", u->mouseinfo->arroworigin);
hm_log(LOG_DEBUG, lg, "heldcard: %lld", u->mouseinfo->heldcard);
hm_log(LOG_DEBUG, lg, "overcard: %lld", u->mouseinfo->overcard);
hm_log(LOG_DEBUG, lg, "x: %lld", u->mouseinfo->x);
hm_log(LOG_DEBUG, lg, "y: %lld", u->mouseinfo->y);
}
if(u->emote != 0) {
hm_log(LOG_DEBUG, lg, "emote: %lld", u->emote);
}
if(u->player_id != 0) {
hm_log(LOG_DEBUG, lg, "player_id: %lld", u->player_id);
}
}
}
+95
View File
@@ -0,0 +1,95 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
static void result2(struct cbop_s *cbop)
{
if(cbop->lcb_error == LCB_SUCCESS) {
hm_log(LOG_DEBUG, lg, "Key [%.*s] updated successfully", (int )CBSR(nkey), (char *)CBSR(key));
} else {
hm_log(LOG_DEBUG, lg, "Key[%.*s] update failed, lcb error: %d", (int )CBSR(nkey), (char *)CBSR(key), cbop->lcb_error);
}
free(cbop);
}
static void result1(struct cbop_s *cbop)
{
if(cbop->lcb_error == LCB_SUCCESS) {
struct json_object *obj;
struct json_tokener *tok = json_tokener_new();
obj = json_tokener_parse_ex(tok, CBGR(bytes), CBGR(nbytes));
if(obj == NULL) {
hm_log(LOG_DEBUG, lg, "Parsing [%.*s] failed", (int)CBGR(nkey), (char *)CBGR(key));
free(cbop);
return;
}
json_object *count;
const char *type;
if((long long)cbop->data == 1) {
hm_log(LOG_DEBUG, lg, "Player [%.*s] set as winner", (int)CBGR(nkey), (char *)CBGR(key));
type = "w";
} else {
hm_log(LOG_DEBUG, lg, "Player [%.*s] set as loser", (int)CBGR(nkey), (char *)CBGR(key));
type = "l";
}
json_object_object_get_ex(obj, type, &count);
if(json_object_get_type(count) == json_type_int) {
int new_count = json_object_get_int(count) + 1;
json_object_object_add(obj, type, json_object_new_int(new_count));
const char *updated = json_object_to_json_string(obj);
char key[128];
snprintf(key, sizeof(key), "%.*s", (int )CBGR(nkey), (char *)CBGR(key));
memset(cbop, 0, sizeof(*cbop));
CBSQ_V0(couchbase_bucket_index("hbs"), LCB_SET, key, strlen(key), updated, strlen(updated), result2, 0, 0, 0, 0)
return;
}
free(cbop);
} else {
hm_log(LOG_DEBUG, lg, "Key [%.*s] lcb error %d", (int)CBGR(nkey), (char *)CBGR(key), cbop->lcb_error);
free(cbop);
}
}
void set_result(const char *k, long long r)
{
struct cbop_s *cbop;
char key[128];
cbop = malloc(sizeof(*cbop));
memset(cbop, 0, sizeof(*cbop));
cbop->data = (void *)r;
snprintf(key, sizeof(key), "u:%s", k);
hm_log(LOG_DEBUG, lg, "Updating player: [%s]", key);
CBGQ_V0(couchbase_bucket_index("hbs"), key, strlen(key), result1, 0, 0)
}
+73
View File
@@ -0,0 +1,73 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
enum ct_e {
C_HELD = 0,
C_ARROWORIGIN = 1,
};
static void set_card(struct conn_client_s *c, struct userui_s *u, enum ct_e type)
{
struct hs_holder_s *p;
p = c->data;
if(u && u->mouseinfo) {
if(type == C_HELD) {
if(u->mouseinfo->heldcard > 0) p->held_card = u->mouseinfo->heldcard;
else if(u->mouseinfo->overcard > 0) p->held_card = u->mouseinfo->overcard;
else p->held_card = 0;
hm_log(LOG_INFO, lg, "Setting heldcard %d based on held %lld over %lld", p->held_card, u->mouseinfo->heldcard, u->mouseinfo->overcard);
}
if(type == C_ARROWORIGIN) {
p->arroworigin = u->mouseinfo->arroworigin;
}
}
}
void user_ui(struct conn_client_s *c, struct userui_s *u)
{
struct packet_s *packet = NULL;
struct hs_holder_s *p;
char output[1024];
char *ptr;
p = c->data;
// update arroworigin
set_card(c, u, C_ARROWORIGIN);
// update held card
set_card(c, u, C_HELD);
// add player id
u->player_id = p->id;
add_packet(&packet, u, P_USERUI);
ptr = output;
int n = serialize(packet, &ptr, ptr + sizeof(output));
userui_dump(u);
packet_free(packet);
// let the opponent know what player is thinking
hm_send(p->opponent.client, output, n);
}
+134
View File
@@ -0,0 +1,134 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
void flags_diff(struct flags_s *old, struct flags_s *new,
struct flag_pr_s ***src_added, int *nsrc_added,
struct flag_pr_s ***src_removed, int *nsrc_removed,
struct card_s *card)
{
int i, j;
unsigned long long t;
for(i = 0; i < MAX_FLAGS_ARRAY; i++) {
for(j = 0; j < LL_BITS; j++) {
t = 1;
t <<= j;
#define FFILL(f_s, f_n, f_t)\
*f_s = realloc(*f_s, ++(*f_n) * sizeof(void *));\
(*f_s)[*f_n - 1] = malloc(sizeof(***f_s));\
(*f_s)[*f_n - 1]->flag = (i * LL_BITS + j);\
if(card->priority_override > 0) {\
(*f_s)[*f_n - 1]->priority = card->priority_override;\
} else {\
(*f_s)[*f_n - 1]->priority = flag_defs[(i * LL_BITS + j)];\
}\
(*f_s)[*f_n - 1]->type = f_t;\
(*f_s)[*f_n - 1]->parent_card = card;
if((old->nibble[i] & t) == t && (new->nibble[i] & t) == 0) {
FFILL(src_removed, nsrc_removed, F_REMOVED)
} else if((old->nibble[i] & t) == 0 && (new->nibble[i] & t) == t) {
FFILL(src_added, nsrc_added, F_ADDED)
}
}
}
}
int flags_copy(struct flags_s *dst, const struct flags_s *src)
{
int i, j;
unsigned long long t;
for(i = 0; i < MAX_FLAGS_ARRAY; i++) {
for(j = 0; j < LL_BITS; j++) {
t = 1;
t <<= j;
if((src->nibble[i] & t) == t) {
dst->nibble[i] |= t;
}
}
}
return 0;
}
int flag_get(struct flags_s *flags, int **f)
{
assert(flags);
if(flags == NULL) {
return -1;
}
int i, j, c = 0;
unsigned long long t;
for(i = 0; i < MAX_FLAGS_ARRAY; i++) {
for(j = 0; j < LL_BITS; j++) {
t = 1;
t <<= j;
if((flags->nibble[i] & t) == t) {
*f = realloc(*f, ++c * sizeof(int));
(*f)[c - 1] = i * LL_BITS + j;
}
}
}
return c;
}
int flag(struct flags_s *flags, enum flags_e src, enum flags_action_e action)
{
int index;
unsigned long long mod = 1;
assert(flags);
if(flags == NULL) {
return -1;
}
if(action == FLAG_DUMP && src == -1) {
int i, j;
unsigned long long t;
for(i = 0; i < MAX_FLAGS_ARRAY; i++) {
for(j = 0; j < LL_BITS; j++) {
t = 1;
t <<= j;
if((flags->nibble[i] & t) == t) {
hm_log(LOG_DEBUG, lg, "flag %p set: %d", flags, i * LL_BITS + j);
}
}
}
return 0;
}
if(src > (MAX_FLAGS_ARRAY * LL_BITS) || src < 0) return -1;
index = src / LL_BITS;
mod <<= (src % LL_BITS);
if(action == FLAG_SET) flags->nibble[index] |= mod;
else if(action == FLAG_UNSET) flags->nibble[index] &= ~(mod);
else if(action == FLAG_ISSET) {
if((flags->nibble[index] & mod) == mod) return 1;
else return 0;
} else return -1;
return 0;
}
+71
View File
@@ -0,0 +1,71 @@
/*
hm_gameserver - hearthmod gameserver
Copyright (C) 2016 Filip Pancik
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <game.h>
static void force_next_turn(struct ev_loop *loop, ev_timer *w, int revents)
{
struct conn_client_s *c;
struct hs_holder_s *p;
c = w->data;
p = c->data;
//c = p->opponent.client;
//p = c->data;
ev_timer_stop(loop, &p->game->force_next_turn);
next_turn(c, p);
}
static void countdown(struct ev_loop *loop, ev_timer *w, int revents)
{
struct conn_client_s *c;
struct hs_holder_s *p;
c = w->data;
p = c->data;
ev_timer_stop(loop, &p->game->turntimer);
net_send_turntimer(c, 15, p->game->turn, 1);
}
void register_turntimer(struct conn_client_s *c)
{
struct hs_holder_s *p;
#ifdef TURNOFF_TIMER
return;
#endif
p = c->data;
// stop first
ev_timer_stop(c->loop, &p->game->turntimer);
ev_timer_stop(c->loop, &p->game->force_next_turn);
p->game->turntimer.data = c;
p->game->force_next_turn.data = c;
ev_timer_init(&p->game->turntimer, countdown, 30, 0);
ev_timer_start(c->loop, &p->game->turntimer);
ev_timer_init(&p->game->force_next_turn, force_next_turn, 45, 0);
ev_timer_start(c->loop, &p->game->force_next_turn);
}