From 4dd36a31648b9e8c406faeadb4c9d92ffabd460d Mon Sep 17 00:00:00 2001 From: ErinaSugino <121646352+ErinaSugino@users.noreply.github.com> Date: Wed, 26 Jun 2024 00:29:55 +0200 Subject: [PATCH 01/12] Lustia Rework Rework of the Lustia dungeon, attempting to integrate addon content more naturally. This version tries to add a closed, run-down version of the arcade from the Omnibrowser addon, with a clearer hint at to where and how to get the content. Currently doesn't work, hard-crashes randomly and doesn't properly generate otherwise. --- dialog/lustiaarcadehintconverse.config | 21 + dungeons/sexscape/sexscape.json | 1701 ++++++++++++++++- npcs/slut2goarcadehint.npctype | 21 + .../sexscapeshops/arcadesign_off.object | 34 + .../sexscapeshops/arcadesign_off.png | Bin 0 -> 519 bytes .../sexscapeshops/arcadesignicon_off.png | Bin 0 -> 147 bytes .../sexbound_cardshop_empty.object | 55 + .../sexscapeshops/sexbound_cardshop_empty.png | Bin 0 -> 1542 bytes .../sexbound_cardshopflip_empty.png | Bin 0 -> 1619 bytes .../sexbound_cardshopportrait_empty.png | Bin 0 -> 1280 bytes .../sexbound_cardshoptiled_empty.png | Bin 0 -> 1542 bytes .../objects-special/sexscape_tileset.json | 64 +- 12 files changed, 1795 insertions(+), 101 deletions(-) create mode 100644 dialog/lustiaarcadehintconverse.config create mode 100644 npcs/slut2goarcadehint.npctype create mode 100644 objects/miscellaneous/sexscapeshops/arcadesign_off.object create mode 100644 objects/miscellaneous/sexscapeshops/arcadesign_off.png create mode 100644 objects/miscellaneous/sexscapeshops/arcadesignicon_off.png create mode 100644 objects/miscellaneous/sexscapeshops/sexbound_cardshop_empty.object create mode 100644 objects/miscellaneous/sexscapeshops/sexbound_cardshop_empty.png create mode 100644 objects/miscellaneous/sexscapeshops/sexbound_cardshopflip_empty.png create mode 100644 objects/miscellaneous/sexscapeshops/sexbound_cardshopportrait_empty.png create mode 100644 objects/miscellaneous/sexscapeshops/sexbound_cardshoptiled_empty.png diff --git a/dialog/lustiaarcadehintconverse.config b/dialog/lustiaarcadehintconverse.config new file mode 100644 index 00000000..cdba7995 --- /dev/null +++ b/dialog/lustiaarcadehintconverse.config @@ -0,0 +1,21 @@ +{ + "greeting": { + "human": { + "default": [ + "Sorry hun~ Arcade is closed." + ] + } + }, + "converse": { + "human" : { + "default" : [ + "Been closed for a while. Real shame.", + "People loved their trading card addiction.", + "They were even selling phones!", + "Me and my pals haven't had much work out of town since then...", + "Something about \"Omnibrowser\" going out of business?", + "Omnibrowser... I wonder what that is..." + ] + } + } +} diff --git a/dungeons/sexscape/sexscape.json b/dungeons/sexscape/sexscape.json index 03310293..ecb4a457 100644 --- a/dungeons/sexscape/sexscape.json +++ b/dungeons/sexscape/sexscape.json @@ -1,18 +1,11 @@ { "backgroundcolor":"#000000", "compressionlevel":-1, - "editorsettings": - { - "export": - { - "target":"." - } - }, "height":312, "infinite":false, "layers":[ { "compression":"zlib", - "data":"eJzt3e1x6rwWBlCfTnZhKSMFpKJUQWH3nAnc6DWKP7A2MdJaMxow2Mjy6M9+xhbTBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPTqktQAAAAAOI89uc6fosmDAAAAAF7H3gyo9ioLAgAAADi3RzKgrZ\/LggAAAADOYe86P+WzYH8qn8mCAAAAAM7nkfWeW90PJAsCAAAAeI5HMpt\/7XOq3w\/0eeA3AQAAAMjxaF5zy4HKZ8H+zD6XBQEAAACcw5GsZinvOZoDyYIAAAAA2jma02TnQLIgAAAAgONaZDTPyIFkQQAAAACPa5XPPCsHkgUBAAAA7Ncym3lmDiQLAgAAANiudS7z7BxIFgQAAACwLiOT+Y0cSBYEAAAAsEwOBAAAADAGORAAAADAGORAAAAAAGOQAwEAAACMQQ4EAAAAMAY5EAAAAMAY5EAAAAAAY5ADAQAAAIxBDgQAAAAwBjkQAAAAwBiyc6D3osmBAAAAAH5PyxymzHw+Z9s\/fS4HAgAAAHiOjPtyyrxny+dyIAAAAIB8Wc9oWR8IAAAA4FzkQAAAAABjkAMBAAAAjEEOBAAAADAGORAAAADAGORAAAAAAGOQAwEAAACMQQ4EAAAAMAY5EAAAAED\/PpN\/+\/3a5u8z+wQAAADgXnYm83Zt5ftMciAAAACAezHl5ya\/kQNFch8AAAAAr6h8Xmut7d33barnQG\/J\/QIAAABwb57PLLUj+65tt+wXAAAAgC9RvO85ByrHCQAAADCquL5mPxdWO\/YZz4XdxgcAAADA9zrRl41t775r9wNl9RvtLhEAAABAF2KSAwEAAACMICY5EAAAAMAo\/G88AAAAwBjkQAAAAABjyM5NallOJjkQAAAAQF12blK7HyiTHAgAAADgXkx95kCR3AcAAADAK7I+EAAAAMAY5vnMUjuy79p2y34BAAAA+BLF+55zoHKcAAAAAKOK62v2c2G1Y5\/xXNhtfAAAAAB8rxN92dj27rt2P1BWv9HuEgEAAAB0ISY5EAAAAMAIYpIDAQAAAIzC\/8YDAAAAjEEOBAAAADCG7NykluVkkgMBAAAA1GXnJrX7gTLJgQAAAADuxdRnDhTJfQAAAAC8IusDAQAAAIxhns8stSP7rm237BcAAACAL1G87zkHKscJAAAAMKq4vmY\/F1Y79hnPhd3GBwAAAMD3OtGXjW3vvmv3A2X1G+0uEQAAAEAXYpIDAQAAAIwgJjkQAAAAwCj8bzwAAADAGORAAAAAAGPIzk1qWU4mORAAAABAXXZuUrsfKJMcCAAAAOBeTH3mQJHcBwAAAMArsj4QAAAAwBjm+cxSO7Lv2nbLfgEAAAD4EsX7nnOgcpwAAAAAo4rra\/ZzYbVjn\/Fc2G18AAAAAHyvE33Z2Pbuu3Y\/UFa\/0e4SAQAAAHQhJjkQAAAAwAhikgMBAAAAjML\/xgMAAACMQQ4EAAAAMIbs3KSW5WSSAwEAAADUZecmtfuBMsmBAAAAAO7F1GcOFMl9AAAAALwi6wMBAAAAjGGezyy1I\/uubbfsFwAAAIAvUbzvOQcqxwkAAAAwqri+ZudAtWe7npED3cYHAAAAwPc60b3dDxTtLhEAAABAF2KSAwEAAACMICY5EAAAAMAo\/G88AAAAwBjkQAAAAABjyM5NallOJjkQAAAAQF12blK7HyiTHAgAAADgXkx95kCR3AcAAADAK7I+EAAAAMAYevzfeAAAAAC+RPG+5xyoHCcAAADAqOL6mv1cWO3YZzwXdhsfAAAAAN\/rRF82tr37rt0PlNVvtLtEAAAAAF2ISQ4EAAAAMIKY5EAAAAAAo\/C\/8QAAAABjkAMBAAAAjCE7N6llOZnkQAAAAAB12blJ7X6gTHIgAAAAgHsx9ZkDRXIfAAAAAK\/I+kAAAAAAY5jnM0vtyL5r2y37BQAAAOBLFO97zoHKcQIAAACMKq6v2c+F1Y59xnNht\/EBAAAA8L1O9GVj27vv2v1AWf1Gu0sEAAAA0IWY5EAAAAAAI4hJDgQAAAAwCv8bDwAAADAGORAAAADAGLJzk1qWk0kOBAAAAFCXnZvU7gfKJAcCAAAAuBdTnzlQJPcBAAAA9ONzmj7eivZve\/79yvF32\/O1cc7C+kB5RppHAAAAcHaXv3V4rdXq96V6fu7If6Y\/2\/zcltqRfde2W\/b7bOYRAAAAnE9Zn\/9Uu\/92\/X6ZfZ8hFs61pxyoHGdL5hEAAACc00\/1+avU71n3eERxrpnPhdWOfUvutxxfK+YRAAAAnNdaff6K9XvrOj429LXnvOb7HrkGR\/qNdpfIPAIAAICT21Kfv3L93moNnNjQ18g5kHkEAAAA57a1Pn\/1+v3S4FrFhr5GzYHMIwAAADi3PfV5D\/V7ixo+e32gpWtw1v+NN48AAADg3PbW573U70dreDnQf5lHAAAAcG6P1Oc91e9HavjsNWJqWU6mI+MxjwAAAGA8t\/r8\/e\/r+7Vev70vv184froeX81AzrQ+b\/a51DKMTCe7th\/\/XkeYRwAAAPCqbvV57T6O8vuF46fr8dUM5Cz1e0x95kCR3MdWo8wjAAAAeGUj3cdhfaA8I80jAAAAeIZH123pbV2XR9d2mZ\/bUjuy79p2y34fYR5ZIwgAAIBzO1Kf91i\/b63hY+Fce8qBynEuMY9kQQAAAJyf+v3x+j2Kc818Lqx27Ftyv+X4tjCP5EAAAACcn\/r9WP0eG\/rac17zfY9cgyP9xs7rYB7JgQAAADg\/9bscSA70+\/MIAAAAsh2tz3ut3\/fU8LHht3rPgcwjWRAAAADnp35vU79nrw+0dA3O8L\/x5pEcCAAAgPNTv8uB5EDnmUcAAACQZa1+bvX7739f36\/1+u39lv5vWUQtxyi\/z7Ln97PP5adrkGXn2D+yzqP8\/RHmEQAAAGR5Vv1eu49jS\/+3+rl2H0f5fZYz5UA\/XYMsZ8yBRphHAAAAkMV9HMu2\/n7s2PdRv3E\/UGzf9yPvTMaZRwAAAJCprKdrrcX32eu6HFkPZ8v3e\/S0PtAe5lHbeQQAAAAZ5vX0vLX+PqN+f1toLb7fY+m39vS7Z8xHfmup7WEetZ1HAAAA0EoUNfOZ6vfbeUVxrmeq38vz+umzjDzmDDnQD2P\/uL03j47NIwAAAMgU0\/e6Kmd4nud2PsX5TdfzW63fn\/E8z+18friW\/5f1XNie7Vb91sZXGfvHNJlHLeYRAAAAZIpr\/XxZaC2+X6vfY1a7F+e3qX6\/LLQW38e2a7n6W3v6ne975Boc6Xfj2M2jRtcSAAAAsoT6XQ7UZuzmUaNrCQAAAFlC\/S4HajN286jRtQQAAIAsMbVZt+Xoui5xsH7PXtcltl3LtHV6fmt9oL05kHl0\/FoCAABAlnhS\/b62HSv1+5EMRA7UTw40wjwCAACAV\/f+Q33+0+eV\/XZ93iPXwDwCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB7zP1ayKgY=", + "data":"eJzt3c1x4zgaBmB2DHPoKwJzFLPeuyNyFJpoNom1y+IYTUMkKAL8AZ6nCiXJggQSjcv3NgkNAwBQy\/+OPgAAAAAAdiEHAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4MxulRoAAAAA57Em1\/kVNXkQAAAAwHWszYBSj7IgAAAAgHN7JgPK\/bssCAAAAOAc1u7zE98L9ivxN1kQAAAAwPk8s99zqeuBZEEAAAAA+3gms\/ls70P6eqD3Dd8JAAAAQB3P5jVjDhTfC\/Zr8ndZEAAAAMA5bMlq5vKerTmQLAgAAACgnK05Te0cSBYEAAAAsF2JjGaPHEgWBAAAAPC8UvnMXjmQLAgAAABgvZLZzJ45kCwIAAAAIF\/pXGbvHEgWBAAAALCsRiZzRA4kCwIAAACYJwcCAAAA6IMcCAAAAKAPciAAAACAPsiBAAAAAPogBwIAAADogxwIAAAAoA9yIAAAAIA+yIEAAAAA+iAHAgAAAOiDHAgAAACgD7VzoNeoyYEAAAAAjlMyh4kzn\/fJ60d\/lwMBAAAA7KPGdTlx3pPzdzkQAAAAQH217tGyPxAAAADAuciBAAAAAPogBwIAAADogxwIAAAAoA9yIAAAAIA+yIEAAAAA+iAHAgAAAOiDHAgAAACgD3IgAAAAgPa9V\/7u13ubPq85JgAAAAA\/1c5kXu4tfl6THAgAAADgpzDUz02OyIFC5TEAAAAArii+X2upre37MqRzoJfK4wIAAADw0zSfmWtb+i69LjkuAAAAAF9C9LzlHCg+TwAAAIBehftj7fvCUp\/d476w8fwAAAAA+N4n+pbZ1vZduh6o1rih3BQBAAAANCEMciAAAACAHoRBDgQAAADQC78bDwAAANAHORAAAABAH2rnJqkspyY5EAAAAEBa7dwkdT1QTXIgAAAAgJ\/C0GYOFCqPAQAAAHBF9gcCAAAA6MM0n5lrW\/ouvS45LgAAAABfQvS85RwoPk8AAACAXoX7Y+37wlKf3eO+sPH8AAAAAPjeJ\/qW2db2XboeqNa4odwUAQAAADQhDHIgAAAAgB6EQQ4EAAAA0Au\/Gw8AAADQBzkQAAAAQB9q5yapLKcmORAAAABAWu3cJHU9UE1yIAAAAICfwtBmDhQqjwEAAABwRfYHAgAAAOjDNJ+Za1v6Lr0uOS4AAAAAX0L0vOUcKD5PAAAAgF6F+2Pt+8JSn93jvrDx\/AAAAAD43if6ltnW9l26HqjWuKHcFAEAAAA0IQxyIAAAAIAehEEOBAAAANALvxsPAAAA0Ac5EAAAAEAfaucmqSynJjkQAAAAQFrt3CR1PVBNciAAAACAn8LQZg4UKo8BAAAAcEX2BwIAAADowzSfmWtb+i69LjkuAAAAAF9C9LzlHCg+TwAAAIBehftj7fvCUp\/d476w8fwAAAAA+N4n+pbZ1vZduh6o1rih3BQBAAAANCEMciAAAACAHoRBDgQAAADQC78bDwAAANAHORAAAABAH2rnJqkspyY5EAAAAEBa7dwkdT1QTXIgAAAAgJ\/C0GYOFCqPAQAAAHBF9gcCAAAA6MM0n5lrW\/ouvS45LgAAAABfQvS85RwoPk8AAACAXoX7Y+0cKHVv1x450Hh+AAAAAHzvE93a9UCh3BQBAAAANCEMciAAAACAHoRBDgQAAADQC78bDwAAANAHORAAAABAH2rnJqkspyY5EAAAAEBa7dwkdT1QTXIgAAAAgJ\/C0GYOFCqPAQAAAHBF9gcCAAAA6EOLvxsPAAAAwJcQPW85B4rPEwAAAKBX4f5Y+76w1Gf3uC9sPD8AAAAAvveJvmW2tX2XrgeqNW4oN0UAAAAATQiDHAgAAACgB2GQAwEAAAD0wu\/GAwAAAPRBDgQAAADQh9q5SSrLqUkOBAAAAJBWOzdJXQ9UkxwIAAAA4KcwtJkDhcpjAAAAAFyR\/YEAAAAA+jDNZ+balr5Lr0uOCwAAAMCXED1vOQeKzxMAAACgV+H+WPu+sNRn97gvbDw\/AAAAAL73ib5ltrV9l64HqjVuKDdFAAAAAE0IgxwIAAAAoAdhkAMBAADAVq\/D8HbVdvTcsS+\/Gw8AAADP+6hD3\/76eLxqe5cFdUUOBAAAAM+ZZkD\/\/f3Vxtf\/RG2u31+JfmOfR983\/c7xM3PfKQuidm6SynJqkgMBAACwlzgHijOY8XmcwfxTuF8qA5pmRqnnqbxIDtSP2rlJ6nqgmuRAAAAA7OHRtUBxHpO6dmeawTy6zudRDjR3jc+zOZAsqA9haDMHCpXHAAAAgFQOdOT1QDn3hU2zqrh\/zznQ57m\/RG06F0tzM81WUnvjnIX9gerpaR0BAAD05tkcKPcerq37A7ke6KfbxzmmWqp+n6vnp7b8Zvrepsc217b0XXpdcty9WUcAAAB9Ottvhdkf6E9xff6odj+6fr9N3q8hzBxrSzlQfJ4lWUcAAAB8inOgz6zlM1\/Z83Ga7Ty6fmgpP2opB3pUn1+lfq91jUeIjrXmfWGpz75UHjc+v1KsIwAAAFLOdk3Q2tZKBrRUn1+xfi9dx4eMsdYc17TvljnYMm4oN0XWEQAAAIteP+q7q7aj566EnPr8yvV7qT1wQsZYPedA1hEAAAC53u+5ytmvr7nKcebKrc+vXr\/fCsxVyBir1xzIOgIAAGCNq+QrVznOHGvq8xbq9xI1fO39gebmoOb+QFtYRwAAAKx1lXzlKse5ZG193kr9vrWGlwP9yToCAABgtGafnffJ41nbs8d59L9F7Jn6vKX6fUsNX3uPmFSWU9OW87GOAAAAiL1M6ri5Fucraz63d3v2OI\/+t6hprM+nWdmYf+XU7\/fPJzOQ2tnLGrWPJZVh1HSyuX37fOxhHQEAAMBVjfV56jqO+P2Zzw\/3zyczkLPU72FoMwcKlcfI1cs6AgAAaF3O\/R6592Ndqc\/Z7gerpafrOOwPVE9P6wgAAKBlOTlQzv1YV+tzxvvBnt23pbV9XZ7d22V6bHNtS9+l1yXHfYZ1ZI8gAACAR+RA57ClPm+xfs+t4cPMsbaUA8XnOcc6kgUBAADMkQOdg\/r9+fo9RMda876w1GdfKo8bn18O60gOBAAAMEcOdA7q9231e8gYa81xTftumYMt44aV82AdyYEAAADmyIHOQf0uB5IDHb+OAAAAWicHOt7W+rzV+n1NDR8yvqv1HMg6kgUBAAAsyanv9vot9z37jL93fQbq9zL1++d31dwfaG4Oau4PlMs6kgMBAAAskQMdT\/0uB5IDnWcdAQAAtGys31IZSvx+zndcqc9Z1D7Wrf++YxaRyjHi92tZ8\/21j+XRHNSy8tzfah1H\/P09rCMAAICWjfVb6v\/54\/dzvuNKfc5ir\/r92X\/fsX5OXccRv1\/LmXKgR3NQyxlzoB7WEQAAQMum91ClXud8x9X6nIXrOOblfn9Y0fdZR1wPFPL7vtU7kn7WEQAAQOt63R\/o6HkfLR1rifdr7+uytMfN1vfXmPuuNeNO+x6xP9Aa1lHZdQQAANCqnPruZaFdsc\/R8z5aOtbS79eo319mWon315j7rjXjrjnnLd8119awjsquIwAAgJaEqGaTA\/05H0fP\/5H1+3hcITrWM9Xv8XE9+tvcd60Zd80575EDPTj3t\/G5dbRtHQEAALQuDN\/7eqyp956pIc\/YZzoPR87\/Ge7nmc5DuD+e5X6e8XgezOW\/at0XtuZ1qXFT55c497dhsI5KrCMAAIDWhcz67kz5Tck+YTj2\/rBx\/m8zrcT7S\/++j+bh4+9Z9fttppV4P+TN5eJ3rRl32nfLHGwZN\/PcraNCcwkAANCykFnfnS2\/kQOp3x8dqxzIOpIDAQAApIXM+u5s+Y0cSP3+6FjlQNaRHAgAACAtZNZ3c\/uG5OwtctY+4UHduvf8H72vy6N5+Ph7Vv1ee1+XkDeXi9+1Zty5vkuvS46bee7WUaG5BAAAaFlI1H9Lr5+pIc\/aJzyoW4+c\/xr1+9LrR\/Pw8ffNGYgcqJ0cqId1BAAA0ItUfXf0MaWUyoGOPo89PTrf3Hl4Xfn3FpkD6wgAAKAl4\/0dr7+\/nx99TAAAAACU9++1Mr+\/nx99TAAAAACU9ffv7\/b6++fr\/yy0K\/b5bAAAAAC9WcqB\/l5oV+zztxwIAAAA6JAcCAAAAKAPciAAAACAPsiBAAAAAPogBwIAAADogxwIAAAAoA9LOdCZfu\/d78YDAAAAPG8uQzlbfiMHAgAAAHje6zC8rfk7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+\/s\/Iigt\/w==", "encoding":"base64", "height":312, "id":1, @@ -26,7 +19,7 @@ }, { "compression":"zlib", - "data":"eJzt3cFt41gSgGHmtOk4gj13AB0RA9izb45gMtBl9zITwJoYc\/o1ZUmUxHqqIr8P+LGzM+2mbQgPqIIoDgMAQD7\/laTAAAAAyMOcBkRxvgAAAORiTgOiOF8AAAByMacBUZwvAAAAuZjTgCjOFwAAgFzMaUAU5wsAAEAu5jQgivMFAAAgF3MaEMX5AgAAkIs5DYjifAEAAMjFnAZEcb4AAADkYk4DojhfAAAAcjGnAVGcLwAAALmY04AozhcAAIBczGlAFOcLAABALuY0IIrzBQAAIBdzGhDF+QIAAJCLOQ2I4nwBAADIxZwGRHG+AAAA5GJOA6I4XwAAAHIxpwFRnC8AAAC5mNOAKM4XAACAXMxpQBTnCwAAQC7mNCCK8wUAACAXcxoQxfkCAACQizkNiOJ8AQAAyMWcBkRxvgAAAORiTgOiOF8AAAByMacBUZwvAAAAuZjTgCjOFwAAgFzMaUAU5wsAAEAu5jQgivMFAAAgF3MaEMX5AgAAkIs5DYjifAEAAMjFnAZEcb4AAADkYk4DojhfAAAAcjGnAVGcLwAAALmY04AozhcAAIBczGlAFOcLAABALuY0IIrzBQAAIBdzGhDF+QIAAJCLOQ2I4nwBAADIxZwGRHG+AAAA5GJOA6I4XwAAAHIxpwFRnC8AAAC5mNOAKM4XAACAXMxpQBTnCwAAQC7mNCCK8wUAACAXcxoQxfkCAACQizkNiOJ8AQAAyMWcBkRxvgAAAORiTgOiOF8AAAByMacBUZwvAAAAuZjTgCjOFwAAgFzMaUAU5wsAAEAu5jQgivMFAAAgF3MaEMX5AgAAkIs5DYjifAEAAMjFnAZEcb4AAADkYk4DojhfAAAAcjGnAVGcLwAAALmY04AozhcAAIBczGm8B8axOV8AAAByMacd27SrOQX93afBLujonC8AAAC5mNOOq93RbL0Lav8+u6Djcr4AAADkYk47pu92M1vtgr77e+yCjsn5AgAAkIs57Xiu7WSe3QVd+3q7oONxvgAAAORiTjuWNbuYa7uc\/z34dfdcn\/1wvgAAAORiTjuOe3Yw974v6J4\/bxd0HM4XAACAXMxpx\/DI7mXtbueRe8nsgo7B+QIAAJCLOW3\/ntm53NrxPPN5QnZB++d8AQAAyMWctm9b7Fou7Xq2eL6YXdC+OV8AAAByMaft15Y7luXOZ6tnzE\/sgvbL+QIAAJCLOW2fInYrp8X\/bskuaJ+cLwAAALmY0\/YncqcSsQOa2QXtj\/MFAAAgF3PavvTYAdkFsZbzBQAAIBdz2n70fB+QXRBrOF8AAAByMaftw7Q7idrNRD4v7NLfaxe0D84XAACAXMxp+zDvTbbezdz6+6KuZw+0D84XAACAXMxp+9DuTbbazaz9eyKuZw+0D84XAACAXMxp+7Dcmzy7m7n367e+nj3QPjhfAAAAcjGn7cN3e5NHdzMZvs4eaB+cLwAAALmY0\/bh0t7k1e\/refTP2wPtg\/MFAAAgF3PaPlzbm7zyc34e\/XP2QPvgfAEAAMjFnLYPt\/Ymr3ru16P\/3R5oH5wvAAAAuZjT9mHN3uTS7mXrHdAW17MH2gfnCwAAQC7mtH1YuzdZ7mCidkDPXs8eaB+cLwAAALmY0\/bhnr3JafG\/0R65nj3QPjhfAAAAcjGn7cO9e5N7d0Af3xR5PXugfXC+AAAA5GJO24et90Brdj737IXsgY7J+QIAAJCLOW0fot8P9Cx7oGNyvgAAAORiTtsHeyAycr4AAADkYk7bB3sgMnK+AAAA5GJO2wd7IDJyvgAAAORiTtsHeyAycr4AAADkYk7bB3sgMnK+AAAA5GJO2wd7IDJyvgAAAORiTtsHeyAycr4AAADkYk7bB3sgMnK+AAAA5GJO2wd7IDJyvgAAAORiTqvv47MfX\/174+a\/9+OrofnnHtekNucLAABALua02qZdyfjZW2Bjc732fT09rmsXVJvzBQAAIBdzWn3te3MiurYHiryuHVB9zhcAAIBczGm1tTugCGv2QFHXtQuqz\/kCAACQizmtruU9YRHW3BcWdV33htXnfAEAAMjFnFaXPRDZOV8AAAByMafV1uO+sPZ5Yafh\/Hlh0delLucLAABALua0+t6\/6uF0+49soufPRBznCwAAQC7mtPrsgcjK+QIAAJCLOa0+eyCycr4AAADkYk6rb\/4snf\/c6I8NrrXFHmj6Pm59r5GfPUQ\/zhcAAIBczGn1zZ\/Z\/K8VPbsLenYP9MeF72uZz4jeB+cLAABALua0+tpnd0U1PyNsGM6fFxZ5TWpzvgAAAORiTqtt2pWMn70FNjbXa98P1OO6dkG1OV8AAAByMafVF\/3enGt7IO8H4hrnCwAAQC7mtNraHVCENXugqOvaBdXnfAEAAMjFnFbX8p6wCGvuC4u6rnvD6nO+AAAA5GJOq8seiOycLwAAALmY02rrcV9Y+7yw03D+vLDo61KX8wUAACAXc1p971\/1cLr9RzbR82cijvMFAAAgF3NaffZAZOV8AQAAyMWcVp89EFk5XwAAAHIxp9UX+Tk9S732QD1\/JuI4XwAAAHIxp9U3f2ZzDz33QD4juj7nCwAAQC7mtPraZ3dFNT8jbBjOnxcWeU1qc74AAADkYk6rbdqVjJ+9BTY212vfD9TjunZBtTlfAAAAcjGn1Rf93pxreyDvB+Ia5wsAAEAu5rTa2h1QhDV7oKjr2gXV53wBAADIxZxW1\/KesAhr7guLuq57w+pzvgAAAORiTqvLHojsnC8AAAC5mNNq63FfWPu8sNNw\/ryw6OtSl\/MFAAAgF3Nafe9f9XC6\/Uc20fNnIo7zBQAAIBdzWn32QGTlfAEAAMjFnFafPRBZOV8AAAByMafVF\/k5PUu99kA9fybiOF8AAAByMafVN39mcw8990A+I7o+5wsAAEAu5rT62md3RTU\/I2wYzp8XFnlNanO+AAAA5GJOq23alYyfvQU2Ntdr3w\/U47p2QbU5XwAAAHIxp9UX\/d6ca3sg7wfiGucLAABALua02todUIQ1e6Co69oF1ed8AQAAyMWcVtfynrAIa+4Li7que8Pqc74AAADkYk6ryx6I7JwvAAAAuZjTautxX1j7vLDTcP68sOjrUpfzBQAAIBdzWn3vX\/Vwuv1HNtHzZyKO8wUAACAXc1p99kBk5XwBAADIxZxWnz0QWTlfAAAAcjGn1Rf5OT1LvfZAPX8m4jhfAAAAcjGn1Td\/ZnMPPfdAPiO6PucLAABALua0+tpnd0U1PyNsGM6fFxZ5TWpzvgAAAORiTqtt2pWMn70FNjbXa98P1OO6dkG1OV8AAAByMafVF\/3enGt7IO8H4hrnCwAAQC7mtNraHVCENXugqOvaBdXnfAEAAMjFnFbX8p6wCGvuC4u6rnvD6nO+AAAA5GJOq8seiOycLwAAALmY02qbdiSRe6Dl88JOw\/nzwiLMP5MdUG3OFwAAgFzMafVF7oGWTrf\/yCZ6\/kzEcb4AAADkYk6rzx6IrJwvAAAAuZjT6rMHIivnCwAAQC7mtPoiP6dnqdceqOfPRBznCwAAQC7mtPrmz2zuoeceyGdE1+d8AQAAyMWcVl\/77K6o5meEDcP588Iir0ltzhcAAIBczGm1TbuScfj1eToRjc312vcD9biuXVBtzhcAAIBczGn1Rb8359oeyPuBuMb5AgAAkIs5rbZ2BxRhzR4o6rp2QfU5XwAAAHIxp9W1vCcswpr7wqKu696w+pwvAAAAuZjT6rIHIjvnCwAAQC7mtNp63BfWPi\/sNJw\/Lyz6utTlfAEAAMjFnFbf+1c9nG7\/kU30\/JmI43wBAADIxZxWnz0QWTlfAAAAcjGn1WcPRFbOFwAAgFzMafVFfk7PUq89UM+fiTjOFwAAgFzMafXNn9ncQ889kM+Irs\/5AgAAkIs5rb722V1Rzc8IG4bz54VFXpPanC8AAAC5mNNqm3Yl42dvgY3N9dr3A\/W4rl1Qbc4XAACAXMxp9UW\/N+faHsj7gbjG+QIAAJCLOa22dgcUYc0eKOq6dkH1OV8AAAByMafVtbwnLMKa+8KiruvesPqcLwAAALmY0+qyByI75wsAAEAu5rTaetwX1j4v7DScPy8s+rrU5XwBAADIxZxW3\/tXPZxu\/5FN9PyZiON8AQAAyMWcVp89EFk5XwAAAHIxp9VnD0RWzhcAAIBczGn1RX5Oz1KvPVDPn4k4zhcAAIBczGn1zZ\/Z3EPPPZDPiK7P+QIAAJCLOa2+9tldUc3PCBuG8+eFRV6T2pwvAAAAuZjTapt2JeNnb4GNzfXa9wP1uK5dUG3OFwAAgFz2MKe9D8PP7\/qxovGz7\/7OaQex5j0r7xfqKfq9Odf2QHt6P9DRX0cR9nC+AAAA7EnFOe3SvJ5pfu81z7c7oAhr9kBR143eBXkdxat4vgAAAOxZlTnt2pz+6N\/5dmN+f3v0Lx76zPLLe8IirLkvLOq6EfeGeR31VeV8AQAAOIrMc9rW8\/pS5Py+FDHL2wOt43X0OpnPFwAAgCPKOqdFzeytnvN7a+tdUPR9YfP9WVOn4fx5YdHXfYbX0WtlPV8AAACOKuOcFj23z141v8+2muF77gFOt\/\/IJjb6vXgdvVjG8wUAAODIss1pvWb3yavn98kWM7w90Ldf73WUQLbzBQAA4OgyzWk9Z\/dJhvl98uwMbw909rVeR0lkOl8AAADIM6f1nt0nWeb3yTMzfOTn9Cz12gM9+jN5HeXaBWU5XwAAAPhbhjntFbP7JNP8Pnl0hp8\/s7mHnnugez8j2uvob5l2QRnOFwAAAH7JMKe9YnafZJvfJ8\/sgSKbnxE2DOfPC4u85j28jn6xBwIAAOA7Gea0eX7\/EdSFHcbPNfN77x3IvfP7R\/O9RjU212vfD9TjuvfsgryOHn8dRclwvgAAAPDLq+e0eXYfv+bprWvn81Pzz+PK+b33DmQcHtsFRb4v59rvIPK6j+yAvI4efx1FePX5AgAAwO9ePadFv4fjx4X5\/Z73cTRf\/4\/I\/cc983u7A4qwZg8Udd17dkFeRznfE\/Tq8wUAAIDfvXpO6\/mZLqfFddbM74uv72Lt\/L68JyzCmveyRF33nnvDvI7O2QMBAACw9Mo5rffn+laZ3ydrZnh7oL95HV326l2QPRAAAEAu9kC15\/ce94XN92dNnYbzzziOvu4tXkeX2QMBAADQsgeqP7\/3nPUz3tPkdXSZPRAAAAAte6D687s9kNfRJfZAAAAAtF41p\/We3SeV5vfJ2hn+yHsgr6PbXrkLsgcCAADIxR6o\/vwe+Tk9S71+B2t\/Jq+j2+yBAAAAmGXZA\/1cdI+1X7vX+X3+zOYeeu6BMn5G9GSvr6MI9kAAAAC5vGpO+5zzf\/bq46vpuvM\/T\/9+zfzePitrGM6fldWjW3p8P6\/4HazZA3kdbfc6imAPBAAAkMur5rTxa36Orp3P2\/dxjCvn97H5d6dv\/nt07fW\/89Hhe3nV72Acbu+CvI62eR1FsQcCAADI5QjvB5qv2c7v97yPo\/n69vtP8z6OHu8recXvINv7gZrfwc\/2+nt5HUWwBwIAAMjlFXPaxzezdQ\/Lz3WZv4ePxb9v9yqLr+9qzT7k0vcapffnRN\/42b2OVrhnr7Y1eyAAAIBces9pH1\/vnZjvt+l57e8+33d+L0fzuS+\/3auz+Pqubt0fde17jdLrd7DiZ\/c6Wume++y2Zg8EAACQiz1Q3fndHsjraA17IAAAAGbuC6t9P0+P+8I+mk6L\/x\/FfWHbcV8YAAAAsyPNacv5\/YGvPzy\/A6+jexzpfAEAAKjgSHOa+f15fgdeR\/c40vkCAABQwZHmNPP78\/wOvI7ucaTzBQAAoIIjzWnm9+f5HXgd3eNI5wsAAEAFR5jTPn5\/jtPZ5\/mu+Pp\/PmM3+vORs6rwO9j686KXf5\/X0f2OcL4AXPKnJEmSpn7+2TznKbqPFf\/+z1\/98322z1j68U2X\/n1Et36n0dd\/5e\/A66jf60iSJEmSpIB+9mq8MduP51\/z2\/f6+d+vztXj63+X4SX+HXgdSZJS95ckSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIk3ej\/YDv6bA==", + "data":"eJzt3cFx40qWhlF40YaMO7Kgl900oCyiAb3WTha0B9zMbHoMGCFKmMoHiiRA4U8mkOdEfNGv66kKRYmREfc+ghwGACDlvyVJTQYAALA1swZAe5zNAABAglkDoD3OZgAAIMGsAdAeZzMAAJBg1gBoj7MZAABIMGsAtMfZDAAAJJg1ANrjbAYAABLMGgDtcTYDAAAJZg2A9jibAQCABLMGQHuczQAAQIJZA6A9zmYAACDBrAHQHmczAACQYNYAaI+zGQAASDBrALTH2QwAACSYNQDa42wGAAASzBoA7XE2AwAACWYNgPY4mwEAgASzBkB7nM0AAECCWQOgPc5mAAAgwawB0B5nMwAAkGDWAGiPsxkAAEgwawC0x9kMAAAkmDUA2uNsBgAAEswaAO1xNgMAAAlmDYD2OJsBAIAEswZAe5zNAABAglkDoD3OZgAAIMGsAdAeZzMAAJBg1gBoj7MZAABIMGsAtMfZDAAAJJg1ANrjbAYAABLMGgDtcTYDAAAJZg2A9jibAQCABLMGQHuczQAAQIJZA6A9zmYAACDBrAHQHmczAACQYNYAaI+zGQAASDBrALTH2QwAACSYNQDa42wGAAASzBoA7XE2AwAACWYNgPY4mwEAgASzBkB7nM0AAECCWQOgPc5mAAAgwawB0B5nMwAAkGDWAGiPsxkAAEgwawC0x9kMAAAkmDUA2uNsBgAAEswaAO1xNgMAAAlmDYD2OJsBAIAEswZAe5zNAABAglkDoD3OZgAAIMGsAdAeZzMAAJBg1gBoj7MZAABIMGsAtMfZDAAAJJg1ANrjbAYAABLMGgDtcTYDAAAJZg2A9jibAQCABLMGQHuczQAAQIJZA6A9zmYAACDBrAHQHmczAACQYNYAaI+zGQAASDBrwPPeg9E3ZzMAAJBg1oDnjLuaS+jPvgx2Qb1zNgMAAAlmDViv3NFsvQsq\/zy7oH45mwEAgASzBqzz3W5mq13Qd3+OXVCfnM0AAECCWQOWu7eT+eku6N7vtwvqj7MZAABIMGvAMkt2Mfd2Of\/z5O9bc32Ow9kMAAAkmDXgsTU7mLWvC1rz9XZB\/XA2AwAACWYNuO+Z3cvS3c4z95LZBfXB2QwAACSYNeC2n+xcHu14fvJ+QnZBx+dsBgAAEswa8L0tdi23dj1bfL6YXdCxOZsBAIAEswZc23LHMt\/5bPUZ8yO7oONyNgMAAAlmDfirxG7lMvvfLdkFHZOzGQAASDBrwB\/JnUpiBzSxCzoeZzMAAJBg1oDfauyA7IJYytkMAAAkmDWg7uuA7IJYwtkMAAAkmDXo3bg7Se1mkp8XduvPtQs6BmczAACQYNagd9PeZOvdzKM\/L3U9e6BjcDYDAAAJZg16V+5NttrNLP1zEtezBzoGZzMAAJBg1qB3873JT3cza3\/\/1tezBzoGZzMAAJBg1qB33+1Nnt3NtPD77IGOwdkMAAAkmDXo3a29yatf1\/Ps19sDHYOzGQAASDBr0Lt7e5NXvs\/Ps19nD3QMzmYAACDBrEHvHu1NXvW5X8\/+e3ugY3A2AwAACWYNerdkb3Jr97L1DmiL69kDHYOzGQAASDBr0Lule5P5Dia1A\/rp9eyBjsHZDAAAJJg16N2avcll9r9pz1zPHugYnM0AAECCWYPerd2brN0BfXxT8nr2QMfgbAYAABLMGvRu6z3Qkp3Pmr2QPVCfnM0AAECCWYPepV8P9FP2QH1yNgMAAAlmDXpnD0SLnM0AAECCWYPe2QPRImczAACQYNagd\/ZAtMjZDAAAJJg16J09EC1yNgMAAAlmDXpnD0SLnM0AAECCWYPe2QPRImczAACQYNagd\/ZAtMjZDAAAJJg16J09EC1yNgMAAAlmDXpnD0SLnM0AAECCWYOefXx2+urvGzf9uR9fDcU\/17gm++ZsBgAAEswa9GrclZw\/ewt2Lq5Xvq6nxnXtgvbN2QwAACSYNehZ+dqcRPf2QMnr2gHtn7MZAABIMGvQq3IHlLBkD5S6rl3Q\/jmbAQCABLMGPZrfE5aw5L6w1HXdG7Z\/zmYAACDBrEGP7IFonbMZAABIMGvQqxr3hZWfF3YZrj8vLH1d9svZDAAAJJg16Nn7VzVcHn\/JJmo+JnKczQAAQIJZg57ZA9EqZzMAAJBg1qBn9kC0ytkMAAAkmDXo2fReOv960L83uNYWe6Dx7\/Ho75p87yHqcTYDAAAJZg16Nr1n838t6Ke7oJ\/ugf594+81z3tEH4OzGQAASDBr0LPys7tSTZ8RNgzXnxeWvCb75mwGAAASzBr0atyVnD97C3Yurle+HqjGde2C9s3ZDAAAJJg16Fn6tTn39kBeD8Q9zmYAACDBrEGvyh1QwpI9UOq6dkH752wGAAASzBr0aH5PWMKS+8JS13Vv2P45mwEAgASzBj2yB6J1zmYAACDBrEGvatwXVn5e2GW4\/ryw9HXZL2czAACQYNagZ+9f1XB5\/CWbqPmYyHE2AwAACWYNemYPRKuczQAAQIJZg57ZA9EqZzMAAJBg1qBnyffpmau1B6r5mMhxNgMAAAlmDXo2vWdzDTX3QN4jev+czQAAQIJZg56Vn92VavqMsGG4\/ryw5DXZN2czAACQYNagV+Ou5PzZW7Bzcb3y9UA1rmsXtG\/OZgAAIMGsQc\/Sr825twfyeiDucTYDAAAJZg16Ve6AEpbsgVLXtQvaP2czAACQYNagR\/N7whKW3BeWuq57w\/bP2QwAACSYNeiRPRCtczYDAAAJZg16VeO+sPLzwi7D9eeFpa\/LfjmbAQCABLMGPXv\/qobL4y\/ZRM3HRI6zGQAASDBr0DN7IFrlbAYAABLMGvTMHohWOZsBAIAEswY9S75Pz1ytPVDNx0SOsxkAAEgwa9Cz6T2ba6i5B\/Ie0fvnbAYAABLMGvSs\/OyuVNNnhA3D9eeFJa\/JvjmbAQCABLMGvRp3JefP3oKdi+uVrweqcV27oH1zNgMAAAlmDXqWfm3OvT2Q1wNxj7MZAABIMGvQq3IHlLBkD5S6rl3Q\/jmbAQCABLMGPZrfE5aw5L6w1HXdG7Z\/zmYAACDBrEGP7IFonbMZAABIMGvQqxr3hZWfF3YZrj8vLH1d9svZDAAAJJg16Nn7VzVcHn\/JJmo+JnKczQAAQIJZg57ZA9EqZzMAAJBg1qBn9kC0ytkMAAAkmDXoWfJ9euZq7YFqPiZynM0AAECCWYOeTe\/ZXEPNPZD3iN4\/ZzMAAJBg1qBn5Wd3pZo+I2wYrj8vLHlN9s3ZDAAAJJg16NW4Kzl\/9hbsXFyvfD1QjevaBe2bsxkAAEgwa9Cz9Gtz7u2BvB6Ie5zNAABAglmDXpU7oIQle6DUde2C9s\/ZDAAAJJg16NH8nrCEJfeFpa7r3rD9czYDAAAJZg16ZA9E65zNAABAglmDXo07kuQeaP55YZfh+vPCEqbHZAe0b85mAAAgwaxBz5J7oLnL4y\/ZRM3HRI6zGQAASDBr0DN7IFrlbAYAABLMGvTMHohWOZsBAIAEswY9S75Pz1ytPVDNx0SOsxkAAEgwa9Cz6T2ba6i5B\/Ie0fvnbAYAABLMGvSs\/OyuVNNnhA3D9eeFJa\/JvjmbAQCABLMGvRp3Jefhz\/vpJDoX1ytfD1TjunZB++ZsBgAAEswa9Cz92px7eyCvB+IeZzMAAJBg1qBX5Q4oYckeKHVdu6D9czYDAAAJZg16NL8nLGHJfWGp67o3bP+czQAAQIJZgx7ZA9E6ZzMAAJBg1qBXNe4LKz8v7DJcf15Y+rrsl7MZAABIMGvQs\/evarg8\/pJN1HxM5DibAQCABLMGPbMHolXOZgAAIMGsQc\/sgWiVsxkAAEgwa9Cz5Pv0zNXaA9V8TOQ4mwEAgASzBj2b3rO5hpp7IO8RvX\/OZgAAIMGsQc\/Kz+5KNX1G2DBcf15Y8prsm7MZAABIMGvQq3FXcv7sLdi5uF75eqAa17UL2jdnMwAAkGDWoGfp1+bc2wN5PRD3OJsBAIAEswa9KndACUv2QKnr2gXtn7MZAABIMGvQo\/k9YQlL7gtLXde9YfvnbAYAABLMGvTIHojWOZsBAIAEswa9qnFfWPl5YZfh+vPC0tdlv5zNAABAglmDnr1\/VcPl8ZdsouZjIsfZDAAAJJg16Jk9EK1yNgMAAAlmDXpmD0SrnM0AAECCWYOeJd+nZ67WHqjmYyLH2QwAACSYNejZ9J7NNdTcA3mP6P1zNgMAAAlmDXpWfnZXqukzwobh+vPCktdk35zNAABAglmDXo27kvNnb8HOxfXK1wPVuK5d0L45mwEAgASzRt\/eh+HXd50WdP7suz9z3EEsec3K+41qSr82594e6EivB+r9eZTgbAYAABLMGn25Na+3NL\/XmufLHVDCkj1Q6rrpXZDnUZ6zGQAASDBrHN+9Of3ZP\/Ptwfz+9uwfPNSZ5ef3hCUsuS8sdd3EvWGeR3U5mwEAgASzxjFtPa\/PJef3ucQsbw+0jOfR6zibAQCABLPG8aRm9lLN+b209S4ofV\/YdH\/W2GW4\/ryw9HV\/wvPotZzNAABAglnjWNJz++RV8\/tkqxm+5h7g8vhLNrHR98Xz6MWczQAAQIJZ4zhqze6jV8\/voy1meHugb3+\/51EDnM0AAECCWeMYas7uoxbm99FPZ3h7oKvf63nUCGczAACQYNbYv9qz+6iV+X30kxk++T49c7X2QM8+Js+jtnZBzmYAACDBrLFvr5jdRy3N76NnZ\/jpPZtrqLkHWvse0Z5Hv7W0C3I2AwAACWtnjVszW29a+T68YnYftTa\/j36yB0o2fUbYMFx\/Xljymmt4Hv1hDwQAAByZPdBzWvk+TPP7KdSNHcavJfN77R3I2vn9o\/i7pjoX1ytfD1Tjumt2QZ5Hzz+PUuyBAACAhGf2QKlZcU+1sAeaZvfz1zy9deVjvBT\/fP7m35em+b32DuQ8PLcLSu0TTg++B8nrPrMD8jx6\/nmUYA8EAAAkPDNrTPPb1n+XPWhlBzRKv4bjdGN+Py2c30\/Fr5Xze3L\/sWZ+L3dACUv2QKnrrtkFeR61+ZogeyAAACDBHmide3NrbTXf0+Uyu86S+X32+6tYOr\/P7wlLWPJaltR119wb5nl0zR4IAAA4KnugdVrZA9V+X9+9zO+jJTO8PdBvnke3vXoXZA8EAAAk2AOtYw\/02xHm9xr3hU33Z41dhuv3OE5f9xHPo9vsgQAAgCOyB1rHHui3o8zvNWf9Fu9p8jy6zR4IAAA4InugdeyBfjvK\/G4P5Hl0iz0QAABwRPZA67SwB6o9u4\/2NL+Pls7wPe+BPI8ee+UuyB4IAABIsAdap4XPjTe\/P7Z0fk++T89cre\/B0sfkefSYPRAAAHA09kDrtLgH+jVrjaW\/96jz+\/SezTXU3AO1+B7Ro6M+jxLsgQAAgIRn90Cnrz6+Gn99+ufTwXv1HqjmY731810yv5eflTUM15+VVaNHavx9XvE9WLIH8jza7nmUYA8EAAAk\/OT1QOX8Vv53\/unfH7VX74FqfX8f\/Xwfze\/n4tcu3\/z7dOX1v\/NR4e\/yqu\/BeXi8C\/I82uZ5lGIPBAAAJPz09UDTr5XzXc3XGbyiV++Baj7W6Zrzn++S+b18HUU5v7f0Oo4aryt5xfegtdcDFd+DX+X1j\/I8SrAHAgAAEtbOGh\/fzHaj+ft+HNX02D9e9Hhvff\/T5j\/fW9+Hcq8y+\/1VLdmH3Pq7ptR+n+gHj93zaIE1e7Wt2QMBAAAJa2aNj6\/\/dj\/d71H+u172QOW9LrV3Qfe+\/2nfvb\/v\/Pswv89q9vurenR\/1L2\/a0qt78GCx+55tNCa++y2Zg8EAAAk2AOtYw\/0297nd3sgz6Ml7IEAAICjcV\/YOu4L++0I9\/PUuC\/so+gy+\/8p7gvbjvvCAACAo9lq1uhlD9Srn\/58a8\/vLfI98Dxawx4IAABIsAdiCfP7z\/keeB6tYQ8EAAAk2AOxhPn953wPPI\/WsAcCAAAS7IFYwvz+c74Hnkdr2AMBAAAJ9kDc8\/HXz3Fa\/f7Y5Xsip98fuVV7+B5s\/X7R8z\/P82g9eyCgZ\/+RJElNdSo+a+i7+e7UQS\/63o\/XrfYYb\/0sy1\/\/z5\/K58f\/f8bS6Ztu\/XqiBc\/laK\/8Hnge1XseSZIkSdKRO\/1tGN4+Z7bz8Oe\/6ZevBxp\/\/e3AjY\/\/Rd\/7X7U6P5jtz9e\/5y9\/1\/Nwf64+N\/A8Ttfw98DzSJLUdP8rSZKaatyDnL7muOFLuQc6PZj9dt\/fXv8zkCRJkiRJqtG4B\/nnZ6Ve3h9ofNz2QJIkSZIkqZfGPcg\/Ot0D\/cMeSJIkSZIkdZQ90Ot\/BpIkSZIkSTWyB3r9z0CSJEmSJKlG9kCv\/xlIkiRJkiTVyB7o9T8DSZIkSZKkGtkDvf5nIEmSJEmSVKOe90A+N16SJEmSJPXUuAf559ce6GMYfn187YDKfz4qeyBJkiRJktRT4x7k9LXzOX3TrV8\/TPZAkiRJkiSpk06v3sM00Kt\/BpIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkSZIkbdH\/AdA6cco=", "encoding":"base64", "height":312, "id":2, @@ -688,76 +681,44 @@ "y":1616 }, { - "gid":2147485887, - "height":56, - "id":2352, - "name":"", - "rotation":0, - "type":"", - "visible":true, - "width":34, - "x":4608, - "y":1752 - }, - { - "gid":2147489030, - "height":16, - "id":2353, - "name":"", - "rotation":0, - "type":"", - "visible":true, - "width":40, - "x":4576, - "y":1752 - }, - { - "gid":2147485887, - "height":56, - "id":2354, - "name":"", - "rotation":0, - "type":"", - "visible":true, - "width":34, - "x":4480, - "y":1752 - }, - { - "gid":2239, - "height":56, - "id":2356, - "name":"", - "rotation":0, - "type":"", - "visible":true, - "width":34, - "x":6584, - "y":1752 - }, - { - "gid":5382, - "height":16, - "id":2357, + "height":8, + "id":2516, "name":"", + "properties": + { + "vehicle":"stationtram" + }, + "propertytypes": + { + "vehicle":"string" + }, "rotation":0, "type":"", "visible":true, - "width":40, - "x":6488, - "y":1752 + "width":8, + "x":3935.99262187088, + "y":1736.00693895477 }, { - "gid":2239, - "height":56, - "id":2358, + "height":8, + "id":2555, "name":"", + "properties": + { + "npc":"human", + "typeName":"slut2goarcadehint" + }, + "propertytypes": + { + "npc":"string", + "typeName":"string" + }, "rotation":0, "type":"", "visible":true, - "width":34, - "x":6456, - "y":1752 + "width":8, + "x":4424, + "y":1720.125 }], "opacity":1, "type":"objectgroup", @@ -771,6 +732,26 @@ "id":12, "name":"objects n wiring", "objects":[ + { + "height":0, + "id":2530, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2.125 + }, + { + "x":6, + "y":21.875 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4394, + "y":1690.125 + }, { "height":0, "id":1701, @@ -6218,6 +6199,1546 @@ "width":48, "x":5688, "y":1176 + }, + { + "gid":2130, + "height":24, + "id":2359, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":3927.99431818182, + "y":1671.91477272727 + }, + { + "gid":2130, + "height":24, + "id":2360, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":3927.99431818182, + "y":1767.91477272727 + }, + { + "gid":2130, + "height":24, + "id":2361, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":3927.99431818182, + "y":1855.91477272727 + }, + { + "gid":3093, + "height":40, + "id":2362, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":48, + "x":4384, + "y":1752 + }, + { + "gid":2147486741, + "height":40, + "id":2363, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":48, + "x":3879.99431818182, + "y":1751.91477272727 + }, + { + "height":0, + "id":2364, + "name":"", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":0, + "y":-72 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3935.99431818182, + "y":1831.91477272727 + }, + { + "height":0, + "id":2365, + "name":"", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":0, + "y":-80 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3935.99431818182, + "y":1743.91477272727 + }, + { + "height":0, + "id":2366, + "name":"", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-32, + "y":8 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3967.99431818182, + "y":1831.91477272727 + }, + { + "height":0, + "id":2367, + "name":"", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-32, + "y":16 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3967.99431818182, + "y":1735.91477272727 + }, + { + "height":0, + "id":2368, + "name":"", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-32, + "y":16 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3967.99431818182, + "y":1639.91477272727 + }, + { + "gid":2597, + "height":8, + "id":2369, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":8, + "x":3967.99431818182, + "y":1743.91477272727 + }, + { + "gid":2597, + "height":8, + "id":2370, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":8, + "x":3967.99431818182, + "y":1647.91477272727 + }, + { + "gid":2597, + "height":8, + "id":2371, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":8, + "x":3967.99431818182, + "y":1839.91477272727 + }, + { + "gid":5047, + "height":8, + "id":2372, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4360, + "y":1592 + }, + { + "gid":5047, + "height":8, + "id":2373, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4287.99431818182, + "y":1687.91477272727 + }, + { + "gid":5047, + "height":8, + "id":2374, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4215.99431818182, + "y":1591.91477272727 + }, + { + "gid":5047, + "height":8, + "id":2375, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4143.99431818182, + "y":1687.91477272727 + }, + { + "gid":5047, + "height":8, + "id":2376, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4071.99431818182, + "y":1591.91477272727 + }, + { + "gid":5047, + "height":8, + "id":2377, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":3999.99431818182, + "y":1687.91477272727 + }, + { + "gid":4997, + "height":8, + "id":2378, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4071.99431818182, + "y":1687.91477272727 + }, + { + "gid":4997, + "height":8, + "id":2379, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":3999.99431818182, + "y":1591.91477272727 + }, + { + "gid":4997, + "height":8, + "id":2380, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4143.99431818182, + "y":1591.91477272727 + }, + { + "gid":4997, + "height":8, + "id":2381, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4215.99431818182, + "y":1687.91477272727 + }, + { + "gid":4997, + "height":8, + "id":2382, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4287.99431818182, + "y":1591.91477272727 + }, + { + "gid":4997, + "height":8, + "id":2383, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4359.99431818182, + "y":1687.91477272727 + }, + { + "gid":4802, + "height":8, + "id":2384, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4359.99431818182, + "y":1783.91477272727 + }, + { + "gid":4802, + "height":8, + "id":2385, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4287.99431818182, + "y":1783.91477272727 + }, + { + "gid":4802, + "height":8, + "id":2386, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4215.99431818182, + "y":1783.91477272727 + }, + { + "gid":4802, + "height":8, + "id":2387, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4143.99431818182, + "y":1783.91477272727 + }, + { + "gid":4802, + "height":8, + "id":2388, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4071.99431818182, + "y":1783.91477272727 + }, + { + "gid":4802, + "height":8, + "id":2389, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":3999.99431818182, + "y":1783.91477272727 + }, + { + "gid":2147489151, + "height":24, + "id":2390, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4383.99431818182, + "y":1847.91477272727 + }, + { + "gid":2147489279, + "height":16, + "id":2391, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4023.99431818182, + "y":1655.91477272727 + }, + { + "gid":2147488946, + "height":16, + "id":2392, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":48, + "x":4055.99431818182, + "y":1847.91477272727 + }, + { + "gid":2147488946, + "height":16, + "id":2393, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":48, + "x":4127.99431818182, + "y":1847.91477272727 + }, + { + "gid":5298, + "height":16, + "id":2394, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":48, + "x":4199.99431818182, + "y":1847.91477272727 + }, + { + "gid":5298, + "height":16, + "id":2395, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":48, + "x":4271.99431818182, + "y":1847.91477272727 + }, + { + "gid":2147489198, + "height":16, + "id":2396, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4367.99431818182, + "y":1847.91477272727 + }, + { + "gid":2147486890, + "height":40, + "id":2397, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4263.99431818182, + "y":1655.91477272727 + }, + { + "gid":3313, + "height":32, + "id":2398, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":4271.99431818182, + "y":1727.91477272727 + }, + { + "gid":3319, + "height":40, + "id":2399, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":4047.99431818182, + "y":1639.91477272727 + }, + { + "gid":3337, + "height":24, + "id":2400, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4367.99431818182, + "y":1735.91477272727 + }, + { + "gid":3423, + "height":40, + "id":2401, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":3991.99431818182, + "y":1655.91477272727 + }, + { + "gid":3428, + "height":40, + "id":2402, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":4335.99431818182, + "y":1751.91477272727 + }, + { + "gid":2147487153, + "height":32, + "id":2403, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4119.99431818182, + "y":1655.91477272727 + }, + { + "gid":3565, + "height":40, + "id":2404, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4223.99431818182, + "y":1655.91477272727 + }, + { + "gid":3584, + "height":24, + "id":2405, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4103.99431818182, + "y":1623.91477272727 + }, + { + "gid":3798, + "height":32, + "id":2406, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":4007.99431818182, + "y":1847.91477272727 + }, + { + "gid":3801, + "height":56, + "id":2407, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":48, + "x":4351.99431818182, + "y":1655.91477272727 + }, + { + "gid":3815, + "height":32, + "id":2408, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":4119.99431818182, + "y":1727.91477272727 + }, + { + "gid":4566, + "height":32, + "id":2409, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4295.99431818182, + "y":1751.91477272727 + }, + { + "gid":3679, + "height":24, + "id":2410, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4303.99431818182, + "y":1623.91477272727 + }, + { + "gid":3297, + "height":40, + "id":2411, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":4087.99431818182, + "y":1751.91477272727 + }, + { + "gid":3253, + "height":24, + "id":2412, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4063.99431818182, + "y":1735.91477272727 + }, + { + "gid":3178, + "height":24, + "id":2413, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4151.99431818182, + "y":1823.91477272727 + }, + { + "gid":6009, + "height":24, + "id":2414, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":64, + "x":4191.99431818182, + "y":1711.91477272727 + }, + { + "gid":3788, + "height":8, + "id":2415, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":40, + "x":3983.99431818182, + "y":1807.91477272727 + }, + { + "gid":5383, + "height":16, + "id":2416, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4071.99431818182, + "y":1751.91477272727 + }, + { + "gid":2147489031, + "height":16, + "id":2417, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4295.99431818182, + "y":1655.91477272727 + }, + { + "gid":5383, + "height":16, + "id":2418, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4279.99431818182, + "y":1751.91477272727 + }, + { + "gid":2147489031, + "height":16, + "id":2419, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4359.99431818182, + "y":1751.91477272727 + }, + { + "gid":5383, + "height":16, + "id":2420, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4207.99431818182, + "y":1655.91477272727 + }, + { + "gid":2147489031, + "height":16, + "id":2421, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4151.99431818182, + "y":1655.91477272727 + }, + { + "gid":2147489030, + "height":16, + "id":2422, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":40, + "x":4071.99431818182, + "y":1655.91477272727 + }, + { + "gid":2139, + "height":36, + "id":2423, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":3975.99431818182, + "y":1847.91477272727 + }, + { + "gid":3640, + "height":24, + "id":2424, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4375.99431818182, + "y":1823.91477272727 + }, + { + "gid":3642, + "height":24, + "id":2425, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4055.99431818182, + "y":1823.91477272727 + }, + { + "gid":3958, + "height":32, + "id":2426, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":3975.99431818182, + "y":1655.91477272727 + }, + { + "gid":2147485887, + "height":56, + "id":2427, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":34, + "x":3839.99431818182, + "y":1751.91477272727 + }, + { + "gid":2147489030, + "height":16, + "id":2428, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":40, + "x":3807.99431818182, + "y":1751.91477272727 + }, + { + "gid":6007, + "height":40, + "id":2429, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":56, + "x":3983.99431818182, + "y":1751.91477272727 + }, + { + "gid":3260, + "height":8, + "id":2430, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4007.99431818182, + "y":1711.91477272727 + }, + { + "gid":4964, + "height":32, + "id":2431, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4039.99431818182, + "y":1751.91477272727 + }, + { + "gid":3260, + "height":8, + "id":2433, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":3975.99431818182, + "y":1711.91477272727 + }, + { + "gid":3827, + "height":16, + "id":2437, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4207.99431818182, + "y":1727.91477272727 + }, + { + "gid":4539, + "height":16, + "id":2438, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":3999.99431818182, + "y":1615.91477272727 + }, + { + "gid":4576, + "height":24, + "id":2439, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":72, + "x":4151.99431818182, + "y":1631.91477272727 + }, + { + "gid":2450, + "height":16, + "id":2440, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":24, + "x":4335.99431818182, + "y":1831.91477272727 + }, + { + "gid":2147488801, + "height":16, + "id":2441, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":32, + "x":4335.99431818182, + "y":1847.91477272727 + }, + { + "gid":4557, + "height":8, + "id":2442, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":8, + "x":4359.99431818182, + "y":1831.91477272727 + }, + { + "gid":4483, + "height":8, + "id":2443, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":8, + "x":4303.99431818182, + "y":1831.91477272727 + }, + { + "gid":4483, + "height":8, + "id":2444, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":8, + "x":4215.99431818182, + "y":1831.91477272727 + }, + { + "gid":4483, + "height":8, + "id":2445, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":8, + "x":4079.99431818182, + "y":1831.91477272727 + }, + { + "gid":4344, + "height":24, + "id":2446, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":12, + "x":4031.99431818182, + "y":1847.91477272727 + }, + { + "gid":3268, + "height":32, + "id":2447, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":40, + "x":4151.99431818182, + "y":1751.91477272727 + }, + { + "gid":3642, + "height":24, + "id":2448, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4359.99431818182, + "y":1815.91477272727 + }, + { + "gid":3640, + "height":24, + "id":2449, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4247.99431818182, + "y":1823.91477272727 + }, + { + "gid":2147485887, + "height":56, + "id":2352, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":34, + "x":4608, + "y":1752 + }, + { + "gid":2147489030, + "height":16, + "id":2353, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":40, + "x":4576, + "y":1752 + }, + { + "gid":2147485887, + "height":56, + "id":2354, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":34, + "x":4480, + "y":1752 + }, + { + "gid":2239, + "height":56, + "id":2356, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":34, + "x":6584, + "y":1752 + }, + { + "gid":5382, + "height":16, + "id":2357, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":40, + "x":6488, + "y":1752 + }, + { + "gid":2239, + "height":56, + "id":2358, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":34, + "x":6456, + "y":1752 + }, + { + "gid":2710, + "height":16, + "id":2527, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4384, + "y":1696 + }, + { + "height":0, + "id":2534, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":-26, + "y":-10 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4394, + "y":1690 + }, + { + "height":0, + "id":2535, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":-26, + "y":86 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4394, + "y":1690 + }, + { + "height":0, + "id":2536, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":-98, + "y":-10 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4394, + "y":1690 + }, + { + "height":0, + "id":2537, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":-98, + "y":86 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4394, + "y":1690 + }, + { + "height":0, + "id":2539, + "name":"", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-24, + "y":-104 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4392, + "y":1688 + }, + { + "height":0, + "id":2540, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":-98, + "y":-106 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4394, + "y":1690 + }, + { + "height":0, + "id":2541, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":-170, + "y":86 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4394, + "y":1690 + }, + { + "height":0, + "id":2542, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":-170, + "y":-10 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4394, + "y":1690 + }, + { + "height":0, + "id":2543, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":-170, + "y":-106 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":4394, + "y":1690 + }, + { + "gid":2710, + "height":16, + "id":2544, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":3952, + "y":1696 + }, + { + "height":0, + "id":2545, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":46, + "y":86 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3962, + "y":1690 + }, + { + "height":0, + "id":2546, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":46, + "y":-10 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3962, + "y":1690 + }, + { + "height":0, + "id":2547, + "name":"", + "polyline":[ + { + "x":-2, + "y":-1.5 + }, + { + "x":46, + "y":-105.5 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3962, + "y":1689.5 + }, + { + "height":0, + "id":2548, + "name":"", + "polyline":[ + { + "x":-2, + "y":-1.75 + }, + { + "x":118, + "y":86.25 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3962, + "y":1689.75 + }, + { + "height":0, + "id":2549, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":118, + "y":-10 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3962, + "y":1690 + }, + { + "height":0, + "id":2550, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":118, + "y":-106 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3962, + "y":1690 + }, + { + "height":0, + "id":2551, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":190, + "y":86 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3962, + "y":1690 + }, + { + "height":0, + "id":2552, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":190, + "y":-10 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3962, + "y":1690 + }, + { + "height":0, + "id":2553, + "name":"", + "polyline":[ + { + "x":-2, + "y":-2 + }, + { + "x":190, + "y":-106 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3962, + "y":1690 }], "opacity":1, "type":"objectgroup", @@ -6226,87 +7747,87 @@ "y":0 }], "nextlayerid":18, - "nextobjectid":2359, + "nextobjectid":2556, "orientation":"orthogonal", "renderorder":"right-down", - "tiledversion":"1.3.5", + "tiledversion":"1.8.0", "tileheight":8, "tilesets":[ { "firstgid":1, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/materials.json" + "source":"..\/..\/tilesets\/packed\/materials.json" }, { "firstgid":198, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/supports.json" + "source":"..\/..\/tilesets\/packed\/supports.json" }, { "firstgid":235, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/miscellaneous.json" + "source":"..\/..\/tilesets\/packed\/miscellaneous.json" }, { "firstgid":259, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/liquids.json" + "source":"..\/..\/tilesets\/packed\/liquids.json" }, { "firstgid":287, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-race\/generic.json" + "source":"..\/..\/tilesets\/packed\/objects-by-race\/generic.json" }, { "firstgid":2271, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-race\/ancient.json" + "source":"..\/..\/tilesets\/packed\/objects-by-race\/ancient.json" }, { "firstgid":2434, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-category\/crafting.json" + "source":"..\/..\/tilesets\/packed\/objects-by-category\/crafting.json" }, { "firstgid":2514, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-category\/wire.json" + "source":"..\/..\/tilesets\/packed\/objects-by-category\/wire.json" }, { "firstgid":2736, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-type\/teleporter.json" + "source":"..\/..\/tilesets\/packed\/objects-by-type\/teleporter.json" }, { "firstgid":2763, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/huge-objects.json" + "source":"..\/..\/tilesets\/packed\/huge-objects.json" }, { "firstgid":2864, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-colonytag\/outpost.json" + "source":"..\/..\/tilesets\/packed\/objects-by-colonytag\/outpost.json" }, { "firstgid":2968, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-colonytag\/apexresearchlab.json" + "source":"..\/..\/tilesets\/packed\/objects-by-colonytag\/apexresearchlab.json" }, { "firstgid":3019, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-category\/door.json" + "source":"..\/..\/tilesets\/packed\/objects-by-category\/door.json" }, { "firstgid":3151, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-category\/decorative.json" + "source":"..\/..\/tilesets\/packed\/objects-by-category\/decorative.json" }, { "firstgid":4592, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-category\/light.json" + "source":"..\/..\/tilesets\/packed\/objects-by-category\/light.json" }, { "firstgid":5050, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-race\/novakid.json" + "source":"..\/..\/tilesets\/packed\/objects-by-race\/novakid.json" }, { "firstgid":5114, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-category\/furniture.json" + "source":"..\/..\/tilesets\/packed\/objects-by-category\/furniture.json" }, { "firstgid":5468, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-category\/storage.json" + "source":"..\/..\/tilesets\/packed\/objects-by-category\/storage.json" }, { "firstgid":5702, - "source":"..\/..\/..\/..\/..\/Starbound\/assets\/packed\/tilesets\/packed\/objects-by-race\/human.json" + "source":"..\/..\/tilesets\/packed\/objects-by-race\/human.json" }, { "firstgid":5990, diff --git a/npcs/slut2goarcadehint.npctype b/npcs/slut2goarcadehint.npctype new file mode 100644 index 00000000..e33110ff --- /dev/null +++ b/npcs/slut2goarcadehint.npctype @@ -0,0 +1,21 @@ +{ + "type" : "slut2goarcadehint", + "baseType" : "slut2gohooker", + + "npcname" : "Arcade Hooker", + + "persistent" : true, + + "scriptConfig" : { + "behavior" : "tutorial", + + "dialog" : { + "greeting" : "/dialog/lustiaarcadehintconverse.config:greeting", + "converse" : "/dialog/lustiaarcadehintconverse.config:converse" + }, + + "questGenerator" : { + "enableParticipation" : false + } + } +} \ No newline at end of file diff --git a/objects/miscellaneous/sexscapeshops/arcadesign_off.object b/objects/miscellaneous/sexscapeshops/arcadesign_off.object new file mode 100644 index 00000000..3b7244ea --- /dev/null +++ b/objects/miscellaneous/sexscapeshops/arcadesign_off.object @@ -0,0 +1,34 @@ +{ + "objectName" : "arcadesign_off", + "colonyTags" : ["hylotl","hylotloceancity","electronic","light"], + "rarity" : "Common", + "category" : "decorative", + "price" : 150, + "lightColor" : [235, 180, 65], + + "description" : "An arcade sign. Sadly, it seems to be off.", + "shortdescription" : "Arcade Sign (off)", + "race" : "hylotl", + + "apexDescription" : "An arcade! Sadly, it seems to be closed.", + "avianDescription" : "An arcade. Too bad it seems to be closed!", + "floranDescription" : "Arcade! It not glowing though!", + "glitchDescription" : "Wanting. An amusement arcade! To bad it's closed.", + "humanDescription" : "I love arcades! Too bad it seems to be closed.", + "hylotlDescription" : "Hmm, it's been a while since my last arcade trip. Sadly it's closed.", + "novakidDescription" : "An arcade? Would be mighta fun if it wasn't closed.", + + "inventoryIcon" : "arcadesignicon_off.png", + "orientations" : [ + { + "image" : "arcadesign_off.png", + "imagePosition" : [-32, -8], + "frames" : 1, + "animationCycle" : 1, + + "spaceScan" : 0.1, + "anchors" : [ "background" ] + + } + ] +} diff --git a/objects/miscellaneous/sexscapeshops/arcadesign_off.png b/objects/miscellaneous/sexscapeshops/arcadesign_off.png new file mode 100644 index 0000000000000000000000000000000000000000..bcb3dd6f676d5c259b7ea5eac7c9bed60f68159a GIT binary patch literal 519 zcmV+i0{H!jP)^n;ud^|n2l-QSX-vqE zxLhvqHWAcXdm)6^T2JhBjWJS64**_DIp*@1ckpw6jtK5&iU5zt1BPLUo`$)#F$R=U z;GBc9EWsEvi8IDb^5|Q4&L#1O{1kOvLs1lYBG~u+(^_ji9$CCOJzn%E(+5I3_j82! zX&c1yQ~1%>G|h4W+P3vdDX6OIrJHfB$U!Q9tbnoJN1V@RP)hl#s&-i-h;NgNjSymd zSnlHjw^XnYhm`W^6wD#C;T(aV6+tdwT*Rmdp`FHu@-a4-Kh^&)A{Y`Hv~h8xEnuw; zwgk7O^3&Xy|Lr1}D?(H#(WjJ(&H+pOd?KZ}Sm0P|%!%MO3BD{8ABfQ2b}8XB}a2R@mk#c%rc)uJwm_%{-e}&VD2F4*@1K)J) v@K;cZ%+9^_{+_?VFXnY=AF7{`CCt%{Y`@+Kfy4OIk1CJOO_)9KulH50q3bJIASn@X&a&FC;X;u3YvEfU3K z%QQw37&;W^)cKOAlRAlrBMRFnP(eV3EIJT7q0)V5xM^v5@#RaC{=eM&+;h%zpWi*t zbI!Tol1nbREecYTCE_W>=+~O?f<>(d8Y|xs`2Ccce zFxI?YzU0iHHD#9>6_eC=iq4+Z2G5@Q*$ps1%~x?2rKK))lL910B++!D(_tsCU^)LbwgV8PmNDXb6s?U$o{YW) zfRAyqXiKW20mQc6Z0lz}#>oJ*HW~r&40adqtra+ZFn?cs>@Y^pV0RlIKGVBMUOUZA ztij%74d)ds2Rg*yl!?tq-6iPHU4zk}Ol-!0C1_=0Gk`-|QXOqGzP_Z4juKU$aDAyK zoW*XpU1SCZXVHE4YbX<&X(|uJc)vpgFcbxdSD<&BTjF?tfCmLkT@{Yo&;atkp2dPy zxd2=_S4(}>XU_mPfPK&rT(=D%b(dhg-(iz-%EV?mTkA01(b3sjX9H(f`0f%yD%ot8mS^#C-Lhg#}y zx~0#e-%S^~&T*P95goy)hI8AgPYVP!vE@ zc_>2~W9TSRiFQYcitMgjmhIea3Etn6Ez2!|e=@d8tjB!Q5e}C9L{Z>H5iV1!U{uIR z)-3VnE7N8XxM!-0fOc^4z5tkp1aUee6@WYXCUhrnSe9*L4#MCR+A8wNC@Ll~eg?we z6pD&3F#r86Xm)9NbfO#p+0A>Her=%P{6TSR7}6L+c2_QfT7#h0Fl)tT0JiSW0buHD z;Q%aHm5ZmpCkIm{$bE(}X0Zq3<7FHw@Lbly^P-F9Kde1gWnCGVp)PRFiH=F-d^YrgQ6Vy3MmGlg5dQPEeqN zjVHZXcHjvg{GcEt#2?iJDX+&26X8O9!};ZO6`5KE8#+I-|KZ)b_Dl1i;bz*}+5qtI z@DT5<6%`dld3ia4AUIszbUK}7HUt5=+_Ffuw_8$QE|*hUYB}Z|zNkk~Ysf2HL#9^2 zlrf{(aOein!@ogyqJUSUeE^s}d$yeqfYQ=ZT3TAf_jI>+%d8(}f0F4B&RP>EPV5sf zE-ubezb2EV4y00>z^qkJ+zM3N`SSDgBQi45&IiERvuDNkbhq1_m-SVSYj7ZN-AYMG zv9XUGJ0=DOpjKP9im7s z_UUeS6o*ZUhJ+>!_-`WN-GwjYq^}$k>F~MXuRosKcVlG*za8Iao1$Tp#`in0?)uGM s1A9?=5&j!1E1rD@okb1xm)!vV2hgZ;bVf+a0ssI207*qoM6N<$g6%WtJ^%m! literal 0 HcmV?d00001 diff --git a/objects/miscellaneous/sexscapeshops/sexbound_cardshopflip_empty.png b/objects/miscellaneous/sexscapeshops/sexbound_cardshopflip_empty.png new file mode 100644 index 0000000000000000000000000000000000000000..ca2e2489f3c8b1514ff094da5cf6da938c00bd73 GIT binary patch literal 1619 zcmV-Z2CVssP)U zj-!*W88(D3jHMylfE8qdhPO|%c@{JjP;?#@IYwWPSdisqjquypkNO|C3d_yzixsYVfNpsmK? z@6!+s4_*~j?@lD$9x}JLs8j9_S%+_-$(N$Zm-5)Vp)`6eBI9c%?QJR8EWJW|IpM5Q zU-{ggIxLs9SUa0s+by=4s5$LIt2)U9DP@A}91lpaZ>8>qWLETgS{g5~X>B?YQ6WS` zg|Ip;75@=K0I+oQ@Q3n@AUiAN#JN3n%vu-E)Ys-QGB^y&WvyV-m4%`!3&m#XB`9bM zPexw6Cz9Uo_K_1?LvvVTUCzo&X#t;YfCsktcthOhEu2WBXhA2@0EPX^TSj4Zs>7Nx1OW2tBN@9SW;K+ zW>lw+O3MRmSeiz8Z7oT&r;@TZm!IrsnWUeAMQY{h1wZUHF_`Hgpd%5z{suk`aa`*% zV=Xn&Y`DS-*-Cz_tU%J>kG0fIYvNY( z4jvlyJBFSo={8yEHdzT$%8)91IZ<)^Lzfoa8k$3PMhJ~97ddvOi?`E;v-4m8@hU0f z76l+1F^nBcd{kl7@m?yYXvH5cXjE&MLa<4)HS~vTg}BKLr3& zRKcjDKM_^3-xh6bxk!242;x;zjvlEef7f-QAC+Kk4(HvE3do�e~G#d|13U1f6UZ zI@v0on=r}Y-`{q+@ZizJ ztE4oxT;$n=VMISFAv}B}i}!}``u1Md77s@e79t!fQzktk3S6zvqFSFN(ybmko$IG` zj9)RI?zS!f%3t|ZAOuiWaRNX@?9jS&w8d2{%qd`0l!8O+(uJ5)RKch;bKO=_^uk-5 zS8Df)>JlX+lgTif&1kh+2c4hP<|N6EcIWESnURQhm zzPwG8@7Z_Pb6c8EiCeV41P&x8F{@K308!T_Qg Rg3 zZA?>F7{`C5Wv()LvAhWdR~^+tCon1!FTO+$_M#N66b{}qfZCAmV_@N*A|8nnh?!Eu> zyU#i2IR^p?D4>7>3Mim}0t(1a)n1$KlKCs#-qpD9XE>L&#O1P&^`xZkVcVnd^U0cH%$<)7|B0Ah{7BwR>g zpxeRSiOm2+IHpRmyj>3RMA1z@1t0YGS+Qo8q4%axr+;Hwp z0w|Pn9DPGxL#D~Lb7!Cn$6sdd40L(H`TVs~j@odI*c2O`E+Zv};^>gQ&eXNhLeBFBo$lAin-cxnNn@}L*WLx9Vjx#u7R--966qZq~**S|1MR#K0!0H zL>f8()4xqjCy~`(ZKC3BqmQZQu*Rm?0O)B^i}P=`_|B3Q8wiaGMK{er)%61uC>9M1 zSJYW3W>CmYXWqtL-0AHE;JW#1Mz!_QYO>I3vLJ8Q(`vG?!RstQS)SXDnkugDIRLjQh9GLOE-TZb{-YV$1B8+-=Ewj&BrR|0d_Zi zPhHF@32uFfiV5*gBkTTlo~yq4N3kT#DWdPh4(V^62|q+#{YlDi{>16Ip8`-LRJvW*BUM~G-tgIP5!wahU zS}D!fO1;`LGm@o66C0zV>}WVkcim;#J{9rtQD~#EI<8(pR$g8%on}%}QfO&u zK@fxot}e6L41gdAgoKFYX>d@i03jhEG&YLc_rr_(9cJ%z%{*i+T@13AdK)9EBHFHiCS*t&JA^p4Z%L>8}};dNlmdadBGoI*5{bPsH|{`vc(?Zt^1 q&q_hpg-gR4KQ2A0zfT7JP5%K>W$Z5)r~yX+0000F7{`CCt%{Y`@+Kfy4OIk1CJOO_)9KulH50q3bJIASn@X&a&FC;X;u3YvEfU3K z%QQw37&;W^)cKOAlRAlrBMRFnP(eV3EIJT7q0)V5xM^v5@#RaC{=eM&+;h%zpWi*t zbI!Tol1nbREecYTCE_W>=+~O?f<>(d8Y|xs`2Ccce zFxI?YzU0iHHD#9>6_eC=iq4+Z2G5@Q*$ps1%~x?2rKK))lL910B++!D(_tsCU^)LbwgV8PmNDXb6s?U$o{YW) zfRAyqXiKW20mQc6Z0lz}#>oJ*HW~r&40adqtra+ZFn?cs>@Y^pV0RlIKGVBMUOUZA ztij%74d)ds2Rg*yl!?tq-6iPHU4zk}Ol-!0C1_=0Gk`-|QXOqGzP_Z4juKU$aDAyK zoW*XpU1SCZXVHE4YbX<&X(|uJc)vpgFcbxdSD<&BTjF?tfCmLkT@{Yo&;atkp2dPy zxd2=_S4(}>XU_mPfPK&rT(=D%b(dhg-(iz-%EV?mTkA01(b3sjX9H(f`0f%yD%ot8mS^#C-Lhg#}y zx~0#e-%S^~&T*P95goy)hI8AgPYVP!vE@ zc_>2~W9TSRiFQYcitMgjmhIea3Etn6Ez2!|e=@d8tjB!Q5e}C9L{Z>H5iV1!U{uIR z)-3VnE7N8XxM!-0fOc^4z5tkp1aUee6@WYXCUhrnSe9*L4#MCR+A8wNC@Ll~eg?we z6pD&3F#r86Xm)9NbfO#p+0A>Her=%P{6TSR7}6L+c2_QfT7#h0Fl)tT0JiSW0buHD z;Q%aHm5ZmpCkIm{$bE(}X0Zq3<7FHw@Lbly^P-F9Kde1gWnCGVp)PRFiH=F-d^YrgQ6Vy3MmGlg5dQPEeqN zjVHZXcHjvg{GcEt#2?iJDX+&26X8O9!};ZO6`5KE8#+I-|KZ)b_Dl1i;bz*}+5qtI z@DT5<6%`dld3ia4AUIszbUK}7HUt5=+_Ffuw_8$QE|*hUYB}Z|zNkk~Ysf2HL#9^2 zlrf{(aOein!@ogyqJUSUeE^s}d$yeqfYQ=ZT3TAf_jI>+%d8(}f0F4B&RP>EPV5sf zE-ubezb2EV4y00>z^qkJ+zM3N`SSDgBQi45&IiERvuDNkbhq1_m-SVSYj7ZN-AYMG zv9XUGJ0=DOpjKP9im7s z_UUeS6o*ZUhJ+>!_-`WN-GwjYq^}$k>F~MXuRosKcVlG*za8Iao1$Tp#`in0?)uGM s1A9?=5&j!1E1rD@okb1xm)!vV2hgZ;bVf+a0ssI207*qoM6N<$g6%WtJ^%m! literal 0 HcmV?d00001 diff --git a/tilesets/packed/objects-special/sexscape_tileset.json b/tilesets/packed/objects-special/sexscape_tileset.json index 38ad45ef..06a8ce79 100644 --- a/tilesets/packed/objects-special/sexscape_tileset.json +++ b/tilesets/packed/objects-special/sexscape_tileset.json @@ -1,12 +1,4 @@ { "columns":0, - "editorsettings": - { - "export": - { - "format":"", - "target":"." - } - }, "grid": { "height":1, @@ -16,8 +8,8 @@ "margin":0, "name":"lustbound_tileset", "spacing":0, - "tilecount":17, - "tiledversion":"1.3.5", + "tilecount":19, + "tiledversion":"1.8.0", "tileheight":88, "tileproperties": { @@ -105,6 +97,25 @@ "object":"sexbound_cardshop", "tilesetDirection":"right" }, + "17": + { + "\/\/description":"A stall that, one day, will sell Monster Girl Cards and related items.", + "\/\/name":"sexbound_cardshop_empty", + "\/\/shortdescription":"Card Sex Shop", + "imagePositionX":"-28", + "imagePositionY":"0", + "object":"sexbound_cardshop_empty", + "tilesetDirection":"right" + }, + "19": + { + "\/\/description":"An arcade sign. Sadly, it seems to be closed.", + "\/\/name":"arcadesign_off", + "\/\/shortdescription":"Arcade Sign (off)", + "imagePositionX":"-32", + "imagePositionY":"-8", + "object":"arcadesign_off" + }, "2": { "\/\/description":"These small bricks are masterfully crafted.", @@ -272,6 +283,25 @@ "object":"string", "tilesetDirection":"string" }, + "17": + { + "\/\/description":"string", + "\/\/name":"string", + "\/\/shortdescription":"string", + "imagePositionX":"string", + "imagePositionY":"string", + "object":"string", + "tilesetDirection":"string" + }, + "19": + { + "\/\/description":"string", + "\/\/name":"string", + "\/\/shortdescription":"string", + "imagePositionX":"string", + "imagePositionY":"string", + "object":"string" + }, "2": { "\/\/description":"string", @@ -409,6 +439,18 @@ "imageheight":40, "imagewidth":56 }, + "17": + { + "image":"..\/..\/..\/objects\/miscellaneous\/sexscapeshops\/sexbound_cardshoptiled_empty.png", + "imageheight":40, + "imagewidth":56 + }, + "19": + { + "image":"..\/..\/..\/objects\/miscellaneous\/sexscapeshops\/arcadesign_off.png", + "imageheight":24, + "imagewidth":64 + }, "2": { "image":"tombbrick3.png", @@ -458,7 +500,7 @@ "imagewidth":34 } }, - "tilewidth":56, + "tilewidth":64, "type":"tileset", "version":1.1 } \ No newline at end of file From e04f668a89ec6b55cc46282342c32a28e5353da0 Mon Sep 17 00:00:00 2001 From: notlexander Date: Sun, 29 Sep 2024 16:29:23 -0500 Subject: [PATCH 02/12] Putting unchanged sexbound defeat into the project for the first time. --- interface/sexbound/defeat.config | 38 ++ interface/sexbound/defeat.lua | 34 ++ interface/sexbound/defeatbody.png | Bin 0 -> 790 bytes npcs/base.npctype.patch | 6 + .../sexbound_main_node.object.patch | 7 + .../sexbound_main_node_centered.object.patch | 7 + player.config.patch | 12 + scripts/sexboundaddons/playerDefeat.lua | 24 + sexbound-defeat.config | 83 ++++ stats/sexbound/monster_primary.lua | 22 + stats/sexbound/npc_primary.lua | 22 + stats/sexbound/player_primary.lua | 23 + stats/sexbound/readme.txt | 10 + stats/sexbound/sexbounddefeat.lua | 444 ++++++++++++++++++ 14 files changed, 732 insertions(+) create mode 100644 interface/sexbound/defeat.config create mode 100644 interface/sexbound/defeat.lua create mode 100644 interface/sexbound/defeatbody.png create mode 100644 objects/sexbound_node/sexbound_main_node.object.patch create mode 100644 objects/sexbound_node/sexbound_main_node_centered.object.patch create mode 100644 scripts/sexboundaddons/playerDefeat.lua create mode 100644 sexbound-defeat.config create mode 100644 stats/sexbound/monster_primary.lua create mode 100644 stats/sexbound/npc_primary.lua create mode 100644 stats/sexbound/player_primary.lua create mode 100644 stats/sexbound/readme.txt create mode 100644 stats/sexbound/sexbounddefeat.lua diff --git a/interface/sexbound/defeat.config b/interface/sexbound/defeat.config new file mode 100644 index 00000000..07ef4cb2 --- /dev/null +++ b/interface/sexbound/defeat.config @@ -0,0 +1,38 @@ +{ + "scripts" : ["/interface/sexbound/defeat.lua"], + + "scriptDelta" : 2, + + "scriptWidgetCallbacks" : [], + + "canvasClickCallbacks" : { + "interface" : "canvasClickEvent" + }, + + "canvasKeyCallbacks" : { + "interface" : "canvasKeyEvent" + }, + + "gui" : { + "panefeature" : { + "type" : "panefeature", + "anchor" : "center", + "positionLocked" : true + }, + "background" : { + "type" : "background", + "fileHeader" : "", + "fileBody" : "/interface/sexbound/defeatbody.png", + "fileFooter": "" + }, + "interface" : { + "type" : "canvas", + "rect" : [0, 0, 10, 10], + "captureKeyboardEvents" : true, + "captureMouseEvents" : true, + "zlevel" : 1 + } + }, + + "config" : {} +} \ No newline at end of file diff --git a/interface/sexbound/defeat.lua b/interface/sexbound/defeat.lua new file mode 100644 index 00000000..d5e38e9f --- /dev/null +++ b/interface/sexbound/defeat.lua @@ -0,0 +1,34 @@ +require "/scripts/messageutil.lua" + +function init() + self.config = config.getParameter("config") + self.canvas = widget.bindCanvas("interface") + self.promise = PromiseKeeper.new() + widget.focus("interface") +end + +function update(dt) + self.promise:add( + world.findUniqueEntity(self.config.nodeUniqueId), + function(result) return end, + function() + pane.dismiss() + end + ) + + self.promise:update() + + self.canvas:clear() +end + +function canvasClickEvent(position, button, isButtonDown) + +end + +function canvasKeyEvent(key, isKeyDown) + +end + +function dismissed() + world.sendEntityMessage(player.id(), "SexboundDefeat:Breakout") +end \ No newline at end of file diff --git a/interface/sexbound/defeatbody.png b/interface/sexbound/defeatbody.png new file mode 100644 index 0000000000000000000000000000000000000000..5d0511451184b0c89a135cd777af252fcaee012e GIT binary patch literal 790 zcmeAS@N?(olHy`uVBq!ia0y~yV2WU1VASDY1B%Goo}C7y7>k44ofy`glX(f0z2NEM z7*a9k?LkIfpwyuS-~Ds>*+qcNQ7{?;LoWnA= self._timeout or not self:isStunned() then + self:setIsDefeated(false) + self:setIsTransformed(false) + self:setTimer(0) + self:untransform() + end + end + + -- Return when is defeated to prevent the default update loop from running + if self:isDefeated() then return end + + oldUpdate(dt) +end + +--- Returns back species name retrieved with the default world API. +--- MonsterType is considered as a species by Sexbound +function SexboundDefeat:findSpecies() + if self:isMonster() then + return world.monsterType(self._entityId) + end + if self:isPlayer() or self:isNPC() then + return world.entitySpecies(self._entityId) + end + return "default" +end + +function SexboundDefeat:handleApplyDamageRequest(originalFunction, damageRequest) + -- Do not return damage while the entity isDefeated is true + if self:isDefeated() then return {} end + + -- Otherwise use the original applyDamageRequest function to process the incoming damage + local damage = originalFunction(damageRequest) + + -- When the this entity's health is greater than 0, generate damage + if status.resource("health") > 0 then return damage end + + -- Store a reference to the hostile entity id that delivered the killing blow to this entity + self._hostileEntityId = damageRequest.sourceEntityId + if self._hostileEntityId ~= nil then + self._hostileEntityType = world.entityType(self._hostileEntityId) + end + + -- Handle the case that the entity has given itself a killing blow + if self:isSuicide() then + self:tryToDie() + return {} + end + + -- Prevent the entity from dying by ticking its health up by a percentage point + status.setResourcePercentage("health", 0.01) + + -- Set this entity as isDefeated + self:setIsDefeated(true) + + -- Reset the defeat timer to 0 + self:setTimer(0) + + -- Attempt to transform this entity into a sexnode + self:retrieveSexboundConfig(function(result) + return self:handleRetrieveSexboundConfigSuccess(result) + end, function() + return self:handleRetrieveSexboundConfigFailure() + end) + + return {} +end + +function SexboundDefeat:loadConfig() + local _,loadedConfig = xpcall(function() + return root.assetJson(self._configFilePath) + end, function(err) + sb.logError("Unable to load config file for Sexbound Defeat!") + end) + return loadedConfig +end + +function SexboundDefeat:outputDefeatedDialog() + if self:isNPC() and not self._config.enableStartDialogForNPCs then return end + if self:isMonster() and not self._config.enableStartDialogForMonsters then return end + local species = self:findSpecies() + local defeatedDialog = self._config.startDialog.defeated[species] or + self._config.startDialog.defeated.default + world.sendEntityMessage( + self._entityId, "Sexbound:Actor:Say", + { + message = util.randomChoice(defeatedDialog) + } + ) +end + +function SexboundDefeat:outputVictoryDialog() + if self._hostileEntityType == "npc" and not self._config.enableStartDialogForNPCs then return end + if self._hostileEntityType == "monster" and not self._config.enableStartDialogForMonsters then return end + local controllerSpecies = world.entitySpecies(self._hostileEntityId) + local victoryDialog = self._config.startDialog.victory[controllerSpecies] or + self._config.startDialog.victory.default + world.sendEntityMessage( + self._hostileEntityId, "Sexbound:Actor:Say", + { + message = util.randomChoice(victoryDialog) + } + ) +end + +function SexboundDefeat:retrieveSexboundConfig(successCallback, failureCallback) + self._promises:add( + world.sendEntityMessage( + self._hostileEntityId, + "Sexbound:Config:Retrieve" + ), + successCallback, + failureCallback + ) +end + +function SexboundDefeat:handleRetrieveSexboundConfigSuccess(sexboundConfig) + -- Output the victory dialog + self:outputVictoryDialog() + self:transform(sexboundConfig, function(result) + result = result or {} + if result.uniqueId == nil then + self:setIsDefeated(false) + self:tryToDie() + return + end + return self:handleTransformSuccess(result.uniqueId) + end, function() + return self:handleTransformFailed() + end) +end + +function SexboundDefeat:handleRetrieveSexboundConfigFailure() + self:setIsDefeated(true) + self:tryToDie() +end + +function SexboundDefeat:transform(sexboundConfig, successCallback, failureCallback) + self._promises:add( + world.sendEntityMessage( + self._entityId, + "Sexbound:Transform", + { + responseRequired = true, + sexboundConfig = sexboundConfig, + timeout = 500 + } + ), + successCallback, + failureCallback + ) +end + +function SexboundDefeat:handleTransformFailed() + self:setIsDefeated(false) + self:setIsTransformed(false) + self:tryToDie() + return false +end + +function SexboundDefeat:handleTransformSuccess(nodeUniqueId) + self._sexNodeId = nodeUniqueId + self:setIsDefeated(true) + self:setIsTransformed(true) + self:setTimer(0) + self:outputDefeatedDialog() + if self:isPlayer() then + if self._config.defeatedPlayersCanUseSexUI then + self._promises:add(world.sendEntityMessage(self._sexNodeId, "Sexbound:Retrieve:UIConfig"), function(config) + world.sendEntityMessage(self._entityId, "Sexbound:UI:Show", {config = config}) + end) + else + world.sendEntityMessage(self._entityId, "Sexbound:UI:Show", {config = self:loadUIConfig()}) + end + status.addEphemeralEffect("dontstarve", self._timeout) + status.addEphemeralEffect("regeneration4", self._timeout) + end + + status.addEphemeralEffect("sexbound_sex", self._timeout) + status.addEphemeralEffect("sexbound_stun", self._timeout) + + -- Try to notify the controlling entity to mount the defeated player. + if (self._sexNodeId and self._hostileEntityId) then + self._promises:add(world.sendEntityMessage(self._sexNodeId, "Sexbound:Retrieve:ControllerId"), function(controllerId) + world.sendEntityMessage(self._hostileEntityId, "notify", {type = "sexbound.setup", targetId = controllerId}) + end) + end + + return true +end + +function SexboundDefeat:loadUIConfig() + local _,_config = xpcall(function() + return root.assetJson(self._uiConfigFilePath) + end, function(error) + sb.logError("Unable to load config file for the Sexbound Defeat!") + end) + _config.config.nodeUniqueId = self._sexNodeId + return _config or {} +end + +function SexboundDefeat:tryToDie() + if not self:isPlayer() and self:isPregnant() and self._config.enableImmortalPregnantNPCs then + local species = self:findSpecies() + local pregnantDialog = self._config.pregnantDialog[species] or self._config.pregnantDialog.default + world.sendEntityMessage(self._entityId, "Sexbound:Actor:Say", {message = util.randomChoice(pregnantDialog)}) + status.setResourcePercentage("health", 1.0) + else + status.setResourcePercentage("health", 0) + end +end + +function SexboundDefeat:smashSexNode(storage) + if not self._sexNodeId then return end + world.sendEntityMessage(self._sexNodeId, "Sexbound:Smash", { storage = storage }) +end + +-- [Helper] Untransform the Entity +function SexboundDefeat:untransform() + if not self:isPlayer() then self:tryToDie() end + local storage = {} -- temp local storage + if not self:isPlayer() and self:isPregnant() and self._config.convertPregnantEnemiesToFriends then + storage = { previousDamageTeam = { type = "friendly", team = 1 } } + end + self:smashSexNode(storage) + if not self._hostileEntityId then return end + if self._hostileEntityType == "player" then return end + world.sendEntityMessage(self._hostileEntityId, "Sexbound:Actor:Respawn") + self._hostileEntityId = nil + self._hostileEntityType = nil + self._sexNodeId = nil + status.removeEphemeralEffect("regeneration4") +end + +-- Validate Configuration +function SexboundDefeat:validateConfig() + self:_validateConvertPregnantEnemiesToFriends(self._config.convertPregnantEnemiesToFriends, false) + self:_validateDefeatedPlayersCanUseSexUI(self._config.defeatedPlayersCanUseSexUI, false) + self:_validateDefeatTimeoutMonster(self._config.defeatTimeoutMonster, 60) + self:_validateDefeatTimeoutNPC(self._config.defeatTimeoutNPC, 60) + self:_validateDefeatTimeoutPlayer(self._config.defeatTimeoutPlayer, 30) + self:_validateEnableImmortalPregnantNPCs(self._config.enableImmortalPregnantNPCs, false) + self:_validateEnableStartDialogForNPCs(self._config.enableStartDialogForNPCs, true) + self:_validateEnableStartDialogForMonsters(self._config.enableStartDialogForMonsters, false) +end + +-- Getters / Setters +function SexboundDefeat:getConfig() + return self._config +end + +function SexboundDefeat:getTimer() + return self._timer +end + +function SexboundDefeat:getTimeout() + return self._timeout +end + +function SexboundDefeat:isDefeated() + return self._isDefeated +end + +function SexboundDefeat:isMonster() + return self._entityType == "monster" +end + +function SexboundDefeat:isNPC() + return self._entityType == "npc" +end + +function SexboundDefeat:isPlayer() + return self._entityType == "player" +end + +function SexboundDefeat:isPregnant() + return status.statusProperty("sexbound_pregnant") +end + +function SexboundDefeat:isStunned() + return status.statusProperty("sexbound_stun") +end + +function SexboundDefeat:isSuicide() + return self._hostileEntityId == nil or self._hostileEntityId == self._entityId +end + +function SexboundDefeat:isTransformed() + return self._isTransformed or false +end + +function SexboundDefeat:setIsDefeated(isDefeated) + self._isDefeated = isDefeated +end + +function SexboundDefeat:setIsTransformed(isTransformed) + self._isTransformed = isTransformed +end + +function SexboundDefeat:setTimer(value) + self._timer = value +end + +function SexboundDefeat:setTimeout(value) + self._timeout = value +end + +-- Misc. helper functions +function SexboundDefeat:_initTimeout() + if self:isMonster() then + self:setTimeout(util.randomInRange(self._config.defeatTimeoutMonster)) + return + end + if self:isNPC() then + self:setTimeout(util.randomInRange(self._config.defeatTimeoutNPC)) + return + end + if self:isPlayer() then + self:setTimeout(util.randomInRange(self._config.defeatTimeoutPlayer)) + return + end +end + +function SexboundDefeat:_isBoolean(value) + return type(value) == "boolean" +end + +function SexboundDefeat:_isPositiveNumberOrNumberRange(value) + if type(value) == "number" and value > 0 then return true end + if type(value) == "table" and #value == 2 then + if type(value[1]) ~= "number" or value[1] <= 0 then return false end + if type(value[2]) ~= "number" or value[2] <= 0 then return false end + return true + end + return false +end + +function SexboundDefeat:_logWarnInvalidValueProvided(optionName, value) + local msg = "Invalid value was set for '" .. optionName .. "' option in " .. self._configFilePath .. " - " + msg = msg .. "Falling back to use the default value: " .. sb.printJson(value) + sb.logWarn(msg) +end + +function SexboundDefeat:_validateConvertPregnantEnemiesToFriends(value, defaultValue) + if self:_isBoolean(value) then return end + self:_logWarnInvalidValueProvided("convertPregnantEnemiesToFriends", defaultValue) + self._config.convertPregnantEnemiesToFriends = defaultValue +end + +function SexboundDefeat:_validateDefeatedPlayersCanUseSexUI(value, defaultValue) + if self:_isBoolean(value) then return end + self:_logWarnInvalidValueProvided("defeatedPlayersCanUseSexUI", defaultValue) + self._config.defeatedPlayersCanUseSexUI = defaultValue +end + +function SexboundDefeat:_validateDefeatTimeoutMonster(value, defaultValue) + if self:_isPositiveNumberOrNumberRange(value) then return end + self:_logWarnInvalidValueProvided("defeatTimeoutMonster", defaultValue) + self._config.defeatTimeoutMonster = defaultValue +end + +function SexboundDefeat:_validateDefeatTimeoutNPC(value, defaultValue) + if self:_isPositiveNumberOrNumberRange(value) then return end + self:_logWarnInvalidValueProvided("defeatTimeoutNPC", defaultValue) + self._config.defeatTimeoutNPC = defaultValue +end + +function SexboundDefeat:_validateDefeatTimeoutPlayer(value, defaultValue) + if self:_isPositiveNumberOrNumberRange(value) then return end + self:_logWarnInvalidValueProvided("defeatTimeoutPlayer", defaultValue) + self._config.defeatTimeoutPlayer = defaultValue +end + +function SexboundDefeat:_validateEnableImmortalPregnantNPCs(value, defaultValue) + if self:_isBoolean(value) then return end + self:_logWarnInvalidValueProvided("enableImmortalPregnantNPCs", defaultValue) + self._config.enableImmortalPregnantNPCs = defaultValue +end + +function SexboundDefeat:_validateEnableStartDialogForNPCs(value, defaultValue) + if self:_isBoolean(value) then return end + self:_logWarnInvalidValueProvided("enableStartDialogForNPCs", defaultValue) + self._config.enableStartDialogForNPCs = defaultValue +end + +function SexboundDefeat:_validateEnableStartDialogForMonsters(value, defaultValue) + if self:_isBoolean(value) then return end + self:_logWarnInvalidValueProvided("enableStartDialogForMonsters", defaultValue) + self._config.enableStartDialogForMonsters = defaultValue +end \ No newline at end of file From abed2469a123b3d4b2d255a0d9761f51601da4c9 Mon Sep 17 00:00:00 2001 From: notlexander Date: Mon, 30 Sep 2024 17:13:10 -0500 Subject: [PATCH 03/12] SBR Defeat Integration updated + stabilized >enabled defeated status detection for sexbound >disables UI based on config setting >enables NPC auto position and auto climax against defeated players >increased climax speed on defeat nodes >updated transform code >scans a wider area (default was a single block) >removed "occupied" detection as it was redundant and innaccurate --- interface/sexbound/common/custombutton.lua | 4 + scripts/sexbound/lib/sexbound.lua | 34 +++++++-- scripts/sexbound/lib/sexbound/actor.lua | 1 + .../sexbound/override/common/transform.lua | 72 +++++++++++------- scripts/sexbound/override/player.lua | 3 +- .../sexbound/override/player/transform.lua | 8 +- scripts/sexbound/plugins/climax/climax.lua | 15 +++- sexbound-defeat.config | 4 +- stats/sexbound/sexbounddefeat.lua | 75 +++++++++---------- 9 files changed, 130 insertions(+), 86 deletions(-) diff --git a/interface/sexbound/common/custombutton.lua b/interface/sexbound/common/custombutton.lua index f9fbb0e8..20af2f7e 100644 --- a/interface/sexbound/common/custombutton.lua +++ b/interface/sexbound/common/custombutton.lua @@ -255,4 +255,8 @@ function CustomButton:setNewImage(image, imageOffset) else self.config.image = nil end +end + +function CustomButton:setEnabled(enabled) + self.config.enabled = not not enabled end \ No newline at end of file diff --git a/scripts/sexbound/lib/sexbound.lua b/scripts/sexbound/lib/sexbound.lua index b7a5990a..a90ca23c 100644 --- a/scripts/sexbound/lib/sexbound.lua +++ b/scripts/sexbound/lib/sexbound.lua @@ -44,7 +44,9 @@ function Sexbound.new(maxActors) _globalActorId = 0, _uiSyncTokens = {positions=0}, _containsPlayer = false, - _sexMusicListeners = {} + _sexMusicListeners = {}, + _containsDefeated = false, + _playerControl = false }, Sexbound_mt) -- Store UUID of the entity running this instance of Sexbound. @@ -336,21 +338,29 @@ function Sexbound:addActor(actorConfig, store) --actor:getApparel():sync() --actor:initPlugins() - - if actor:getEntityType() == "player" then self._containsPlayer = true end - + self._positions:filterPositions(self._actors) self._UI:refresh() - actor:openUI() + + if actor:getStatus():hasStatus("sexbound_defeated") then self._containsDefeated = true end + + if actor:getEntityType() == "player" then + self._containsPlayer = true + -- Open UI if not defeated or is allowed to while defeated. + if not actor:getStatus():hasStatus("sexbound_defeated") or actor:getStatus():hasStatus("sexbound_defeated_can_use_ui") then + actor:openUI() + self._playerControl = true + end + end -- Resort actors based on changed environment self:helper_reassignAllRoles() if self._config.position.forceJoin then self._positions:switchPosition(self._config.position.forceJoin) - -- If we only have NPCs, try to initiate sex (switch from idle to a random available position) - elseif not self._containsPlayer and self._config.sex.npcStartSex then + -- If we have no controlling player, try to initiate sex (switch from idle to a random available position) + elseif not self._playerControl and self._config.sex.npcStartSex then self._positions:switchRandomSexPosition(true) end @@ -376,10 +386,13 @@ function Sexbound:removeActor(entityId) self:getLog():debug("Officially removed actor for entity "..tostring(entityId).." - new count: "..#self._actors) local containsPlayer = false + local containsDefeated = false for _,a in ipairs(self._actors) do - if a:getEntityType() == "player" then containsPlayer = true break end + if a:getEntityType() == "player" then containsPlayer = true end + if a:getStatus():hasStatus("sexbound_defeated") then containsDefeated = true end end self._containsPlayer = containsPlayer + self._containsDefeated = containsDefeated self._positions:filterPositions(self._actors) self:helper_reassignAllRoles() @@ -1480,6 +1493,11 @@ function Sexbound:getContainsPlayer() return self._containsPlayer end +--- Returns if the node currently contains a defeated actor +function Sexbound:getContainsDefeated() + return self._containsDefeated +end + --- Returns a reference to this instance's sextalk manager function Sexbound:getSextalk() return self._sextalk diff --git a/scripts/sexbound/lib/sexbound/actor.lua b/scripts/sexbound/lib/sexbound/actor.lua index f4734e03..4b34c066 100644 --- a/scripts/sexbound/lib/sexbound/actor.lua +++ b/scripts/sexbound/lib/sexbound/actor.lua @@ -642,6 +642,7 @@ function Sexbound.Actor:setup(actorConfig) if self._config.arousedStrong then actorStatus:addStatus("sexbound_aroused_strong") end if self._config.inHeat then actorStatus:addStatus("sexbound_aroused_heat") end if self._config.isDefeated then actorStatus:addStatus("sexbound_defeated") end + if self._config.canUseSexUIDefeated then actorStatus:addStatus("sexbound_defeated_can_use_ui") end if self._config.identity.sxbNaturalStatus then for _,s in ipairs(self._config.identity.sxbNaturalStatus) do diff --git a/scripts/sexbound/override/common/transform.lua b/scripts/sexbound/override/common/transform.lua index 446ca5ac..959d7b28 100644 --- a/scripts/sexbound/override/common/transform.lua +++ b/scripts/sexbound/override/common/transform.lua @@ -23,9 +23,8 @@ function Sexbound.Common.Transform:init(parent) self._feetOffset = self:calculateFeetPositionOffset() end ---- Returns a nearby position within the specified rectangle. --- @param rectSize -function Sexbound.Common.Transform:findNearbyOpenSpace(rectSize) +--- Returns 5 nearby positions within 10 blocks underneath the entity. +function Sexbound.Common.Transform:findNearbyOpenSpace() local yOffset = 0.5 local startPosition = entity.position() @@ -34,28 +33,34 @@ function Sexbound.Common.Transform:findNearbyOpenSpace(rectSize) local endPosition = vec2.add(startPosition, {0, -10}) local position = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) - - if position == nil then - return false + startPosition[1] = startPosition[1] - 1 + local positionL = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) + startPosition[1] = startPosition[1] - 1 + local positionLL = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) + startPosition[1] = startPosition[1] + 3 + local positionR = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) + startPosition[1] = startPosition[1] + 1 + local positionRR = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) + + if position == nil and positionL == nil and positionLL == nil and positionR == nil and positionRR == nil then + return false, false, false, false, false end position = vec2.floor(position) + positionL = vec2.floor(positionL) + positionLL = vec2.floor(positionLL) + positionR = vec2.floor(positionR) + positionRR = vec2.floor(positionRR) - if not world.tileIsOccupied(position, true) then - return position - end - return false + return position, positionL, positionLL, positionR, positionRR end ---- Attempts to place a sex node at a specified position. +--- Attempts to place a sex node beneath an entity. -- @param position -- @param spawnOptions -function Sexbound.Common.Transform:placeSexNode(position, spawnOptions) - local dungeonId = Sexbound.Util.tileProtectionDisable(position) - local result = self:helper_SpawnSexNode(position, spawnOptions) - - Sexbound.Util.tileProtectionEnable(dungeonId) +function Sexbound.Common.Transform:placeSexNode(spawnOptions) + local result = self:helper_SpawnSexNode(spawnOptions) return result end @@ -79,10 +84,21 @@ function Sexbound.Common.Transform:calculateFeetPositionOffset() return 2.5 -- Else take a wild guess that it's 2.5 end --- [Helper] Handles the process of spawning a sex node at a specified position. +-- [Helper] Handles the process of spawning a sex node in a tile beneath the entity. -- @param position -- @param spawnOptions -function Sexbound.Common.Transform:helper_SpawnSexNode(position, spawnOptions) +function Sexbound.Common.Transform:helper_SpawnSexNode(spawnOptions) + + local position, positionL, positionLL, positionR, positionRR = self:findNearbyOpenSpace() + + local targetTiles = { + [1] = position, + [2] = positionL, + [3] = positionR, + [4] = positionLL, + [5] = positionRR + } + spawnOptions = spawnOptions or {} local params = { @@ -105,16 +121,22 @@ function Sexbound.Common.Transform:helper_SpawnSexNode(position, spawnOptions) facingDirection = mcontroller.facingDirection() end - if world.placeObject(self._nodeName, position, facingDirection, params) then - self:setPosition(position[1], position[2] + self._feetOffset) - - if not spawnOptions.noEffect then - world.sendEntityMessage(entity.id(), "applyStatusEffect", "sexbound_transform") + -- Iterate through list of scanned tile positions until node is placed. + for _, targetTile in ipairs(targetTiles) do + -- In the future, we'll need to handle tile protection on a different entity in case of a player being transformed + local dungeonId = Sexbound.Util.tileProtectionDisable(position) + if world.placeObject(self._nodeName, targetTile, facingDirection, params) then + self:setPosition(position[1], position[2] + self._feetOffset) + + if not spawnOptions.noEffect then + world.sendEntityMessage(entity.id(), "applyStatusEffect", "sexbound_transform") + end + return params.uniqueId end - - return params.uniqueId + Sexbound.Util.tileProtectionEnable(dungeonId) end + return nil end diff --git a/scripts/sexbound/override/player.lua b/scripts/sexbound/override/player.lua index 155851fe..7048366b 100644 --- a/scripts/sexbound/override/player.lua +++ b/scripts/sexbound/override/player.lua @@ -517,7 +517,8 @@ function Sexbound.Player:getActorData() aroused = status.statusProperty("sexbound_aroused", false), arousedStrong = status.statusProperty("sexbound_aroused_strong", false), inHeat = status.statusProperty("sexbound_aroused_heat", false), - isDefeated = self.sexboundDefeat and self.sexboundDefeat:isDefeated(), + isDefeated = status.statusProperty("sexbound_defeated", false), + canUseSexUIDefeated = status.statusProperty("can_use_sex_ui_defeated", false), generationFertility = status.statusProperty("generationFertility", 1.0), fertilityPenalty = status.statusProperty("fertilityPenalty", 1.0) } diff --git a/scripts/sexbound/override/player/transform.lua b/scripts/sexbound/override/player/transform.lua index 2e01baf9..73ba85af 100644 --- a/scripts/sexbound/override/player/transform.lua +++ b/scripts/sexbound/override/player/transform.lua @@ -46,14 +46,8 @@ function Sexbound.Player.Transform:handleTransform(args) end function Sexbound.Player.Transform:tryCreateNode(spawnOptions) - local position = self:findNearbyOpenSpace() - if self._parent:canLog("debug") then sb.logInfo("Looking for valid spawn position") end - if position == false then - return nil - end - if self._parent:canLog("debug") then sb.logInfo("Found valid position, attempting to place actual node") end -- Place Sexnode and store Unique ID - local uniqueId = self:placeSexNode(position, { + local uniqueId = self:placeSexNode({ randomStartPosition = true, noEffect = spawnOptions.noEffect or false }) diff --git a/scripts/sexbound/plugins/climax/climax.lua b/scripts/sexbound/plugins/climax/climax.lua index bd01fb70..eae65598 100644 --- a/scripts/sexbound/plugins/climax/climax.lua +++ b/scripts/sexbound/plugins/climax/climax.lua @@ -130,6 +130,10 @@ function Sexbound.Actor.Climax:onUpdateSexState(dt) local multiplier = actor:getPosition():getAnimationState("sexState"):getClimaxMultiplier(actorNumber) or 1 local increase = util.randomInRange(self:getDefaultIncrease()) * multiplier * dt + -- increase point gain if this is a defeat node to allow for climaxing during the limited sexnode duration + if self:getParent():getParent():getContainsDefeated() then + increase = increase * 2.1 + end self._config.currentPoints = util.clamp(self._config.currentPoints + increase, self:getMinPoints(), self:getMaxPoints()) @@ -527,7 +531,6 @@ end --- Attempts to cause this actor to begin climaxing. function Sexbound.Actor.Climax:tryAutoClimax() local entityType = self:getParent():getEntityType() - local containsPlayer = false local playerControl = false if entityType == "player" then @@ -535,14 +538,18 @@ function Sexbound.Actor.Climax:tryAutoClimax() else for _, actor in ipairs(self:getParent():getParent():getActors()) do if actor:getActorNumber() ~= self:getParent():getActorNumber() then - if actor:getEntityType() == "player" then containsPlayer = true end - if not actor:getStatus():hasStatus("sexbound_defeated") then playerControl = true end + if actor:getEntityType() == "player" then + if not actor:getStatus():hasStatus("sexbound_defeated") or actor:getStatus():hasStatus("sexbound_defeated_can_use_ui") then + playerControl = true + end + end end end end - if self._config.prioritizePlayer and containsPlayer and playerControl then + if self._config.prioritizePlayer and playerControl then -- Prevent auto climax if we have a player and that player is in control (not raped as part of sexbound defeat) + sb.logInfo("bailing climax due to config and player control") return end diff --git a/sexbound-defeat.config b/sexbound-defeat.config index e44dceda..77191219 100644 --- a/sexbound-defeat.config +++ b/sexbound-defeat.config @@ -42,10 +42,10 @@ "enableStartDialogForMonsters" : false, /* - [Bugged] Setting this to true enables a defeated player to have access to use the Sex UI. + Setting this to true enables a defeated player to have access to use the Sex UI. Valid options are true & false. Default: false */ - "defeatedPlayersCanUseSexUI" : false, + "defeatedPlayersCanUseSexUI" : true, /* Define 'victory' and 'defeated' start dialog for NPCs. the 'default' species is a fallback. */ "startDialog" : { diff --git a/stats/sexbound/sexbounddefeat.lua b/stats/sexbound/sexbounddefeat.lua index c0650ec5..4235aa7a 100644 --- a/stats/sexbound/sexbounddefeat.lua +++ b/stats/sexbound/sexbounddefeat.lua @@ -37,6 +37,9 @@ function SexboundDefeat:new(entityType) -- Set the default timeout as configured in the settings _self:_initTimeout() + -- Set "Can use sexbound UI while defeated." state as a status for use with other scripts + status.setStatusProperty("can_use_sex_ui_defeated", _self._config.defeatedPlayersCanUseSexUI) + return _self end @@ -50,15 +53,15 @@ end function SexboundDefeat:update(dt, oldUpdate) self._promises:update() - if self:isTransformed() then - self._timer = self._timer + dt - -- Untransform the NPC when the timer runs out - if self._timer >= self._timeout or not self:isStunned() then - self:setIsDefeated(false) - self:setIsTransformed(false) - self:setTimer(0) - self:untransform() - end + if self:isTransformed() then + self._timer = self._timer + dt + -- Untransform the NPC when the timer runs out + if self._timer >= self._timeout or not self:isStunned() then + self:setIsDefeated(false) + self:setIsTransformed(false) + self:setTimer(0) + self:untransform() + end end -- Return when is defeated to prevent the default update loop from running @@ -174,18 +177,15 @@ function SexboundDefeat:handleRetrieveSexboundConfigSuccess(sexboundConfig) self:transform(sexboundConfig, function(result) result = result or {} if result.uniqueId == nil then - self:setIsDefeated(false) - self:tryToDie() - return + return self:handleTransformFailed() end return self:handleTransformSuccess(result.uniqueId) end, function() return self:handleTransformFailed() - end) + end ) end function SexboundDefeat:handleRetrieveSexboundConfigFailure() - self:setIsDefeated(true) self:tryToDie() end @@ -206,26 +206,19 @@ function SexboundDefeat:transform(sexboundConfig, successCallback, failureCallba end function SexboundDefeat:handleTransformFailed() - self:setIsDefeated(false) - self:setIsTransformed(false) self:tryToDie() return false end function SexboundDefeat:handleTransformSuccess(nodeUniqueId) self._sexNodeId = nodeUniqueId - self:setIsDefeated(true) self:setIsTransformed(true) self:setTimer(0) self:outputDefeatedDialog() + self:_initTimeout() if self:isPlayer() then - if self._config.defeatedPlayersCanUseSexUI then - self._promises:add(world.sendEntityMessage(self._sexNodeId, "Sexbound:Retrieve:UIConfig"), function(config) - world.sendEntityMessage(self._entityId, "Sexbound:UI:Show", {config = config}) - end) - else - world.sendEntityMessage(self._entityId, "Sexbound:UI:Show", {config = self:loadUIConfig()}) - end + -- Check config for using invisible "UI" that allows escape with ESC key + --world.sendEntityMessage(self._entityId, "Sexbound:UI:Show", {config = self:loadUIConfig()}) status.addEphemeralEffect("dontstarve", self._timeout) status.addEphemeralEffect("regeneration4", self._timeout) end @@ -244,24 +237,26 @@ function SexboundDefeat:handleTransformSuccess(nodeUniqueId) end function SexboundDefeat:loadUIConfig() - local _,_config = xpcall(function() - return root.assetJson(self._uiConfigFilePath) - end, function(error) - sb.logError("Unable to load config file for the Sexbound Defeat!") - end) + local _,_config = xpcall(function() + return root.assetJson(self._uiConfigFilePath) + end, function(error) + sb.logError("Unable to load config file for the Sexbound Defeat!") + end) _config.config.nodeUniqueId = self._sexNodeId - return _config or {} + return _config or {} end function SexboundDefeat:tryToDie() - if not self:isPlayer() and self:isPregnant() and self._config.enableImmortalPregnantNPCs then - local species = self:findSpecies() + self:setIsDefeated(false) + self:setIsTransformed(false) + if not self:isPlayer() and self:isPregnant() and self._config.enableImmortalPregnantNPCs then + local species = self:findSpecies() local pregnantDialog = self._config.pregnantDialog[species] or self._config.pregnantDialog.default - world.sendEntityMessage(self._entityId, "Sexbound:Actor:Say", {message = util.randomChoice(pregnantDialog)}) - status.setResourcePercentage("health", 1.0) - else - status.setResourcePercentage("health", 0) - end + world.sendEntityMessage(self._entityId, "Sexbound:Actor:Say", {message = util.randomChoice(pregnantDialog)}) + status.setResourcePercentage("health", 1.0) + else + status.setResourcePercentage("health", 0) + end end function SexboundDefeat:smashSexNode(storage) @@ -328,11 +323,11 @@ function SexboundDefeat:isPlayer() end function SexboundDefeat:isPregnant() - return status.statusProperty("sexbound_pregnant") + return status.statusProperty("sexbound_pregnant") end function SexboundDefeat:isStunned() - return status.statusProperty("sexbound_stun") + return status.statusProperty("sexbound_stun") end function SexboundDefeat:isSuicide() @@ -345,6 +340,8 @@ end function SexboundDefeat:setIsDefeated(isDefeated) self._isDefeated = isDefeated + status.setStatusProperty("sexbound_defeated", isDefeated) + end function SexboundDefeat:setIsTransformed(isTransformed) From ca8202a019cb35a3af19dd15442e51e008c18e40 Mon Sep 17 00:00:00 2001 From: notlexander Date: Mon, 30 Sep 2024 17:30:28 -0500 Subject: [PATCH 04/12] minor change to defeat config --- sexbound-defeat.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sexbound-defeat.config b/sexbound-defeat.config index 77191219..ad7bc699 100644 --- a/sexbound-defeat.config +++ b/sexbound-defeat.config @@ -45,7 +45,7 @@ Setting this to true enables a defeated player to have access to use the Sex UI. Valid options are true & false. Default: false */ - "defeatedPlayersCanUseSexUI" : true, + "defeatedPlayersCanUseSexUI" : false, /* Define 'victory' and 'defeated' start dialog for NPCs. the 'default' species is a fallback. */ "startDialog" : { From c168306819aef29889a91f7e1d8ceb9f09e39404 Mon Sep 17 00:00:00 2001 From: ErinaSugino <121646352+ErinaSugino@users.noreply.github.com> Date: Fri, 4 Oct 2024 21:27:07 +0200 Subject: [PATCH 05/12] Hotfix configurable kid stage Wrong config reference made kid stage always be skipped. --- scripts/sexbound/plugins/pregnant/baby.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/sexbound/plugins/pregnant/baby.lua b/scripts/sexbound/plugins/pregnant/baby.lua index f66ee6f2..3d761fd9 100644 --- a/scripts/sexbound/plugins/pregnant/baby.lua +++ b/scripts/sexbound/plugins/pregnant/baby.lua @@ -369,8 +369,8 @@ function Baby:_convertBabyConfigToSpawnableNPC(babyConfig, babyName) generationFertility = babyConfig.generationFertility, fertilityPenalty = babyConfig.generationFertility } - if self._parent._parent._config.enableKidStage then - params.statusControllerSettings.statusProperties.kid = world.time() + 840*(self._parent._parent._config.kidDayCount or 5) --Config based days of being a kid + if self._config.enableKidStage then + params.statusControllerSettings.statusProperties.kid = world.time() + 840*(self._config.kidDayCount or 5) --Config based days of being a kid end params.identity = {} params.identity.gender = babyConfig.birthGender From 2a831134eb68588911fc162ca0f63e3f2095f82c Mon Sep 17 00:00:00 2001 From: ErinaSugino <121646352+ErinaSugino@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:20:13 +0200 Subject: [PATCH 06/12] Updated Lustia Permanently added the arcade of the `Lustbound Omnibrowser Addon` into the Lustia instanceworld, in a naturally closed/derelict state. Added a natural status effect to Lustia which increases the rate of arousal gain for all entities. Added a stat and code to allow status effects to cumulatively influence the rate of arousal gain via multipliers. --- dungeons/sexscape/sexscape.json | 658 +++++++++--------- interface/statuses/lustia.png | Bin 0 -> 378 bytes npcs/base.npctype.patch | 6 + player.config.patch | 6 + scripts/sexbound/override/common/arousal.lua | 6 +- .../lustia_hornybuff/lustia_hornybuff.lua | 9 + .../lustia_hornybuff.statuseffect | 9 + .../objects-special/sexscape_tileset.json | 6 +- weather.config.patch | 4 +- weather/lustia/lustiaclear.weather | 13 + weather/lustia/lustiaglowingrain.weather | 21 + 11 files changed, 413 insertions(+), 325 deletions(-) create mode 100644 interface/statuses/lustia.png create mode 100644 stats/effects/lustia_hornybuff/lustia_hornybuff.lua create mode 100644 stats/effects/lustia_hornybuff/lustia_hornybuff.statuseffect create mode 100644 weather/lustia/lustiaclear.weather create mode 100644 weather/lustia/lustiaglowingrain.weather diff --git a/dungeons/sexscape/sexscape.json b/dungeons/sexscape/sexscape.json index ecb4a457..7c01942a 100644 --- a/dungeons/sexscape/sexscape.json +++ b/dungeons/sexscape/sexscape.json @@ -362,8 +362,8 @@ "type":"", "visible":true, "width":8, - "x":5595.33333333333, - "y":1612.66666666667 + "x":5592, + "y":1616 }, { "height":8, @@ -383,8 +383,8 @@ "type":"", "visible":true, "width":8, - "x":5396.66666666667, - "y":1712.66666666667 + "x":5400, + "y":1712 }, { "height":8, @@ -404,8 +404,8 @@ "type":"", "visible":true, "width":8, - "x":5633.33333333333, - "y":1714.66666666667 + "x":5632, + "y":1712 }, { "height":8, @@ -425,8 +425,8 @@ "type":"", "visible":true, "width":8, - "x":6001.33333333333, - "y":1708 + "x":6000, + "y":1712 }, { "height":8, @@ -446,8 +446,8 @@ "type":"", "visible":true, "width":8, - "x":5162, - "y":1709.33333333333 + "x":5160, + "y":1712 }, { "height":8, @@ -696,8 +696,8 @@ "type":"", "visible":true, "width":8, - "x":3935.99262187088, - "y":1736.00693895477 + "x":3936, + "y":1736 }, { "height":8, @@ -718,7 +718,7 @@ "visible":true, "width":8, "x":4424, - "y":1720.125 + "y":1720 }], "opacity":1, "type":"objectgroup", @@ -738,19 +738,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2.125 + "x":0, + "y":0 }, { - "x":6, - "y":21.875 + "x":8, + "y":24 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":4394, - "y":1690.125 + "x":4392, + "y":1688 }, { "height":0, @@ -6209,8 +6209,8 @@ "type":"", "visible":true, "width":24, - "x":3927.99431818182, - "y":1671.91477272727 + "x":3928, + "y":1672 }, { "gid":2130, @@ -6221,8 +6221,8 @@ "type":"", "visible":true, "width":24, - "x":3927.99431818182, - "y":1767.91477272727 + "x":3928, + "y":1768 }, { "gid":2130, @@ -6233,8 +6233,8 @@ "type":"", "visible":true, "width":24, - "x":3927.99431818182, - "y":1855.91477272727 + "x":3928, + "y":1856 }, { "gid":3093, @@ -6257,8 +6257,8 @@ "type":"", "visible":true, "width":48, - "x":3879.99431818182, - "y":1751.91477272727 + "x":3880, + "y":1752 }, { "height":0, @@ -6277,8 +6277,8 @@ "type":"", "visible":true, "width":0, - "x":3935.99431818182, - "y":1831.91477272727 + "x":3936, + "y":1832 }, { "height":0, @@ -6297,8 +6297,8 @@ "type":"", "visible":true, "width":0, - "x":3935.99431818182, - "y":1743.91477272727 + "x":3936, + "y":1744 }, { "height":0, @@ -6317,8 +6317,8 @@ "type":"", "visible":true, "width":0, - "x":3967.99431818182, - "y":1831.91477272727 + "x":3968, + "y":1832 }, { "height":0, @@ -6337,8 +6337,8 @@ "type":"", "visible":true, "width":0, - "x":3967.99431818182, - "y":1735.91477272727 + "x":3968, + "y":1736 }, { "height":0, @@ -6357,8 +6357,8 @@ "type":"", "visible":true, "width":0, - "x":3967.99431818182, - "y":1639.91477272727 + "x":3968, + "y":1640 }, { "gid":2597, @@ -6369,8 +6369,8 @@ "type":"", "visible":true, "width":8, - "x":3967.99431818182, - "y":1743.91477272727 + "x":3968, + "y":1744 }, { "gid":2597, @@ -6381,8 +6381,8 @@ "type":"", "visible":true, "width":8, - "x":3967.99431818182, - "y":1647.91477272727 + "x":3968, + "y":1648 }, { "gid":2597, @@ -6393,8 +6393,8 @@ "type":"", "visible":true, "width":8, - "x":3967.99431818182, - "y":1839.91477272727 + "x":3968, + "y":1840 }, { "gid":5047, @@ -6405,8 +6405,8 @@ "type":"", "visible":true, "width":16, - "x":4360, - "y":1592 + "x":4360.00568181818, + "y":1592.08522727273 }, { "gid":5047, @@ -6417,8 +6417,8 @@ "type":"", "visible":true, "width":16, - "x":4287.99431818182, - "y":1687.91477272727 + "x":4288, + "y":1688 }, { "gid":5047, @@ -6429,8 +6429,8 @@ "type":"", "visible":true, "width":16, - "x":4215.99431818182, - "y":1591.91477272727 + "x":4216, + "y":1592 }, { "gid":5047, @@ -6441,8 +6441,8 @@ "type":"", "visible":true, "width":16, - "x":4143.99431818182, - "y":1687.91477272727 + "x":4144, + "y":1688 }, { "gid":5047, @@ -6453,8 +6453,8 @@ "type":"", "visible":true, "width":16, - "x":4071.99431818182, - "y":1591.91477272727 + "x":4072, + "y":1592 }, { "gid":5047, @@ -6465,8 +6465,8 @@ "type":"", "visible":true, "width":16, - "x":3999.99431818182, - "y":1687.91477272727 + "x":4000, + "y":1688 }, { "gid":4997, @@ -6477,8 +6477,8 @@ "type":"", "visible":true, "width":16, - "x":4071.99431818182, - "y":1687.91477272727 + "x":4072, + "y":1688 }, { "gid":4997, @@ -6489,8 +6489,8 @@ "type":"", "visible":true, "width":16, - "x":3999.99431818182, - "y":1591.91477272727 + "x":4000, + "y":1592 }, { "gid":4997, @@ -6501,8 +6501,8 @@ "type":"", "visible":true, "width":16, - "x":4143.99431818182, - "y":1591.91477272727 + "x":4144, + "y":1592 }, { "gid":4997, @@ -6513,8 +6513,8 @@ "type":"", "visible":true, "width":16, - "x":4215.99431818182, - "y":1687.91477272727 + "x":4216, + "y":1688 }, { "gid":4997, @@ -6525,8 +6525,8 @@ "type":"", "visible":true, "width":16, - "x":4287.99431818182, - "y":1591.91477272727 + "x":4288, + "y":1592 }, { "gid":4997, @@ -6537,8 +6537,8 @@ "type":"", "visible":true, "width":16, - "x":4359.99431818182, - "y":1687.91477272727 + "x":4360, + "y":1688 }, { "gid":4802, @@ -6549,8 +6549,8 @@ "type":"", "visible":true, "width":16, - "x":4359.99431818182, - "y":1783.91477272727 + "x":4360, + "y":1784 }, { "gid":4802, @@ -6561,8 +6561,8 @@ "type":"", "visible":true, "width":16, - "x":4287.99431818182, - "y":1783.91477272727 + "x":4288, + "y":1784 }, { "gid":4802, @@ -6573,8 +6573,8 @@ "type":"", "visible":true, "width":16, - "x":4215.99431818182, - "y":1783.91477272727 + "x":4216, + "y":1784 }, { "gid":4802, @@ -6585,8 +6585,8 @@ "type":"", "visible":true, "width":16, - "x":4143.99431818182, - "y":1783.91477272727 + "x":4144, + "y":1784 }, { "gid":4802, @@ -6597,8 +6597,8 @@ "type":"", "visible":true, "width":16, - "x":4071.99431818182, - "y":1783.91477272727 + "x":4072, + "y":1784 }, { "gid":4802, @@ -6609,8 +6609,8 @@ "type":"", "visible":true, "width":16, - "x":3999.99431818182, - "y":1783.91477272727 + "x":4000, + "y":1784 }, { "gid":2147489151, @@ -6621,8 +6621,8 @@ "type":"", "visible":true, "width":16, - "x":4383.99431818182, - "y":1847.91477272727 + "x":4384, + "y":1848 }, { "gid":2147489279, @@ -6633,8 +6633,8 @@ "type":"", "visible":true, "width":16, - "x":4023.99431818182, - "y":1655.91477272727 + "x":4024, + "y":1656 }, { "gid":2147488946, @@ -6645,8 +6645,8 @@ "type":"", "visible":true, "width":48, - "x":4055.99431818182, - "y":1847.91477272727 + "x":4056, + "y":1848 }, { "gid":2147488946, @@ -6657,8 +6657,8 @@ "type":"", "visible":true, "width":48, - "x":4127.99431818182, - "y":1847.91477272727 + "x":4128, + "y":1848 }, { "gid":5298, @@ -6669,8 +6669,8 @@ "type":"", "visible":true, "width":48, - "x":4199.99431818182, - "y":1847.91477272727 + "x":4200, + "y":1848 }, { "gid":5298, @@ -6681,8 +6681,8 @@ "type":"", "visible":true, "width":48, - "x":4271.99431818182, - "y":1847.91477272727 + "x":4272, + "y":1848 }, { "gid":2147489198, @@ -6693,8 +6693,8 @@ "type":"", "visible":true, "width":16, - "x":4367.99431818182, - "y":1847.91477272727 + "x":4368, + "y":1848 }, { "gid":2147486890, @@ -6705,8 +6705,8 @@ "type":"", "visible":true, "width":32, - "x":4263.99431818182, - "y":1655.91477272727 + "x":4264, + "y":1656 }, { "gid":3313, @@ -6717,8 +6717,8 @@ "type":"", "visible":true, "width":24, - "x":4271.99431818182, - "y":1727.91477272727 + "x":4272.00568181818, + "y":1728.08522727273 }, { "gid":3319, @@ -6729,8 +6729,8 @@ "type":"", "visible":true, "width":24, - "x":4047.99431818182, - "y":1639.91477272727 + "x":4048, + "y":1640 }, { "gid":3337, @@ -6741,8 +6741,8 @@ "type":"", "visible":true, "width":16, - "x":4367.99431818182, - "y":1735.91477272727 + "x":4368, + "y":1736 }, { "gid":3423, @@ -6753,8 +6753,8 @@ "type":"", "visible":true, "width":32, - "x":3991.99431818182, - "y":1655.91477272727 + "x":3992, + "y":1656 }, { "gid":3428, @@ -6765,8 +6765,8 @@ "type":"", "visible":true, "width":24, - "x":4335.99431818182, - "y":1751.91477272727 + "x":4336, + "y":1752 }, { "gid":2147487153, @@ -6777,8 +6777,8 @@ "type":"", "visible":true, "width":32, - "x":4119.99431818182, - "y":1655.91477272727 + "x":4120, + "y":1656 }, { "gid":3565, @@ -6789,8 +6789,8 @@ "type":"", "visible":true, "width":32, - "x":4223.99431818182, - "y":1655.91477272727 + "x":4224, + "y":1656 }, { "gid":3584, @@ -6801,8 +6801,8 @@ "type":"", "visible":true, "width":32, - "x":4103.99431818182, - "y":1623.91477272727 + "x":4104, + "y":1624 }, { "gid":3798, @@ -6813,8 +6813,8 @@ "type":"", "visible":true, "width":24, - "x":4007.99431818182, - "y":1847.91477272727 + "x":4008, + "y":1848 }, { "gid":3801, @@ -6825,8 +6825,8 @@ "type":"", "visible":true, "width":48, - "x":4351.99431818182, - "y":1655.91477272727 + "x":4352, + "y":1656 }, { "gid":3815, @@ -6837,8 +6837,8 @@ "type":"", "visible":true, "width":24, - "x":4119.99431818182, - "y":1727.91477272727 + "x":4120, + "y":1728 }, { "gid":4566, @@ -6849,8 +6849,8 @@ "type":"", "visible":true, "width":32, - "x":4295.99431818182, - "y":1751.91477272727 + "x":4296, + "y":1752 }, { "gid":3679, @@ -6861,8 +6861,8 @@ "type":"", "visible":true, "width":32, - "x":4303.99431818182, - "y":1623.91477272727 + "x":4304, + "y":1624 }, { "gid":3297, @@ -6873,8 +6873,8 @@ "type":"", "visible":true, "width":24, - "x":4087.99431818182, - "y":1751.91477272727 + "x":4088, + "y":1752 }, { "gid":3253, @@ -6885,8 +6885,8 @@ "type":"", "visible":true, "width":16, - "x":4063.99431818182, - "y":1735.91477272727 + "x":4064, + "y":1736 }, { "gid":3178, @@ -6897,11 +6897,11 @@ "type":"", "visible":true, "width":32, - "x":4151.99431818182, - "y":1823.91477272727 + "x":4152, + "y":1824 }, { - "gid":6009, + "gid":6008, "height":24, "id":2414, "name":"", @@ -6909,8 +6909,8 @@ "type":"", "visible":true, "width":64, - "x":4191.99431818182, - "y":1711.91477272727 + "x":4192, + "y":1712 }, { "gid":3788, @@ -6921,8 +6921,8 @@ "type":"", "visible":true, "width":40, - "x":3983.99431818182, - "y":1807.91477272727 + "x":3984, + "y":1808 }, { "gid":5383, @@ -6933,8 +6933,8 @@ "type":"", "visible":true, "width":16, - "x":4071.99431818182, - "y":1751.91477272727 + "x":4072, + "y":1752 }, { "gid":2147489031, @@ -6945,8 +6945,8 @@ "type":"", "visible":true, "width":16, - "x":4295.99431818182, - "y":1655.91477272727 + "x":4296, + "y":1656 }, { "gid":5383, @@ -6957,8 +6957,8 @@ "type":"", "visible":true, "width":16, - "x":4279.99431818182, - "y":1751.91477272727 + "x":4280, + "y":1752 }, { "gid":2147489031, @@ -6969,8 +6969,8 @@ "type":"", "visible":true, "width":16, - "x":4359.99431818182, - "y":1751.91477272727 + "x":4360, + "y":1752 }, { "gid":5383, @@ -6981,8 +6981,8 @@ "type":"", "visible":true, "width":16, - "x":4207.99431818182, - "y":1655.91477272727 + "x":4208, + "y":1656 }, { "gid":2147489031, @@ -6993,8 +6993,8 @@ "type":"", "visible":true, "width":16, - "x":4151.99431818182, - "y":1655.91477272727 + "x":4152, + "y":1656 }, { "gid":2147489030, @@ -7005,8 +7005,8 @@ "type":"", "visible":true, "width":40, - "x":4071.99431818182, - "y":1655.91477272727 + "x":4072, + "y":1656 }, { "gid":2139, @@ -7017,8 +7017,8 @@ "type":"", "visible":true, "width":32, - "x":3975.99431818182, - "y":1847.91477272727 + "x":3976, + "y":1848 }, { "gid":3640, @@ -7029,8 +7029,8 @@ "type":"", "visible":true, "width":16, - "x":4375.99431818182, - "y":1823.91477272727 + "x":4376, + "y":1824 }, { "gid":3642, @@ -7041,8 +7041,8 @@ "type":"", "visible":true, "width":16, - "x":4055.99431818182, - "y":1823.91477272727 + "x":4056, + "y":1824 }, { "gid":3958, @@ -7053,8 +7053,8 @@ "type":"", "visible":true, "width":16, - "x":3975.99431818182, - "y":1655.91477272727 + "x":3976, + "y":1656 }, { "gid":2147485887, @@ -7065,8 +7065,8 @@ "type":"", "visible":true, "width":34, - "x":3839.99431818182, - "y":1751.91477272727 + "x":3840, + "y":1752 }, { "gid":2147489030, @@ -7077,8 +7077,8 @@ "type":"", "visible":true, "width":40, - "x":3807.99431818182, - "y":1751.91477272727 + "x":3808, + "y":1752 }, { "gid":6007, @@ -7089,8 +7089,8 @@ "type":"", "visible":true, "width":56, - "x":3983.99431818182, - "y":1751.91477272727 + "x":3984, + "y":1752 }, { "gid":3260, @@ -7101,8 +7101,8 @@ "type":"", "visible":true, "width":32, - "x":4007.99431818182, - "y":1711.91477272727 + "x":4008, + "y":1712 }, { "gid":4964, @@ -7113,8 +7113,8 @@ "type":"", "visible":true, "width":16, - "x":4039.99431818182, - "y":1751.91477272727 + "x":4040, + "y":1752 }, { "gid":3260, @@ -7125,8 +7125,8 @@ "type":"", "visible":true, "width":32, - "x":3975.99431818182, - "y":1711.91477272727 + "x":3976, + "y":1712 }, { "gid":3827, @@ -7137,8 +7137,8 @@ "type":"", "visible":true, "width":32, - "x":4207.99431818182, - "y":1727.91477272727 + "x":4208, + "y":1728 }, { "gid":4539, @@ -7149,8 +7149,8 @@ "type":"", "visible":true, "width":16, - "x":3999.99431818182, - "y":1615.91477272727 + "x":4000, + "y":1616 }, { "gid":4576, @@ -7161,8 +7161,8 @@ "type":"", "visible":true, "width":72, - "x":4151.99431818182, - "y":1631.91477272727 + "x":4152, + "y":1632 }, { "gid":2450, @@ -7173,8 +7173,8 @@ "type":"", "visible":true, "width":24, - "x":4335.99431818182, - "y":1831.91477272727 + "x":4336, + "y":1832 }, { "gid":2147488801, @@ -7185,8 +7185,8 @@ "type":"", "visible":true, "width":32, - "x":4335.99431818182, - "y":1847.91477272727 + "x":4336, + "y":1848 }, { "gid":4557, @@ -7197,8 +7197,8 @@ "type":"", "visible":true, "width":8, - "x":4359.99431818182, - "y":1831.91477272727 + "x":4360, + "y":1832 }, { "gid":4483, @@ -7209,8 +7209,8 @@ "type":"", "visible":true, "width":8, - "x":4303.99431818182, - "y":1831.91477272727 + "x":4304, + "y":1832 }, { "gid":4483, @@ -7221,8 +7221,8 @@ "type":"", "visible":true, "width":8, - "x":4215.99431818182, - "y":1831.91477272727 + "x":4216, + "y":1832 }, { "gid":4483, @@ -7233,8 +7233,8 @@ "type":"", "visible":true, "width":8, - "x":4079.99431818182, - "y":1831.91477272727 + "x":4080, + "y":1832 }, { "gid":4344, @@ -7245,8 +7245,8 @@ "type":"", "visible":true, "width":12, - "x":4031.99431818182, - "y":1847.91477272727 + "x":4032, + "y":1848 }, { "gid":3268, @@ -7257,8 +7257,8 @@ "type":"", "visible":true, "width":40, - "x":4151.99431818182, - "y":1751.91477272727 + "x":4152, + "y":1752 }, { "gid":3642, @@ -7269,8 +7269,8 @@ "type":"", "visible":true, "width":16, - "x":4359.99431818182, - "y":1815.91477272727 + "x":4360, + "y":1816 }, { "gid":3640, @@ -7281,8 +7281,8 @@ "type":"", "visible":true, "width":16, - "x":4247.99431818182, - "y":1823.91477272727 + "x":4248, + "y":1824 }, { "gid":2147485887, @@ -7356,37 +7356,25 @@ "x":6456, "y":1752 }, - { - "gid":2710, - "height":16, - "id":2527, - "name":"", - "rotation":0, - "type":"", - "visible":true, - "width":16, - "x":4384, - "y":1696 - }, { "height":0, "id":2534, "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":-26, - "y":-10 + "x":-24, + "y":-8 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":4394, - "y":1690 + "x":4392, + "y":1688 }, { "height":0, @@ -7394,19 +7382,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":-26, - "y":86 + "x":-24, + "y":88 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":4394, - "y":1690 + "x":4392, + "y":1688 }, { "height":0, @@ -7414,19 +7402,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":-98, - "y":-10 + "x":-96, + "y":-8 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":4394, - "y":1690 + "x":4392, + "y":1688 }, { "height":0, @@ -7434,19 +7422,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":-98, - "y":86 + "x":-96, + "y":88 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":4394, - "y":1690 + "x":4392, + "y":1688 }, { "height":0, @@ -7474,19 +7462,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":-98, - "y":-106 + "x":-96, + "y":-104 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":4394, - "y":1690 + "x":4392, + "y":1688 }, { "height":0, @@ -7494,19 +7482,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":-170, - "y":86 + "x":-168, + "y":88 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":4394, - "y":1690 + "x":4392, + "y":1688 }, { "height":0, @@ -7514,19 +7502,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":-170, - "y":-10 + "x":-168, + "y":-8 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":4394, - "y":1690 + "x":4392, + "y":1688 }, { "height":0, @@ -7534,31 +7522,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":-170, - "y":-106 + "x":-168, + "y":-104 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":4394, - "y":1690 - }, - { - "gid":2710, - "height":16, - "id":2544, - "name":"", - "rotation":0, - "type":"", - "visible":true, - "width":16, - "x":3952, - "y":1696 + "x":4392, + "y":1688 }, { "height":0, @@ -7566,19 +7542,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":46, - "y":86 + "x":48, + "y":88 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":3962, - "y":1690 + "x":3960, + "y":1688 }, { "height":0, @@ -7586,19 +7562,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":46, - "y":-10 + "x":48, + "y":-8 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":3962, - "y":1690 + "x":3960, + "y":1688 }, { "height":0, @@ -7606,19 +7582,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-1.5 + "x":0, + "y":0 }, { - "x":46, - "y":-105.5 + "x":48, + "y":-104 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":3962, - "y":1689.5 + "x":3960, + "y":1688 }, { "height":0, @@ -7626,19 +7602,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-1.75 + "x":0, + "y":0 }, { - "x":118, - "y":86.25 + "x":120, + "y":88 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":3962, - "y":1689.75 + "x":3960, + "y":1688 }, { "height":0, @@ -7646,19 +7622,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":118, - "y":-10 + "x":120, + "y":-8 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":3962, - "y":1690 + "x":3960, + "y":1688 }, { "height":0, @@ -7666,19 +7642,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":118, - "y":-106 + "x":120, + "y":-104 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":3962, - "y":1690 + "x":3960, + "y":1688 }, { "height":0, @@ -7686,19 +7662,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":190, - "y":86 + "x":192, + "y":88 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":3962, - "y":1690 + "x":3960, + "y":1688 }, { "height":0, @@ -7706,19 +7682,19 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 }, { - "x":190, - "y":-10 + "x":192, + "y":-8 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":3962, - "y":1690 + "x":3960, + "y":1688 }, { "height":0, @@ -7726,19 +7702,63 @@ "name":"", "polyline":[ { - "x":-2, - "y":-2 + "x":0, + "y":0 + }, + { + "x":192, + "y":-104 + }], + "rotation":0, + "type":"", + "visible":true, + "width":0, + "x":3960, + "y":1688 + }, + { + "gid":2717, + "height":16, + "id":2556, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":4384, + "y":1696 + }, + { + "gid":2717, + "height":16, + "id":2557, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":16, + "x":3952, + "y":1696 + }, + { + "height":0, + "id":2558, + "name":"", + "polyline":[ + { + "x":0, + "y":0 }, { - "x":190, - "y":-106 + "x":-64, + "y":24 }], "rotation":0, "type":"", "visible":true, "width":0, - "x":3962, - "y":1690 + "x":3960, + "y":1688 }], "opacity":1, "type":"objectgroup", @@ -7747,7 +7767,7 @@ "y":0 }], "nextlayerid":18, - "nextobjectid":2556, + "nextobjectid":2559, "orientation":"orthogonal", "renderorder":"right-down", "tiledversion":"1.8.0", diff --git a/interface/statuses/lustia.png b/interface/statuses/lustia.png new file mode 100644 index 0000000000000000000000000000000000000000..e280bc8bec0259a316b4647d19ec60a29d924fca GIT binary patch literal 378 zcmV-=0fqjFP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ-07*naRCwCdlP!+JFc3zct7=h6X{3^>WE5mtV6rS1Fe%RkasVG77YHx$1A8lA~m_LQ`|3;xL>CDx=!`10HBKTVGFlnzUi?dck!abijZ&m`;dn< zYVG~dnXDjp4!ha{U{~7&a8$3oA2v4wup$#M-@vTMK!0pjEM*si- literal 0 HcmV?d00001 diff --git a/npcs/base.npctype.patch b/npcs/base.npctype.patch index b2960dcb..52db7bcc 100644 --- a/npcs/base.npctype.patch +++ b/npcs/base.npctype.patch @@ -77,6 +77,12 @@ } }, + { + "op": "add", + "path": "/statusControllerSettings/stats/arousalMult", + "value": { "baseValue": 1.0 } + }, + { "op" : "add", "path" : "/statusControllerSettings/resources/arousal", diff --git a/player.config.patch b/player.config.patch index 1169a979..8a68f03b 100644 --- a/player.config.patch +++ b/player.config.patch @@ -58,6 +58,12 @@ "path": "/statusControllerSettings/stats/climaxThreshold", "value": { "baseValue": 0.5 } }, + + { + "op": "add", + "path": "/statusControllerSettings/stats/arousalMult", + "value": { "baseValue": 1.0 } + }, { "op": "add", diff --git a/scripts/sexbound/override/common/arousal.lua b/scripts/sexbound/override/common/arousal.lua index 514d07a4..c241e83e 100644 --- a/scripts/sexbound/override/common/arousal.lua +++ b/scripts/sexbound/override/common/arousal.lua @@ -4,7 +4,8 @@ Sexbound.Common.Arousal_mt = { __index = Sexbound.Common.Arousal } --- Instantiates this class function Sexbound.Common.Arousal:new() return setmetatable({ - _resourceName = "arousal" + _resourceName = "arousal", + _multiplierName = "arousalMult" }, Sexbound.Common.Arousal_mt) end @@ -92,6 +93,9 @@ end function Sexbound.Common.Arousal:addAmount(amount) if self._parent._isKid then return end + -- Account for environmental multiplier + local mult = status.stat(self._multiplierName) + if mult > 0 then amount = amount * mult end status.modifyResource(self._resourceName, amount) end diff --git a/stats/effects/lustia_hornybuff/lustia_hornybuff.lua b/stats/effects/lustia_hornybuff/lustia_hornybuff.lua new file mode 100644 index 00000000..4d63679f --- /dev/null +++ b/stats/effects/lustia_hornybuff/lustia_hornybuff.lua @@ -0,0 +1,9 @@ +function init() + effect.addStatModifierGroup({ + { stat = "arousalMult", effectiveMultiplier = 5 } + }) +end + +function uninit() + +end diff --git a/stats/effects/lustia_hornybuff/lustia_hornybuff.statuseffect b/stats/effects/lustia_hornybuff/lustia_hornybuff.statuseffect new file mode 100644 index 00000000..c0f5ccdc --- /dev/null +++ b/stats/effects/lustia_hornybuff/lustia_hornybuff.statuseffect @@ -0,0 +1,9 @@ +{ + "name" : "lustia_hornybuff", + "blockingStat" : "sexboundImmunity", + "defaultDuration" : 999, + "effectConfig" : {}, + "icon" : "/interface/statuses/lustia.png", + "label" : "Lustia makes you horny", + "scripts" : [ "lustia_hornybuff.lua" ] +} diff --git a/tilesets/packed/objects-special/sexscape_tileset.json b/tilesets/packed/objects-special/sexscape_tileset.json index 06a8ce79..00ccd888 100644 --- a/tilesets/packed/objects-special/sexscape_tileset.json +++ b/tilesets/packed/objects-special/sexscape_tileset.json @@ -107,7 +107,7 @@ "object":"sexbound_cardshop_empty", "tilesetDirection":"right" }, - "19": + "18": { "\/\/description":"An arcade sign. Sadly, it seems to be closed.", "\/\/name":"arcadesign_off", @@ -293,7 +293,7 @@ "object":"string", "tilesetDirection":"string" }, - "19": + "18": { "\/\/description":"string", "\/\/name":"string", @@ -445,7 +445,7 @@ "imageheight":40, "imagewidth":56 }, - "19": + "18": { "image":"..\/..\/..\/objects\/miscellaneous\/sexscapeshops\/arcadesign_off.png", "imageheight":24, diff --git a/weather.config.patch b/weather.config.patch index 37698d95..429bc2bc 100644 --- a/weather.config.patch +++ b/weather.config.patch @@ -5,11 +5,11 @@ "value": [ [ 0.6, - "clear" + "lustiaclear" ], [ 0.4, - "glowingrain" + "lustiaglowingrain" ] ] } diff --git a/weather/lustia/lustiaclear.weather b/weather/lustia/lustiaclear.weather new file mode 100644 index 00000000..3a46dd71 --- /dev/null +++ b/weather/lustia/lustiaclear.weather @@ -0,0 +1,13 @@ +{ + "name" : "lustiaclear", + + "particleDensity" : 0, + "particles" : [ ], + "projectiles" : [ ], + + "statusEffects" : ["lustia_hornybuff"], + + "duration" : [40, 100], + "lightningFrequency" : 0.0, + "weatherNoises" : [ ] +} diff --git a/weather/lustia/lustiaglowingrain.weather b/weather/lustia/lustiaglowingrain.weather new file mode 100644 index 00000000..7b6d18fe --- /dev/null +++ b/weather/lustia/lustiaglowingrain.weather @@ -0,0 +1,21 @@ +{ + "name" : "lustiaglowingrain", + + "projectiles" : [ + { + "projectile" : "glowingrain", + "parameters" : { + "power" : 0 + }, + "velocity" : [0, -30], + "ratePerX" : 0.05, + "spawnAboveRegion" : 30, + "spawnHorizontalPad" : 30, + "windAffectAmount" : 1.0 + } + ], + "duration" : [50, 400], + "maximumWind" : 10.0, + + "statusEffects" : ["lustia_hornybuff"] +} From c068f5b0cfc21e5f77a7258799bac62dc9c01d11 Mon Sep 17 00:00:00 2001 From: ErinaSugino <121646352+ErinaSugino@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:31:33 +0200 Subject: [PATCH 07/12] Local sync Cleanup development pipeline by syncing all my local discrepancies to the repo. --- interface/sexbound/common/custombutton.lua | 4 ++++ interface/sexbound/customizer/customizerui.lua | 5 +++++ .../customizer/icons/addon_mod_ahego.png | Bin 598 -> 616 bytes sexbound-ES-changelog.txt | 3 ++- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/interface/sexbound/common/custombutton.lua b/interface/sexbound/common/custombutton.lua index f9fbb0e8..20af2f7e 100644 --- a/interface/sexbound/common/custombutton.lua +++ b/interface/sexbound/common/custombutton.lua @@ -255,4 +255,8 @@ function CustomButton:setNewImage(image, imageOffset) else self.config.image = nil end +end + +function CustomButton:setEnabled(enabled) + self.config.enabled = not not enabled end \ No newline at end of file diff --git a/interface/sexbound/customizer/customizerui.lua b/interface/sexbound/customizer/customizerui.lua index faa26d52..1e4961ad 100644 --- a/interface/sexbound/customizer/customizerui.lua +++ b/interface/sexbound/customizer/customizerui.lua @@ -43,4 +43,9 @@ end function sterilizeConfirm() if not self.customizer._inited then return end self.customizer.tabs["General"]:sterilize() +end + +function infertileConfirm() + if not self.customizer._inited then return end + self.customizer.tabs["General"]:makeFertile() end \ No newline at end of file diff --git a/interface/sexbound/customizer/icons/addon_mod_ahego.png b/interface/sexbound/customizer/icons/addon_mod_ahego.png index 308a32c7359d61f9ac0b98bababc164d7ea13df6..de4e5d42806f23960489ba71cec6cbe9300832e5 100644 GIT binary patch delta 575 zcmV-F0>J&&1n2~i7=Hu<0002(-QrRJ00D$)LqkwWLqi~Na&Km7Y-IodD3N`UJxIeq z9K~N#r6LsvD~LE`s7_Wyi#SRZi(sL&6nNgNw7S4z7YA z_yOYT;-u&zCH^ldw21NGxF7HCJ?`ECLZiY|vuhGiHOolFV}D{cw<-o+5rlw2L@^;T zQ%|H9Gw>W=_we!cF2b|C&;2?2l)T9RpGZ8%bi*RvAfDN@bk6(4Ay$$U;&bA0gDyz? z$aUG}H_k9%C|}6BtZ?4qtX68Qbx;1nU|w5E zbDic0;#figNq>ltQ9~IOScuT7kzyi6`!Nsyu;WjXOD0ztj2sK7LWSh`!T;cQw`O5_ z%1sK!fbJLD{ul)UyFjyU+uz5w-8=#O&%l+|_E#Ig>?i5$WEE0hc?# z(3371k|X(P3WWmjen#Jv0|st^-Zi(k);>-jfDCoDd?y1O90FrS%3k+)cTZ<;|DI{} z_XFMDa?;PH0p|b!03=XMR7C&)0F$}_A%B^x#Y_MI00DGTPE!Ct=GbNc000McNliru z=L`ZCD+(rJZ>0bL08dFoK~xCWV_?7nI668Ybc>4%nAK8VUS84wWVBbUT2&5atXj2d zIf&7*EIn-nh{2wgp61Q~VYsA&^_Qik6hIki5C%|=0hPf}UVv;h08`Bvo+lH0O$-14 N002ovPDHLkV1h0{{dE8U delta 556 zcmV+{0@MBI1l9zQ7=H)@0000eEe}%w00D(*LqkwWLqi~Na&Km7Y-IodD3N`UJxIe) z6opS)rJ@xFD~JeYsJd7X6>-!m6rn<>66%3Vlia4UE8s+=bE-Re3IIE=!YxK!q7|LoZ z%Uq`#L>!A)f`14BGAbyd1Pf8xHBw9@={)A)A8`C4xnyz`!N{?IGE_*8AN&t~&(_RM zPPj>-7|{M=+aJR~a2KdoZTtJ!w(BQA;2F5mn*MSPnE52V+SDRPK+iUCaoyD9J>YT& z=zr2BLvo}5l|PpQ-p}ZpGC=Pw(7EQ$t#OXi2OveWN+sL?2Zz8&p0d|H-rdnUw}0<6 z=Jx}HoN})Fw``FB001FSOjJdaya6G5QX-Ga0000BbW%=J0RR90|NsC0|NsAec74?V z002lyL_t&-m5q);3IH((1BDPn|Nr4tDBHM)vH=enCSb(RNSYl;C&~)sLK6*R6*--& u!&ga?b;tn#o=p=IHZWn2;s(OM_~ZfjpaI{mP)3LV0000 [GENERAL] Support for non-humanoid species [B] => [GENERAL] Add commands [C] => [GENERAL] Add humping variety to sex animation [Probably impossible] [I] + => [GENERAL] Add balancing debuffs for debug consumables (hyper fertility pill, birthing pill) <- + => [GENERAL] Add birth speedup pill (progression speed multiplier) as non-cheaty, non-debuff alternative to birthing pill (like normal fertility pill) <- => [CLIMAX] Make condoms degrading (climax with condom -> used condom -> broken condom) [S] => [CLIMAX] Upgrade status prevention/condoms to be gender specific [S] => [CLIMAX] Fix scripted climax cancel conditions [BUGFIX] @@ -273,7 +275,6 @@ => [PREGNANCY] Add maximum complexity logic (lingering cum, washing) [L] => [PREGNANCY] NPC realistic pregnancy logic [L]/[F]? => [MODDING] Assimilate "Sexbound Defeat" if allowed [C] - => [MODDING] Update default animation depth to the level of Red's "Relayer" project? [I] => [IDEA] Rework of climax system ==> Climax available at 100 From 60b00172e59ae5b9fb3f92520684520bec232fd2 Mon Sep 17 00:00:00 2001 From: ErinaSugino <121646352+ErinaSugino@users.noreply.github.com> Date: Sat, 5 Oct 2024 03:50:36 +0200 Subject: [PATCH 08/12] Pill Update I Made the birthcontrol pill actually functioning. Made the birthing pill more failsave with blocking status conditions. Added debug versions of the birthing and hyper fertility pill, which will retain old functionality and are only obtainble via commands. Added placeholders for penalties applied by the normal birthing pill and hyper fertility pill. (Missing content) Added placeholder for speed birth pill, a less OP and penalty-free version of the birthing pill (like the normal fertility pill). (Missing content) --- .../other/debug_birthingpill.consumable | 18 ++++++++++++++++++ items/generic/other/debug_birthingpill.png | Bin 0 -> 306 bytes .../other/debug_hyperfertilitypil.consumable | 14 ++++++++++++++ .../other/debug_hyperfertilitypill.png | Bin 0 -> 1891 bytes .../other/sexbound_birthspeedpill.consumable | 18 ++++++++++++++++++ .../generic/other/sexbound_birthspeedpill.png | Bin 0 -> 192 bytes scripts/sexbound/lib/sexbound/actor.lua | 3 ++- scripts/sexbound/override/player.lua | 1 + .../sexbound_birthcontrol.lua | 4 ++++ .../sexbound_birthing/sexbound_birthing.lua | 4 +++- .../sexbound_birthspeedpill.lua | 11 +++++++++++ .../sexbound_birthspeedpill.statuseffect | 8 ++++++++ .../sexbound_custom_hyper_fertility.lua | 5 +++++ .../sexbound_debug_hyper_fertility.lua | 9 +++++++++ ...exbound_debug_hyper_fertility.statuseffect | 9 +++++++++ 15 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 items/generic/other/debug_birthingpill.consumable create mode 100644 items/generic/other/debug_birthingpill.png create mode 100644 items/generic/other/debug_hyperfertilitypil.consumable create mode 100644 items/generic/other/debug_hyperfertilitypill.png create mode 100644 items/generic/other/sexbound_birthspeedpill.consumable create mode 100644 items/generic/other/sexbound_birthspeedpill.png create mode 100644 stats/effects/sexbound_birthspeedpill/sexbound_birthspeedpill.lua create mode 100644 stats/effects/sexbound_birthspeedpill/sexbound_birthspeedpill.statuseffect create mode 100644 stats/effects/sexbound_debug_hyper_fertility/sexbound_debug_hyper_fertility.lua create mode 100644 stats/effects/sexbound_debug_hyper_fertility/sexbound_debug_hyper_fertility.statuseffect diff --git a/items/generic/other/debug_birthingpill.consumable b/items/generic/other/debug_birthingpill.consumable new file mode 100644 index 00000000..5027388f --- /dev/null +++ b/items/generic/other/debug_birthingpill.consumable @@ -0,0 +1,18 @@ +{ + "itemName" : "debug_birthingpill", + "price" : 1, + "rarity" : "Common", + "category" : "medicine", + "inventoryIcon" : "debug_birthingpill.png", + "description" : "Debug version of the Birthing Pill without downsides.", + "shortdescription" : "Birthing Pill (Debug)", + "maxStack" : 1000, + "effects" : [ [ + { + "effect" : "debug_birthingpill", + "duration" : 5 + } + ] ], + "emote" : "", + "emitters" : [ "drinking" ] +} diff --git a/items/generic/other/debug_birthingpill.png b/items/generic/other/debug_birthingpill.png new file mode 100644 index 0000000000000000000000000000000000000000..e94c30dd7bfbf1eea91452e21759aec44100d619 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`>?NMQuIx`Z;X z!~g$cE&t5IT3ohTE4RtH<;?mY@5WK_LFvY~RWsTQ6tn+HcdfGAuhj2oYt4VozG8Oc z!qVsUBKk_w4NMNR5*cm^#3V9on|qNX*w|=?WvNhG_y(zlcU&{vByRA3IrY9%fH@&9 zAtmnYi4Xr}m>n4|>tt-0A($^Az-_Qd@UHfWiyb+?e{*k4FceFX!p00i_>zopr0PiblivR!s literal 0 HcmV?d00001 diff --git a/items/generic/other/debug_hyperfertilitypil.consumable b/items/generic/other/debug_hyperfertilitypil.consumable new file mode 100644 index 00000000..4116c903 --- /dev/null +++ b/items/generic/other/debug_hyperfertilitypil.consumable @@ -0,0 +1,14 @@ +{ + "itemName" : "debug_hyperfertilitypill", + "price" : 1, + "rarity" : "Legendary", + "category" : "medicine", + "inventoryIcon" : "debug_hyperfertilitypill.png", + "description" : "Debug version of the Hyper Fertility Pill without downsides!", + "shortdescription" : "Fertility Pill (Debug)", + "effects" : [ + [ "sexbound_debug_hyper_fertility" ] + ], + "emote" : "", + "emitters" : [ "drinking" ] +} diff --git a/items/generic/other/debug_hyperfertilitypill.png b/items/generic/other/debug_hyperfertilitypill.png new file mode 100644 index 0000000000000000000000000000000000000000..d7538b63e45c2352bfb059d7ef3b8130e6919311 GIT binary patch literal 1891 zcmV-p2b}ncP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+O1Ywva2`@{P!wm36|vNa{R2C9nA8lZA?NSImykr zP+%i$xz#NTRQvDWuKvNnEI}FTgNx2-944B`37w#~V{1v9d0!8D?>yMm?FGXmXk~kJ zZH-T`+xrA>mOVe(l`qRrSdMnj%b|>w8J)U7E=R(foz}C8ymgX0gtM+*I1ZD|+pF`l z@gSpG_!Cy#ghbCfZ!5{TSQ1)4?}UMRT1W(UmU!h)=_7|H0&l$&f4VHY-09dH?P0kS zPs>jBIe(L-BO>D4%6vqWtoHhN9Qo@t^xn4Ul5q-jxfRqN%IskvC^a&tIh-DsMc>ae z;tV?J0@W%)%}QrHL}D=B$xx+4o!V>*6+krH*rR1GEYlXmbL28)5Hn8d?3F~R5}-tZ zaso5ou+UsLj`gruz{-^{k_paeDtkE9+3@Z8;HdYJ=0rN&xB@O7`2`q5xpBuR2ts{v zYA3&>wnm?iA*?__J82FGFzLLx$d>N8B~xe7R$-{o+kPQmmjh6QwJpGqKmqMYEIHDi z*%N`s0DTgWvlz}$fUL4yfs&1ggE)c5+L+^Mj%CZ68RZ2+SaH}k0Rkn6WsEfr`z;`a zlColrwbog0gN-&hamHEaoOh#6B`@B1>z(&L_~=uRV1f-U_z*%2DRLB)F{`4BK86@$ zN?0_R1YZf`6AYQNWRq=n+2@dBP6g>xOtHlkUqXo`RjyJ|0#tR?*HB|kjT%y^nP!`7 zzJ(TB>d3V&-E`Ys_dWF3(@nLd>Z59B<$hL;mTEkO8sq$3HJH8MUC<~ec4!90*bo%= zLjfc-56yHSV|XYxG}DnqiC6|oJH)9p6oZ1M5!+5T?e5CG)J=iiKh=$&DW`^Xe?vJn zq&p~g)$NIDHO+D>Q=qX6!6_=FVEbV}3yDJ--=(iw_3gyZ9rawcZYeG4H2eB>tDe7* zru*z>gPrsVDD@JAAQPsmSh@>ueW@2OT1vCmf)x7+K6Sv8*5odxXC(0U0-rDWAUO4z zH17dkRr?Z{dUPUbTdJFkJdGDIE4givQgyHOra=#?ZEsqU=E^V7Jqe9@p|W0DyEw05 zdmT#0uDoGYufX0xKgE2(sy?9djIkS9&nTD8ZfmOts@p!HqH7+5ke{)u&%r;zeo$FG zml?Hjfp3E3)6FiY)tKJAzYOT=6wW#RTDC_g2ogbg3hdSlQ%PRS>Tx1e%JKhcZ5IHh???0 zbs=gW+{kWk0004nX+uL$Nkc;*aB^>EX>4Tx0C=2zkv&MmKpe$iQ?()$2MdabWT?7W z6curlDi*;)X)CnqU~=gfG-*guTpR`0f`cE6RR*plX&8kA%fkdR6qjq60(d!zjijX6n(zViGOK*F8LZy$kWI z*602l-Acw}fJY>rW4d7xZxGLHS~}-_;sDD_3h_Ddm_ZjLe&o9B@*C%z!vfC?7|HlN zae!FNHL={pEN`g9)5JkV)hJ&`xvX&B;;a_StbR}aLVreENpPL!AR<^o6fua9QAPnp zSP0RokzyiF`{5S;0mmOBmrSk#7&#VDf(ps;ga5(rZq4k}q?_aq1MM%i{V@#qc7a;O zw!e>UyLJM2pMfi_;V)Hz*-z3d4J~*C^lSqc*9}eH11@)f{wG~BBuDbn6tY?1{fxdT z4fNguU2AS{^?jT^07>d<`35*R1V(a{z24&8oz1=dd#2vs5BZsL-PLm{?EnA(24YJ` zL;wH)ssR50u8c$g000SaNLh0L04^f{04^f|c%?sf00007bV*G`2j&L>01X|`{rlbk z007fTL_t(I%av2n3Bw>1yw_$2Cnz{W=@6DcX0ha3l35CY3{g5mAQL!5upc4%#Awn3 zKa_X(PVPNI3WqW%dja5_wPm&t5wA+fpKnpXSql=vZ6f5!rURtJDLn4pNp+^478M*^ z$H*lWyVrq8Zziz4)lcLd)Cw?t=-g;8!g1NNON;Wwbkjj(?#lwSD7d*_PqUIE6948j zB{9Y@Jpc`~n%(8`7qViRh?6;pB5PRXFh=&NeeKTyj|l@$Lmn>1xoKqG_m|0Z<*8)k dJ%PX1`3FrOQyoDI2wwmI002ovPDHLkV1hm3dO83A literal 0 HcmV?d00001 diff --git a/items/generic/other/sexbound_birthspeedpill.consumable b/items/generic/other/sexbound_birthspeedpill.consumable new file mode 100644 index 00000000..666cf3ec --- /dev/null +++ b/items/generic/other/sexbound_birthspeedpill.consumable @@ -0,0 +1,18 @@ +{ + "itemName" : "sexbound_birthspeedpill", + "price" : 100, + "rarity" : "Common", + "category" : "medicine", + "inventoryIcon" : "sexbound_birthspeedpill.png", + "description" : "Swallow this to speed up the birthing process.", + "shortdescription" : "Speed Birth Pill", + "maxStack" : 1000, + "effects" : [ [ + { + "effect" : "sexbound_birthspeedpill", + "duration" : 840 + } + ] ], + "emote" : "", + "emitters" : [ "drinking" ] +} diff --git a/items/generic/other/sexbound_birthspeedpill.png b/items/generic/other/sexbound_birthspeedpill.png new file mode 100644 index 0000000000000000000000000000000000000000..e1cef36080853eaa1a58806441cdc0929629290c GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`?Vc`wgs87OA|lkQq2DJ!$*?12lrKHGPR z&(z>`QA@ck*~^jbP|g~umvN)*C6n8;t35pb&kJ7L^WTj5@cYh=h9yxF0#CV0ZWpR8 q*}t%(<%nYI1c&QBQ 0 then effect.expire() return end + self._aborted = status.stat('specialStatusImmunity') > 0 + if self._aborted then effect.expire() return end effect.addStatModifierGroup({ { stat = "invulnerable", amount = 1 }, @@ -22,6 +23,7 @@ function update() end function uninit() + if self._aborted then return end if status.isResource("stunned") then status.setResource("stunned", 0) end status.setStatusProperty("sexbound_stun", false) end \ No newline at end of file diff --git a/stats/effects/sexbound_birthspeedpill/sexbound_birthspeedpill.lua b/stats/effects/sexbound_birthspeedpill/sexbound_birthspeedpill.lua new file mode 100644 index 00000000..c9869ecb --- /dev/null +++ b/stats/effects/sexbound_birthspeedpill/sexbound_birthspeedpill.lua @@ -0,0 +1,11 @@ +function init() + +end + +function update() + +end + +function uninit() + +end \ No newline at end of file diff --git a/stats/effects/sexbound_birthspeedpill/sexbound_birthspeedpill.statuseffect b/stats/effects/sexbound_birthspeedpill/sexbound_birthspeedpill.statuseffect new file mode 100644 index 00000000..cc7640d9 --- /dev/null +++ b/stats/effects/sexbound_birthspeedpill/sexbound_birthspeedpill.statuseffect @@ -0,0 +1,8 @@ +{ + "name" : "sexbound_birthspeedpill", + "blockingStat" : "sexboundImmunity", + "defaultDuration" : 840, + "effectConfig" : {}, + "label" : "Speed Birthing", + "scripts" : [ "sexbound_birthspeedpill.lua" ] +} diff --git a/stats/effects/sexbound_custom_hyper_fertility/sexbound_custom_hyper_fertility.lua b/stats/effects/sexbound_custom_hyper_fertility/sexbound_custom_hyper_fertility.lua index ada4a4bf..3f5e95e2 100644 --- a/stats/effects/sexbound_custom_hyper_fertility/sexbound_custom_hyper_fertility.lua +++ b/stats/effects/sexbound_custom_hyper_fertility/sexbound_custom_hyper_fertility.lua @@ -1,4 +1,6 @@ function init() + self._aborted = status.getStatusProperty("sexbound_penalty_hyper_fertility", false) + if self._aborted then effect.expire() end status.setStatusProperty("sexbound_custom_hyper_fertility", true) world.sendEntityMessage(entity.id(), "Sexbound:Pregnant:AddStatus", "sexbound_custom_hyper_fertility") end @@ -7,3 +9,6 @@ function uninit() status.setStatusProperty("sexbound_custom_hyper_fertility", false) world.sendEntityMessage(entity.id(), "Sexbound:Pregnant:RemoveStatus", "sexbound_custom_hyper_fertility") end + +function onExpire() +end diff --git a/stats/effects/sexbound_debug_hyper_fertility/sexbound_debug_hyper_fertility.lua b/stats/effects/sexbound_debug_hyper_fertility/sexbound_debug_hyper_fertility.lua new file mode 100644 index 00000000..ada4a4bf --- /dev/null +++ b/stats/effects/sexbound_debug_hyper_fertility/sexbound_debug_hyper_fertility.lua @@ -0,0 +1,9 @@ +function init() + status.setStatusProperty("sexbound_custom_hyper_fertility", true) + world.sendEntityMessage(entity.id(), "Sexbound:Pregnant:AddStatus", "sexbound_custom_hyper_fertility") +end + +function uninit() + status.setStatusProperty("sexbound_custom_hyper_fertility", false) + world.sendEntityMessage(entity.id(), "Sexbound:Pregnant:RemoveStatus", "sexbound_custom_hyper_fertility") +end diff --git a/stats/effects/sexbound_debug_hyper_fertility/sexbound_debug_hyper_fertility.statuseffect b/stats/effects/sexbound_debug_hyper_fertility/sexbound_debug_hyper_fertility.statuseffect new file mode 100644 index 00000000..12f48d83 --- /dev/null +++ b/stats/effects/sexbound_debug_hyper_fertility/sexbound_debug_hyper_fertility.statuseffect @@ -0,0 +1,9 @@ +{ + "name" : "sexbound_debug_hyper_fertility", + "blockingStat" : "sexboundImmunity", + "defaultDuration" : 300, + "effectConfig" : {}, + "icon" : "/interface/statuses/hyperfertile.png", + "label" : "Extremely Fertile!", + "scripts" : [ "sexbound_debug_hyper_fertility.lua" ] +} From 90d7603f70e4e7b2227d9cefc4265b403fc95ff0 Mon Sep 17 00:00:00 2001 From: notlexander Date: Sat, 5 Oct 2024 23:49:00 -0500 Subject: [PATCH 09/12] Bug Fixes, Transform code update, and monster >Defeat nodes are no longer interactable when a second actor joins >players defeated by other players maybe still can interact before their attacker joins >Transform code further stabilized and updated to move players to the placed node. >New config option allowing players to bail from defeat nodes with ESC. >Custom regen buff added to remove regen particles during defeat scene. >NPCs and Monsters that defeat the player now handle node placement to allow tile protection to be turned off/on in protected areas. --- scripts/sexbound/lib/sexbound.lua | 16 ++- .../sexbound/override/common/transform.lua | 99 +++++++++---------- scripts/sexbound/override/monster.lua | 5 +- .../sexbound/override/monster/transform.lua | 26 ++--- scripts/sexbound/override/npc.lua | 5 +- scripts/sexbound/override/npc/transform.lua | 28 +++--- scripts/sexbound/override/player.lua | 5 +- .../sexbound/override/player/transform.lua | 6 +- sexbound-defeat.config | 6 ++ .../effects/sexbound_regen/sexbound_regen.lua | 14 +++ .../sexbound_regen1.statuseffect | 16 +++ .../sexbound_regen2.statuseffect | 16 +++ .../sexbound_regen3.statuseffect | 16 +++ .../sexbound_regen4.statuseffect | 16 +++ stats/sexbound/player_primary.lua | 3 + stats/sexbound/sexbounddefeat.lua | 68 ++++++++++--- 16 files changed, 237 insertions(+), 108 deletions(-) create mode 100644 stats/effects/sexbound_regen/sexbound_regen.lua create mode 100644 stats/effects/sexbound_regen/sexbound_regen1.statuseffect create mode 100644 stats/effects/sexbound_regen/sexbound_regen2.statuseffect create mode 100644 stats/effects/sexbound_regen/sexbound_regen3.statuseffect create mode 100644 stats/effects/sexbound_regen/sexbound_regen4.statuseffect diff --git a/scripts/sexbound/lib/sexbound.lua b/scripts/sexbound/lib/sexbound.lua index a90ca23c..8abe307b 100644 --- a/scripts/sexbound/lib/sexbound.lua +++ b/scripts/sexbound/lib/sexbound.lua @@ -342,17 +342,26 @@ function Sexbound:addActor(actorConfig, store) self._positions:filterPositions(self._actors) self._UI:refresh() - - if actor:getStatus():hasStatus("sexbound_defeated") then self._containsDefeated = true end if actor:getEntityType() == "player" then self._containsPlayer = true -- Open UI if not defeated or is allowed to while defeated. - if not actor:getStatus():hasStatus("sexbound_defeated") or actor:getStatus():hasStatus("sexbound_defeated_can_use_ui") then + if not actor:getStatus():hasStatus("sexbound_defeated") then actor:openUI() self._playerControl = true + else + if actor:getStatus():hasStatus("sexbound_defeated_can_use_ui") then + actor:openUI() + end end end + if self._containsDefeated then + -- Disable node interaction if an actor joins a defeat node + object.setInteractive(false) + end + + -- Mark node as a defeat node. + if actor:getStatus():hasStatus("sexbound_defeated") then self._containsDefeated = true end -- Resort actors based on changed environment self:helper_reassignAllRoles() @@ -391,6 +400,7 @@ function Sexbound:removeActor(entityId) if a:getEntityType() == "player" then containsPlayer = true end if a:getStatus():hasStatus("sexbound_defeated") then containsDefeated = true end end + if not containsDefeated then object.setInteractive(true) end self._containsPlayer = containsPlayer self._containsDefeated = containsDefeated diff --git a/scripts/sexbound/override/common/transform.lua b/scripts/sexbound/override/common/transform.lua index 959d7b28..729a5924 100644 --- a/scripts/sexbound/override/common/transform.lua +++ b/scripts/sexbound/override/common/transform.lua @@ -12,7 +12,8 @@ function Sexbound.Common.Transform:new() return setmetatable({ _canTransform = false, _nodeName = "sexbound_main_node", - _timeout = 300 + _timeout = 300, + _promises = PromiseKeeper.new() }, Sexbound.Common.Transform_mt) end @@ -24,45 +25,47 @@ function Sexbound.Common.Transform:init(parent) end --- Returns 5 nearby positions within 10 blocks underneath the entity. -function Sexbound.Common.Transform:findNearbyOpenSpace() +function Sexbound.Common.Transform:findNearbyOpenSpace(startPosition) local yOffset = 0.5 - - local startPosition = entity.position() + local distance = 6 + local positive = true + local positions = {} + local counter = 0 + local position = nil + startPosition = startPosition or entity.position() startPosition[2] = (startPosition[2] - self._feetOffset) + yOffset - local endPosition = vec2.add(startPosition, {0, -10}) + for i=0,distance * 2 do + position = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) + table.insert(positions, position) + counter = counter + 1 + if positive then + startPosition[1] = startPosition[1] + counter + endPosition[1] = endPosition[1] + counter + positive = false + else + startPosition[1] = startPosition[1] - counter + endPosition[1] = endPosition[1] - counter + positive = true + end - local position = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) - startPosition[1] = startPosition[1] - 1 - local positionL = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) - startPosition[1] = startPosition[1] - 1 - local positionLL = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) - startPosition[1] = startPosition[1] + 3 - local positionR = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) - startPosition[1] = startPosition[1] + 1 - local positionRR = world.lineCollision(startPosition, endPosition, {"Block", "Platform"}) - - if position == nil and positionL == nil and positionLL == nil and positionR == nil and positionRR == nil then - return false, false, false, false, false end - position = vec2.floor(position) - positionL = vec2.floor(positionL) - positionLL = vec2.floor(positionLL) - positionR = vec2.floor(positionR) - positionRR = vec2.floor(positionRR) - + if positions == {} then + return false + end - return position, positionL, positionLL, positionR, positionRR + return positions end --- Attempts to place a sex node beneath an entity. -- @param position -- @param spawnOptions -function Sexbound.Common.Transform:placeSexNode(spawnOptions) - local result = self:helper_SpawnSexNode(spawnOptions) - - return result +function Sexbound.Common.Transform:placeSexNode(spawnOptions, position, actorData) + local dungeonId = Sexbound.Util.tileProtectionDisable(position or entity.position()) + local uniqueId = self:helper_SpawnSexNode(spawnOptions, position or nil, actorData or nil) + Sexbound.Util.tileProtectionEnable(dungeonId) + return uniqueId end --- This function may never actually work while the NPC is stunned @@ -87,32 +90,23 @@ end -- [Helper] Handles the process of spawning a sex node in a tile beneath the entity. -- @param position -- @param spawnOptions -function Sexbound.Common.Transform:helper_SpawnSexNode(spawnOptions) - - local position, positionL, positionLL, positionR, positionRR = self:findNearbyOpenSpace() - - local targetTiles = { - [1] = position, - [2] = positionL, - [3] = positionR, - [4] = positionLL, - [5] = positionRR - } - - spawnOptions = spawnOptions or {} - +function Sexbound.Common.Transform:helper_SpawnSexNode(spawnOptions, position, actorData) + local positions = self:findNearbyOpenSpace(position) local params = { mindControl = { timeout = self._timeout -- 5 minutes by default unless overrided }, respawner = storage.respawner, sexboundConfig = self:getSexboundConfig(), - storedActor = self:getParent():getActorData(), + storedActor = actorData or nil, uniqueId = sb.makeUuid() } + + spawnOptions = spawnOptions or {} + -- Randomize the start position when true - params.sexboundConfig.randomStartPosition = spawnOptions.randomStartPosition + --params.sexboundConfig.randomStartPosition = spawnOptions.randomStartPosition local facingDirection = 1 @@ -122,18 +116,21 @@ function Sexbound.Common.Transform:helper_SpawnSexNode(spawnOptions) end -- Iterate through list of scanned tile positions until node is placed. - for _, targetTile in ipairs(targetTiles) do + local uniqueId = params.uniqueId + for _, targetTile in ipairs(positions) do -- In the future, we'll need to handle tile protection on a different entity in case of a player being transformed - local dungeonId = Sexbound.Util.tileProtectionDisable(position) - if world.placeObject(self._nodeName, targetTile, facingDirection, params) then - self:setPosition(position[1], position[2] + self._feetOffset) - + local placed = world.placeObject(self._nodeName, targetTile, facingDirection, params) + if placed then + if actorData.entityType == "player" then + world.sendEntityMessage(actorData.entityId, "Sexbound:Defeat:SetPosition", {targetTile[1], targetTile[2] + 2.5}) + elseif mcontroller then + mcontroller.setPosition(targetTile[1], targetTile[2] + self._feetOffset) + end if not spawnOptions.noEffect then - world.sendEntityMessage(entity.id(), "applyStatusEffect", "sexbound_transform") + world.sendEntityMessage(actorData.entityId, "applyStatusEffect", "sexbound_transform") end return params.uniqueId end - Sexbound.Util.tileProtectionEnable(dungeonId) end diff --git a/scripts/sexbound/override/monster.lua b/scripts/sexbound/override/monster.lua index 155332c5..5f67e7e3 100644 --- a/scripts/sexbound/override/monster.lua +++ b/scripts/sexbound/override/monster.lua @@ -114,6 +114,9 @@ function Sexbound.Monster:initMessageHandlers() message.setHandler("Sexbound:Actor:Say", function(_, _, args) return self:handleSay(args) end) + message.setHandler("Sexbound:Actor:GetActorData", function(_, _, args) + return self:getActorData(), args + end) message.setHandler("Sexbound:Config:Retrieve", function(_, _, args) return self:handleRetrieveConfig(args) end) @@ -176,7 +179,7 @@ function Sexbound.Monster:restore() end function Sexbound.Monster:handleRetrieveConfig(args) - return config.getParameter("sexboundConfig") + return config.getParameter("sexboundConfig"), args end function Sexbound.Monster:handleSay(args) diff --git a/scripts/sexbound/override/monster/transform.lua b/scripts/sexbound/override/monster/transform.lua index 5e7beb6d..2e8087f1 100644 --- a/scripts/sexbound/override/monster/transform.lua +++ b/scripts/sexbound/override/monster/transform.lua @@ -14,15 +14,15 @@ function Sexbound.Monster.Transform:new(parent) _self:setCanTransform(true); - message.setHandler("Sexbound:Transform", function(_, _, args) - return _self:handleTransform(args) + message.setHandler("Sexbound:Transform", function(_, _, args, actorData) + return _self:handleTransform(args, actorData) end) return _self end -function Sexbound.Monster.Transform:handleTransform(args) - if self:getCanTransform() then +function Sexbound.Monster.Transform:handleTransform(args, actorData) + if self:getCanTransform() or actorData ~= nil then self:setSexboundConfig(args.sexboundConfig) self:setTimeout(args.timeout) @@ -30,7 +30,7 @@ function Sexbound.Monster.Transform:handleTransform(args) if not args.responseRequired then self:notifyTransform() else - local result = self:tryCreateNode() + local result = self:tryCreateNode(args.spawnOptions or {}, args.position or nil, actorData or nil) if result ~= nil and args.applyStatusEffects ~= nil then for _, statusName in ipairs(args.applyStatusEffects) do @@ -60,17 +60,11 @@ function Sexbound.Monster.Transform:handleTransform(args) return false end -function Sexbound.Monster.Transform:tryCreateNode() - local position = self:findNearbyOpenSpace() - - if position == false then - return nil - end - - -- Place Sexnode and store Unique ID - local uniqueId = self:placeSexNode(position, { - randomStartPosition = true - }) +function Sexbound.Monster.Transform:tryCreateNode(spawnOptions, position, actorData) + local uniqueId = self:placeSexNode({ + randomStartPosition = true, + noEffect = spawnOptions.noEffect or false + }, position or nil, actorData or nil) if uniqueId ~= nil then world.sendEntityMessage(entity.id(), "Sexbound:Transform:Success", { diff --git a/scripts/sexbound/override/npc.lua b/scripts/sexbound/override/npc.lua index 71d67565..2ce412ed 100644 --- a/scripts/sexbound/override/npc.lua +++ b/scripts/sexbound/override/npc.lua @@ -185,6 +185,9 @@ function Sexbound.NPC:initMessageHandlers() message.setHandler("Sexbound:Actor:Say", function(_, _, args) return self:handleSay(args) end) + message.setHandler("Sexbound:Actor:GetActorData", function(_, _, args) + return self:getActorData(), args + end) message.setHandler("Sexbound:Config:Retrieve", function(_, _, args) return self:handleRetrieveConfig(args) end) @@ -266,7 +269,7 @@ function Sexbound.NPC:handleRestore(args) end function Sexbound.NPC:handleRetrieveConfig(args) - return config.getParameter("sexboundConfig") + return config.getParameter("sexboundConfig"), args end function Sexbound.NPC:handleSay(args) diff --git a/scripts/sexbound/override/npc/transform.lua b/scripts/sexbound/override/npc/transform.lua index a0e3bdae..9da3b729 100644 --- a/scripts/sexbound/override/npc/transform.lua +++ b/scripts/sexbound/override/npc/transform.lua @@ -15,17 +15,17 @@ function Sexbound.NPC.Transform:new(parent) _self:setCanTransform(true); - message.setHandler("Sexbound:Transform", function(_, _, args) - return _self:handleTransform(args) + message.setHandler("Sexbound:Transform", function(_, _, args, actorData) + return _self:handleTransform(args, actorData) end) return _self end -function Sexbound.NPC.Transform:handleTransform(args) +function Sexbound.NPC.Transform:handleTransform(args, actorData) if self._parent._isKid then return false end - - if self:getCanTransform() then + + if self:getCanTransform() or actorData ~= nil then -- Override sexbound config that is supplied to the spawned sexnode self:setSexboundConfig(args.sexboundConfig) @@ -34,7 +34,7 @@ function Sexbound.NPC.Transform:handleTransform(args) if not args.responseRequired then self:notifyTransform() else - local result = self:tryCreateNode() + local result = self:tryCreateNode(args.spawnOptions or {}, args.position or nil, actorData or nil) if result ~= nil and args.applyStatusEffects ~= nil then for _, statusName in ipairs(args.applyStatusEffects) do @@ -73,19 +73,13 @@ function Sexbound.NPC.Transform:notifyTransform() end end -function Sexbound.NPC.Transform:tryCreateNode() +function Sexbound.NPC.Transform:tryCreateNode(spawnOptions, position, actorData) if self._parent._isKid then return nil end - local position = self:findNearbyOpenSpace() - - if position == false then - return nil - end - - -- Place Sexnode and store Unique ID - local uniqueId = self:placeSexNode(position, { - randomStartPosition = true - }) + local uniqueId = self:placeSexNode({ + randomStartPosition = true, + noEffect = spawnOptions.noEffect or false + }, position or nil, actorData or nil) if uniqueId ~= nil then world.sendEntityMessage(entity.id(), "Sexbound:Transform:Success", { diff --git a/scripts/sexbound/override/player.lua b/scripts/sexbound/override/player.lua index 7048366b..18b06b0d 100644 --- a/scripts/sexbound/override/player.lua +++ b/scripts/sexbound/override/player.lua @@ -275,7 +275,7 @@ function Sexbound.Player:restore() end function Sexbound.Player:handleRetrieveConfig(args) - return nil + return nil, args end function Sexbound.Player:handleRetrieveStorage(args) @@ -364,6 +364,9 @@ function Sexbound.Player:initMessageHandlers() message.setHandler("Sexbound:Actor:Respawn", function(_, _, args) return self:handleRespawn(args) end) + message.setHandler("Sexbound:Actor:GetActorData", function(_, _, args) + return self:getActorData(), args + end) message.setHandler("Sexbound:Config:Retrieve", function(_, _, args) return self:handleRetrieveConfig(args) end) diff --git a/scripts/sexbound/override/player/transform.lua b/scripts/sexbound/override/player/transform.lua index 73ba85af..3e9e6385 100644 --- a/scripts/sexbound/override/player/transform.lua +++ b/scripts/sexbound/override/player/transform.lua @@ -31,7 +31,7 @@ function Sexbound.Player.Transform:handleTransform(args) self:setTimeout(args.timeout) - local result = self:tryCreateNode(args.spawnOptions or {}) + local result = self:tryCreateNode(args.spawnOptions or {}, args.position or nil) if result ~= nil and args.applyStatusEffects ~= nil then for _, statusName in ipairs(args.applyStatusEffects) do @@ -45,12 +45,12 @@ function Sexbound.Player.Transform:handleTransform(args) return false end -function Sexbound.Player.Transform:tryCreateNode(spawnOptions) +function Sexbound.Player.Transform:tryCreateNode(spawnOptions, position, data) -- Place Sexnode and store Unique ID local uniqueId = self:placeSexNode({ randomStartPosition = true, noEffect = spawnOptions.noEffect or false - }) + }, position or nil, data or nil) if self._parent:canLog("debug") then sb.logInfo("Placed node with UUID "..tostring(uniqueId)) end if uniqueId ~= nil then world.sendEntityMessage(entity.id(), "Sexbound:Transform:Success", { diff --git a/sexbound-defeat.config b/sexbound-defeat.config index ad7bc699..d0a84b42 100644 --- a/sexbound-defeat.config +++ b/sexbound-defeat.config @@ -47,6 +47,12 @@ */ "defeatedPlayersCanUseSexUI" : false, + /* + Setting this to true enables a defeated player to escape the defeat scene. + Valid options are true & false. Default: false + */ + "enableDefeatedPlayerEscape" : false, + /* Define 'victory' and 'defeated' start dialog for NPCs. the 'default' species is a fallback. */ "startDialog" : { "victory" : { diff --git a/stats/effects/sexbound_regen/sexbound_regen.lua b/stats/effects/sexbound_regen/sexbound_regen.lua new file mode 100644 index 00000000..c5f6d05b --- /dev/null +++ b/stats/effects/sexbound_regen/sexbound_regen.lua @@ -0,0 +1,14 @@ +function init() + + script.setUpdateDelta(5) + + self.healingRate = 1.0 / config.getParameter("healTime", 60) +end + +function update(dt) + status.modifyResourcePercentage("health", self.healingRate * dt) +end + +function uninit() + +end diff --git a/stats/effects/sexbound_regen/sexbound_regen1.statuseffect b/stats/effects/sexbound_regen/sexbound_regen1.statuseffect new file mode 100644 index 00000000..f8a15784 --- /dev/null +++ b/stats/effects/sexbound_regen/sexbound_regen1.statuseffect @@ -0,0 +1,16 @@ +{ + "name" : "sexbound_regen1", + "blockingStat" : "healingStatusImmunity", + + "effectConfig" : { + "healTime" : 60 + }, + "defaultDuration" : 5, + + "scripts" : [ + "sexbound_regen.lua" + ], + + "label" : "Defeat Regeneration", + "icon" : "/interface/statuses/heal.png" +} diff --git a/stats/effects/sexbound_regen/sexbound_regen2.statuseffect b/stats/effects/sexbound_regen/sexbound_regen2.statuseffect new file mode 100644 index 00000000..8f71d531 --- /dev/null +++ b/stats/effects/sexbound_regen/sexbound_regen2.statuseffect @@ -0,0 +1,16 @@ +{ + "name" : "sexbound_regen2", + "blockingStat" : "healingStatusImmunity", + + "effectConfig" : { + "healTime" : 50 + }, + "defaultDuration" : 5, + + "scripts" : [ + "sexbound_regen.lua" + ], + + "label" : "Defeat Regeneration", + "icon" : "/interface/statuses/heal.png" +} diff --git a/stats/effects/sexbound_regen/sexbound_regen3.statuseffect b/stats/effects/sexbound_regen/sexbound_regen3.statuseffect new file mode 100644 index 00000000..323534db --- /dev/null +++ b/stats/effects/sexbound_regen/sexbound_regen3.statuseffect @@ -0,0 +1,16 @@ +{ + "name" : "sexbound_regen3", + "blockingStat" : "healingStatusImmunity", + + "effectConfig" : { + "healTime" : 40 + }, + "defaultDuration" : 5, + + "scripts" : [ + "sexbound_regen.lua" + ], + + "label" : "Defeat Regeneration", + "icon" : "/interface/statuses/heal.png" +} diff --git a/stats/effects/sexbound_regen/sexbound_regen4.statuseffect b/stats/effects/sexbound_regen/sexbound_regen4.statuseffect new file mode 100644 index 00000000..83b4b4e5 --- /dev/null +++ b/stats/effects/sexbound_regen/sexbound_regen4.statuseffect @@ -0,0 +1,16 @@ +{ + "name" : "sexbound_regen4", + "blockingStat" : "healingStatusImmunity", + + "effectConfig" : { + "healTime" : 30 + }, + "defaultDuration" : 5, + + "scripts" : [ + "sexbound_regen.lua" + ], + + "label" : "Defeat Regeneration", + "icon" : "/interface/statuses/heal.png" +} diff --git a/stats/sexbound/player_primary.lua b/stats/sexbound/player_primary.lua index 7f34eee4..a6dd9be7 100644 --- a/stats/sexbound/player_primary.lua +++ b/stats/sexbound/player_primary.lua @@ -8,6 +8,9 @@ function init() status.removeEphemeralEffect("sexbound_sex") status.removeEphemeralEffect("sexbound_stun") status.removeEphemeralEffect("regeneration4") + message.setHandler("Sexbound:Defeat:SetPosition", function(_, _, position) + mcontroller.setPosition(position) + end) end -- Override Update Hook diff --git a/stats/sexbound/sexbounddefeat.lua b/stats/sexbound/sexbounddefeat.lua index 4235aa7a..780799ec 100644 --- a/stats/sexbound/sexbounddefeat.lua +++ b/stats/sexbound/sexbounddefeat.lua @@ -24,9 +24,12 @@ function SexboundDefeat:new(entityType) _timeout = 60, _isDefeated = false, _isTransformed = false, - _sexNodeId = nil + _sexNodeId = nil, + _actorData = nil }, SexboundDefeat_mt) + _self:setIsDefeated(false) + -- Load the Sexbound Defeat config settings _self._config = _self:loadConfig() _self:validateConfig(_self._config) @@ -114,15 +117,33 @@ function SexboundDefeat:handleApplyDamageRequest(originalFunction, damageRequest self:setTimer(0) -- Attempt to transform this entity into a sexnode - self:retrieveSexboundConfig(function(result) - return self:handleRetrieveSexboundConfigSuccess(result) - end, function() - return self:handleRetrieveSexboundConfigFailure() - end) + self:retrieveActorData() return {} end +function SexboundDefeat:retrieveActorData() + local entityId = self._entityId + self._promises:add( + world.sendEntityMessage( + entityId, + "Sexbound:Actor:GetActorData" + ), + function(actorData) + self._actorData = actorData + self:retrieveSexboundConfig(function(result) + return self:handleRetrieveSexboundConfigSuccess(result) + end, function() + return self:handleRetrieveSexboundConfigFailure() + end, + actorData) + end, + function() + self:tryToDie() + end) + +end + function SexboundDefeat:loadConfig() local _,loadedConfig = xpcall(function() return root.assetJson(self._configFilePath) @@ -182,23 +203,33 @@ function SexboundDefeat:handleRetrieveSexboundConfigSuccess(sexboundConfig) return self:handleTransformSuccess(result.uniqueId) end, function() return self:handleTransformFailed() - end ) + end, + self._actorData + ) end function SexboundDefeat:handleRetrieveSexboundConfigFailure() self:tryToDie() end -function SexboundDefeat:transform(sexboundConfig, successCallback, failureCallback) +function SexboundDefeat:transform(sexboundConfig, successCallback, failureCallback, actorData) + local position = nil + local entityId = self._entityId + if self:isPlayer() then + position = entity.position() + entityId = self._hostileEntityId + end self._promises:add( world.sendEntityMessage( - self._entityId, + entityId, "Sexbound:Transform", { responseRequired = true, sexboundConfig = sexboundConfig, - timeout = 500 - } + timeout = 500, + position = position + }, + actorData or nil ), successCallback, failureCallback @@ -218,9 +249,9 @@ function SexboundDefeat:handleTransformSuccess(nodeUniqueId) self:_initTimeout() if self:isPlayer() then -- Check config for using invisible "UI" that allows escape with ESC key - --world.sendEntityMessage(self._entityId, "Sexbound:UI:Show", {config = self:loadUIConfig()}) + if self._config.enableDefeatedPlayerEscape then world.sendEntityMessage(self._entityId, "Sexbound:UI:Show", {config = self:loadUIConfig()}) end status.addEphemeralEffect("dontstarve", self._timeout) - status.addEphemeralEffect("regeneration4", self._timeout) + status.addEphemeralEffect("sexbound_regen4", self._timeout) end status.addEphemeralEffect("sexbound_sex", self._timeout) @@ -278,7 +309,7 @@ function SexboundDefeat:untransform() self._hostileEntityId = nil self._hostileEntityType = nil self._sexNodeId = nil - status.removeEphemeralEffect("regeneration4") + status.removeEphemeralEffect("sexbound_regen4") end -- Validate Configuration @@ -291,6 +322,7 @@ function SexboundDefeat:validateConfig() self:_validateEnableImmortalPregnantNPCs(self._config.enableImmortalPregnantNPCs, false) self:_validateEnableStartDialogForNPCs(self._config.enableStartDialogForNPCs, true) self:_validateEnableStartDialogForMonsters(self._config.enableStartDialogForMonsters, false) + self:_validateEnableDefeatedPlayerEscape(self._config.enableDefeatedPlayerEscape, false) end -- Getters / Setters @@ -307,7 +339,7 @@ function SexboundDefeat:getTimeout() end function SexboundDefeat:isDefeated() - return self._isDefeated + return self._isDefeated or status.statusProperty("sexbound_defeated") end function SexboundDefeat:isMonster() @@ -438,4 +470,10 @@ function SexboundDefeat:_validateEnableStartDialogForMonsters(value, defaultValu if self:_isBoolean(value) then return end self:_logWarnInvalidValueProvided("enableStartDialogForMonsters", defaultValue) self._config.enableStartDialogForMonsters = defaultValue +end + +function SexboundDefeat:_validateEnableDefeatedPlayerEscape(value, defaultValue) + if self:_isBoolean(value) then return end + self:_logWarnInvalidValueProvided("enableDefeatedPlayerEscape", defaultValue) + self._config.enableDefeatedPlayerEscape = defaultValue end \ No newline at end of file From aef98f3dc154612c2636216907db6920e3b9daa1 Mon Sep 17 00:00:00 2001 From: notlexander Date: Sat, 12 Oct 2024 10:33:02 -0500 Subject: [PATCH 10/12] Implemented hostile entity tracking system >Defeat no longer relies on damage source entity >Instead checks for nearest tracked hostile >Fixes death by DoT or other means >Fixed transform bug from last commit --- scripts/actions/notification.lua | 52 ++++++++ .../sexbound/override/common/transform.lua | 2 +- stats/sexbound/sexbounddefeat.lua | 126 ++++++++++++++---- 3 files changed, 152 insertions(+), 28 deletions(-) create mode 100644 scripts/actions/notification.lua diff --git a/scripts/actions/notification.lua b/scripts/actions/notification.lua new file mode 100644 index 00000000..35ad777d --- /dev/null +++ b/scripts/actions/notification.lua @@ -0,0 +1,52 @@ +-- param type +function receivedNotification(args, board) + if args.type == nil then return false end + + for i,notification in pairs(self.notifications) do + if notification.type == args.type then + table.remove(self.notifications, i) + return true, {source = notification.sourceId, target = notification.targetId, targetPosition = notification.targetPosition} + end + end + return false +end + +-- param type +-- param entity +-- param target +function sendNotification(args, board) + if args.entity == nil or args.type == nil then return false end + + local notification = { + sourceId = entity.id(), + targetId = args.target, + type = args.type + } + world.callScriptedEntity(args.entity, "notify", notification) + return true +end + +-- param type +-- param position +-- param range +-- param entityTypes +-- param target +function broadcastNotification(args, board) + if args.type == nil or args.position == nil or args.range == nil then return false end + if args.target == nil then args.target = "nil" end + sb.logInfo("notification: type="..args.type.." target="..args.target) + if args.target == "nil" then args.target = nil end + + local notification = { + sourceId = entity.id(), + targetId = args.target, + type = args.type + } + if args.type == "attack" or args.type == "notifyFindTarget" then world.sendEntityMessage(args.target, "SexboundDefeat:TargetedBy", entity.id()) end + local notified = world.entityQuery(args.position, args.range, { includedTypes = args.entityTypes, callScript = "notify", callScriptArgs = {notification} }) + if #notified > 0 then + return true + else + return false + end +end diff --git a/scripts/sexbound/override/common/transform.lua b/scripts/sexbound/override/common/transform.lua index 729a5924..92ad5566 100644 --- a/scripts/sexbound/override/common/transform.lua +++ b/scripts/sexbound/override/common/transform.lua @@ -124,7 +124,7 @@ function Sexbound.Common.Transform:helper_SpawnSexNode(spawnOptions, position, a if actorData.entityType == "player" then world.sendEntityMessage(actorData.entityId, "Sexbound:Defeat:SetPosition", {targetTile[1], targetTile[2] + 2.5}) elseif mcontroller then - mcontroller.setPosition(targetTile[1], targetTile[2] + self._feetOffset) + mcontroller.setPosition({targetTile[1], targetTile[2] + self._feetOffset}) end if not spawnOptions.noEffect then world.sendEntityMessage(actorData.entityId, "applyStatusEffect", "sexbound_transform") diff --git a/stats/sexbound/sexbounddefeat.lua b/stats/sexbound/sexbounddefeat.lua index 780799ec..84e28fe1 100644 --- a/stats/sexbound/sexbounddefeat.lua +++ b/stats/sexbound/sexbounddefeat.lua @@ -25,7 +25,9 @@ function SexboundDefeat:new(entityType) _isDefeated = false, _isTransformed = false, _sexNodeId = nil, - _actorData = nil + _hostileEntities = {}, + _actorData = nil, + _sexboundConfig = nil }, SexboundDefeat_mt) _self:setIsDefeated(false) @@ -41,7 +43,7 @@ function SexboundDefeat:new(entityType) _self:_initTimeout() -- Set "Can use sexbound UI while defeated." state as a status for use with other scripts - status.setStatusProperty("can_use_sex_ui_defeated", _self._config.defeatedPlayersCanUseSexUI) + status.setStatusProperty("can_use_sex_ui_defeated", _self._config.defeatedPlayersCanUseSexUI) return _self end @@ -50,6 +52,36 @@ function SexboundDefeat:initMessageHandlers() message.setHandler("SexboundDefeat:Breakout", function(_,_,args) self._timer = self._timeout end) + message.setHandler("SexboundDefeat:TargetedBy", function(_,_,entityId) + sb.logInfo("being targetd by entity: "..entityId) + local found = false + for i, v in ipairs(self._hostileEntities) do + if v[1] == entityId then found = true end + end + if not found then + self:retrieveSexboundConfig(function(result) + world.sendEntityMessage(entityId, "SexboundDefeat:InCombatWith", self._entityId) + return self:handleRetrieveSexboundConfigSuccess(result,entityId) + end, function() + return + end, + entityId) + end + end) + message.setHandler("SexboundDefeat:InCombatWith", function(_,_,entityId) + local found = false + for i, v in ipairs(self._hostileEntities) do + if v[1] == entityId then found = true end + end + if not found then + self:retrieveSexboundConfig(function(result) + return self:handleRetrieveSexboundConfigSuccess(result,entityId) + end, function() + return + end, + entityId) + end + end) end -- Update Loop @@ -96,17 +128,22 @@ function SexboundDefeat:handleApplyDamageRequest(originalFunction, damageRequest if status.resource("health") > 0 then return damage end -- Store a reference to the hostile entity id that delivered the killing blow to this entity - self._hostileEntityId = damageRequest.sourceEntityId - if self._hostileEntityId ~= nil then - self._hostileEntityType = world.entityType(self._hostileEntityId) + local hostileEntityId = damageRequest.sourceEntityId + local hostileEntityType = nil + if hostileEntityId ~= nil then + hostileEntityType = world.entityType(hostileEntityId) end -- Handle the case that the entity has given itself a killing blow if self:isSuicide() then - self:tryToDie() + self:tryToDie("suicide") return {} end + if self._entityId == "player" and hostileEntityType == "player" then + world.sendEntityMessage(self._entityId, "SexboundDefeat:TargetedBy", hostileEntityId) + end + -- Prevent the entity from dying by ticking its health up by a percentage point status.setResourcePercentage("health", 0.01) @@ -117,12 +154,12 @@ function SexboundDefeat:handleApplyDamageRequest(originalFunction, damageRequest self:setTimer(0) -- Attempt to transform this entity into a sexnode - self:retrieveActorData() + self:retrieveActorData(hostileEntityId, hostileEntityType) return {} end -function SexboundDefeat:retrieveActorData() +function SexboundDefeat:retrieveActorData(damageSourceEntity, damageSourceEntityType) local entityId = self._entityId self._promises:add( world.sendEntityMessage( @@ -130,16 +167,47 @@ function SexboundDefeat:retrieveActorData() "Sexbound:Actor:GetActorData" ), function(actorData) - self._actorData = actorData - self:retrieveSexboundConfig(function(result) - return self:handleRetrieveSexboundConfigSuccess(result) - end, function() - return self:handleRetrieveSexboundConfigFailure() - end, - actorData) + --find closest entity that's in the table + local found = false + local hostileEntityId = nil + local sexboundConfig = nil + local entities = world.entityQuery(entity.position(), 25, {includedTypes = {"monster","npc","player"}, order = "nearest"}) + for i,v in ipairs(entities) do + sb.logInfo("entity query returned: "..v) + for i2,v2 in ipairs(self._hostileEntities) do + sb.logInfo ("Checking entity list: queried "..v.." against list "..v2[1]) + if v == v2[1] then + found = true + hostileEntityId = v2[1] + sexboundConfig = v2[2] + self._hostileEntityId = hostileEntityId + self._hostileEntityType = world.entityType(self._hostileEntityId) + break + end + end + if found then break end + end + if hostileEntityId then + --victory dialog, transform attempt + self:outputVictoryDialog() + self:transform(sexboundConfig, + function(result) + result = result or {} + if result.uniqueId == nil then + return self:handleTransformFailed() + end + return self:handleTransformSuccess(result.uniqueId) + end, function() + return self:handleTransformFailed() + end, + actorData + ) + else + self:tryToDie("Hostile entity not found in table") + end end, function() - self:tryToDie() + self:tryToDie("Actor data retrieval failed") end) end @@ -181,10 +249,10 @@ function SexboundDefeat:outputVictoryDialog() ) end -function SexboundDefeat:retrieveSexboundConfig(successCallback, failureCallback) +function SexboundDefeat:retrieveSexboundConfig(successCallback, failureCallback, entityId) self._promises:add( world.sendEntityMessage( - self._hostileEntityId, + entityId, "Sexbound:Config:Retrieve" ), successCallback, @@ -192,8 +260,13 @@ function SexboundDefeat:retrieveSexboundConfig(successCallback, failureCallback) ) end -function SexboundDefeat:handleRetrieveSexboundConfigSuccess(sexboundConfig) - -- Output the victory dialog +function SexboundDefeat:handleRetrieveSexboundConfigSuccess(sexboundConfig, hostileEntityId) + table.insert(self._hostileEntities, 1, {hostileEntityId, sexboundConfig}) + + if #self._hostileEntities > 8 then + table.remove(self._hostileEntities) + end + --[[ Output the victory dialog self:outputVictoryDialog() self:transform(sexboundConfig, function(result) result = result or {} @@ -206,11 +279,9 @@ function SexboundDefeat:handleRetrieveSexboundConfigSuccess(sexboundConfig) end, self._actorData ) + ]] end -function SexboundDefeat:handleRetrieveSexboundConfigFailure() - self:tryToDie() -end function SexboundDefeat:transform(sexboundConfig, successCallback, failureCallback, actorData) local position = nil @@ -237,7 +308,7 @@ function SexboundDefeat:transform(sexboundConfig, successCallback, failureCallba end function SexboundDefeat:handleTransformFailed() - self:tryToDie() + self:tryToDie("Transform failed") return false end @@ -277,7 +348,8 @@ function SexboundDefeat:loadUIConfig() return _config or {} end -function SexboundDefeat:tryToDie() +function SexboundDefeat:tryToDie(reason) + if reason then sb.logInfo("tryToDie reason: "..reason) end self:setIsDefeated(false) self:setIsTransformed(false) if not self:isPlayer() and self:isPregnant() and self._config.enableImmortalPregnantNPCs then @@ -297,7 +369,7 @@ end -- [Helper] Untransform the Entity function SexboundDefeat:untransform() - if not self:isPlayer() then self:tryToDie() end + if not self:isPlayer() then self:tryToDie("non-player untransform") end local storage = {} -- temp local storage if not self:isPlayer() and self:isPregnant() and self._config.convertPregnantEnemiesToFriends then storage = { previousDamageTeam = { type = "friendly", team = 1 } } @@ -363,7 +435,7 @@ function SexboundDefeat:isStunned() end function SexboundDefeat:isSuicide() - return self._hostileEntityId == nil or self._hostileEntityId == self._entityId + return self._hostileEntityId == self._entityId end function SexboundDefeat:isTransformed() From 3b1aa1a63f07bd3a63c33810db61179a0a1737fd Mon Sep 17 00:00:00 2001 From: notlexander Date: Tue, 22 Oct 2024 14:54:08 -0500 Subject: [PATCH 11/12] Numerous updates: customizer, invincibility, fixes -moved message sending for the defeat entity tracker to behaviors instead of overriding or hooking notification.lua -added on/off switches for defeat functionality using customizer -momentary invincibility buff after defeat so you don't get auto smacked. (1.5 seconds) -disabled normal dialog on defeat nodes -added code to bail out of defeat sexnodes when no valid positions exist -ensured old transform functionality remains for other mods that use transform code (tested EB's whips, works fine) --- .../monsters/modular/targeting.behavior.patch | 92 ++++++++++++++++ behaviors/npc/hostiletracking.behavior.patch | 103 ++++++++++++++++++ .../sexbound/customizer/customizer.config | 78 ++++++++++++- .../sexbound/customizer/customizergeneral.lua | 36 +++++- .../sexbound/customizer/customizerui.lua | 10 ++ scripts/actions/notification.lua | 52 --------- scripts/sexbound/lib/sexbound.lua | 16 ++- scripts/sexbound/lib/sexbound/positions.lua | 5 +- scripts/sexbound/lib/sexbound/sextalk.lua | 4 + scripts/sexbound/override/common/status.lua | 8 ++ .../sexbound/override/common/transform.lua | 8 +- scripts/sexbound/override/player.lua | 8 +- scripts/sexbound/plugins/climax/climax.lua | 1 - .../sexbound_defeat_invuln.lua | 9 ++ .../sexbound_defeat_invuln.statuseffect | 9 ++ .../sexbound_defeat_stun.lua | 29 +++++ .../sexbound_defeat_stun.statuseffect | 9 ++ stats/sexbound/monster_primary.lua | 2 +- stats/sexbound/npc_primary.lua | 2 +- stats/sexbound/player_primary.lua | 2 +- stats/sexbound/sexbounddefeat.lua | 33 ++++-- 21 files changed, 439 insertions(+), 77 deletions(-) create mode 100644 behaviors/monsters/modular/targeting.behavior.patch create mode 100644 behaviors/npc/hostiletracking.behavior.patch delete mode 100644 scripts/actions/notification.lua create mode 100644 stats/effects/sexbound_defeat_invuln/sexbound_defeat_invuln.lua create mode 100644 stats/effects/sexbound_defeat_invuln/sexbound_defeat_invuln.statuseffect create mode 100644 stats/effects/sexbound_defeat_stun/sexbound_defeat_stun.lua create mode 100644 stats/effects/sexbound_defeat_stun/sexbound_defeat_stun.statuseffect diff --git a/behaviors/monsters/modular/targeting.behavior.patch b/behaviors/monsters/modular/targeting.behavior.patch new file mode 100644 index 00000000..b16cb1db --- /dev/null +++ b/behaviors/monsters/modular/targeting.behavior.patch @@ -0,0 +1,92 @@ +[ + { + "op": "add", + "path": "/root/children/1/children/0/children/1/child/children/0/child/children/1/child/children/2", + "value": { + + "title": "listPush", + "type": "action", + "name": "listPush", + "parameters": { + "entity": {"key": "self"}, + "list": {"key": "entitySelf"} + }, + "output": { + "list": "entitySelf" + } + } + }, + { + "op": "add", + "path": "/root/children/1/children/0/children/1/child/children/0/child/children/1/child/children/3", + "value": { + "title": "sendEntityMessage", + "type": "action", + "name": "sendEntityMessage", + "parameters": { + "entity": {"key": "filterItem"}, + "message": {"value": "SexboundDefeat:TargetedBy"}, + "arguments": {"key": "entitySelf"} + } + } + }, + { + "op": "add", + "path": "/root/children/1/children/0/children/1/child/children/0/child/children/1/child/children/4", + "value": { + "title": "listPop", + "type": "action", + "name": "listPop", + "parameters": { + "list": {"key": "entitySelf"} + }, + "output": { + } + } + }, + { + "op": "add", + "path": "/root/children/1/children/0/children/1/child/children/1/child/children/1", + "value": { + + "title": "listPush", + "type": "action", + "name": "listPush", + "parameters": { + "entity": {"key": "self"}, + "list": {"key": "entitySelf"} + }, + "output": { + "list": "entitySelf" + } + } + }, + { + "op": "add", + "path": "/root/children/1/children/0/children/1/child/children/1/child/children/2", + "value": { + "title": "sendEntityMessage", + "type": "action", + "name": "sendEntityMessage", + "parameters": { + "entity": {"key": "damageSource"}, + "message": {"value": "SexboundDefeat:TargetedBy"}, + "arguments": {"key": "entitySelf"} + } + } + }, + { + "op": "add", + "path": "/root/children/1/children/0/children/1/child/children/1/child/children/3", + "value": { + "title": "listPop", + "type": "action", + "name": "listPop", + "parameters": { + "list": {"key": "entitySelf"} + }, + "output": { + } + } + } +] \ No newline at end of file diff --git a/behaviors/npc/hostiletracking.behavior.patch b/behaviors/npc/hostiletracking.behavior.patch new file mode 100644 index 00000000..94838526 --- /dev/null +++ b/behaviors/npc/hostiletracking.behavior.patch @@ -0,0 +1,103 @@ +[ + { + "op": "add", + "path": "/root/children/1/children/0/children/0/children/0/children/7", + "value": { + + "title": "listPush", + "type": "action", + "name": "listPush", + "parameters": { + "entity": {"key": "self"}, + "list": {"key": "entitySelf"} + }, + "output": { + "list": "entitySelf" + } + } + }, + { + "op": "add", + "path": "/root/children/1/children/0/children/0/children/0/children/8", + "value": { + "title": "sendEntityMessage", + "type": "action", + "name": "sendEntityMessage", + "parameters": { + "entity": {"key": "target"}, + "message": {"value": "SexboundDefeat:TargetedBy"}, + "arguments": {"key": "entitySelf"} + } + } + }, + { + "op": "add", + "path": "/root/children/1/children/0/children/0/children/0/children/9", + "value": { + "title": "listPop", + "type": "action", + "name": "listPop", + "parameters": { + "list": {"key": "entitySelf"} + }, + "output": { + } + } + }, + { + "op": "replace", + "path": "/root/children/1/children/1/children/2/child/child", + "value": { + "title": "sequence", + "type": "composite", + "name": "sequence", + "parameters": {}, + "children": [ + { + "title": "broadcastNotification", + "type": "action", + "name": "broadcastNotification", + "parameters": { + "entityTypes": {"value": ["npc"]}, + "position": {"key": "self"}, + "range": {"value": 40}, + "target": {"key": "target"}, + "type": {"value": "attack"} + } + }, + { + "title": "listPush", + "type": "action", + "name": "listPush", + "parameters": { + "entity": {"key": "self"}, + "list": {"key": "entitySelf"} + }, + "output": { + "list": "entitySelf" + } + }, + { + "title": "sendEntityMessage", + "type": "action", + "name": "sendEntityMessage", + "parameters": { + "entity": {"key": "target"}, + "message": {"value": "SexboundDefeat:TargetedBy"}, + "arguments": {"key": "entitySelf"} + } + }, + { + "title": "listPop", + "type": "action", + "name": "listPop", + "parameters": { + "list": {"key": "entitySelf"} + }, + "output": { + } + } + ] + } + } +] \ No newline at end of file diff --git a/interface/sexbound/customizer/customizer.config b/interface/sexbound/customizer/customizer.config index 3f4d34b3..056c2c4b 100644 --- a/interface/sexbound/customizer/customizer.config +++ b/interface/sexbound/customizer/customizer.config @@ -190,6 +190,80 @@ "hAnchor" : "left", "width" : 50, "value" : "^shadow;2000", + "color" : [255, 255, 255] + }, + "canBeDefeatedLabel" : { + "fontSize": 10, + "type": "label", + "position": [20, 132], + "hAnchor": "left", + "vAnchor": "top", + "width": 210, + "value": "^shadow;You currently ^orange;will not^reset;^shadow; be fuckable after being defeated.", + "wrapWidth": 210, + "color": [255, 255, 255] + }, + "canBeDefeatedConfirm": { + "type": "button", + "base": "/interface/sexbound/customizer/smallbutton.png", + "hover": "/interface/sexbound/customizer/smallbutton-hover.png", + "pressed": "/interface/sexbound/customizer/smallbutton-hover.png", + "disabledImage": "/interface/sexbound/customizer/smallbutton-disabled.png", + "pressedOffset": [1,-1], + "caption": "Change", + "fontColor": [255, 255, 255], + "textAlign": "center", + "position": [240, 121] + }, + "canBeDefeatedPriceIcon": { + "type" : "image", + "file" : "/interface/sexbound/customizer/icons/sexbux.png", + "position" : [300, 123] + }, + "canBeDefeatedPrice": { + "type" : "label", + "fontSize" : 8, + "position" : [310, 123], + "hAnchor" : "left", + "width" : 50, + "value" : "^shadow;0", + "color" : [255, 255, 255] + }, + "canDefeatOthersLabel" : { + "fontSize": 10, + "type": "label", + "position": [20, 104], + "hAnchor": "left", + "vAnchor": "top", + "width": 210, + "value": "^shadow;Supported enemies currently ^orange;will not^reset;^shadow; be fuckable after defeating them.", + "wrapWidth": 210, + "color": [255, 255, 255] + }, + "canDefeatOthersConfirm": { + "type": "button", + "base": "/interface/sexbound/customizer/smallbutton.png", + "hover": "/interface/sexbound/customizer/smallbutton-hover.png", + "pressed": "/interface/sexbound/customizer/smallbutton-hover.png", + "disabledImage": "/interface/sexbound/customizer/smallbutton-disabled.png", + "pressedOffset": [1,-1], + "caption": "Change", + "fontColor": [255, 255, 255], + "textAlign": "center", + "position": [240, 93] + }, + "canDefeatOthersPriceIcon": { + "type" : "image", + "file" : "/interface/sexbound/customizer/icons/sexbux.png", + "position" : [300, 95] + }, + "canDefeatOthersPrice": { + "type" : "label", + "fontSize" : 8, + "position" : [310, 95], + "hAnchor" : "left", + "width" : 50, + "value" : "^shadow;0", "color" : [255, 255, 255] } } @@ -395,7 +469,9 @@ "subGenderSelector.down", "subGenderConfirm", "sterilizeConfirm", - "infertileConfirm" + "infertileConfirm", + "canBeDefeatedConfirm", + "canDefeatOthersConfirm" ], "scripts" : [ diff --git a/interface/sexbound/customizer/customizergeneral.lua b/interface/sexbound/customizer/customizergeneral.lua index e3e62b41..472c9647 100644 --- a/interface/sexbound/customizer/customizergeneral.lua +++ b/interface/sexbound/customizer/customizergeneral.lua @@ -12,7 +12,9 @@ function Customizer.General:new(parent) currentSubGenderIndex = 1, subGenderList = {}, sterilized = false, - infertile = false + infertile = false, + canBeDefeated = false, + canDefeatOthers = false }, Customizer.General_mt) end @@ -38,6 +40,16 @@ function Customizer.General:init() if self.infertile == nil then self.infertile = false end if self.infertile then widget.setText("generalTab.infertileLabel", "^shadow;You currently ^orange;are^reset;^shadow; infertile.") else widget.setButtonEnabled("generalTab.infertileConfirm", false) end + + self.canBeDefeated = self._parent.config.canBeDefeated + if self.canBeDefeated == nil then self.canBeDefeated = false end + if self.canBeDefeated then widget.setText("generalTab.canBeDefeatedLabel", "^shadow;You currently ^orange;will^reset;^shadow; be fuckable after being defeated.") + else widget.setButtonEnabled("generalTab.canBeDefeatedLabel", false) end + + self.canDefeatOthers = self._parent.config.canDefeatOthers + if self.canDefeatOthers == nil then self.canDefeatOthers = false end + if self.canDefeatOthers then widget.setText("generalTab.canDefeatOthersLabel", "^shadow;Supported enemies currently ^orange;will^reset;^shadow; be fuckable after defeating them.") + else widget.setButtonEnabled("generalTab.canDefeatOthersLabel", false) end end function Customizer.General:handleMessage(message) @@ -162,4 +174,26 @@ function Customizer.General:makeFertile() world.sendEntityMessage(player.id(), "Sexbound:Status:RemoveStatus", "infertile") self.infertile = false +end + +function Customizer.General:toggleCanBeDefeated() + if self.canBeDefeated then + widget.setText("generalTab.canBeDefeatedLabel", "^shadow;You currently ^orange;will not^reset;^shadow; be fuckable after being defeated.") + world.sendEntityMessage(player.id(), "Sexbound:Status:RemoveStatus", "canBeDefeated") + else + widget.setText("generalTab.canBeDefeatedLabel", "^shadow;You currently ^orange;will^reset;^shadow; be fuckable after being defeated.") + world.sendEntityMessage(player.id(), "Sexbound:Status:AddStatus", "canBeDefeated") + end + self.canBeDefeated = not self.canBeDefeated +end + +function Customizer.General:toggleCanDefeatOthers() + if self.canDefeatOthers then + widget.setText("generalTab.canDefeatOthersLabel", "^shadow;Supported enemies currently ^orange;will not^reset;^shadow; be fuckable after defeating them.") + world.sendEntityMessage(player.id(), "Sexbound:Status:RemoveStatus", "canDefeatOthers") + else + widget.setText("generalTab.canDefeatOthersLabel", "^shadow;Supported enemies currently ^orange;will^reset;^shadow; be fuckable after defeating them.") + world.sendEntityMessage(player.id(), "Sexbound:Status:AddStatus", "canDefeatOthers") + end + self.canDefeatOthers = not self.canDefeatOthers end \ No newline at end of file diff --git a/interface/sexbound/customizer/customizerui.lua b/interface/sexbound/customizer/customizerui.lua index faa26d52..5d3dbf12 100644 --- a/interface/sexbound/customizer/customizerui.lua +++ b/interface/sexbound/customizer/customizerui.lua @@ -43,4 +43,14 @@ end function sterilizeConfirm() if not self.customizer._inited then return end self.customizer.tabs["General"]:sterilize() +end + +function canBeDefeatedConfirm() + if not self.customizer._inited then return end + self.customizer.tabs["General"]:toggleCanBeDefeated() +end + +function canDefeatOthersConfirm() + if not self.customizer._inited then return end + self.customizer.tabs["General"]:toggleCanDefeatOthers() end \ No newline at end of file diff --git a/scripts/actions/notification.lua b/scripts/actions/notification.lua deleted file mode 100644 index 35ad777d..00000000 --- a/scripts/actions/notification.lua +++ /dev/null @@ -1,52 +0,0 @@ --- param type -function receivedNotification(args, board) - if args.type == nil then return false end - - for i,notification in pairs(self.notifications) do - if notification.type == args.type then - table.remove(self.notifications, i) - return true, {source = notification.sourceId, target = notification.targetId, targetPosition = notification.targetPosition} - end - end - return false -end - --- param type --- param entity --- param target -function sendNotification(args, board) - if args.entity == nil or args.type == nil then return false end - - local notification = { - sourceId = entity.id(), - targetId = args.target, - type = args.type - } - world.callScriptedEntity(args.entity, "notify", notification) - return true -end - --- param type --- param position --- param range --- param entityTypes --- param target -function broadcastNotification(args, board) - if args.type == nil or args.position == nil or args.range == nil then return false end - if args.target == nil then args.target = "nil" end - sb.logInfo("notification: type="..args.type.." target="..args.target) - if args.target == "nil" then args.target = nil end - - local notification = { - sourceId = entity.id(), - targetId = args.target, - type = args.type - } - if args.type == "attack" or args.type == "notifyFindTarget" then world.sendEntityMessage(args.target, "SexboundDefeat:TargetedBy", entity.id()) end - local notified = world.entityQuery(args.position, args.range, { includedTypes = args.entityTypes, callScript = "notify", callScriptArgs = {notification} }) - if #notified > 0 then - return true - else - return false - end -end diff --git a/scripts/sexbound/lib/sexbound.lua b/scripts/sexbound/lib/sexbound.lua index 8abe307b..9854c506 100644 --- a/scripts/sexbound/lib/sexbound.lua +++ b/scripts/sexbound/lib/sexbound.lua @@ -360,9 +360,6 @@ function Sexbound:addActor(actorConfig, store) object.setInteractive(false) end - -- Mark node as a defeat node. - if actor:getStatus():hasStatus("sexbound_defeated") then self._containsDefeated = true end - -- Resort actors based on changed environment self:helper_reassignAllRoles() @@ -370,8 +367,19 @@ function Sexbound:addActor(actorConfig, store) self._positions:switchPosition(self._config.position.forceJoin) -- If we have no controlling player, try to initiate sex (switch from idle to a random available position) elseif not self._playerControl and self._config.sex.npcStartSex then - self._positions:switchRandomSexPosition(true) + local success = self._positions:switchRandomSexPosition(true) + -- Smash the defeat node if there's no valid position to avoid boring standing around + if not success and self._containsDefeated then + self:forEachActor(function(index,actor) + if actor:getStatus():hasStatus("sexbound_defeated") then + world.sendEntityMessage(actor:getEntityId(), "SexboundDefeat:Untransform") + end + end) + end end + -- Mark node as a defeat node. + if actor:getStatus():hasStatus("sexbound_defeated") then self._containsDefeated = true end + -- Reset all actors to refresh their appearances self:resetAllActors() diff --git a/scripts/sexbound/lib/sexbound/positions.lua b/scripts/sexbound/lib/sexbound/positions.lua index 9797a535..988f7d37 100644 --- a/scripts/sexbound/lib/sexbound/positions.lua +++ b/scripts/sexbound/lib/sexbound/positions.lua @@ -292,11 +292,12 @@ end function Sexbound.Positions:switchRandomSexPosition(fromIdle) fromIdle = fromIdle or false - if self._positionCount < 1 then return end - if fromIdle and self._index ~= -1 then return end + if self._positionCount < 1 then return false end + if fromIdle and self._index ~= -1 then return false end local randomIndex = util.randomIntInRange({1, self._positionCount}) self:switchPosition(randomIndex) + return true end --- Returns a reference to the Positions Configuration. diff --git a/scripts/sexbound/lib/sexbound/sextalk.lua b/scripts/sexbound/lib/sexbound/sextalk.lua index 78fc94f2..964d9c54 100644 --- a/scripts/sexbound/lib/sexbound/sextalk.lua +++ b/scripts/sexbound/lib/sexbound/sextalk.lua @@ -95,6 +95,10 @@ end --- Function to choose a random available function Sexbound.Sextalk:triggerTalk() + + -- disable dialog if its a defeat node (will have separate dialog in the future) + if self._parent._containsDefeated then return end + local viableActors = {} for _,a in ipairs(self._parent:getActors()) do local sxt = a:getPlugins("sextalk") diff --git a/scripts/sexbound/override/common/status.lua b/scripts/sexbound/override/common/status.lua index 914f2622..0a316cfb 100644 --- a/scripts/sexbound/override/common/status.lua +++ b/scripts/sexbound/override/common/status.lua @@ -75,6 +75,10 @@ function Sexbound.Common.Status:addStatus(statusName, persistent) local l = self._listeners.add[n] xpcall(function() l({query="add", name=statusName, isPersistent=persistent}) end, function(err) sb.logWarn("Error in #"..entity.id().."'s status listener") sb.logWarn(err) end) end + + if statusName == "canBeDefeated" or statusName == "canDefeatOthers" then + status.setStatusProperty(statusName, true) + end return true end @@ -133,6 +137,10 @@ end -- @param statusName function Sexbound.Common.Status:removeStatus(statusName, persistent) if persistent == nil then persistent = true end + + if statusName == "canBeDefeated" or statusName == "canDefeatOthers" then + status.setStatusProperty(statusName, false) + end for index, status in ipairs(self:getStatusList()) do if (status == statusName) then diff --git a/scripts/sexbound/override/common/transform.lua b/scripts/sexbound/override/common/transform.lua index 92ad5566..86e9af0a 100644 --- a/scripts/sexbound/override/common/transform.lua +++ b/scripts/sexbound/override/common/transform.lua @@ -98,7 +98,7 @@ function Sexbound.Common.Transform:helper_SpawnSexNode(spawnOptions, position, a }, respawner = storage.respawner, sexboundConfig = self:getSexboundConfig(), - storedActor = actorData or nil, + storedActor = actorData or self:getParent():getActorData(), uniqueId = sb.makeUuid() } @@ -121,13 +121,13 @@ function Sexbound.Common.Transform:helper_SpawnSexNode(spawnOptions, position, a -- In the future, we'll need to handle tile protection on a different entity in case of a player being transformed local placed = world.placeObject(self._nodeName, targetTile, facingDirection, params) if placed then - if actorData.entityType == "player" then - world.sendEntityMessage(actorData.entityId, "Sexbound:Defeat:SetPosition", {targetTile[1], targetTile[2] + 2.5}) + if params.storedActor.entityType == "player" then + world.sendEntityMessage(params.storedActor.entityId, "Sexbound:Defeat:SetPosition", {targetTile[1], targetTile[2] + 2.5}) elseif mcontroller then mcontroller.setPosition({targetTile[1], targetTile[2] + self._feetOffset}) end if not spawnOptions.noEffect then - world.sendEntityMessage(actorData.entityId, "applyStatusEffect", "sexbound_transform") + world.sendEntityMessage(params.storedActor.entityId, "applyStatusEffect", "sexbound_transform") end return params.uniqueId end diff --git a/scripts/sexbound/override/player.lua b/scripts/sexbound/override/player.lua index 18b06b0d..22b285c3 100644 --- a/scripts/sexbound/override/player.lua +++ b/scripts/sexbound/override/player.lua @@ -73,7 +73,9 @@ function Sexbound.Player.new() _loungeId = nil, _states = {"defaultState", "havingSexState"}, _isSterilized = false, - _isInfertile = false + _isInfertile = false, + _canBeDefeated = false, + _canDefeatOthers = false }, Sexbound.Player_mt) self:init(self, "player") @@ -125,6 +127,8 @@ function Sexbound.Player.new() self._isSterilized = self._status:hasStatus("sterilized") self._isInfertile = self._status:hasStatus("infertile") + self._canBeDefeated = self._status:hasStatus("canBeDefeated") + self._canDefeatOthers = self._status:hasStatus("canDefeatOthers") self._hasInited = true self:updateTraitEffects() @@ -231,6 +235,8 @@ function Sexbound.Player:handleGetCutomizerData(args) _loadedConfig.subGenders = self._subGender:getAllSubGenders() _loadedConfig.sterilized = self._status:hasStatus("sterilized") _loadedConfig.infertile = self._status:hasStatus("infertile") + _loadedConfig.canBeDefeated = self._status:hasStatus("canBeDefeated") + _loadedConfig.canDefeatOthers = self._status:hasStatus("canDefeatOthers") return _loadedConfig end diff --git a/scripts/sexbound/plugins/climax/climax.lua b/scripts/sexbound/plugins/climax/climax.lua index eae65598..a6caff8a 100644 --- a/scripts/sexbound/plugins/climax/climax.lua +++ b/scripts/sexbound/plugins/climax/climax.lua @@ -549,7 +549,6 @@ function Sexbound.Actor.Climax:tryAutoClimax() if self._config.prioritizePlayer and playerControl then -- Prevent auto climax if we have a player and that player is in control (not raped as part of sexbound defeat) - sb.logInfo("bailing climax due to config and player control") return end diff --git a/stats/effects/sexbound_defeat_invuln/sexbound_defeat_invuln.lua b/stats/effects/sexbound_defeat_invuln/sexbound_defeat_invuln.lua new file mode 100644 index 00000000..b7ed139c --- /dev/null +++ b/stats/effects/sexbound_defeat_invuln/sexbound_defeat_invuln.lua @@ -0,0 +1,9 @@ +function init() + effect.addStatModifierGroup({ + { stat = "invulnerable", amount = 1 }, + { stat = "fireStatusImmunity", amount = 1 }, + { stat = "iceStatusImmunity", amount = 1 }, + { stat = "electricStatusImmunity", amount = 1 }, + { stat = "poisonStatusImmunity", amount = 1 } + }) +end \ No newline at end of file diff --git a/stats/effects/sexbound_defeat_invuln/sexbound_defeat_invuln.statuseffect b/stats/effects/sexbound_defeat_invuln/sexbound_defeat_invuln.statuseffect new file mode 100644 index 00000000..881fb046 --- /dev/null +++ b/stats/effects/sexbound_defeat_invuln/sexbound_defeat_invuln.statuseffect @@ -0,0 +1,9 @@ +{ + "name" : "sexbound_defeat_invuln", + "blockingStat" : "specialStatusImmunity", + "defaultDuration" : 1.5, + "effectConfig" : {}, + "icon" : "/interface/statuses/timefreeze.png", + "label" : "Recovering", + "scripts" : [ "sexbound_defeat_invuln.lua" ] +} diff --git a/stats/effects/sexbound_defeat_stun/sexbound_defeat_stun.lua b/stats/effects/sexbound_defeat_stun/sexbound_defeat_stun.lua new file mode 100644 index 00000000..cca84516 --- /dev/null +++ b/stats/effects/sexbound_defeat_stun/sexbound_defeat_stun.lua @@ -0,0 +1,29 @@ +function init() + if status.isResource("energy") then + status.setResourcePercentage("energy", 0) + end + effect.addStatModifierGroup({ + { stat = "invulnerable", amount = 1 }, + { stat = "fireStatusImmunity", amount = 1 }, + { stat = "iceStatusImmunity", amount = 1 }, + { stat = "electricStatusImmunity", amount = 1 }, + { stat = "poisonStatusImmunity", amount = 1 }, + { stat = "powerMultiplier", effectiveMultiplier = 0 } + }) + if status.isResource("stunned") then + status.setResource("stunned", math.max(status.resource("stunned"), effect.duration())) + end + mcontroller.setVelocity({ 0, 0 }) + status.setStatusProperty("sexbound_defeat_stun", true) +end + +function update() + mcontroller.setVelocity({ 0, 0 }) + mcontroller.controlModifiers({ facingSuppressed = true, movementSuppressed = true }) +end + +function uninit() + if status.isResource("stunned") then status.setResource("stunned", 0) end + status.setStatusProperty("sexbound_defeat_stun", false) + status.addEphemeralEffect("sexbound_defeat_invuln") +end \ No newline at end of file diff --git a/stats/effects/sexbound_defeat_stun/sexbound_defeat_stun.statuseffect b/stats/effects/sexbound_defeat_stun/sexbound_defeat_stun.statuseffect new file mode 100644 index 00000000..fd6145c5 --- /dev/null +++ b/stats/effects/sexbound_defeat_stun/sexbound_defeat_stun.statuseffect @@ -0,0 +1,9 @@ +{ + "name" : "sexbound_defeat_stun", + "blockingStat" : "specialStatusImmunity", + "defaultDuration" : 300, + "effectConfig" : {}, + "icon" : "/interface/statuses/timefreeze.png", + "label" : "Defeated", + "scripts" : [ "sexbound_defeat_stun.lua" ] +} diff --git a/stats/sexbound/monster_primary.lua b/stats/sexbound/monster_primary.lua index 38f73f64..7687af77 100644 --- a/stats/sexbound/monster_primary.lua +++ b/stats/sexbound/monster_primary.lua @@ -6,7 +6,7 @@ function init() self.sexboundDefeat = SexboundDefeat:new("monster") sexbound_defeat_init() -- call actual init function status.removeEphemeralEffect("sexbound_sex") - status.removeEphemeralEffect("sexbound_stun") + status.removeEphemeralEffect("sexbound_defeat_stun") end -- Override Update Hook diff --git a/stats/sexbound/npc_primary.lua b/stats/sexbound/npc_primary.lua index d2206cd4..c037e8b7 100644 --- a/stats/sexbound/npc_primary.lua +++ b/stats/sexbound/npc_primary.lua @@ -6,7 +6,7 @@ function init() self.sexboundDefeat = SexboundDefeat:new("npc") sexbound_defeat_init() -- call actual init function status.removeEphemeralEffect("sexbound_sex") - status.removeEphemeralEffect("sexbound_stun") + status.removeEphemeralEffect("sexbound_defeat_stun") end -- Override Update Hook diff --git a/stats/sexbound/player_primary.lua b/stats/sexbound/player_primary.lua index a6dd9be7..d2e9eb2d 100644 --- a/stats/sexbound/player_primary.lua +++ b/stats/sexbound/player_primary.lua @@ -6,7 +6,7 @@ function init() self.sexboundDefeat = SexboundDefeat:new("player") sexbound_defeat_init() -- call actual init function status.removeEphemeralEffect("sexbound_sex") - status.removeEphemeralEffect("sexbound_stun") + status.removeEphemeralEffect("sexbound_defeat_stun") status.removeEphemeralEffect("regeneration4") message.setHandler("Sexbound:Defeat:SetPosition", function(_, _, position) mcontroller.setPosition(position) diff --git a/stats/sexbound/sexbounddefeat.lua b/stats/sexbound/sexbounddefeat.lua index 84e28fe1..994a7dab 100644 --- a/stats/sexbound/sexbounddefeat.lua +++ b/stats/sexbound/sexbounddefeat.lua @@ -45,6 +45,11 @@ function SexboundDefeat:new(entityType) -- Set "Can use sexbound UI while defeated." state as a status for use with other scripts status.setStatusProperty("can_use_sex_ui_defeated", _self._config.defeatedPlayersCanUseSexUI) + -- Enable canBeDefeated and canDefeatOthers on non-players. Additional conditions could be added. + if _self.entityType ~= "player" then + status.setStatusProperty("canBeDefeated", true) + status.setStatusProperty("canDefeatOthers", true) + end return _self end @@ -53,14 +58,17 @@ function SexboundDefeat:initMessageHandlers() self._timer = self._timeout end) message.setHandler("SexboundDefeat:TargetedBy", function(_,_,entityId) - sb.logInfo("being targetd by entity: "..entityId) + -- Send hostile entity a message to add self to their hostile entity table + if status.statusProperty("canDefeatOthers") then + world.sendEntityMessage(entityId, "SexboundDefeat:InCombatWith", self._entityId) + end local found = false for i, v in ipairs(self._hostileEntities) do if v[1] == entityId then found = true end end if not found then self:retrieveSexboundConfig(function(result) - world.sendEntityMessage(entityId, "SexboundDefeat:InCombatWith", self._entityId) + -- Run function that adds entity with their sexbound config into the hostile entity table return self:handleRetrieveSexboundConfigSuccess(result,entityId) end, function() return @@ -68,6 +76,7 @@ function SexboundDefeat:initMessageHandlers() entityId) end end) + -- Ends the hostile entity "handshake". Does same as "TargetedBy" but will not an additional message. message.setHandler("SexboundDefeat:InCombatWith", function(_,_,entityId) local found = false for i, v in ipairs(self._hostileEntities) do @@ -82,6 +91,10 @@ function SexboundDefeat:initMessageHandlers() entityId) end end) + -- Sets the entity's status to untransform at the earliers opportunity + message.setHandler("SexboundDefeat:Untransform", function(_,_) + self:setTimer(self._timeout - 3) + end) end -- Update Loop @@ -96,6 +109,7 @@ function SexboundDefeat:update(dt, oldUpdate) self:setIsTransformed(false) self:setTimer(0) self:untransform() + status.removeEphemeralEffect("sexbound_defeat_stun") end end @@ -127,6 +141,12 @@ function SexboundDefeat:handleApplyDamageRequest(originalFunction, damageRequest -- When the this entity's health is greater than 0, generate damage if status.resource("health") > 0 then return damage end + -- Handle the case where the entity doesn't have the status allowing being fucked after defeat. + if not status.statusProperty("canBeDefeated") then + self:tryToDie("entity does not have \"canBeDefeated\" status") + return {} + end + -- Store a reference to the hostile entity id that delivered the killing blow to this entity local hostileEntityId = damageRequest.sourceEntityId local hostileEntityType = nil @@ -173,9 +193,7 @@ function SexboundDefeat:retrieveActorData(damageSourceEntity, damageSourceEntity local sexboundConfig = nil local entities = world.entityQuery(entity.position(), 25, {includedTypes = {"monster","npc","player"}, order = "nearest"}) for i,v in ipairs(entities) do - sb.logInfo("entity query returned: "..v) for i2,v2 in ipairs(self._hostileEntities) do - sb.logInfo ("Checking entity list: queried "..v.." against list "..v2[1]) if v == v2[1] then found = true hostileEntityId = v2[1] @@ -326,7 +344,7 @@ function SexboundDefeat:handleTransformSuccess(nodeUniqueId) end status.addEphemeralEffect("sexbound_sex", self._timeout) - status.addEphemeralEffect("sexbound_stun", self._timeout) + status.addEphemeralEffect("sexbound_defeat_stun", self._timeout) -- Try to notify the controlling entity to mount the defeated player. if (self._sexNodeId and self._hostileEntityId) then @@ -349,7 +367,7 @@ function SexboundDefeat:loadUIConfig() end function SexboundDefeat:tryToDie(reason) - if reason then sb.logInfo("tryToDie reason: "..reason) end + --if reason then sb.logInfo("Sexbound Defeat Death: Name="..world.entityName(self._entityId).." reason: "..reason) end self:setIsDefeated(false) self:setIsTransformed(false) if not self:isPlayer() and self:isPregnant() and self._config.enableImmortalPregnantNPCs then @@ -431,7 +449,7 @@ function SexboundDefeat:isPregnant() end function SexboundDefeat:isStunned() - return status.statusProperty("sexbound_stun") + return status.statusProperty("sexbound_defeat_stun") end function SexboundDefeat:isSuicide() @@ -445,7 +463,6 @@ end function SexboundDefeat:setIsDefeated(isDefeated) self._isDefeated = isDefeated status.setStatusProperty("sexbound_defeated", isDefeated) - end function SexboundDefeat:setIsTransformed(isTransformed) From 1690bbc7a627af44ceb97934c9b426b12cccb6f7 Mon Sep 17 00:00:00 2001 From: notlexander Date: Sat, 26 Oct 2024 11:26:23 -0500 Subject: [PATCH 12/12] Misc changes, floating bug fix -removed starve prevention status for players during transform success -renamed the status for enabling ui when defeated for consistency -removed update loop prevention during defeat status and tested, appears to work fine -merged player_primary.lua, npc_primary.lua, and monster_primary.lua to their respective main paths -fixed "floating" bug when sexnodes are destroyed by removing the new stun status --- interface/sexbound/defeat.lua | 13 +++------- npcs/base.npctype.patch | 6 ----- player.config.patch | 12 --------- scripts/sexbound/lib/sexbound.lua | 6 +---- scripts/sexbound/lib/sexbound/actor.lua | 2 +- scripts/sexbound/override/monster.lua | 1 + scripts/sexbound/override/npc.lua | 1 + .../sexbound/override/player/transform.lua | 2 +- .../override/stats/monster_primary.lua | 19 ++++++++++++++ .../sexbound/override/stats/npc_primary.lua | 20 ++++++++++++++ .../override/stats/player_primary.lua | 20 +++++++++++++- scripts/sexbound/plugins/climax/climax.lua | 13 +--------- scripts/sexboundaddons/playerDefeat.lua | 24 ----------------- stats/sexbound/monster_primary.lua | 22 ---------------- stats/sexbound/npc_primary.lua | 22 ---------------- stats/sexbound/player_primary.lua | 26 ------------------- stats/sexbound/readme.txt | 10 ------- stats/sexbound/sexbounddefeat.lua | 6 +---- 18 files changed, 68 insertions(+), 157 deletions(-) delete mode 100644 scripts/sexboundaddons/playerDefeat.lua delete mode 100644 stats/sexbound/monster_primary.lua delete mode 100644 stats/sexbound/npc_primary.lua delete mode 100644 stats/sexbound/player_primary.lua delete mode 100644 stats/sexbound/readme.txt diff --git a/interface/sexbound/defeat.lua b/interface/sexbound/defeat.lua index d5e38e9f..ea58504b 100644 --- a/interface/sexbound/defeat.lua +++ b/interface/sexbound/defeat.lua @@ -3,20 +3,13 @@ require "/scripts/messageutil.lua" function init() self.config = config.getParameter("config") self.canvas = widget.bindCanvas("interface") - self.promise = PromiseKeeper.new() widget.focus("interface") end function update(dt) - self.promise:add( - world.findUniqueEntity(self.config.nodeUniqueId), - function(result) return end, - function() - pane.dismiss() - end - ) - - self.promise:update() + if not status.statusProperty("sexbound_defeated") then + pane.dismiss() + end self.canvas:clear() end diff --git a/npcs/base.npctype.patch b/npcs/base.npctype.patch index f64b48f7..52db7bcc 100644 --- a/npcs/base.npctype.patch +++ b/npcs/base.npctype.patch @@ -101,11 +101,5 @@ "deltaValue" : 0.0, "initialPercentage" : 0.0 } - }, - - { - "op" : "add", - "path" : "/statusControllerSettings/primaryScriptSources/-", - "value" : "/stats/sexbound/npc_primary.lua" } ] \ No newline at end of file diff --git a/player.config.patch b/player.config.patch index 8582f220..8a68f03b 100644 --- a/player.config.patch +++ b/player.config.patch @@ -83,17 +83,5 @@ "deltaValue": 0.0, "initialPercentage": 0.0 } - }, - - { - "op" : "add", - "path" : "/companionsConfig/scripts/-", - "value" : "/scripts/sexboundaddons/playerDefeat.lua" - }, - - { - "op" : "add", - "path" : "/statusControllerSettings/primaryScriptSources/-", - "value" : "/stats/sexbound/player_primary.lua" } ] diff --git a/scripts/sexbound/lib/sexbound.lua b/scripts/sexbound/lib/sexbound.lua index 9854c506..599e1e3c 100644 --- a/scripts/sexbound/lib/sexbound.lua +++ b/scripts/sexbound/lib/sexbound.lua @@ -346,13 +346,9 @@ function Sexbound:addActor(actorConfig, store) if actor:getEntityType() == "player" then self._containsPlayer = true -- Open UI if not defeated or is allowed to while defeated. - if not actor:getStatus():hasStatus("sexbound_defeated") then + if not actor:getStatus():hasStatus("sexbound_defeated") or actor:getStatus():hasStatus("can_use_sex_ui_defeated") then actor:openUI() self._playerControl = true - else - if actor:getStatus():hasStatus("sexbound_defeated_can_use_ui") then - actor:openUI() - end end end if self._containsDefeated then diff --git a/scripts/sexbound/lib/sexbound/actor.lua b/scripts/sexbound/lib/sexbound/actor.lua index 9698aca3..5d552572 100644 --- a/scripts/sexbound/lib/sexbound/actor.lua +++ b/scripts/sexbound/lib/sexbound/actor.lua @@ -643,7 +643,7 @@ function Sexbound.Actor:setup(actorConfig) if self._config.inHeat then actorStatus:addStatus("sexbound_aroused_heat") end if self._config.isDefeated then actorStatus:addStatus("sexbound_defeated") end if self._config.birthcontrol then actorStatus:addStatus("birthcontrol") end - if self._config.canUseSexUIDefeated then actorStatus:addStatus("sexbound_defeated_can_use_ui") end + if self._config.canUseSexUIDefeated then actorStatus:addStatus("can_use_sex_ui_defeated") end if self._config.identity.sxbNaturalStatus then for _,s in ipairs(self._config.identity.sxbNaturalStatus) do diff --git a/scripts/sexbound/override/monster.lua b/scripts/sexbound/override/monster.lua index 5f67e7e3..5c2f06d3 100644 --- a/scripts/sexbound/override/monster.lua +++ b/scripts/sexbound/override/monster.lua @@ -175,6 +175,7 @@ function Sexbound.Monster:restore() if entityId then world.sendEntityMessage(entityId, "Sexbound:removeStatusEffect", "sexbound_invisible") world.sendEntityMessage(entityId, "Sexbound:removeStatusEffect", "sexbound_stun") + world.sendEntityMessage(entityId, "Sexbound:removeStatusEffect", "sexbound_defeat_stun") end end diff --git a/scripts/sexbound/override/npc.lua b/scripts/sexbound/override/npc.lua index 2ce412ed..d005017a 100644 --- a/scripts/sexbound/override/npc.lua +++ b/scripts/sexbound/override/npc.lua @@ -345,6 +345,7 @@ function Sexbound.NPC:removeAllStunningStatusEffects() status.removeEphemeralEffect("sexbound_stun") status.setResource("stunned", 0) status.setStatusProperty("sexbound_stun", false) + status.removeEphemeralEffect("sexbound_defeat_stun") end function Sexbound.NPC:removeWeaponsWhenShouldHaveEmptyHands() diff --git a/scripts/sexbound/override/player/transform.lua b/scripts/sexbound/override/player/transform.lua index 3e9e6385..45a5d1f0 100644 --- a/scripts/sexbound/override/player/transform.lua +++ b/scripts/sexbound/override/player/transform.lua @@ -7,7 +7,7 @@ Sexbound.Player.Transform_mt = { function Sexbound.Player.Transform:new(parent) local _self = setmetatable({ - _canTransform = false, + _canTransform = true, _mindControl = {}, _nodeName = "sexbound_main_node", _parent = parent diff --git a/scripts/sexbound/override/stats/monster_primary.lua b/scripts/sexbound/override/stats/monster_primary.lua index 3199758b..f85ba244 100644 --- a/scripts/sexbound/override/stats/monster_primary.lua +++ b/scripts/sexbound/override/stats/monster_primary.lua @@ -1,3 +1,5 @@ +require "/stats/sexbound/sexbounddefeat.lua" + local sexbound_monster_primary_init = init function init() sexbound_monster_primary_init() @@ -5,4 +7,21 @@ function init() message.setHandler("Sexbound:removeStatusEffect", function(_, _, effectName) status.removeEphemeralEffect(effectName) end) + + --Defeat Init + self.sexboundDefeat = SexboundDefeat:new("monster") + status.removeEphemeralEffect("sexbound_sex") + status.removeEphemeralEffect("sexbound_defeat_stun") end + +-- Override Update Hook (Defeat) +local sexbound_defeat_update = update +function update(dt) + self.sexboundDefeat:update(dt, sexbound_defeat_update) +end + +-- Override Apply Damage Request Hook (Defeat) +local sexbound_defeat_applyDamageRequest = applyDamageRequest +function applyDamageRequest(damageRequest) + return self.sexboundDefeat:handleApplyDamageRequest(sexbound_defeat_applyDamageRequest, damageRequest) +end \ No newline at end of file diff --git a/scripts/sexbound/override/stats/npc_primary.lua b/scripts/sexbound/override/stats/npc_primary.lua index 125b0e3e..66b25163 100644 --- a/scripts/sexbound/override/stats/npc_primary.lua +++ b/scripts/sexbound/override/stats/npc_primary.lua @@ -1,3 +1,5 @@ +require "/stats/sexbound/sexbounddefeat.lua" + local sexbound_NPC_Primary_init = init function init() sexbound_NPC_Primary_init() @@ -5,4 +7,22 @@ function init() message.setHandler("Sexbound:removeStatusEffect", function(_, _, effectName) status.removeEphemeralEffect(effectName) end) + + -- Defeat init + self.sexboundDefeat = SexboundDefeat:new("npc") + status.removeEphemeralEffect("sexbound_sex") + status.removeEphemeralEffect("sexbound_defeat_stun") + end + +-- Override Update Hook (defeat) +local sexbound_defeat_update = update +function update(dt) + self.sexboundDefeat:update(dt, sexbound_defeat_update) +end + +-- Override Apply Damage Request Hook (defeat) +local sexbound_defeat_applyDamageRequest = applyDamageRequest +function applyDamageRequest(damageRequest) + return self.sexboundDefeat:handleApplyDamageRequest(sexbound_defeat_applyDamageRequest, damageRequest) +end \ No newline at end of file diff --git a/scripts/sexbound/override/stats/player_primary.lua b/scripts/sexbound/override/stats/player_primary.lua index 60e32f32..3681985c 100644 --- a/scripts/sexbound/override/stats/player_primary.lua +++ b/scripts/sexbound/override/stats/player_primary.lua @@ -1,4 +1,5 @@ require "/scripts/sexbound/util.lua" +require "/stats/sexbound/sexbounddefeat.lua" local Sexbound_Override_Player_Primary_init = init function init() @@ -7,9 +8,26 @@ function init() message.setHandler("Sexbound:removeStatusEffect", function(_, _, effectName) status.removeEphemeralEffect(effectName) end) + + -- Defeat init + self.sexboundDefeat = SexboundDefeat:new("player") + status.removeEphemeralEffect("sexbound_sex") + status.removeEphemeralEffect("sexbound_defeat_stun") + status.removeEphemeralEffect("regeneration4") + + message.setHandler("Sexbound:Defeat:SetPosition", function(_, _, position) + mcontroller.setPosition(position) + end) + end local Sexbound_Override_Player_Primary_update = update function update(dt) - Sexbound_Override_Player_Primary_update(dt) + self.sexboundDefeat:update(dt, Sexbound_Override_Player_Primary_update) +end + +-- Override Apply Damage Request Hook (Defeat) +local sexbound_defeat_applyDamageRequest = applyDamageRequest +function applyDamageRequest(damageRequest) + return self.sexboundDefeat:handleApplyDamageRequest(sexbound_defeat_applyDamageRequest, damageRequest) end diff --git a/scripts/sexbound/plugins/climax/climax.lua b/scripts/sexbound/plugins/climax/climax.lua index a6caff8a..ec69249f 100644 --- a/scripts/sexbound/plugins/climax/climax.lua +++ b/scripts/sexbound/plugins/climax/climax.lua @@ -531,23 +531,12 @@ end --- Attempts to cause this actor to begin climaxing. function Sexbound.Actor.Climax:tryAutoClimax() local entityType = self:getParent():getEntityType() - local playerControl = false if entityType == "player" then return - else - for _, actor in ipairs(self:getParent():getParent():getActors()) do - if actor:getActorNumber() ~= self:getParent():getActorNumber() then - if actor:getEntityType() == "player" then - if not actor:getStatus():hasStatus("sexbound_defeated") or actor:getStatus():hasStatus("sexbound_defeated_can_use_ui") then - playerControl = true - end - end - end - end end - if self._config.prioritizePlayer and playerControl then + if self._config.prioritizePlayer and self:getParent():getParent()._playerControl then -- Prevent auto climax if we have a player and that player is in control (not raped as part of sexbound defeat) return end diff --git a/scripts/sexboundaddons/playerDefeat.lua b/scripts/sexboundaddons/playerDefeat.lua deleted file mode 100644 index 4359dea2..00000000 --- a/scripts/sexboundaddons/playerDefeat.lua +++ /dev/null @@ -1,24 +0,0 @@ ---[[ - This script is responsbile for enabling the Player to be transformed into a SexNode. - - By default, the player cannot be transformed. -]]-- - - -Player_Sexbound_Defeat = {} -Player_Sexbound_Defeat_mt = { __index = Player_Sexbound_Defeat } - ---- Hook (init) -local Player_Sexbound_Defeat_Init = init -function init() - xpcall(function() - Player_Sexbound_Defeat_Init() - -- Change player to be able to transform into SexNode - if self.sb_player then - local transform = self.sb_player:getTransform() or {} - transform:setCanTransform(true) - end - end, function(err) - sb.logError(err) - end) -end \ No newline at end of file diff --git a/stats/sexbound/monster_primary.lua b/stats/sexbound/monster_primary.lua deleted file mode 100644 index 7687af77..00000000 --- a/stats/sexbound/monster_primary.lua +++ /dev/null @@ -1,22 +0,0 @@ -require "/stats/sexbound/sexbounddefeat.lua" - --- Override Init Hook -local sexbound_defeat_init = init -function init() - self.sexboundDefeat = SexboundDefeat:new("monster") - sexbound_defeat_init() -- call actual init function - status.removeEphemeralEffect("sexbound_sex") - status.removeEphemeralEffect("sexbound_defeat_stun") -end - --- Override Update Hook -local sexbound_defeat_update = update -function update(dt) - self.sexboundDefeat:update(dt, sexbound_defeat_update) -end - --- Override Apply Damage Request Hook -local sexbound_defeat_applyDamageRequest = applyDamageRequest -function applyDamageRequest(damageRequest) - return self.sexboundDefeat:handleApplyDamageRequest(sexbound_defeat_applyDamageRequest, damageRequest) -end diff --git a/stats/sexbound/npc_primary.lua b/stats/sexbound/npc_primary.lua deleted file mode 100644 index c037e8b7..00000000 --- a/stats/sexbound/npc_primary.lua +++ /dev/null @@ -1,22 +0,0 @@ -require "/stats/sexbound/sexbounddefeat.lua" - --- Override Init Hook -local sexbound_defeat_init = init -function init() - self.sexboundDefeat = SexboundDefeat:new("npc") - sexbound_defeat_init() -- call actual init function - status.removeEphemeralEffect("sexbound_sex") - status.removeEphemeralEffect("sexbound_defeat_stun") -end - --- Override Update Hook -local sexbound_defeat_update = update -function update(dt) - self.sexboundDefeat:update(dt, sexbound_defeat_update) -end - --- Override Apply Damage Request Hook -local sexbound_defeat_applyDamageRequest = applyDamageRequest -function applyDamageRequest(damageRequest) - return self.sexboundDefeat:handleApplyDamageRequest(sexbound_defeat_applyDamageRequest, damageRequest) -end diff --git a/stats/sexbound/player_primary.lua b/stats/sexbound/player_primary.lua deleted file mode 100644 index d2e9eb2d..00000000 --- a/stats/sexbound/player_primary.lua +++ /dev/null @@ -1,26 +0,0 @@ -require "/stats/sexbound/sexbounddefeat.lua" - --- Override Init Hook -local sexbound_defeat_init = init -function init() - self.sexboundDefeat = SexboundDefeat:new("player") - sexbound_defeat_init() -- call actual init function - status.removeEphemeralEffect("sexbound_sex") - status.removeEphemeralEffect("sexbound_defeat_stun") - status.removeEphemeralEffect("regeneration4") - message.setHandler("Sexbound:Defeat:SetPosition", function(_, _, position) - mcontroller.setPosition(position) - end) -end - --- Override Update Hook -local sexbound_defeat_update = update -function update(dt) - self.sexboundDefeat:update(dt, sexbound_defeat_update) -end - --- Override Apply Damage Request Hook -local sexbound_defeat_applyDamageRequest = applyDamageRequest -function applyDamageRequest(damageRequest) - return self.sexboundDefeat:handleApplyDamageRequest(sexbound_defeat_applyDamageRequest, damageRequest) -end diff --git a/stats/sexbound/readme.txt b/stats/sexbound/readme.txt deleted file mode 100644 index 6f9ae750..00000000 --- a/stats/sexbound/readme.txt +++ /dev/null @@ -1,10 +0,0 @@ -# READ ME - -The *_primary.lua scripts are used to override the default Starbound primary scripts. - -## SCRIPTS - -* Monster - monster_primary.lua -* NPC - npc_primary.lua -* PLAYER - player_primary.lua - diff --git a/stats/sexbound/sexbounddefeat.lua b/stats/sexbound/sexbounddefeat.lua index 994a7dab..f2a51c47 100644 --- a/stats/sexbound/sexbounddefeat.lua +++ b/stats/sexbound/sexbounddefeat.lua @@ -113,9 +113,6 @@ function SexboundDefeat:update(dt, oldUpdate) end end - -- Return when is defeated to prevent the default update loop from running - if self:isDefeated() then return end - oldUpdate(dt) end @@ -339,7 +336,6 @@ function SexboundDefeat:handleTransformSuccess(nodeUniqueId) if self:isPlayer() then -- Check config for using invisible "UI" that allows escape with ESC key if self._config.enableDefeatedPlayerEscape then world.sendEntityMessage(self._entityId, "Sexbound:UI:Show", {config = self:loadUIConfig()}) end - status.addEphemeralEffect("dontstarve", self._timeout) status.addEphemeralEffect("sexbound_regen4", self._timeout) end @@ -367,7 +363,7 @@ function SexboundDefeat:loadUIConfig() end function SexboundDefeat:tryToDie(reason) - --if reason then sb.logInfo("Sexbound Defeat Death: Name="..world.entityName(self._entityId).." reason: "..reason) end + if reason then sb.logInfo("Sexbound Defeat Death: Name="..world.entityName(self._entityId).." reason: "..reason) end self:setIsDefeated(false) self:setIsTransformed(false) if not self:isPlayer() and self:isPregnant() and self._config.enableImmortalPregnantNPCs then