diff --git a/modules/vadentis-actor-sheet.js b/modules/vadentis-actor-sheet.js
new file mode 100644
index 0000000..8ca9c42
--- /dev/null
+++ b/modules/vadentis-actor-sheet.js
@@ -0,0 +1,155 @@
+/**
+ * Extend the basic ActorSheet with some very simple modifications
+ * @extends {ActorSheet}
+ */
+
+import { VadentisUtility } from "./vadentis-utility.js";
+
+/* -------------------------------------------- */
+export class VadentisActorSheet extends ActorSheet {
+
+ /** @override */
+ static get defaultOptions() {
+ return mergeObject(super.defaultOptions, {
+ classes: ["sos", "sheet", "actor"],
+ template: "systems/foundryvtt-vadentis/templates/actor-sheet.html",
+ width: 640,
+ height: 720,
+ tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "stats" }],
+ dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
+ editStatSkill: false
+ });
+ }
+
+ /* -------------------------------------------- */
+ getData() {
+ let data = super.getData();
+
+ this.actor.checkDeck();
+
+
+ return data;
+ }
+
+ /* -------------------------------------------- */
+ /** @override */
+ activateListeners(html) {
+ super.activateListeners(html);
+
+ //HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
+
+ // Everything below here is only needed if the sheet is editable
+ if (!this.options.editable) return;
+
+ // Update Inventory Item
+ html.find('.item-edit').click(ev => {
+ const li = $(ev.currentTarget).parents(".item");
+ const item = this.actor.getOwnedItem(li.data("item-id"));
+ item.sheet.render(true);
+ });
+ html.find('.item-equip').click(ev => {
+ const li = $(ev.currentTarget).parents(".item");
+ const item = this.actor.equipObject( li.data("item-id") );
+ this.render(true);
+ });
+ html.find('.item-worn').click(ev => {
+ const li = $(ev.currentTarget).parents(".item");
+ const item = this.actor.wornObject( li.data("item-id") );
+ this.render(true);
+ });
+
+ // Delete Inventory Item
+ html.find('.item-delete').click(ev => {
+ const li = $(ev.currentTarget).parents(".item");
+ SoSUtility.confirmDelete(this, li);
+ });
+
+ html.find('.stat-label a').click((event) => {
+ let statName = event.currentTarget.attributes.name.value;
+ this.actor.rollStat(statName);
+ });
+ html.find('.skill-label a').click((event) => {
+ const li = $(event.currentTarget).parents(".item");
+ const skill = this.actor.getOwnedItem(li.data("item-id"));
+ this.actor.rollSkill(skill);
+ });
+ html.find('.weapon-label a').click((event) => {
+ const li = $(event.currentTarget).parents(".item");
+ const weapon = this.actor.getOwnedItem(li.data("item-id"));
+ this.actor.rollWeapon(weapon);
+ });
+ html.find('.skill-value').change((event) => {
+ let skillName = event.currentTarget.attributes.skillname.value;
+ //console.log("Competence changed :", skillName);
+ this.actor.updateSkill(skillName, parseInt(event.target.value));
+ });
+ html.find('.skill-xp').change((event) => {
+ let skillName = event.currentTarget.attributes.skillname.value;
+ //console.log("Competence changed :", skillName);
+ this.actor.updateSkillExperience(skillName, parseInt(event.target.value));
+ });
+ html.find('.wound-value').change((event) => {
+ let woundName = event.currentTarget.attributes.woundname.value;
+ //console.log("Competence changed :", skillName);
+ this.actor.updateWound(woundName, parseInt(event.target.value));
+ });
+ html.find('.reset-deck-full').click((event) => {
+ this.actor.resetDeckFull();
+ this.render(true);
+ });
+ html.find('.draw-new-edge').click((event) => {
+ this.actor.drawNewEdge();
+ this.render(true);
+ });
+ html.find('.reset-deck').click((event) => {
+ this.actor.resetDeck();
+ this.render(true);
+ });
+ html.find('.discard-card').click((event) => {
+ const cardName = $(event.currentTarget).data("discard");
+ this.actor.discardEdge( cardName );
+ });
+ html.find('.consequence-severity').click((event) => {
+ const li = $(event.currentTarget).parents(".item");
+ const item = this.actor.getOwnedItem(li.data("item-id"));
+ let severity = $(event.currentTarget).val();
+ this.actor.updateOwnedItem( { _id: item._id, 'data.severity': severity});
+ this.render(true);
+ });
+ html.find('.lock-unlock-sheet').click((event) => {
+ this.options.editStatSkill = !this.options.editStatSkill;
+ this.render(true);
+ });
+ html.find('.item-link a').click((event) => {
+ const itemId = $(event.currentTarget).data("item-id");
+ const item = this.actor.getOwnedItem(itemId);
+ item.sheet.render(true);
+ });
+
+ }
+
+ /* -------------------------------------------- */
+ async _onDrop(event) {
+ let toSuper = await SoSUtility.processItemDropEvent(this, event);
+ if ( toSuper) {
+ super._onDrop(event);
+ }
+ }
+
+ /* -------------------------------------------- */
+ /** @override */
+ setPosition(options = {}) {
+ const position = super.setPosition(options);
+ const sheetBody = this.element.find(".sheet-body");
+ const bodyHeight = position.height - 192;
+ sheetBody.css("height", bodyHeight);
+ return position;
+ }
+
+ /* -------------------------------------------- */
+ /** @override */
+ _updateObject(event, formData) {
+ // Update the Actor
+ return this.object.update(formData);
+ }
+}
diff --git a/modules/vadentis-actor.js b/modules/vadentis-actor.js
new file mode 100644
index 0000000..0d92442
--- /dev/null
+++ b/modules/vadentis-actor.js
@@ -0,0 +1,52 @@
+import { VadentisUtility } from "./vadentis-utility.js";
+
+
+/* -------------------------------------------- */
+/**
+ * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system.
+ * @extends {Actor}
+ */
+export class VadentisActor extends Actor {
+
+ /* -------------------------------------------- */
+ /**
+ * Override the create() function to provide additional SoS functionality.
+ *
+ * This overrided create() function adds initial items
+ * Namely: Basic skills, money,
+ *
+ * @param {Object} data Barebones actor data which this function adds onto.
+ * @param {Object} options (Unused) Additional options which customize the creation workflow.
+ *
+ */
+
+ static async create(data, options) {
+
+ // Case of compendium global import
+ if (data instanceof Array) {
+ return super.create(data, options);
+ }
+ // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic
+ if (data.items) {
+ let actor = super.create(data, options);
+ return actor;
+ }
+
+ data.items = [];
+ let compendiumName = "foundryvtt-vadentis.competences";
+ if ( compendiumName ) {
+ let skills = await SoSUtility.loadCompendium(compendiumName);
+ data.items = data.items.concat( skills );
+ }
+
+ return super.create(data, options);
+ }
+
+ /* -------------------------------------------- */
+ async prepareData() {
+ super.prepareData();
+
+ }
+
+
+}
diff --git a/modules/vadentis-combat.js b/modules/vadentis-combat.js
new file mode 100644
index 0000000..b24d9ef
--- /dev/null
+++ b/modules/vadentis-combat.js
@@ -0,0 +1,189 @@
+import { VadentisUtility } from "./vadentis-utility.js";
+
+/* -------------------------------------------- */
+export class VadentisCombat extends Combat {
+
+ /* -------------------------------------------- */
+ requestActions() {
+ if ( game.user.isGM && !this.actionsRequested) {
+ console.log("REQUEST ACTIONS !!!");
+ this.actionsRequested = true;
+ this.phaseSetup = {}; // Reset each new round/update
+ for( let combatant of this.combatants) {
+ this.setInitiative(combatant._id, -1 ); // Reset init
+ let uniq = randomID(16);
+ const name = combatant.actor ? combatant.actor.data.name : combatant.name;
+ if ( combatant.players[0]) {
+ // A player controls this combatant -> message !
+ ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
+ Declare actions`,
+ whisper: [ combatant.players[0].data._id] } );
+ } else {
+ ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
+ Declare actions`,
+ whisper: [ ChatMessage.getWhisperRecipients("GM") ] } );
+ }
+ }
+ }
+ }
+
+ /* -------------------------------------------- */
+ async nextRound() {
+ this.actionsRequested = false;
+ super.nextRound();
+ }
+
+ /* -------------------------------------------- */
+ gotoNextTurn() {
+ this.phaseNumber -= 1;
+ if ( this.phaseNumber <= 0) {
+ this.applyConsequences();
+ this.nextRound(); // Auto-switch to next round
+ } else {
+ this.nextTurn();
+ }
+ }
+
+ /* -------------------------------------------- */
+ async nextTurn() {
+ console.log("Going to phase !", this.phaseNumber );
+ // Get all actions for this phase
+ let phaseIndex = this.phaseNumber - 1;
+ let actionList = [];
+ let actionMsg = `