diff --git a/rpg-docs/Model/Character/Spells.js b/rpg-docs/Model/Character/Spells.js
index 58f21cd2..2b5876b2 100644
--- a/rpg-docs/Model/Character/Spells.js
+++ b/rpg-docs/Model/Character/Spells.js
@@ -83,3 +83,170 @@ Spells.after.update(function (userId, spell, fieldNames) {
Spells.allow(CHARACTER_SUBSCHEMA_ALLOW);
Spells.deny(CHARACTER_SUBSCHEMA_DENY);
+
+
+
+
+var checkMovePermission = function(spellId, parent, destinationOnly) {
+ var spell = Spells.findOne(spellId);
+ if (!spell)
+ throw new Meteor.Error("No such spell",
+ "An spell could not be found to move");
+ //handle permissions
+ var permission;
+
+ if (!destinationOnly) { //if we're not modifying the origin, only the destination
+ permission = Meteor.call("canWriteCharacter", spell.charId);
+ if (!permission){
+ throw new Meteor.Error("Access denied",
+ "Not permitted to move spells from this character");
+ }
+ }
+ if (parent.collection === "Characters"){
+ permission = Meteor.call("canWriteCharacter", parent.id);
+ if (!permission){
+ throw new Meteor.Error("Access denied",
+ "Not permitted to move spells to this character");
+ }
+ } else {
+ var parentCollectionObject = global[parent.collection];
+ var parentObject = null;
+ if (parentCollectionObject)
+ parentObject = parentCollectionObject.findOne(
+ parent.id, {fields: {_id: 1, charId: 1}}
+ );
+ if (!parentObject) throw new Meteor.Error(
+ "Invalid parent",
+ "The destination parent " + parent.id +
+ " does not exist in the collection " + parent.collection
+ );
+ if (parentObject.charId){
+ permission = Meteor.call("canWriteCharacter", parentObject.charId);
+ if (!permission){
+ throw new Meteor.Error("Access denied",
+ "Not permitted to move spells to this character");
+ }
+ }
+ }
+};
+
+var moveSpell = function(spellId, targetCollection, targetId) {
+ var spell = Spells.findOne(spellId);
+ if (!spell) return;
+ targetCollection = targetCollection || spell.parent.collection;
+ targetId = targetId || spell.parent.id;
+
+ if (Meteor.isServer) {
+ checkMovePermission(spellId, {collection: targetCollection, id: targetId}, false);
+ }
+
+ if (targetCollection == "Characters") { //then we are copying the spell to a different character.
+ targetList = SpellLists.findOne({"charId": targetId});
+ targetListId = targetList && targetList._id;
+ if (!targetListId) {
+ targetListId = SpellLists.insert({ //create a spell list if we don't already have one
+ name: "New SpellList",
+ charId: targetId,
+ saveDC: "8 + intelligenceMod + proficiencyBonus",
+ attackBonus: "intelligenceMod + proficiencyBonus",
+ });
+ }
+
+ Spells.update(
+ spellId,
+ {$set: {
+ charId: targetId,
+ "parent.collection": "SpellLists",
+ "parent.id": targetListId,
+ }}
+ );
+ }
+ else { //we are moving the spell within the same character
+ //update the spell provided the update will actually change something
+ if (
+ spell.parent.collection !== targetCollection ||
+ spell.parent.id !== targetId
+ ){
+ Spells.update(
+ spellId,
+ {$set: {
+ "parent.collection": targetCollection,
+ "parent.id": targetId,
+ }}
+ );
+ }
+ }
+};
+
+var copySpell = function(spellId, targetCollection, targetId) {
+ var spell = Spells.findOne(spellId);
+ if (!spell) return;
+ targetCollection = targetCollection || spell.parent.collection;
+ targetId = targetId || spell.parent.id;
+
+ if (Meteor.isServer) {
+ checkMovePermission(spellId, {collection: targetCollection, id: targetId}, true); //we're only reading from the source character
+ }
+
+
+ if (targetCollection == "Characters") { //then we are copying the spell to a different character.
+ targetList = SpellLists.findOne({"charId": targetId});
+ targetListId = targetList && targetList._id;
+ if (!targetListId) {
+ targetListId = SpellLists.insert({ //create a spell list if we don't already have one
+ name: "New SpellList",
+ charId: targetId,
+ saveDC: "8 + intelligenceMod + proficiencyBonus",
+ attackBonus: "intelligenceMod + proficiencyBonus",
+ });
+ }
+
+ newSpell = _.clone(spell);
+ delete newSpell._id;
+ newSpellId = Spells.insert(newSpell); //add a new copy of the spell
+ Spells.update(
+ newSpellId,
+ {$set: {
+ charId: targetId,
+ "parent.collection": "SpellLists",
+ "parent.id": targetListId,
+ }}
+ );
+ }
+ else { //else we are copying the spell within the same character
+ newSpell = _.clone(spell);
+ delete newSpell._id;
+ newSpellId = Spells.insert(newSpell); //add a new copy of the spell
+ Spells.update(
+ newSpellId,
+ {$set: {
+ "parent.collection": targetCollection,
+ "parent.id": targetId,
+ }}
+ );
+ }
+};
+
+
+Meteor.methods({
+ moveSpellToList: function(spellId, spellListId) {
+ check(spellId, String);
+ check(spellListId, String);
+ moveSpell(spellId, "SpellLists", spellListId);
+ },
+ copySpellToList: function(spellId, spellListId) {
+ check(spellId, String);
+ check(spellListId, String);
+ copySpell(spellId, "SpellLists", spellListId);
+ },
+ moveSpellToCharacter: function(spellId, charId) {
+ check(spellId, String);
+ check(charId, String);
+ moveSpell(spellId, "Characters", charId);
+ },
+ copySpellToCharacter: function(spellId, charId) {
+ check(spellId, String);
+ check(charId, String);
+ copySpell(spellId, "Characters", charId);
+ },
+});
\ No newline at end of file
diff --git a/rpg-docs/client/views/character/characterSettings/unshareCharacterConfirmation.html b/rpg-docs/client/views/character/characterSettings/unshareCharacterConfirmation.html
new file mode 100644
index 00000000..c5c689d8
--- /dev/null
+++ b/rpg-docs/client/views/character/characterSettings/unshareCharacterConfirmation.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+ Unshare Character
+
+
+
+
+
+
+
diff --git a/rpg-docs/client/views/character/characterSettings/unshareCharacterConfirmation.js b/rpg-docs/client/views/character/characterSettings/unshareCharacterConfirmation.js
new file mode 100644
index 00000000..de240ee3
--- /dev/null
+++ b/rpg-docs/client/views/character/characterSettings/unshareCharacterConfirmation.js
@@ -0,0 +1,31 @@
+Template.unshareCharacterConfirmation.onCreated(function() {
+ this.canUnshare = new ReactiveVar(false);
+});
+
+Template.unshareCharacterConfirmation.helpers({
+ cantUnshare: function() {
+ return !Template.instance().canUnshare.get();
+ },
+ getStyle: function() {
+ if (Template.instance().canUnshare.get()) {
+ return "background: #d23f31; color: white;";
+ }
+ }
+});
+
+Template.unshareCharacterConfirmation.events({
+ "change #nameInput, input #nameInput": function(event, instance) {
+ var can = instance.find("#nameInput").value === this.name;
+ instance.canUnshare.set(can);
+ },
+ "click #unshareButton": function(event, instance) {
+ if (instance.find("#nameInput").value === this.name) {
+ setTimeout(popDialogStack, 100); //weird things happen without the delay.
+ Router.go("/characterList");
+ Meteor.call("removeMeFromReaders", this._id);
+ }
+ },
+ "click .cancelButton": function(event, instance){
+ popDialogStack();
+ },
+});
diff --git a/rpg-docs/client/views/character/characterSheet.html b/rpg-docs/client/views/character/characterSheet.html
index cc6f11e3..9fd7a65f 100644
--- a/rpg-docs/client/views/character/characterSheet.html
+++ b/rpg-docs/client/views/character/characterSheet.html
@@ -30,6 +30,16 @@
+ {{else}}
+
{{/if}}
diff --git a/rpg-docs/client/views/character/characterSheet.js b/rpg-docs/client/views/character/characterSheet.js
index c7052c44..528cf42d 100644
--- a/rpg-docs/client/views/character/characterSheet.js
+++ b/rpg-docs/client/views/character/characterSheet.js
@@ -210,4 +210,11 @@ Template.characterSheet.events({
element: event.currentTarget.parentElement.parentElement,
});
},
+ "click #unshareCharacter": function(event, instance){
+ pushDialogStack({
+ data: this,
+ template: "unshareCharacterConfirmation",
+ element: event.currentTarget.parentElement.parentElement,
+ });
+ },
});
diff --git a/rpg-docs/client/views/character/features/featureDialog/featureDialog.html b/rpg-docs/client/views/character/features/featureDialog/featureDialog.html
index f7abb24d..c73a988c 100644
--- a/rpg-docs/client/views/character/features/featureDialog/featureDialog.html
+++ b/rpg-docs/client/views/character/features/featureDialog/featureDialog.html
@@ -36,7 +36,9 @@
{{> effectsViewList charId=charId parentId=_id}}
{{> proficiencyViewList charId=charId parentId=_id}}
+ {{> attacksViewList charId=charId parentId=_id}}
{{> customBuffViewList charId=charId parentId=_id}}
+
@@ -77,5 +79,6 @@
{{> effectsEditList parentId=_id parentCollection="Features" charId=charId name=name enabled=enabled}}
{{> proficiencyEditList parentId=_id parentCollection="Features" charId=charId enabled=enabled}}
+ {{> attackEditList parentId=_id parentCollection="Features" charId=charId enabled=enabled name=name}}
{{> customBuffEditList parentId=_id parentCollection="Features" charId=charId}}
diff --git a/rpg-docs/client/views/character/features/features.css b/rpg-docs/client/views/character/features/features.css
index 6d6d9e6c..520f9e55 100644
--- a/rpg-docs/client/views/character/features/features.css
+++ b/rpg-docs/client/views/character/features/features.css
@@ -6,6 +6,10 @@
margin-bottom: 8px;
}
+.card.featureCard .bottom {
+ padding-bottom: 8px;
+}
+
.containerMain.featureDescription {
white-space: pre-line;
}
diff --git a/rpg-docs/client/views/character/features/features.html b/rpg-docs/client/views/character/features/features.html
index d399b097..b7157b11 100644
--- a/rpg-docs/client/views/character/features/features.html
+++ b/rpg-docs/client/views/character/features/features.html
@@ -78,7 +78,7 @@
{{/if}}
- {{#if description}}
+ {{#if hasCharacters (evaluateShortString charId description)}}
{{#markdown}}{{evaluateShortString charId description}}{{/markdown}}
{{> customBuffViewList charId=charId parentId=_id}}
diff --git a/rpg-docs/client/views/character/features/features.js b/rpg-docs/client/views/character/features/features.js
index 2ab8f277..92a5eb06 100644
--- a/rpg-docs/client/views/character/features/features.js
+++ b/rpg-docs/client/views/character/features/features.js
@@ -56,6 +56,9 @@ Template.features.helpers({
var profs = Proficiencies.find({charId: this._id, type: "tool"});
return removeDuplicateProficiencies(profs);
},
+ hasCharacters: function(string){
+ return string.match(/\S/);
+ },
});
Template.features.events({
diff --git a/rpg-docs/client/views/character/inventory/containerDialog/containerDialog.html b/rpg-docs/client/views/character/inventory/containerDialog/containerDialog.html
index c6be3bcd..e11b1202 100644
--- a/rpg-docs/client/views/character/inventory/containerDialog/containerDialog.html
+++ b/rpg-docs/client/views/character/inventory/containerDialog/containerDialog.html
@@ -17,6 +17,9 @@
+
+ Carried
+
diff --git a/rpg-docs/client/views/character/inventory/containerDialog/containerDialog.js b/rpg-docs/client/views/character/inventory/containerDialog/containerDialog.js
index 2bce0102..288999c5 100644
--- a/rpg-docs/client/views/character/inventory/containerDialog/containerDialog.js
+++ b/rpg-docs/client/views/character/inventory/containerDialog/containerDialog.js
@@ -54,4 +54,8 @@ Template.containerEdit.events({
trimStrings: false,
});
},
+ "change #carriedToggle": function(event, instance){
+ var carried = !this.isCarried;
+ Containers.update(this._id, {$set: {isCarried: carried}});
+ }
});
diff --git a/rpg-docs/client/views/character/inventory/inventory.js b/rpg-docs/client/views/character/inventory/inventory.js
index f7f2e1a6..ac31e39f 100644
--- a/rpg-docs/client/views/character/inventory/inventory.js
+++ b/rpg-docs/client/views/character/inventory/inventory.js
@@ -331,21 +331,23 @@ Template.layout.events({
Session.set("inventory.dragItemId", null);
},
"drop .characterRepresentative": function(event, instance) {
- var itemId = event.originalEvent.dataTransfer.getData("dicecloud-id/items");
- if (event.ctrlKey){
- //split the stack to the container
- pushDialogStack({
- template: "splitStackDialog",
- data: {
- id: itemId,
- parentCollection: "Characters",
- parentId: this._id,
- },
- });
- } else {
- //move item to the character
- Meteor.call("moveItemToCharacter", itemId, this._id);
+ if (_.contains(event.originalEvent.dataTransfer.types, "dicecloud-id/items")){
+ var itemId = event.originalEvent.dataTransfer.getData("dicecloud-id/items");
+ if (event.ctrlKey){
+ //split the stack to the container
+ pushDialogStack({
+ template: "splitStackDialog",
+ data: {
+ id: itemId,
+ parentCollection: "Characters",
+ parentId: this._id,
+ },
+ });
+ } else {
+ //move item to the character
+ Meteor.call("moveItemToCharacter", itemId, this._id);
+ }
+ Session.set("inventory.dragItemId", null);
}
- Session.set("inventory.dragItemId", null);
},
});
diff --git a/rpg-docs/client/views/character/spells/spells.html b/rpg-docs/client/views/character/spells/spells.html
index 7158c8c3..b5011f82 100644
--- a/rpg-docs/client/views/character/spells/spells.html
+++ b/rpg-docs/client/views/character/spells/spells.html
@@ -83,7 +83,9 @@
{{#each spells ../_id ../../_id}}
{{#if showSpell ../../_id}}