Initial commit
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);\
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
*/
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user