inventory.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. // This inventory system is totally scripted, no C++ code involved.
  23. // It uses object datablock names to track inventory and is generally
  24. // object type, or class, agnostic. In other words, it will inventory
  25. // any kind of ShapeBase object, though the throw method does assume
  26. // that the objects are small enough to throw :)
  27. //
  28. // For a ShapeBase object to support inventory, it must have an array
  29. // of inventory max values:
  30. // %this.maxInv[GunAmmo] = 100;
  31. // %this.maxInv[SpeedGun] = 1;
  32. // where the names "SpeedGun" and "GunAmmo" are datablocks.
  33. //
  34. // For objects to be inventoriable, they must provide a set of inventory
  35. // callback methods, mainly:
  36. // onUse
  37. // onThrow
  38. // onPickup
  39. //
  40. // Example methods are given further down. The item.cs file also contains
  41. // example inventory items.
  42. //-----------------------------------------------------------------------------
  43. //-----------------------------------------------------------------------------
  44. // Inventory server commands
  45. //-----------------------------------------------------------------------------
  46. function serverCmdUse(%client, %data)
  47. {
  48. %client.getControlObject().use(%data);
  49. }
  50. //-----------------------------------------------------------------------------
  51. // ShapeBase inventory support
  52. //-----------------------------------------------------------------------------
  53. //-----------------------------------------------------------------------------
  54. function ShapeBase::use(%this, %data)
  55. {
  56. // Use an object in the inventory.
  57. // Need to prevent weapon changing when zooming, but only shapes
  58. // that have a connection.
  59. %conn = %this.getControllingClient();
  60. if (%conn)
  61. {
  62. %defaultFov = %conn.getControlCameraDefaultFov();
  63. %fov = %conn.getControlCameraFov();
  64. if (%fov != %defaultFov)
  65. return false;
  66. }
  67. if (%this.getInventory(%data) > 0)
  68. return %data.onUse(%this);
  69. return false;
  70. }
  71. function ShapeBase::throw(%this, %data, %amount)
  72. {
  73. // Throw objects from inventory. The onThrow method is
  74. // responsible for decrementing the inventory.
  75. if (%this.getInventory(%data) > 0)
  76. {
  77. %obj = %data.onThrow(%this, %amount);
  78. if (%obj)
  79. {
  80. %this.throwObject(%obj);
  81. serverPlay3D(ThrowSnd, %this.getTransform());
  82. return true;
  83. }
  84. }
  85. return false;
  86. }
  87. function ShapeBase::pickup(%this, %obj, %amount)
  88. {
  89. // This method is called to pickup an object and add it to the inventory.
  90. // The datablock onPickup method is actually responsible for doing all the
  91. // work, including incrementing the inventory.
  92. %data = %obj.getDatablock();
  93. // Try and pickup the max if no value was specified
  94. if (%amount $= "")
  95. %amount = %this.maxInventory(%data) - %this.getInventory(%data);
  96. // The datablock does the work...
  97. if (%amount < 0)
  98. %amount = 0;
  99. if (%amount)
  100. return %data.onPickup(%obj, %this, %amount);
  101. return false;
  102. }
  103. //-----------------------------------------------------------------------------
  104. function ShapeBase::hasInventory(%this, %data)
  105. {
  106. return (%this.inv[%data] > 0);
  107. }
  108. function ShapeBase::hasAmmo(%this, %weapon)
  109. {
  110. if (%weapon.image.ammo $= "")
  111. return(true);
  112. else
  113. return(%this.getInventory(%weapon.image.ammo) > 0);
  114. }
  115. function ShapeBase::maxInventory(%this, %data)
  116. {
  117. if (%data.isField("clip"))
  118. {
  119. // Use the clip system which uses the maxInventory
  120. // field on the ammo itself.
  121. return %data.maxInventory;
  122. }
  123. else
  124. {
  125. // Use the ammo pool system which uses the maxInv[]
  126. // array on the object's datablock.
  127. // If there is no limit defined, we assume 0
  128. return %this.getDatablock().maxInv[%data.getName()];
  129. }
  130. }
  131. function ShapeBase::incInventory(%this, %data, %amount)
  132. {
  133. // Increment the inventory by the given amount. The return value
  134. // is the amount actually added, which may be less than the
  135. // requested amount due to inventory restrictions.
  136. %max = %this.maxInventory(%data);
  137. %total = %this.inv[%data.getName()];
  138. if (%total < %max)
  139. {
  140. if (%total + %amount > %max)
  141. %amount = %max - %total;
  142. %this.setInventory(%data, %total + %amount);
  143. return %amount;
  144. }
  145. return 0;
  146. }
  147. function ShapeBase::decInventory(%this, %data, %amount)
  148. {
  149. // Decrement the inventory by the given amount. The return value
  150. // is the amount actually removed.
  151. %total = %this.inv[%data.getName()];
  152. if (%total > 0)
  153. {
  154. if (%total < %amount)
  155. %amount = %total;
  156. %this.setInventory(%data, %total - %amount);
  157. return %amount;
  158. }
  159. return 0;
  160. }
  161. //-----------------------------------------------------------------------------
  162. function ShapeBase::getInventory(%this, %data)
  163. {
  164. // Return the current inventory amount
  165. return %this.inv[%data.getName()];
  166. }
  167. function ShapeBase::setInventory(%this, %data, %value)
  168. {
  169. // Set the inventory amount for this datablock and invoke inventory
  170. // callbacks. All changes to inventory go through this single method.
  171. // Impose inventory limits
  172. if (%value < 0)
  173. %value = 0;
  174. else
  175. {
  176. %max = %this.maxInventory(%data);
  177. if (%value > %max)
  178. %value = %max;
  179. }
  180. // Set the value and invoke object callbacks
  181. %name = %data.getName();
  182. if (%this.inv[%name] != %value)
  183. {
  184. %this.inv[%name] = %value;
  185. %data.onInventory(%this, %value);
  186. %this.getDataBlock().onInventory(%data, %value);
  187. }
  188. return %value;
  189. }
  190. //-----------------------------------------------------------------------------
  191. function ShapeBase::clearInventory(%this)
  192. {
  193. // To be filled in...
  194. }
  195. //-----------------------------------------------------------------------------
  196. function ShapeBase::throwObject(%this, %obj)
  197. {
  198. // Throw the given object in the direction the shape is looking.
  199. // The force value is hardcoded according to the current default
  200. // object mass and mission gravity (20m/s^2).
  201. %throwForce = %this.getDataBlock().throwForce;
  202. if (!%throwForce)
  203. %throwForce = 20;
  204. // Start with the shape's eye vector...
  205. %eye = %this.getEyeVector();
  206. %vec = vectorScale(%eye, %throwForce);
  207. // Add a vertical component to give the object a better arc
  208. %verticalForce = %throwForce / 2;
  209. %dot = vectorDot("0 0 1", %eye);
  210. if (%dot < 0)
  211. %dot = -%dot;
  212. %vec = vectorAdd(%vec, vectorScale("0 0 "@%verticalForce, 1 - %dot));
  213. // Add the shape's velocity
  214. %vec = vectorAdd(%vec, %this.getVelocity());
  215. // Set the object's position and initial velocity
  216. %pos = getBoxCenter(%this.getWorldBox());
  217. %obj.setTransform(%pos);
  218. %obj.applyImpulse(%pos, %vec);
  219. // Since the object is thrown from the center of the shape,
  220. // the object needs to avoid colliding with it's thrower.
  221. %obj.setCollisionTimeout(%this);
  222. }
  223. //-----------------------------------------------------------------------------
  224. // Callback hooks invoked by the inventory system
  225. //-----------------------------------------------------------------------------
  226. //-----------------------------------------------------------------------------
  227. // ShapeBase object callbacks invoked by the inventory system
  228. function ShapeBase::onInventory(%this, %data, %value)
  229. {
  230. // Invoked on ShapeBase objects whenever their inventory changes
  231. // for the given datablock.
  232. }
  233. //-----------------------------------------------------------------------------
  234. // ShapeBase datablock callback invoked by the inventory system.
  235. function ShapeBaseData::onUse(%this, %user)
  236. {
  237. // Invoked when the object uses this datablock, should return
  238. // true if the item was used.
  239. return false;
  240. }
  241. function ShapeBaseData::onThrow(%this, %user, %amount)
  242. {
  243. // Invoked when the object is thrown. This method should
  244. // construct and return the actual mission object to be
  245. // physically thrown. This method is also responsible for
  246. // decrementing the user's inventory.
  247. return 0;
  248. }
  249. function ShapeBaseData::onPickup(%this, %obj, %user, %amount)
  250. {
  251. // Invoked when the user attempts to pickup this datablock object.
  252. // The %amount argument is the space in the user's inventory for
  253. // this type of datablock. This method is responsible for
  254. // incrementing the user's inventory is something is addded.
  255. // Should return true if something was added to the inventory.
  256. return false;
  257. }
  258. function ShapeBaseData::onInventory(%this, %user, %value)
  259. {
  260. // Invoked whenever an user's inventory total changes for
  261. // this datablock.
  262. }