#define HOLDER_ROLE_UNUSED 0 #define HOLDER_ROLE_CREATURE 1 #define HOLDER_ROLE_EFFECT 2 #define HOLDER_ROLE_DISCARD 3 #define HOLDER_ROLE_GIBBED 4 #define HOLDER_ROLE_DECK 5 #define HOLDER_ROLE_AREA 6 #define PHASE_BEGIN 1 #define PHASE_DRAW 2 #define PHASE_MAIN 3 #define PHASE_BATTLE 4 #define PHASE_END 5 /datum/griffening_controller var/obj/griffening_central/field_center var/list/field_decoration = list() var/obj/griffening_area/area_indicator = null var/list/mobs_card_holder = list(list(null, null, null, null, null), list(null, null, null, null, null)) var/list/effects_card_holder = list(list(null, null, null, null, null), list(null, null, null, null, null)) var/list/deck_holder = list(null, null) var/list/discard_holder = list(null, null) var/list/gibbed_holder = list(null, null) var/list/area_holder = list(null, null) var/list/players = list(null, null) var/list/spectators = list() var/turn = 0 var/current_player = 0 var/static/next_game_id = 1 var/game_id = 0 var/bound_left var/bound_right var/bound_bottom var/bound_top var/phase = null var/phase_arguments = null New(var/obj/griffening_central/F) field_center = F proc/announce(message) var/formatted = "\[GRIFENING\]: [message]" for (var/mob/M in players) boutput(M, formatted) for (var/mob/M in spectators) boutput(M, formatted) proc/confirm(var/question, var/mob/M) if (!M) M = usr var/answer = alert(M, question,,"Yes","No") return answer == "Yes" proc/update_game_status(var/message) for (var/mob/M in players) boutput(M, "[message]") proc/action(var/obj/griffening_card_holder/holder, var/mob/M) if (holder.controller != src) return var/active_player = holder.player if (players[active_player] != M) boutput(M, "You cannot play cards here.") var/obj/item/playing_cards/card = M.equipped() var/datum/playing_card/griffening/C if (card) if (card.cards.len == 1) C = card.cards[1] for (var/datum/playing_card/Card in card.cards) if (!istype(Card, /datum/playing_card/griffening)) boutput(usr, "[Card.card_name] is not a card for this game.") return if (C.available_game_id != game_id) boutput(usr, "[Card.card_name] doesn't belong in this game.") return if (current_player != active_player) boutput(M, "Not your turn.") return switch (holder.role) if (HOLDER_ROLE_UNUSED) boutput(M, "You cannot play cards here.") return if (HOLDER_ROLE_DECK) if (card) boutput(M, "You cannot play cards here.") return if (phase == PHASE_DRAW) var/obj/item/playing_cards/stack = holder.card for (var/i = 1, i <= phase_arguments, i++) if (!stack || !stack.cards.len) boutput(M, "You lose.") // @todo return card = stack.draw_card(card, null, 1) if (card.loc != M) if (!M.put_in_hand(card)) card.loc = M.loc else boutput(M, "You cannot draw cards right now.") if (HOLDER_ROLE_GIBBED) boutput(M, "You cannot play cards here.") return if (HOLDER_ROLE_DISCARD) if (phase == PHASE_MAIN) if (!card) boutput(M, "You must take the cards you wish to discard into your active hand.") return if (confirm("Are you sure you want to discard [C ? C.card_name : "these [card.cards.len] cards"]?", M)) merge_into(holder, card, M) update_game_status("Player [active_player] discards [C ? "1 card" : "[card.cards.len] cards"].") else boutput(M, "You cannot discard cards right now.") return if (HOLDER_ROLE_CREATURE) if (phase == PHASE_MAIN) if (!card) if (!holder.card) boutput(M, "You must take the card you wish to play into your active hand.") return return if (holder.card) boutput(M, "There is already a creature here.") return if (!C) boutput(M, "You must take a single card into your active hand.") return if (!istype(C, /datum/playing_card/griffening/creature)) boutput(M, "You cannot play that here.") return if (!phase_arguments) boutput(M, "You cannot play any more creatures this turn.") return var/face_up = confirm("Would you like to play this creature face up?", M) var/datum/playing_card/griffening/creature/Cr = C if (!Cr.can_play(src, face_up, active_player)) boutput(M, "You cannot play this creature.") return if (!Cr.before_play(src, face_up, active_player, M)) return phase_arguments-- holder.card = card M.u_equip(card) card.loc = holder update_game_status("Player [active_player] plays [face_up ? "creature [card.card_name]" : "a creature face down"].") show_informational() proc/merge_into(var/obj/griffening_card_holder/holder, var/obj/item/playing_cards/card, var/mob/M) if (M) M.u_equip(card) var/obj/item/playing_cards/merge_deck = holder.card if (!merge_deck) holder.card = card merge_deck = holder.card card.set_loc(holder) else merge_deck.add_cards(card) proc/register_player(var/playerid, var/mob/M, var/obj/item/playing_cards/deck) if (players[playerid]) return players[playerid] = M M.eye = area_indicator var/obj/griffening_card_holder/deck_area = deck_holder[playerid] deck_area.card = deck deck.loc = deck_area if (!game_id) game_id = next_game_id next_game_id++ for (var/datum/playing_card/griffening/Card in deck.cards) Card.available_game_id = game_id deck_area.update_overlays() if (players[1] && players[2]) announce("Let the games begin!") current_player = 1 turn = 1 proc/in_playing_area(var/mob/M) if (M.loc && M.loc.y == bound_bottom && M.loc.x >= bound_left && M.loc.x <= bound_right) return 1 if (M.loc && M.loc.y == bound_top && M.loc.x >= bound_left && M.loc.x <= bound_right) return 2 return 0 proc/retrieve_card_type_from_player_deck(var/card_type, var/active_player, var/forced = 0) var/mob/M = players[active_player] var/obj/griffening_card_holder/holder = deck_holder[active_player] var/obj/item/playing_cards/deck = holder.card if (!deck) return null var/list/matches = list() for (var/datum/playing_card/griffening/C in deck.cards) if (istype(C, card_type)) matches[C.card_name] = C if (matches.len == 0) var/datum/playing_card/griffening/expected = new card_type() var/cname = expected.card_name qdel(expected) boutput(M, "You don't have the appropriate card ([cname]) in your deck.") return null var/datum/playing_card/griffening/chosen = null if (matches.len == 1) if (!forced) if (!confirm("Take [matches[1]] into your hand from your deck?", M)) return null chosen = matches[matches[1]] else var/chosen_name if (forced) chosen_name = input("Which card would you like to draw?", "Pick a card", null) in matches else chosen_name = input("Which card would you like to draw?", "Pick a card", null) as null|anything in matches if (!chosen_name) return null chosen = matches[chosen_name] var/obj/item/playing_cards/E = M.equipped() if (!istype(E)) M.drop_item() E = new() if (!M.put_in_hand(E)) E.set_loc(M.loc) if (!istype(E.cards, /list)) E.cards = list() E.cards += chosen deck.cards -= E E.update_cards() deck.update_cards() proc/get_face_up_area_card() var/obj/griffening_card_holder/holder = area_holder[1] if (holder.card && holder.card.face_up) return holder.card.cards[1] holder = area_holder[2] if (holder.card && holder.card.face_up) return holder.card.cards[2] proc/player_has_card(var/card_type, var/active_player) var/checked_player = active_player if (ispath(card_type, /datum/playing_card/griffening/effect)) for (var/obj/griffening_card_holder/holder in effects_card_holder[checked_player]) if (holder.card) var/datum/Card = holder.card.cards[1] if (Card.type == card_type) return 1 else if (ispath(card_type, /datum/playing_card/griffening/area)) var/obj/griffening_card_holder/holder = area_holder[checked_player] if (holder.card) var/datum/Card = holder.card.cards[1] return Card.type == card_type else for (var/obj/griffening_card_holder/holder in mobs_card_holder[checked_player]) if (holder.card) var/datum/Card = holder.card.cards[1] if (Card.type == card_type) return 1 return 0 proc/player_has_card_face_up(var/card_type, var/active_player) var/checked_player = active_player if (ispath(card_type, /datum/playing_card/griffening/effect)) for (var/obj/griffening_card_holder/holder in effects_card_holder[checked_player]) if (holder.card && holder.card.face_up) var/datum/Card = holder.card.cards[1] if (Card.type == card_type) return 1 else if (ispath(card_type, /datum/playing_card/griffening/area)) var/obj/griffening_card_holder/holder = area_holder[checked_player] if (holder.card && holder.card.face_up) var/datum/Card = holder.card.cards[1] return Card.type == card_type else for (var/obj/griffening_card_holder/holder in mobs_card_holder[checked_player]) if (holder.card && holder.card.face_up) var/datum/Card = holder.card.cards[1] if (Card.type == card_type) return 1 return 0 proc/opponent_has_card_face_up(var/card_type, var/active_player) return player_has_card_face_up(card_type, active_player == 1 ? 2 : 1) proc/player_creatures_with_attribute_face_up(var/card_attribute, var/active_player) var/list/ret = list() var/list/mobs_card_holder_player = mobs_card_holder[active_player] for (var/i = 1, i <= 5, i++) var/obj/griffening_card_holder/holder = mobs_card_holder_player[i] if (holder.card && holder.card.face_up) var/datum/playing_card/griffening/creature/Card = holder.card.cards[1] if (Card.attributes & card_attribute == card_attribute) ret += Card ret[Card] = "[active_player]C[i]" return ret proc/opponent_creatures_with_attribute_face_up(var/card_attribute, var/active_player) return player_creatures_with_attribute_face_up(card_attribute, active_player == 1 ? 2 : 1) proc/player_discarded_creatures_with_attribute(var/card_attribute, var/active_player) var/list/ret = list() var/obj/griffening_card_holder/holder = discard_holder[active_player] var/obj/item/playing_cards/PC = holder.card if (!PC) return ret for (var/i = 1, i <= PC.cards.len, i++) var/datum/playing_card/griffening/creature/Card = PC.cards[i] if (!istype(Card)) continue if (Card.attributes & card_attribute == card_attribute) ret += Card ret[Card] = "[active_player]D[i]" return ret proc/opponent_discarded_creatures_with_attribute(var/card_attribute, var/active_player) return player_discarded_creatures_with_attribute(card_attribute, active_player == 1 ? 2 : 1) proc/player_effects_face_up(var/active_player) var/list/ret = list() var/list/effects_card_holder_player = effects_card_holder[active_player] for (var/i = 1, i <= 5, i++) var/obj/griffening_card_holder/holder = effects_card_holder_player[i] if (holder.card && holder.card.face_up) var/datum/playing_card/griffening/effect/Card = holder.card.cards[1] if (!(Card.card_type & GRIFFENING_TYPE_EQUIP)) ret += Card ret[Card] = "[active_player]E[i]" return ret proc/opponent_effects_face_up(var/active_player) return player_effects_face_up(active_player == 1 ? 2 : 1) proc/player_equipment_face_up(var/active_player) var/list/ret = list() var/list/effects_card_holder_player = effects_card_holder[active_player] for (var/i = 1, i <= 5, i++) var/obj/griffening_card_holder/holder = effects_card_holder_player[i] if (holder.card && holder.card.face_up) var/datum/playing_card/griffening/effect/Card = holder.card.cards[1] if (Card.card_type & GRIFFENING_TYPE_EQUIP) ret += Card ret[Card] = "[active_player]E[i]" return ret proc/opponent_equipment_face_up(var/active_player) return player_equipment_face_up(active_player == 1 ? 2 : 1) proc/player_effects_and_equipment(var/active_player) var/list/ret = list() var/list/effects_card_holder_player = effects_card_holder[active_player] for (var/i = 1, i <= 5, i++) var/obj/griffening_card_holder/holder = effects_card_holder_player[i] if (holder.card) var/datum/playing_card/griffening/effect/Card = holder.card.cards[1] ret += Card ret[Card] = "[active_player]E[i]" return ret proc/opponent_effects_and_equipment(var/active_player) return player_effects_and_equipment(active_player == 1 ? 2 : 1) proc/player_has_attributed_creature_face_up(var/card_attribute, var/active_player) var/list/creatures = player_creatures_with_attribute_face_up(card_attribute, active_player) return creatures.len > 0 proc/opponent_has_attributed_creature_face_up(var/card_attribute, var/active_player) return player_has_attributed_creature_face_up(card_attribute, active_player == 1 ? 2 : 1) proc/ask_player(var/list/choices, var/active_player, var/question = "Choose an option", var/timeout = 30) var/mob/asked = players[active_player] if (!istype(asked)) return null if (!asked.client) return null var/answer = input(asked, question, question, null) as null|anything in choices return answer proc/locate_card(var/designation) var/playerid = text2num(chs(designation, 1)) if (!playerid) return null var/array = chs(designation, 2) switch (array) if ("C") var/list/choice = mobs_card_holder[playerid] var/cardid = text2num(chs(designation, 3)) var/obj/griffening_card_holder/holder = choice[cardid] if (!holder.card) return null var/obj/item/playing_cards/PC = holder.card return PC.cards[1] if ("E") var/list/choice = effects_card_holder[playerid] var/cardid = text2num(chs(designation, 3)) var/obj/griffening_card_holder/holder = choice[cardid] if (!holder.card) return null var/obj/item/playing_cards/PC = holder.card return PC.cards[1] if ("A") var/obj/griffening_card_holder/holder = area_holder[playerid] if (!holder.card) return null var/obj/item/playing_cards/PC = holder.card return PC.cards[1] if ("D") var/obj/griffening_card_holder/holder = discard_holder[playerid] if (holder.card) return null var/cardid = text2num(copytext(designation, 3)) var/obj/item/playing_cards/PC = holder.card if (PC.cards.len <= cardid) return PC.cards[cardid] return null if ("G") var/obj/griffening_card_holder/holder = gibbed_holder[playerid] if (holder.card) return null var/cardid = text2num(copytext(designation, 3)) var/obj/item/playing_cards/PC = holder.card if (PC.cards.len <= cardid) return PC.cards[cardid] return null if ("K") var/obj/griffening_card_holder/holder = deck_holder[playerid] if (holder.card) return null var/cardid = text2num(copytext(designation, 3)) var/obj/item/playing_cards/PC = holder.card if (PC.cards.len <= cardid) return PC.cards[cardid] return null return null proc/spawn_field() if (!field_center) return var/turf/T = get_turf(field_center) var/x = T.x var/y = T.y var/z = T.z bound_bottom = y - 6 bound_top = y + 6 bound_left = x - 3 bound_right = x + 3 // we need a range(7) area to be free if (x + 7 >= world.maxx || y + 7 >= world.maxy || y - 7 <= 1 || x - 7 <= 1) return for (var/turf/Q in block(locate(x - 3, y - 6, z), locate(x + 3, y + 6, z))) var/turf/R = new /turf/unsimulated/floor/griffening(Q) field_decoration += R if (R.x == x - 3 && !(abs(R.y - y) % 3)) var/obj/LT = new /obj/machinery/light(R) LT.dir = 8 if (R.x == x + 3 && !(abs(R.y - y) % 3)) var/obj/LT = new /obj/machinery/light(R) LT.dir = 4 if (R.y == y - 5 || R.y == y + 4 || R.y == y + 5 || R.y == y - 4) var/obj/griffening_card_holder/GCH = new /obj/griffening_card_holder(R, src) if (R.y > y) GCH.player = 2 if (R.y == y - 5 || R.y == y + 4) if (R.x == x - 3) GCH.icon_state = "card_holder_bottom_left" else if (R.x == x + 3) GCH.icon_state = "card_holder_bottom_right" else GCH.icon_state = "card_holder_bottom" GCH.card_offset = 8 else if (R.x == x - 3) GCH.icon_state = "card_holder_top_left" else if (R.x == x + 3) GCH.icon_state = "card_holder_top_right" else GCH.icon_state = "card_holder_top" GCH.card_offset = -8 if (R.y == y - 5 && R.x == x - 3) GCH.name = "Deck" GCH.role = HOLDER_ROLE_DECK deck_holder[1] = GCH else if (R.y == y + 5 && R.x == x - 3) GCH.name = "Deck" GCH.role = HOLDER_ROLE_DECK deck_holder[2] = GCH else if (R.y == y - 4 && R.x == x - 3) GCH.name = "Discard" GCH.role = HOLDER_ROLE_DISCARD discard_holder[1] = GCH else if (R.y == y + 4 && R.x == x - 3) GCH.name = "Discard" GCH.role = HOLDER_ROLE_DISCARD discard_holder[2] = GCH else if (R.y == y - 4 && R.x == x + 3) GCH.name = "Gibbed" GCH.role = HOLDER_ROLE_GIBBED gibbed_holder[1] = GCH else if (R.y == y + 4 && R.x == x + 3) GCH.name = "Gibbed" GCH.role = HOLDER_ROLE_GIBBED gibbed_holder[2] = GCH else if (R.y == y - 5 && R.x == x + 3) GCH.name = "Area" GCH.role = HOLDER_ROLE_AREA area_holder[1] = GCH else if (R.y == y + 5 && R.x == x + 3) GCH.name = "Area" GCH.role = HOLDER_ROLE_AREA area_holder[2] = GCH else if (R.y == y - 5 || R.y == y - 4 || R.y == y + 4 || R.y == y + 5) var/id = R.x - (x - 3) if (R.y == y - 5) GCH.name = "Effect/Equip Slot #[id]" GCH.role = HOLDER_ROLE_EFFECT var/list/p1_effects_card_holder = effects_card_holder[1] p1_effects_card_holder[id] = GCH GCH.position_hologram(x, R.y - 3) else if (R.y == y + 5) GCH.name = "Effect/Equip Slot #[id]" GCH.role = HOLDER_ROLE_EFFECT var/list/p2_effects_card_holder = effects_card_holder[2] p2_effects_card_holder[id] = GCH GCH.position_hologram(x, R.y + 3) else if (R.y == y - 4) GCH.name = "Creature Slot #[id]" GCH.role = HOLDER_ROLE_CREATURE var/list/p1_mobs_card_holder = mobs_card_holder[1] p1_mobs_card_holder[id] = GCH GCH.position_hologram(x, R.y - 2) else if (R.y == y + 4) GCH.name = "Creature Slot #[id]" GCH.role = HOLDER_ROLE_CREATURE var/list/p2_mobs_card_holder = mobs_card_holder[2] p2_mobs_card_holder[id] = GCH GCH.position_hologram(x, R.y + 2) for (var/turf/Q in block(locate(x - 4, y - 6, z), locate(x - 4, y + 6, z))) var/turf/R = new /turf/unsimulated/wall/griffening(Q) field_decoration += R for (var/turf/Q in block(locate(x + 4, y - 6, z), locate(x + 4, y + 6, z))) var/turf/R = new /turf/unsimulated/wall/griffening(Q) field_decoration += R area_indicator = new /obj/griffening_area(T, src) field_decoration += area_indicator #define addinfo(x) p1 += x; p2 += x; sp += x #define addinfo1(x,y) p1 += x; p2 += y; sp += y #define addinfo2(x,y) p1 += y; p2 += x; sp += y proc/show_informational() var/p1 = "" var/p2 = "" var/sp = "" var/stylesheet = {"table { width: 100%; } td, th { width: 50%; } .attention: { border: 2px solid red; } .question { width: 100%; text-align: center; margin-top: 5px; } .answer-wrapper { width: 100%; margin-top: 20px; margin-bottom: 5px; text-align: center; } .answer { display: inline-block; margin-right: 5px; margin-left: 5px; }"} addinfo("
| Player 1 | Player 2 |
|---|---|
| Creatures (left to right) ") var/list/card_holders = mobs_card_holder[1] for (var/i = 1, i <= 5, i++) addinfo("Creature #[i]: ") var/obj/griffening_card_holder/holder = card_holders[i] if (holder.card) var/obj/item/playing_cards/PC = holder.card var/datum/playing_card/griffening/C = PC.cards[1] if (PC.face_up) addinfo("[C.card_name] [C.card_data] ") else addinfo1("[C.card_name] [C.card_data] \[FACE DOWN\] ", "Face down card") else addinfo("<none> ") addinfo(" Effects (left to right) ") card_holders = effects_card_holder[1] for (var/i = 1, i <= 5, i++) addinfo("Effect #[i]: ") var/obj/griffening_card_holder/holder = card_holders[i] if (holder.card) var/obj/item/playing_cards/PC = holder.card var/datum/playing_card/griffening/C = PC.cards[1] if (PC.face_up) addinfo("[C.card_name] [C.card_data] ") else addinfo1("[C.card_name] [C.card_data] \[FACE DOWN\] ", "Face down card") else addinfo("<none> ") var/obj/griffening_card_holder/D = discard_holder[1] var/obj/item/playing_cards/discard = D.card var/list/discards = list() if (discard) discards = discard.cards addinfo(" Discard pile: [discards.len] cards ") p1 += "
" D = gibbed_holder[1] discard = D.card discards = list() if (discard) discards = discard.cards addinfo(" Gibbed pile: [discards.len] cards ") p1 += "
| Creatures (left to right) ") card_holders = mobs_card_holder[2] for (var/i = 1, i <= 5, i++) addinfo("Creature #[i]: ") var/obj/griffening_card_holder/holder = card_holders[i] if (holder.card) var/obj/item/playing_cards/PC = holder.card var/datum/playing_card/griffening/C = PC.cards[1] if (PC.face_up) addinfo("[C.card_name] [C.card_data] ") else addinfo2("[C.card_name] [C.card_data] \[FACE DOWN\] ", "Face down card") else addinfo("<none> ") addinfo(" Effects (left to right) ") card_holders = effects_card_holder[2] for (var/i = 1, i <= 5, i++) addinfo("Effect #[i]: ") var/obj/griffening_card_holder/holder = card_holders[i] if (holder.card) var/obj/item/playing_cards/PC = holder.card var/datum/playing_card/griffening/C = PC.cards[1] if (PC.face_up) addinfo("[C.card_name] [C.card_data] ") else addinfo2("[C.card_name] [C.card_data] \[FACE DOWN\] ", "Face down card") else addinfo("<none> ") D = discard_holder[2] discard = D.card discards = list() if (discard) discards = discard.cards addinfo(" Discard pile: [discards.len] cards ") p2 += "
" D = gibbed_holder[2] discard = D.card discards = list() if (discard) discards = discard.cards addinfo(" Gibbed pile: [discards.len] cards ") p2 += "
|