Persistence #1 featuring quill (#508)

* Add .scalafmt.conf

* Adopt quill for database access

* Removed postgresql-async
* Refactored all instances of database access
* Creating duplicate characters of the same account is no longer possible
* Rewrote large parts of LoginSessionActor

* Implement migrations

* Move overrides into subdirectory

* Make usernames case insensitive

* Use LOWER(?) comparison instead of storing lowercased username

* import scala.util.{Success, Failure}

* Add config and joda-time dependencies

* Add sbt-scalafmt

* Use defaultWithAlign scalafmt preset

* Format all

* Add scalafix

* Remove unused imports

* Don't lowercase username when inserting

* Update readme

* Listen on worldserver.Hostname address

* Remove database test on startup

It could fail when the global thread pool is busy loading zone
maps. Migrations run on the main thread and also serve the
purpose of verifying the database configuration so it's fine to
remove the test altogether.

* Refactor chat message handlers, zones

What started as a small change to how zones are stored turned
into a pretty big effort of refactoring the chat message handler.
The !hack command was removed, the /capturebase commandwas added.

* Expose db ports in docker-compose.yml

* Silence property override log

* Rework configuration

* Unify configuration using the typesafe.config library
* Add configuration option for public address
* Configuration is now loaded from application.conf rather than worldserver.ini
* Refactor PsLogin and remove unnecessary logging
* Move pslogin into net.psforever.pslogin namespace

* Fix coverage
This commit is contained in:
Jakob Gillich 2020-07-14 05:54:05 +02:00 committed by GitHub
parent 88b194fde2
commit e0defe8240
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
850 changed files with 144487 additions and 47476 deletions

3
.gitignore vendored
View file

@ -13,8 +13,7 @@ out/
project/metals.sbt
# User configs
config/worldserver.ini
pslogin/src/main/resources/user.conf
config/psforever.conf
# Log files
*.log

6
.scalafix.conf Normal file
View file

@ -0,0 +1,6 @@
rules = [
RemoveUnused
]
RemoveUnused.imports = true
RemoveUnused.privates = false
RemoveUnused.locals = false

3
.scalafmt.conf Normal file
View file

@ -0,0 +1,3 @@
version = 2.6.1
preset = defaultWithAlign
maxColumn = 120

View file

@ -78,7 +78,11 @@ The Login and World servers require PostgreSQL for persistence.
- Linux - [Debian](https://www.postgresql.org/download/linux/debian/) or [Ubuntu](https://www.postgresql.org/download/linux/ubuntu/)
- macOS - Application https://www.postgresql.org/download/ (or `brew install postgresql && brew services start postgresql`)
The default database is named `psforever` and the credentials are `psforever:psforever`. To change these, make a copy of [`config/worldserver.ini.dist`](config/worldserver.ini.dist) to `config/worldserver.ini` and change the corresponding fields in the database section. This database user will need ALL access to tables, sequences, and functions.
The default database is named `psforever` and the credentials are
`psforever:psforever`. To change these, create a configuration file at
`config/psforever.conf`. For configuration options and their defaults, see
[`pslogin/src/main/resources/application.conf`]. This database user will need
ALL access to tables, sequences, and functions.
The permissions required can be summarized by the SQL below.
Loading this in requires access to a graphical tool such as [pgAdmin](https://www.pgadmin.org/download/) (highly recommended) or a PostgreSQL terminal (`psql`) for advanced users.
@ -95,9 +99,9 @@ ALTER DEFAULT PRIVILEGES IN SCHEMA PUBLIC GRANT ALL ON FUNCTIONS TO psforever;
**NOTE:** applying default privileges _after_ importing the schema will not apply them to existing objects. To fix this, you must drop all objects and try again or apply permissions manually using the Query Tool / `psql`.
Now you need to synchronize the schema. This is currently available in [`schema.sql`](schema.sql).
To do this right click on the psforever database -> Query Tool... -> Copy and paste / Open the `schema.sql` file into the editor -> Hit the "Play/Run" button. The schema should be loaded into the database.
Once you have the schema loaded in, the LoginServer will automatically create accounts on first login. If you'd like a nice account management interface, check out the [PSFPortal](https://github.com/psforever/PSFPortal) web interface.
The server will automatically apply the latest schema. Migrations can also be applied manually using
the [Flyway CLI](https://flywaydb.org/documentation/commandline/). Existing databases before the
introduction of migrations must be baselined using the `flyway baseline` command.
### Becoming a GM
@ -161,33 +165,6 @@ Using SBT, you can generate documentation for both the common and pslogin projec
Current documentation is available at [https://psforever.github.io/docs/master/index.html](https://psforever.github.io/docs/master/index.html)
## Troubleshooting
#### Unable to initialize pscrypto
If you get an error like below
```
12:17:28.037 [main] ERROR PsLogin - Unable to initialize pscrypto
java.lang.UnsatisfiedLinkError: Unable to load library 'pscrypto': Native library (win32-x86-64/pscrypto.dll) not found in resource path
```
Then you are missing the native library required to provide cryptographic functions to the login server. To fix this, you need a binary build of [PSCrypto](#downloading-pscrypto).
If you are still having trouble on Linux, try putting the library in `root directory/pscrypto-lib/libpscrypto.so`.
## Contributing
Please fork the project and provide a pull request to contribute code. Coding guidelines and contribution checklists coming soon.
## Get in touch
- Website: http://psforever.net
- Discord (chat with us): https://discord.gg/0nRe5TNbTYoUruA4
- Join the #code channel and ask any questions you have there
Chord is the lead developer and you can contact him on Discord as Chord or by email [chord@tuta.io](mailto:chord@tuta.io). Discord is preferred.
## Tools
### decodePackets
@ -217,6 +194,33 @@ psf-decode-packets -o ./output-directory foo.gcap bar.gcap
By default, decodePackets takes in `.gcap` files, but it can also take gcapy ascii files with the
`-p` option. Run `psf-decode-packets --help` to get usage info.
## Troubleshooting
#### Unable to initialize pscrypto
If you get an error like below
```
12:17:28.037 [main] ERROR PsLogin - Unable to initialize pscrypto
java.lang.UnsatisfiedLinkError: Unable to load library 'pscrypto': Native library (win32-x86-64/pscrypto.dll) not found in resource path
```
Then you are missing the native library required to provide cryptographic functions to the login server. To fix this, you need a binary build of [PSCrypto](#downloading-pscrypto).
If you are still having trouble on Linux, try putting the library in `root directory/pscrypto-lib/libpscrypto.so`.
## Contributing
Please fork the project and provide a pull request to contribute code. Coding guidelines and contribution checklists coming soon.
## Get in touch
- Website: http://psforever.net
- Discord (chat with us): https://discord.gg/0nRe5TNbTYoUruA4
- Join the #code channel and ask any questions you have there
Chord is the lead developer and you can contact him on Discord as Chord or by email [chord@tuta.io](mailto:chord@tuta.io). Discord is preferred.
## License
GNU GPLv3. See LICENSE.md for the full copy.

160
build.sbt
View file

@ -4,8 +4,18 @@ lazy val commonSettings = Seq(
organization := "net.psforever",
version := "1.0.2-SNAPSHOT",
scalaVersion := "2.13.2",
scalacOptions := Seq("-unchecked", "-feature", "-deprecation", "-encoding", "utf8", "-language:postfixOps"),
semanticdbEnabled := true,
semanticdbVersion := scalafixSemanticdb.revision,
scalacOptions := Seq(
"-unchecked",
"-feature",
"-deprecation",
"-encoding",
"utf8",
"-language:postfixOps",
"-Wunused:imports",
"-Xmacro-settings:materialize-derivations"
),
// Quiet test options
// https://github.com/etorreborre/specs2/blob/8305db76c5084e4b3ce5827ce23117f6fb6beee4/common/shared/src/main/scala/org/specs2/main/Report.scala#L94
// https://etorreborre.github.io/specs2/guide/SPECS2-2.4.17/org.specs2.guide.Runners.html
@ -14,41 +24,56 @@ lazy val commonSettings = Seq(
testOptions in QuietTest += Tests.Argument(TestFrameworks.ScalaTest, "-oCEHILMNOPQRX"),
// Trick taken from https://groups.google.com/d/msg/scala-user/mxV9ok7J_Eg/kt-LnsrD0bkJ
// scaladoc flags: https://github.com/scala/scala/blob/2.11.x/src/scaladoc/scala/tools/nsc/doc/Settings.scala
scalacOptions in (Compile,doc) := { Seq(
scalacOptions in (Compile, doc) ++= Seq(
"-groups",
"-implicits",
"-doc-title", "PSF-LoginServer - ",
"-doc-version", "master",
"-doc-footer", "Copyright PSForever",
"-doc-title",
"PSF-LoginServer - ",
"-doc-version",
"master",
"-doc-footer",
"Copyright PSForever",
// For non unidoc builds, you may need bd.getName before the template parameter
"-doc-source-url", "https://github.com/psforever/PSF-LoginServer/blob/master/€{FILE_PATH}.scala",
"-sourcepath", baseDirectory.value.getAbsolutePath // needed for scaladoc relative source paths
)
},
"-doc-source-url",
"https://github.com/psforever/PSF-LoginServer/blob/master/€{FILE_PATH}.scala",
"-sourcepath",
baseDirectory.value.getAbsolutePath // needed for scaladoc relative source paths
),
classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat,
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor" % "2.6.5",
"com.typesafe.akka" %% "akka-testkit" % "2.6.5" % "test",
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
"org.specs2" %% "specs2-core" % "4.9.4" % "test",
"org.scalatest" %% "scalatest" % "3.1.2" % "test",
"org.scodec" %% "scodec-core" % "1.11.7",
"net.java.dev.jna" % "jna" % "5.5.0",
"com.typesafe.akka" %% "akka-slf4j" % "2.6.5",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"org.log4s" %% "log4s" % "1.8.2",
"org.fusesource.jansi" % "jansi" % "1.12",
"com.typesafe.akka" %% "akka-actor" % "2.6.6",
"com.typesafe.akka" %% "akka-slf4j" % "2.6.6",
"com.typesafe.akka" %% "akka-protobuf-v3" % "2.6.6",
"com.typesafe.akka" %% "akka-stream" % "2.6.6",
"com.typesafe.akka" %% "akka-testkit" % "2.6.6" % "test",
"com.typesafe.akka" %% "akka-actor-typed" % "2.6.6",
"com.typesafe.akka" %% "akka-cluster-typed" % "2.6.6",
"com.typesafe.scala-logging" %% "scala-logging" % "3.9.2",
"org.specs2" %% "specs2-core" % "4.9.4" % "test",
"org.scalatest" %% "scalatest" % "3.1.2" % "test",
"org.scodec" %% "scodec-core" % "1.11.7",
"net.java.dev.jna" % "jna" % "5.5.0",
"com.typesafe.akka" %% "akka-slf4j" % "2.6.5",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"org.log4s" %% "log4s" % "1.8.2",
"org.fusesource.jansi" % "jansi" % "1.12",
"org.scoverage" %% "scalac-scoverage-plugin" % "1.4.1",
"com.github.nscala-time" %% "nscala-time" % "2.24.0",
"com.github.postgresql-async" %% "postgresql-async" % "0.3.0",
"com.github.t3hnar" %% "scala-bcrypt" % "4.1",
"org.ini4j" % "ini4j" % "0.5.4",
"org.scala-graph" %% "graph-core" % "1.13.1",
"io.kamon" %% "kamon-bundle" % "2.1.0",
"io.kamon" %% "kamon-apm-reporter" % "2.1.0",
"org.json4s" %% "json4s-native" % "3.6.8",
"com.typesafe.akka" %% "akka-stream" % "2.6.5"
"com.github.nscala-time" %% "nscala-time" % "2.24.0",
"com.github.t3hnar" %% "scala-bcrypt" % "4.1",
"org.scala-graph" %% "graph-core" % "1.13.1",
"io.kamon" %% "kamon-bundle" % "2.1.0",
"io.kamon" %% "kamon-apm-reporter" % "2.1.0",
"org.json4s" %% "json4s-native" % "3.6.8",
"com.typesafe.akka" %% "akka-stream" % "2.6.5",
"io.getquill" %% "quill-jasync-postgres" % "3.5.2",
"org.flywaydb" % "flyway-core" % "6.5.0",
"org.postgresql" % "postgresql" % "42.2.14",
"com.typesafe" % "config" % "1.4.0",
"com.github.pureconfig" %% "pureconfig" % "0.13.0",
"com.beachape" %% "enumeratum" % "1.6.1",
"joda-time" % "joda-time" % "2.10.6",
"commons-io" % "commons-io" % "2.6"
)
)
@ -61,63 +86,58 @@ lazy val pscryptoSettings = Seq(
lazy val psloginPackSettings = Seq(
packMain := Map("ps-login" -> "PsLogin"),
packArchivePrefix := "pslogin",
packExtraClasspath := Map("ps-login" -> Seq("${PROG_HOME}/pscrypto-lib",
"${PROG_HOME}/config")),
packResourceDir += (baseDirectory.value / "pscrypto-lib" -> "pscrypto-lib"),
packResourceDir += (baseDirectory.value / "config" -> "config"),
packExtraClasspath := Map("ps-login" -> Seq("${PROG_HOME}/pscrypto-lib", "${PROG_HOME}/config")),
packResourceDir += (baseDirectory.value / "pscrypto-lib" -> "pscrypto-lib"),
packResourceDir += (baseDirectory.value / "config" -> "config"),
packResourceDir += (baseDirectory.value / "pslogin/src/main/resources" -> "config")
)
lazy val root = (project in file(".")).
configs(QuietTest).
enablePlugins(PackPlugin).
settings(commonSettings: _*).
settings(psloginPackSettings: _*).
enablePlugins(ScalaUnidocPlugin).
aggregate(pslogin, common).
dependsOn(pslogin, common)
lazy val root = (project in file("."))
.configs(QuietTest)
.enablePlugins(PackPlugin)
.settings(commonSettings: _*)
.settings(psloginPackSettings: _*)
.enablePlugins(ScalaUnidocPlugin)
.aggregate(pslogin, common)
lazy val pslogin = (project in file("pslogin")).
configs(QuietTest).
settings(commonSettings: _*).
settings(
lazy val pslogin = (project in file("pslogin"))
.configs(QuietTest)
.settings(commonSettings: _*)
.settings(
name := "pslogin",
// ActorTests have specific timing requirements and will be flaky if run in parallel
parallelExecution in Test := false,
// TODO(chord): remove exclusion when WorldSessionActor is refactored: https://github.com/psforever/PSF-LoginServer/issues/279
coverageExcludedPackages := "WorldSessionActor.*;zonemaps.*",
coverageExcludedPackages := "net.psforever.pslogin.WorldSessionActor.*;net.psforever.pslogin.zonemaps.*",
// Copy all tests from Test -> QuietTest (we're only changing the run options)
inConfig(QuietTest)(Defaults.testTasks)
).
settings(pscryptoSettings: _*).
dependsOn(common)
)
.settings(pscryptoSettings: _*)
.dependsOn(common)
lazy val common = (project in file("common")).
configs(QuietTest).
settings(commonSettings: _*).
settings(
lazy val common = (project in file("common"))
.configs(QuietTest)
.settings(commonSettings: _*)
.settings(
name := "common",
// Copy all tests from Test -> QuietTest (we're only changing the run options)
inConfig(QuietTest)(Defaults.testTasks)
).
settings(pscryptoSettings: _*)
)
.settings(pscryptoSettings: _*)
lazy val decodePackets = (project in file("tools/decode-packets")).
enablePlugins(PackPlugin).
settings(commonSettings: _*).
settings(decodePacketsPackSettings: _*).
settings(
lazy val decodePackets = (project in file("tools/decode-packets"))
.enablePlugins(PackPlugin)
.settings(commonSettings: _*)
.settings(decodePacketsPackSettings: _*)
.settings(
libraryDependencies ++= Seq(
"org.scala-lang.modules" %% "scala-parallel-collections" % "0.2.0",
"com.github.scopt" %% "scopt" % "4.0.0-RC2",
"commons-io" % "commons-io" % "2.6"
"org.scala-lang.modules" %% "scala-parallel-collections" % "0.2.0",
"com.github.scopt" %% "scopt" % "4.0.0-RC2"
)
).
dependsOn(common)
)
.dependsOn(common)
lazy val decodePacketsPackSettings = Seq(
packMain := Map("psf-decode-packets" -> "DecodePackets"),
)
lazy val decodePacketsPackSettings = Seq(packMain := Map("psf-decode-packets" -> "DecodePackets"))
// Special test configuration for really quiet tests (used in CI)
lazy val QuietTest = config("quiet") extend(Test)
lazy val QuietTest = config("quiet") extend (Test)

View file

@ -1,13 +1,13 @@
// Copyright (c) 2017 PSForever
// Taken from http://code.hootsuite.com/logging-contextual-info-in-an-asynchronous-scala-application/
package akka.actor
// Taken from https://medium.com/hootsuite-engineering/logging-contextual-info-in-an-asynchronous-scala-application-8ea33bfec9b3
import akka.util.Timeout
import org.slf4j.MDC
import scala.concurrent.Future
trait MDCContextAware extends Actor with ActorLogging {
trait MDCContextAware extends Actor with ActorLogging {
import MDCContextAware._
// This is why this needs to be in package akka.actor
@ -52,7 +52,7 @@ object MDCContextAware {
* the current MDC values. Note: we MUST capture the ActorContext in order for senders
* to be correct! This was a bug from the original author.
*/
def !>(msg: Any)(implicit context: ActorContext) : Unit =
def !>(msg: Any)(implicit context: ActorContext): Unit =
ref.tell(MdcMsg(MDC.getCopyOfContextMap, msg), context.self)
/**
@ -63,4 +63,4 @@ object MDCContextAware {
ref.ask(MdcMsg(MDC.getCopyOfContextMap, msg), context.self)
}
}
}
}

View file

@ -0,0 +1,69 @@
package akka.actor
// Taken from https://medium.com/hootsuite-engineering/logging-contextual-info-in-an-asynchronous-scala-application-8ea33bfec9b3
import org.slf4j.MDC
import scala.concurrent.ExecutionContext
trait MDCPropagatingExecutionContext extends ExecutionContext {
// name the self-type "self" so we can refer to it inside the nested class
self =>
override def prepare(): ExecutionContext =
new ExecutionContext {
// Save the call-site MDC state
val context = MDC.getCopyOfContextMap
def execute(r: Runnable): Unit =
self.execute(new Runnable {
def run(): Unit = {
// Save the existing execution-site MDC state
val oldContext = MDC.getCopyOfContextMap
try {
// Set the call-site MDC state into the execution-site MDC
if (context != null)
MDC.setContextMap(context)
else
MDC.clear()
r.run()
} finally {
// Restore the existing execution-site MDC state
if (oldContext != null)
MDC.setContextMap(oldContext)
else
MDC.clear()
}
}
})
def reportFailure(t: Throwable): Unit = self.reportFailure(t)
}
}
object MDCPropagatingExecutionContext {
object Implicits {
// Convenience wrapper around the Scala global ExecutionContext so you can just do:
// import MDCPropagatingExecutionContext.Implicits.global
implicit lazy val global = MDCPropagatingExecutionContextWrapper(ExecutionContext.Implicits.global)
}
}
/**
* Wrapper around an existing ExecutionContext that makes it propagate MDC information.
*/
class MDCPropagatingExecutionContextWrapper(wrapped: ExecutionContext)
extends ExecutionContext
with MDCPropagatingExecutionContext {
override def execute(r: Runnable): Unit = wrapped.execute(r)
override def reportFailure(t: Throwable): Unit = wrapped.reportFailure(t)
}
object MDCPropagatingExecutionContextWrapper {
def apply(wrapped: ExecutionContext): MDCPropagatingExecutionContextWrapper = {
new MDCPropagatingExecutionContextWrapper(wrapped)
}
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2017 PSForever
package net.psforever
class ObjectFinalizedException(msg : String) extends Exception(msg)
class ObjectFinalizedException(msg: String) extends Exception(msg)
trait IFinalizable {
var closed = false
@ -11,12 +11,14 @@ trait IFinalizable {
}
def assertNotClosed = {
if(closed)
throw new ObjectFinalizedException(this.getClass.getCanonicalName + ": already finalized. Cannot interact with object")
if (closed)
throw new ObjectFinalizedException(
this.getClass.getCanonicalName + ": already finalized. Cannot interact with object"
)
}
override def finalize() = {
if(!closed)
if (!closed)
println(this.getClass.getCanonicalName + ": class not closed. memory leaked")
}
}

View file

@ -1,240 +0,0 @@
// Copyright (c) 2019 PSForever
package net.psforever.config
import org.ini4j
import scala.reflect.ClassTag
import scala.reflect.runtime.universe.TypeTag
import scala.annotation.implicitNotFound
import scala.concurrent.duration._
import scala.collection.mutable.Map
case class ConfigValueMapper[T](name: String)(f: (String => Option[T])) {
def apply(t: String): Option[T] = f(t)
}
object ConfigValueMapper {
import scala.language.implicitConversions
implicit val toInt : ConfigValueMapper[Int] = ConfigValueMapper[Int]("toInt") { e =>
try {
Some(e.toInt)
} catch {
case e: Exception => None
}
}
// TypeTag is necessary to be able to retrieve an instance of the Enum class
// at runtime as it is usually erased at runtime. This is low cost as its only
// used during the config parsing
implicit def toEnum[E <: Enumeration#Value](implicit m: TypeTag[E]) : ConfigValueMapper[E] = ConfigValueMapper[E]("toEnum") { e =>
try {
Some(EnumReflector.withName[E](e))
} catch {
case e: Exception => None
}
}
implicit val toBool : ConfigValueMapper[Boolean] = ConfigValueMapper[Boolean]("toBool") { e =>
if (e == "yes") {
Some(true)
} else if (e == "no") {
Some(false)
} else {
None
}
}
implicit val toFloat : ConfigValueMapper[Float] = ConfigValueMapper[Float]("toFloat") { e =>
try {
Some(e.toFloat)
} catch {
case e: Exception => None
}
}
implicit val toDuration : ConfigValueMapper[Duration] = ConfigValueMapper[Duration]("toDuration") { e =>
try {
Some(Duration(e))
} catch {
case e: Exception => None
}
}
implicit val toStr : ConfigValueMapper[String] = ConfigValueMapper[String]("toString") { e =>
Some(e)
}
}
sealed trait ConfigEntry {
type Value
val key : String
val default : Value
def getType : String
val constraints : Seq[Constraint[Value]]
def read(v: String): Option[Value]
}
final case class ConfigEntryString(key: String, default : String, constraints : Constraint[String]*) extends ConfigEntry {
type Value = String
def getType = "String"
def read(v : String) = ConfigValueMapper.toStr(v)
}
final case class ConfigEntryInt(key: String, default : Int, constraints : Constraint[Int]*) extends ConfigEntry {
type Value = Int
def getType = "Int"
def read(v : String) = ConfigValueMapper.toInt(v)
}
final case class ConfigEntryBool(key: String, default : Boolean, constraints : Constraint[Boolean]*) extends ConfigEntry {
type Value = Boolean
def getType = "Bool"
def read(v : String) = ConfigValueMapper.toBool(v)
}
final case class ConfigEntryEnum[E <: Enumeration](key: String, default : E#Value)(implicit m : TypeTag[E#Value], implicit val m2 : TypeTag[E#ValueSet]) extends ConfigEntry {
type Value = E#Value
val constraints : Seq[Constraint[E#Value]] = Seq()
def getType = EnumReflector.values[E#ValueSet](m2).mkString(", ")
def read(v : String) = ConfigValueMapper.toEnum[E#Value](m)(v)
}
final case class ConfigEntryFloat(key: String, default : Float, constraints : Constraint[Float]*) extends ConfigEntry {
type Value = Float
def getType = "Float"
def read(v : String) = ConfigValueMapper.toFloat(v)
}
final case class ConfigEntryTime(key: String, default : Duration, constraints : Constraint[Duration]*) extends ConfigEntry {
type Value = Duration
def getType = "Time"
def read(v : String) = ConfigValueMapper.toDuration(v)
}
case class ConfigSection(name: String, entries: ConfigEntry*)
@implicitNotFound("Nothing was inferred")
sealed trait ConfigTypeRequired[-T]
object ConfigTypeRequired {
implicit object cfgTypeRequired extends ConfigTypeRequired[Any]
//We do not want Nothing to be inferred, so make an ambiguous implicit
implicit object `\n The Get[T] call needs a type T matching the corresponding ConfigEntry` extends ConfigTypeRequired[Nothing]
}
trait ConfigParser {
protected var config_map : Map[String, Any] = Map()
protected val config_template : Seq[ConfigSection]
// Misuse of this function can lead to run time exceptions when the types don't match
// ClassTag is needed due to type erasure on T
// https://dzone.com/articles/scala-classtag-a-simple-use-case
def Get[T : ConfigTypeRequired](key : String)(implicit m: ClassTag[T]) : T = {
config_map.get(key) match {
case Some(value : T) => value
case None =>
throw new NoSuchElementException(s"Config key '${key}' not found")
case Some(value : Any) =>
throw new ClassCastException(s"Incorrect type T = ${m.runtimeClass.getSimpleName} passed to Get[T]: needed ${value.getClass.getSimpleName}")
}
}
def Load(filename : String) : ValidationResult = {
var map : Map[String, Any] = scala.collection.mutable.Map()
LoadMap(filename, map) match {
case i : Invalid =>
i
case Valid =>
ReplaceConfig(map)
// run post-parse validation only if we successfully parsed
postParseChecks match {
case i : Invalid =>
i
case Valid =>
Valid
}
}
}
def LoadMap(filename : String, map : Map[String, Any]) : ValidationResult = {
val ini = new org.ini4j.Ini()
try {
ini.load(new java.io.File(filename))
} catch {
case e : org.ini4j.InvalidFileFormatException =>
return Invalid(e.getMessage)
case e : java.io.FileNotFoundException =>
return Invalid(e.getMessage)
}
val result : Seq[ValidationResult] = config_template.map { section =>
val sectionIni = ini.get(section.name)
if (sectionIni == null)
Seq(Invalid("section.missing", section.name))
else
section.entries.map(parseSection(sectionIni, _, map))
}.reduceLeft((x, y) => x ++ y)
val errors : Seq[Invalid] = result.collect { case iv : Invalid => iv }
if (errors.length > 0)
errors.reduceLeft((x, y) => x ++ y)
else
Valid
}
def ReplaceConfig(map : Map[String, Any]) : Unit = {
config_map = map
}
def GetRawConfig : Map[String, Any] = {
config_map
}
def FormatErrors(invalidResult : Invalid) : Seq[String] = {
var count = 0;
invalidResult.errors.map((error) => {
var message = error.message;
if (error.args.length > 0)
message += " ("+error.args(0)+")"
count += 1;
s"Error ${count}: ${message}"
});
}
protected def postParseChecks : ValidationResult = {
Valid
}
protected def parseSection(sectionIni : org.ini4j.Profile.Section, entry : ConfigEntry, map : Map[String, Any]) : ValidationResult = {
var rawValue = sectionIni.get(entry.key, 0)
val full_key : String = sectionIni.getName + "." + entry.key
val value = if (rawValue == null) {
println(s"config warning: missing key '${entry.key}', using default value '${entry.default}'")
entry.default
} else {
rawValue = rawValue.stripPrefix("\"").stripSuffix("\"")
entry.read(rawValue) match {
case Some(v) => v
case None => return Invalid(ValidationError(String.format("%s: value format error (expected: %s)", full_key, entry.getType)))
}
}
map += (full_key -> value)
ParameterValidator(entry.constraints, Some(value)) match {
case v @ Valid => v
case i @ Invalid(errors) => {
Invalid(errors.map(x => ValidationError(x.messages.map(full_key + ": " + _), x.args: _*)))
}
}
}
}

View file

@ -1,290 +0,0 @@
// Copyright (c) 2019 PSForever
// Lifted from https://raw.githubusercontent.com/playframework/playframework/2.7.x/core/play/src/main/scala/play/api/data/validation/Validation.scala
package net.psforever.config
/**
* A form constraint.
*
* @tparam T type of values handled by this constraint
* @param name the constraint name, to be displayed to final user
* @param args the message arguments, to format the constraint name
* @param f the validation function
*/
case class Constraint[-T](name: Option[String], args: Seq[Any])(f: (T => ValidationResult)) {
/**
* Run the constraint validation.
*
* @param t the value to validate
* @return the validation result
*/
def apply(t: T): ValidationResult = f(t)
}
/**
* This object provides helpers for creating `Constraint` values.
*
* For example:
* {{{
* val negative = Constraint[Int] {
* case i if i < 0 => Valid
* case _ => Invalid("Must be a negative number.")
* }
* }}}
*/
object Constraint {
/**
* Creates a new anonymous constraint from a validation function.
*
* @param f the validation function
* @return a constraint
*/
def apply[T](f: (T => ValidationResult)): Constraint[T] = apply(None, Nil)(f)
/**
* Creates a new named constraint from a validation function.
*
* @param name the constraint name
* @param args the constraint arguments, used to format the constraint name
* @param f the validation function
* @return a constraint
*/
def apply[T](name: String, args: Any*)(f: (T => ValidationResult)): Constraint[T] = apply(Some(name), args.toSeq)(f)
}
/**
* Defines a set of built-in constraints.
*/
object Constraints extends Constraints
/**
* Defines a set of built-in constraints.
*
* @define emailAddressDoc Defines an emailAddress constraint for `String` values which will validate email addresses.
*
* '''name'''[constraint.email]
* '''error'''[error.email]
*
* @define nonEmptyDoc Defines a required constraint for `String` values, i.e. one in which empty strings are invalid.
*
* '''name'''[constraint.required]
* '''error'''[error.required]
*/
trait Constraints {
private val emailRegex =
"""^[a-zA-Z0-9\.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$""".r
/**
* $emailAddressDoc
*/
def emailAddress(errorMessage: String = "error.email"): Constraint[String] = Constraint[String]("constraint.email") {
e =>
if (e == null) Invalid(ValidationError(errorMessage))
else if (e.trim.isEmpty) Invalid(ValidationError(errorMessage))
else
emailRegex
.findFirstMatchIn(e)
.map(_ => Valid)
.getOrElse(Invalid(ValidationError(errorMessage)))
}
/**
* $emailAddressDoc
*
*/
def emailAddress: Constraint[String] = emailAddress()
/**
* $nonEmptyDoc
*/
def nonEmpty(errorMessage: String = "error.required"): Constraint[String] =
Constraint[String]("constraint.required") { o =>
if (o == null) Invalid(ValidationError(errorMessage))
else if (o.trim.isEmpty) Invalid(ValidationError(errorMessage))
else Valid
}
/**
* $nonEmptyDoc
*
*/
def nonEmpty: Constraint[String] = nonEmpty()
/**
* Defines a minimum value for `Ordered` values, by default the value must be greater than or equal to the constraint parameter
*
* '''name'''[constraint.min(minValue)]
* '''error'''[error.min(minValue)] or [error.min.strict(minValue)]
*/
def min[T](
minValue: T,
strict: Boolean = false,
errorMessage: String = "error.min",
strictErrorMessage: String = "error.min.strict"
)(implicit ordering: scala.math.Ordering[T]): Constraint[T] = Constraint[T]("constraint.min", minValue) { o =>
(ordering.compare(o, minValue).sign, strict) match {
case (1, _) | (0, false) => Valid
case (_, false) => Invalid(ValidationError(errorMessage, minValue))
case (_, true) => Invalid(ValidationError(strictErrorMessage, minValue))
}
}
/**
* Defines a maximum value for `Ordered` values, by default the value must be less than or equal to the constraint parameter
*
* '''name'''[constraint.max(maxValue)]
* '''error'''[error.max(maxValue)] or [error.max.strict(maxValue)]
*/
def max[T](
maxValue: T,
strict: Boolean = false,
errorMessage: String = "error.max",
strictErrorMessage: String = "error.max.strict"
)(implicit ordering: scala.math.Ordering[T]): Constraint[T] = Constraint[T]("constraint.max", maxValue) { o =>
(ordering.compare(o, maxValue).sign, strict) match {
case (-1, _) | (0, false) => Valid
case (_, false) => Invalid(ValidationError(errorMessage, maxValue))
case (_, true) => Invalid(ValidationError(strictErrorMessage, maxValue))
}
}
/**
* Defines a minimum length constraint for `String` values, i.e. the strings length must be greater than or equal to the constraint parameter
*
* '''name'''[constraint.minLength(length)]
* '''error'''[error.minLength(length)]
*/
def minLength(length: Int, errorMessage: String = "error.minLength"): Constraint[String] =
Constraint[String]("constraint.minLength", length) { o =>
require(length >= 0, "string minLength must not be negative")
if (o == null) Invalid(ValidationError(errorMessage, length))
else if (o.size >= length) Valid
else Invalid(ValidationError(errorMessage, length))
}
/**
* Defines a maximum length constraint for `String` values, i.e. the strings length must be less than or equal to the constraint parameter
*
* '''name'''[constraint.maxLength(length)]
* '''error'''[error.maxLength(length)]
*/
def maxLength(length: Int, errorMessage: String = "error.maxLength"): Constraint[String] =
Constraint[String]("constraint.maxLength", length) { o =>
require(length >= 0, "string maxLength must not be negative")
if (o == null) Invalid(ValidationError(errorMessage, length))
else if (o.size <= length) Valid
else Invalid(ValidationError(errorMessage, length))
}
/**
* Defines a regular expression constraint for `String` values, i.e. the string must match the regular expression pattern
*
* '''name'''[constraint.pattern(regex)] or defined by the name parameter.
* '''error'''[error.pattern(regex)] or defined by the error parameter.
*/
def pattern(
regex: => scala.util.matching.Regex,
name: String = "constraint.pattern",
error: String = "error.pattern"
): Constraint[String] = Constraint[String](name, () => regex) { o =>
require(regex != null, "regex must not be null")
require(name != null, "name must not be null")
require(error != null, "error must not be null")
if (o == null) Invalid(ValidationError(error, regex))
else regex.unapplySeq(o).map(_ => Valid).getOrElse(Invalid(ValidationError(error, name)))
}
}
/**
* A validation result.
*/
sealed trait ValidationResult
/**
* Validation was a success.
*/
case object Valid extends ValidationResult
/**
* Validation was a failure.
*
* @param errors the resulting errors
*/
case class Invalid(errors: Seq[ValidationError]) extends ValidationResult {
/**
* Combines these validation errors with another validation failure.
*
* @param other validation failure
* @return a new merged `Invalid`
*/
def ++(other: Invalid): Invalid = Invalid(this.errors ++ other.errors)
}
/**
* This object provides helper methods to construct `Invalid` values.
*/
object Invalid {
/**
* Creates an `Invalid` value with a single error.
*
* @param error the validation error
* @return an `Invalid` value
*/
def apply(error: ValidationError): Invalid = Invalid(Seq(error))
/**
* Creates an `Invalid` value with a single error.
*
* @param error the validation error message
* @param args the validation error message arguments
* @return an `Invalid` value
*/
def apply(error: String, args: Any*): Invalid = Invalid(Seq(ValidationError(error, args: _*)))
}
object ParameterValidator {
def apply[T](constraints: Iterable[Constraint[T]], optionalParam: Option[T]*) =
optionalParam.flatMap {
_.map { param =>
constraints.flatMap {
_(param) match {
case i: Invalid => Some(i)
case _ => None
}
}
}
}.flatten match {
case Nil => Valid
case invalids =>
invalids.reduceLeft { (a, b) =>
a ++ b
}
}
}
/**
* A validation error.
*
* @param messages the error message, if more then one message is passed it will use the last one
* @param args the error message arguments
*/
case class ValidationError(messages: Seq[String], args: Any*) {
lazy val message = messages.last
}
object ValidationError {
def apply(message: String, args: Any*) = new ValidationError(Seq(message), args: _*)
}

View file

@ -1,54 +0,0 @@
// Copyright (c) 2019 PSForever
package net.psforever.config
import scala.reflect.runtime.universe._
/**
* Scala [[Enumeration]] helpers implementing Scala versions of
* Java's [[java.lang.Enum.valueOf(Class[Enum], String)]].
* @author Dmitriy Yefremov (http://yefremov.net/blog/scala-enum-by-name/)
*/
object EnumReflector {
private val mirror: Mirror = runtimeMirror(getClass.getClassLoader)
/**
* Returns a value of the specified enumeration with the given name.
* @param name value name
* @tparam T enumeration type
* @return enumeration value, see [[scala.Enumeration.withName(String)]]
*/
def withName[T <: Enumeration#Value: TypeTag](name: String): T = {
typeOf[T] match {
case valueType @ TypeRef(enumType, _, _) =>
val methodSymbol = factoryMethodSymbol(enumType, "withName")
val moduleSymbol = enumType.termSymbol.asModule
reflect(moduleSymbol, methodSymbol)(name).asInstanceOf[T]
}
}
/**
* Returns the set of values of an enumeration
* @tparam T enumeration type
* @return possible enumeration values, see [[scala.Enumeration.values()]]
*/
def values[T <: Enumeration#ValueSet: TypeTag]: T = {
typeOf[T] match {
case valueType @ TypeRef(enumType, _, _) =>
val methodSymbol = factoryMethodSymbol(enumType, "values")
val moduleSymbol = enumType.termSymbol.asModule
reflect(moduleSymbol, methodSymbol)().asInstanceOf[T]
}
}
private def factoryMethodSymbol(enumType: Type, name : String): MethodSymbol = {
enumType.member(TermName(name)).asMethod
}
private def reflect(module: ModuleSymbol, method: MethodSymbol)(args: Any*): Any = {
val moduleMirror = mirror.reflectModule(module)
val instanceMirror = mirror.reflect(moduleMirror.instance)
instanceMirror.reflectMethod(method)(args:_*)
}
}

View file

@ -4,33 +4,33 @@ package net.psforever.crypto
import com.sun.jna.ptr.IntByReference
import net.psforever.IFinalizable
import sna.Library
import com.sun.jna.{NativeLibrary, Pointer}
import com.sun.jna.Pointer
import scodec.bits.ByteVector
object CryptoInterface {
final val libName = "pscrypto"
final val fullLibName = libName
final val libName = "pscrypto"
final val fullLibName = libName
final val PSCRYPTO_VERSION_MAJOR = 1
final val PSCRYPTO_VERSION_MINOR = 1
/**
NOTE: this is a single, global shared library for the entire server's crypto needs
Unfortunately, access to this object didn't used to be synchronized. I noticed that
tests for this module were hanging ("arrive at a shared secret" & "must fail to agree on
a secret..."). This heisenbug was responsible for failed Travis test runs and developer
issues as well. Using Windows minidumps, I tracked the issue to a single thread deep in
pscrypto.dll. It appeared to be executing an EB FE instruction (on Intel x86 this is
`jmp $-2` or jump to self), which is an infinite loop. The stack trace made little to no
sense and after banging my head on the wall for many hours, I assumed that something deep
in CryptoPP, the libgcc libraries, or MSVC++ was the cause (or myself). Now all access to
pscrypto functions that allocate and deallocate memory (DH_Start, RC5_Init) are synchronized.
This *appears* to have fixed the problem.
*/
* NOTE: this is a single, global shared library for the entire server's crypto needs
*
* Unfortunately, access to this object didn't used to be synchronized. I noticed that
* tests for this module were hanging ("arrive at a shared secret" & "must fail to agree on
* a secret..."). This heisenbug was responsible for failed Travis test runs and developer
* issues as well. Using Windows minidumps, I tracked the issue to a single thread deep in
* pscrypto.dll. It appeared to be executing an EB FE instruction (on Intel x86 this is
* `jmp $-2` or jump to self), which is an infinite loop. The stack trace made little to no
* sense and after banging my head on the wall for many hours, I assumed that something deep
* in CryptoPP, the libgcc libraries, or MSVC++ was the cause (or myself). Now all access to
* pscrypto functions that allocate and deallocate memory (DH_Start, RC5_Init) are synchronized.
* This *appears* to have fixed the problem.
*/
final val psLib = new Library(libName)
final val RC5_BLOCK_SIZE = 8
final val MD5_MAC_SIZE = 16
final val MD5_MAC_SIZE = 16
val functionsList = List(
"PSCrypto_Init",
@ -51,7 +51,7 @@ object CryptoInterface {
* Used to initialize the crypto library at runtime. The version is checked and
* all functions are mapped.
*/
def initialize() : Unit = {
def initialize(): Unit = {
// preload all library functions for speed
functionsList foreach psLib.prefetch
@ -60,24 +60,26 @@ object CryptoInterface {
psLib.PSCrypto_Get_Version(libraryMajor, libraryMinor)[Unit]
if(!psLib.PSCrypto_Init(PSCRYPTO_VERSION_MAJOR, PSCRYPTO_VERSION_MINOR)[Boolean]) {
throw new IllegalArgumentException(s"Invalid PSCrypto library version ${libraryMajor.getValue}.${libraryMinor.getValue}. Expected " +
s"$PSCRYPTO_VERSION_MAJOR.$PSCRYPTO_VERSION_MINOR")
if (!psLib.PSCrypto_Init(PSCRYPTO_VERSION_MAJOR, PSCRYPTO_VERSION_MINOR)[Boolean]) {
throw new IllegalArgumentException(
s"Invalid PSCrypto library version ${libraryMajor.getValue}.${libraryMinor.getValue}. Expected " +
s"$PSCRYPTO_VERSION_MAJOR.$PSCRYPTO_VERSION_MINOR"
)
}
}
/**
* Used for debugging object loading
*/
def printEnvironment() : Unit = {
* Used for debugging object loading
*/
def printEnvironment(): Unit = {
import java.io.File
val classpath = System.getProperty("java.class.path")
val classpath = System.getProperty("java.class.path")
val classpathEntries = classpath.split(File.pathSeparator)
val myLibraryPath = System.getProperty("user.dir")
val jnaLibrary = System.getProperty("jna.library.path")
val javaLibrary = System.getProperty("java.library.path")
val jnaLibrary = System.getProperty("jna.library.path")
val javaLibrary = System.getProperty("java.library.path")
println("User dir: " + myLibraryPath)
println("JNA Lib: " + jnaLibrary)
println("Java Lib: " + javaLibrary)
@ -87,13 +89,13 @@ object CryptoInterface {
println("Required data model: " + System.getProperty("sun.arch.data.model"))
}
def MD5MAC(key : ByteVector, message : ByteVector, bytesWanted : Int) : ByteVector = {
def MD5MAC(key: ByteVector, message: ByteVector, bytesWanted: Int): ByteVector = {
val out = Array.ofDim[Byte](bytesWanted)
// WARNING BUG: the function must be cast to something (even if void) otherwise it doesnt work
val ret = psLib.MD5_MAC(key.toArray, key.length, message.toArray, message.length, out, out.length)[Boolean]
if(!ret)
if (!ret)
throw new Exception("MD5MAC failed to process")
ByteVector(out)
@ -106,15 +108,15 @@ object CryptoInterface {
* @param mac1 A MAC value
* @param mac2 Another MAC value
*/
def verifyMAC(mac1 : ByteVector, mac2 : ByteVector) : Boolean = {
def verifyMAC(mac1: ByteVector, mac2: ByteVector): Boolean = {
var okay = true
// prevent byte by byte guessing
if(mac1.length != mac2.length)
if (mac1.length != mac2.length)
return false
for(i <- 0 until mac1.length.toInt) {
okay = okay && mac1{i} == mac2{i}
for (i <- 0 until mac1.length.toInt) {
okay = okay && mac1 { i } == mac2 { i }
}
okay
@ -124,22 +126,22 @@ object CryptoInterface {
var started = false
// these types MUST be Arrays of bytes for JNA to work
val privateKey = Array.ofDim[Byte](16)
val publicKey = Array.ofDim[Byte](16)
val p = Array.ofDim[Byte](16)
val g = Array.ofDim[Byte](16)
var dhHandle = Pointer.NULL
val publicKey = Array.ofDim[Byte](16)
val p = Array.ofDim[Byte](16)
val g = Array.ofDim[Byte](16)
var dhHandle = Pointer.NULL
def start(modulus : ByteVector, generator : ByteVector) : Unit = {
def start(modulus: ByteVector, generator: ByteVector): Unit = {
assertNotClosed
if(started)
if (started)
throw new IllegalStateException("DH state has already been started")
psLib.synchronized {
dhHandle = psLib.DH_Start(modulus.toArray, generator.toArray, privateKey, publicKey)[Pointer]
}
if(dhHandle == Pointer.NULL)
if (dhHandle == Pointer.NULL)
throw new Exception("DH initialization failed!")
modulus.copyToArray(p, 0)
@ -148,37 +150,37 @@ object CryptoInterface {
started = true
}
def start() : Unit = {
def start(): Unit = {
assertNotClosed
if(started)
if (started)
throw new IllegalStateException("DH state has already been started")
psLib.synchronized {
dhHandle = psLib.DH_Start_Generate(privateKey, publicKey, p, g)[Pointer]
}
if(dhHandle == Pointer.NULL)
if (dhHandle == Pointer.NULL)
throw new Exception("DH initialization failed!")
started = true
}
def agree(otherPublicKey : ByteVector) = {
if(!started)
def agree(otherPublicKey: ByteVector) = {
if (!started)
throw new IllegalStateException("DH state has not been started")
val agreedValue = Array.ofDim[Byte](16)
val agreed = psLib.DH_Agree(dhHandle, agreedValue, privateKey, otherPublicKey.toArray)[Boolean]
val agreed = psLib.DH_Agree(dhHandle, agreedValue, privateKey, otherPublicKey.toArray)[Boolean]
if(!agreed)
if (!agreed)
throw new Exception("Failed to DH agree")
ByteVector.view(agreedValue)
}
private def checkAndReturnView(array : Array[Byte]) = {
if(!started)
private def checkAndReturnView(array: Array[Byte]) = {
if (!started)
throw new IllegalStateException("DH state has not been started")
ByteVector.view(array)
@ -201,7 +203,7 @@ object CryptoInterface {
}
override def close = {
if(started) {
if (started) {
// TODO: zero private key material
psLib.synchronized {
psLib.Free_DH(dhHandle)[Unit]
@ -213,46 +215,45 @@ object CryptoInterface {
}
}
class CryptoState(val decryptionKey : ByteVector,
val encryptionKey : ByteVector) extends IFinalizable {
class CryptoState(val decryptionKey: ByteVector, val encryptionKey: ByteVector) extends IFinalizable {
// Note that the keys must be returned as primitive Arrays for JNA to work
var encCryptoHandle : Pointer = Pointer.NULL
var decCryptoHandle : Pointer = Pointer.NULL
var encCryptoHandle: Pointer = Pointer.NULL
var decCryptoHandle: Pointer = Pointer.NULL
psLib.synchronized {
encCryptoHandle = psLib.RC5_Init(encryptionKey.toArray, encryptionKey.length, true)[Pointer]
decCryptoHandle = psLib.RC5_Init(decryptionKey.toArray, decryptionKey.length, false)[Pointer]
}
if(encCryptoHandle == Pointer.NULL)
if (encCryptoHandle == Pointer.NULL)
throw new Exception("Encryption initialization failed!")
if(decCryptoHandle == Pointer.NULL)
if (decCryptoHandle == Pointer.NULL)
throw new Exception("Decryption initialization failed!")
def encrypt(plaintext : ByteVector) : ByteVector = {
if(plaintext.length % RC5_BLOCK_SIZE != 0)
def encrypt(plaintext: ByteVector): ByteVector = {
if (plaintext.length % RC5_BLOCK_SIZE != 0)
throw new IllegalArgumentException(s"input must be padded to the nearest $RC5_BLOCK_SIZE byte boundary")
val ciphertext = Array.ofDim[Byte](plaintext.length.toInt)
val ret = psLib.RC5_Encrypt(encCryptoHandle, plaintext.toArray, plaintext.length, ciphertext)[Boolean]
if(!ret)
if (!ret)
throw new Exception("Failed to encrypt plaintext")
ByteVector.view(ciphertext)
}
def decrypt(ciphertext : ByteVector) : ByteVector = {
if(ciphertext.length % RC5_BLOCK_SIZE != 0)
def decrypt(ciphertext: ByteVector): ByteVector = {
if (ciphertext.length % RC5_BLOCK_SIZE != 0)
throw new IllegalArgumentException(s"input must be padded to the nearest $RC5_BLOCK_SIZE byte boundary")
val plaintext = Array.ofDim[Byte](ciphertext.length.toInt)
val ret = psLib.RC5_Decrypt(decCryptoHandle, ciphertext.toArray, ciphertext.length, plaintext)[Boolean]
if(!ret)
if (!ret)
throw new Exception("Failed to decrypt ciphertext")
ByteVector.view(plaintext)
@ -267,17 +268,20 @@ object CryptoInterface {
}
}
class CryptoStateWithMAC(decryptionKey : ByteVector,
encryptionKey : ByteVector,
val decryptionMACKey : ByteVector,
val encryptionMACKey : ByteVector) extends CryptoState(decryptionKey, encryptionKey) {
class CryptoStateWithMAC(
decryptionKey: ByteVector,
encryptionKey: ByteVector,
val decryptionMACKey: ByteVector,
val encryptionMACKey: ByteVector
) extends CryptoState(decryptionKey, encryptionKey) {
/**
* Performs a MAC operation over the message. Used when encrypting packets
*
* @param message the input message
* @return ByteVector
*/
def macForEncrypt(message : ByteVector) : ByteVector = {
def macForEncrypt(message: ByteVector): ByteVector = {
MD5MAC(encryptionMACKey, message, MD5_MAC_SIZE)
}
@ -287,18 +291,18 @@ object CryptoInterface {
* @param message the input message
* @return ByteVector
*/
def macForDecrypt(message : ByteVector) : ByteVector = {
def macForDecrypt(message: ByteVector): ByteVector = {
MD5MAC(decryptionMACKey, message, MD5_MAC_SIZE)
}
/**
* MACs the plaintext message, encrypts it, and then returns the encrypted message with the
* MAC appended to the end.
*
*
* @param message Arbitrary set of bytes
* @return ByteVector
*/
def macAndEncrypt(message : ByteVector) : ByteVector = {
def macAndEncrypt(message: ByteVector): ByteVector = {
encrypt(message) ++ MD5MAC(encryptionMACKey, message, MD5_MAC_SIZE)
}
}

View file

@ -1,13 +1,14 @@
// Copyright (c) 2017 PSForever
package net.psforever.newcodecs
import scodec.{ Codec, SizeBound }
import scodec.Codec
import scodec.bits.BitVector
private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]) extends Codec[A] {
private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A])
extends Codec[A] {
private lazy val evaluatedCodec_true = codec_true
private lazy val evaluatedCodec_false = codec_false
override def sizeBound = if (choice) evaluatedCodec_true.sizeBound else evaluatedCodec_false.sizeBound
@ -26,6 +27,7 @@ private[newcodecs] final class BinaryChoiceCodec[A](choice: Boolean, codec_true:
evaluatedCodec_false.decode(buffer)
}
override def toString = if(choice) s"binarychoice(true, $evaluatedCodec_true, ?)" else "binarychoice(false, ?, $evaluatedCodec_false)"
override def toString =
if (choice) s"binarychoice(true, $evaluatedCodec_true, ?)" else "binarychoice(false, ?, $evaluatedCodec_false)"
}

View file

@ -4,30 +4,33 @@ package net.psforever.newcodecs
import scodec._
import scodec.bits.BitVector
final class PrefixedVectorCodec[A](firstCodec: Codec[A], codec: Codec[A], limit: Option[Int] = None) extends Codec[Vector[A]] {
final class PrefixedVectorCodec[A](firstCodec: Codec[A], codec: Codec[A], limit: Option[Int] = None)
extends Codec[Vector[A]] {
def sizeBound = limit match {
case None => SizeBound.unknown
case Some(lim) => codec.sizeBound * lim.toLong
}
def sizeBound =
limit match {
case None => SizeBound.unknown
case Some(lim) => codec.sizeBound * lim.toLong
}
def encode(vector: Vector[A]) = Encoder.encodeSeq(firstCodec)(vector.slice(0,1)).map { bits =>
def encode(vector: Vector[A]) =
Encoder.encodeSeq(firstCodec)(vector.slice(0, 1)).map { bits =>
if (vector.length > 1)
bits ++ (Encoder.encodeSeq(codec)(vector.tail) getOrElse BitVector.empty)
else
bits
}
}
def decode(buffer: BitVector) : scodec.Attempt[scodec.DecodeResult[Vector[A]]] = {
Decoder.decodeCollect[Vector, A](firstCodec, Some(1))(buffer) match {
case Attempt.Successful(firstValue) =>
Decoder.decodeCollect[Vector, A](codec, limit map { _ - 1 })(firstValue.remainder) match {
case Attempt.Successful(secondValue) =>
Attempt.successful(DecodeResult(firstValue.value ++ secondValue.value, secondValue.remainder))
case Attempt.Failure(e) => Attempt.failure(e)
}
case Attempt.Failure(e) => Attempt.failure(e)
}
def decode(buffer: BitVector): scodec.Attempt[scodec.DecodeResult[Vector[A]]] = {
Decoder.decodeCollect[Vector, A](firstCodec, Some(1))(buffer) match {
case Attempt.Successful(firstValue) =>
Decoder.decodeCollect[Vector, A](codec, limit map { _ - 1 })(firstValue.remainder) match {
case Attempt.Successful(secondValue) =>
Attempt.successful(DecodeResult(firstValue.value ++ secondValue.value, secondValue.remainder))
case Attempt.Failure(e) => Attempt.failure(e)
}
case Attempt.Failure(e) => Attempt.failure(e)
}
}
override def toString = s"vector($codec)"

View file

@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever
package net.psforever.newcodecs
import scodec.{ Attempt, Codec, DecodeResult, Err, SizeBound }
import scodec.bits.{ BitVector, ByteOrdering }
import scodec.{Attempt, Codec, DecodeResult, Err, SizeBound}
import scodec.bits.{BitVector, ByteOrdering}
final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Codec[Double] {
@ -14,14 +14,14 @@ final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Co
override def sizeBound = SizeBound.exact(bitsL)
def QuantizeDouble(value : Double) : Int = {
val range : Double = max - min;
def QuantizeDouble(value: Double): Int = {
val range: Double = max - min;
if (range == 0.0)
return 0
val bit_max : Int = 1 << bits;
val rounded_quantized : Int = math.floor((value - min) * bit_max.toDouble / range + 0.5).toInt
val bit_max: Int = 1 << bits;
val rounded_quantized: Int = math.floor((value - min) * bit_max.toDouble / range + 0.5).toInt
if (rounded_quantized < 0)
return 0
@ -32,7 +32,7 @@ final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Co
return rounded_quantized
}
def UnquantizeDouble(value : Int) : Double = {
def UnquantizeDouble(value: Int): Double = {
return ((max - min) * value.toDouble / (1 << bitsL.toInt).toDouble + min)
}
@ -42,7 +42,9 @@ final class QuantizedDoubleCodec(min: Double, max: Double, bits: Int) extends Co
override def decode(buffer: BitVector) = {
if (buffer.sizeGreaterThanOrEqual(bitsL))
Attempt.successful(DecodeResult(UnquantizeDouble(buffer.take(bitsL).toInt(false, ByteOrdering.LittleEndian)), buffer.drop(bitsL)))
Attempt.successful(
DecodeResult(UnquantizeDouble(buffer.take(bitsL).toInt(false, ByteOrdering.LittleEndian)), buffer.drop(bitsL))
)
else
Attempt.failure(Err.insufficientBits(bitsL, buffer.size))
}

View file

@ -2,23 +2,28 @@
package net.psforever.newcodecs
import scodec.Attempt
import scodec.Attempt.{Failure, Successful}
import scodec._
import scodec.bits.BitVector
package object newcodecs {
def q_double(min: Double, max: Double, bits: Int): Codec[Double] = new QuantizedDoubleCodec(min, max, bits)
def q_float(min : Double, max : Double, bits : Int): Codec[Float] = q_double(min, max, bits).narrow(v => Attempt.successful(v.toFloat), _.toDouble)
def q_float(min: Double, max: Double, bits: Int): Codec[Float] =
q_double(min, max, bits).narrow(v => Attempt.successful(v.toFloat), _.toDouble)
def binary_choice[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]): Codec[A] = new BinaryChoiceCodec(choice, codec_true, codec_false)
def binary_choice[A](choice: Boolean, codec_true: => Codec[A], codec_false: => Codec[A]): Codec[A] =
new BinaryChoiceCodec(choice, codec_true, codec_false)
def prefixedVectorOfN[A](countCodec: Codec[Int], firstValueCodec: Codec[A], valueCodec: Codec[A]): Codec[Vector[A]] =
countCodec.
flatZip { count => new PrefixedVectorCodec(firstValueCodec, valueCodec, Some(count)) }.
narrow[Vector[A]]({ case (cnt, xs) =>
if (xs.size == cnt) Attempt.successful(xs)
else Attempt.failure(Err(s"Insufficient number of elements: decoded ${xs.size} but should have decoded $cnt"))
}, xs => (xs.size, xs)).
withToString(s"vectorOfN($countCodec, $valueCodec)")
countCodec
.flatZip { count => new PrefixedVectorCodec(firstValueCodec, valueCodec, Some(count)) }
.narrow[Vector[A]](
{
case (cnt, xs) =>
if (xs.size == cnt) Attempt.successful(xs)
else
Attempt.failure(Err(s"Insufficient number of elements: decoded ${xs.size} but should have decoded $cnt"))
},
xs => (xs.size, xs)
)
.withToString(s"vectorOfN($countCodec, $valueCodec)")
}

View file

@ -1,8 +1,8 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects
class Account(private val accountId : Int, private val username : String, private val gm : Boolean = false) {
def AccountId : Int = accountId
def Username : String = username
def GM : Boolean = gm
class Account(private val accountId: Int, private val username: String, private val gm: Boolean = false) {
def AccountId: Int = accountId
def Username: String = username
def GM: Boolean = gm
}

View file

@ -5,37 +5,36 @@ import net.psforever.objects.definition.AmmoBoxDefinition
import net.psforever.objects.equipment.{Ammo, Equipment}
import net.psforever.types.PlanetSideEmpire
class AmmoBox(private val ammoDef : AmmoBoxDefinition,
cap : Option[Int] = None
) extends Equipment {
private var capacity = if(cap.isDefined) { AmmoBox.limitCapacity(cap.get, 1) } else { FullCapacity }
class AmmoBox(private val ammoDef: AmmoBoxDefinition, cap: Option[Int] = None) extends Equipment {
private var capacity = if (cap.isDefined) { AmmoBox.limitCapacity(cap.get, 1) }
else { FullCapacity }
def AmmoType : Ammo.Value = ammoDef.AmmoType
def AmmoType: Ammo.Value = ammoDef.AmmoType
def Capacity : Int = capacity
def Capacity: Int = capacity
def Capacity_=(toCapacity : Int) : Int = {
def Capacity_=(toCapacity: Int): Int = {
capacity = AmmoBox.limitCapacity(toCapacity)
Capacity
}
def FullCapacity : Int = ammoDef.Capacity
def FullCapacity: Int = ammoDef.Capacity
def Definition : AmmoBoxDefinition = ammoDef
def Definition: AmmoBoxDefinition = ammoDef
override def Faction_=(fact : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = Faction
override def Faction_=(fact: PlanetSideEmpire.Value): PlanetSideEmpire.Value = Faction
override def toString : String = {
override def toString: String = {
AmmoBox.toString(this)
}
}
object AmmoBox {
def apply(ammoDef : AmmoBoxDefinition) : AmmoBox = {
def apply(ammoDef: AmmoBoxDefinition): AmmoBox = {
new AmmoBox(ammoDef)
}
def apply(ammoDef : AmmoBoxDefinition, capacity : Int) : AmmoBox = {
def apply(ammoDef: AmmoBoxDefinition, capacity: Int): AmmoBox = {
new AmmoBox(ammoDef, Some(capacity))
}
@ -48,25 +47,25 @@ object AmmoBox {
* @param box an `AmmoBox` object of unspecified capacity
* @return a `List` of `AmmoBox` objects with correct capacities
*/
def Split(box : AmmoBox) : List[AmmoBox] = {
val ammoDef = box.Definition
val boxCap : Int = box.Capacity
val maxCap : Int = ammoDef.Capacity
val splitCap : Int = boxCap / maxCap
def Split(box: AmmoBox): List[AmmoBox] = {
val ammoDef = box.Definition
val boxCap: Int = box.Capacity
val maxCap: Int = ammoDef.Capacity
val splitCap: Int = boxCap / maxCap
box.Capacity = math.min(box.Capacity, maxCap)
val list : List[AmmoBox] = if(splitCap == 0) { Nil } else { box +: List.fill(splitCap - 1)(new AmmoBox(ammoDef)) }
val list: List[AmmoBox] = if (splitCap == 0) { Nil }
else { box +: List.fill(splitCap - 1)(new AmmoBox(ammoDef)) }
val leftover = boxCap - maxCap * splitCap
if(leftover > 0) {
if (leftover > 0) {
list :+ AmmoBox(ammoDef, leftover)
}
else {
} else {
list
}
}
def limitCapacity(count : Int, min : Int = 0) : Int = math.min(math.max(min, count), 65535)
def limitCapacity(count: Int, min: Int = 0): Int = math.min(math.max(min, count), 65535)
def toString(obj : AmmoBox) : String = {
def toString(obj: AmmoBox): String = {
s"box of ${obj.AmmoType} ammo (${obj.Capacity})"
}
}

View file

@ -10,16 +10,28 @@ import net.psforever.types._
import scala.annotation.tailrec
import scala.collection.mutable
class Avatar(private val char_id : Long, val name : String, val faction : PlanetSideEmpire.Value, val sex : CharacterGender.Value, val head : Int, val voice : CharacterVoice.Value) {
class Avatar(
private val char_id: Long,
val name: String,
val faction: PlanetSideEmpire.Value,
val sex: CharacterGender.Value,
val head: Int,
val voice: CharacterVoice.Value
) {
/** char_id, Character ID; a unique identifier corresponding to a database table row index */
/** Battle Experience Points */
private var bep : Long = 0
private var bep: Long = 0
/** Command Experience Points */
private var cep : Long = 0
/** Cosmetics **/
private var pStyle : Option[Cosmetics] = None
private var cep: Long = 0
/** Cosmetics * */
private var pStyle: Option[Cosmetics] = None
/** Certifications */
private val certs : mutable.Set[CertificationType.Value] = mutable.Set[CertificationType.Value]()
private val certs: mutable.Set[CertificationType.Value] = mutable.Set[CertificationType.Value]()
/** Implants<br>
* Unlike other objects, all `ImplantSlot` objects are already built into the `Avatar`.
* Additionally, implants do not have tightly-coupled "`Definition` objects" that explain a formal implant object.
@ -28,53 +40,60 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @see `ImplantSlot`
* @see `DetailedCharacterData.implants`
*/
private val implants : Array[ImplantSlot] = Array.fill[ImplantSlot](3)(new ImplantSlot)
private val implants: Array[ImplantSlot] = Array.fill[ImplantSlot](3)(new ImplantSlot)
/** Equipment Loadouts<br>
* 0-9 are Infantry loadouts<br>
* 10-14 are Vehicle loadouts
*/
private val equipmentLoadouts : LoadoutManager = new LoadoutManager(15)
private val equipmentLoadouts: LoadoutManager = new LoadoutManager(15)
/**
* Squad Loadouts
*/
private val squadLoadouts : LoadoutManager = new LoadoutManager(10)
private val squadLoadouts: LoadoutManager = new LoadoutManager(10)
/** Locker */
private val locker : LockerContainer = new LockerContainer() {
override def toString : String = {
private val locker: LockerContainer = new LockerContainer() {
override def toString: String = {
s"$name's ${Definition.Name}"
}
}
private val deployables : DeployableToolbox = new DeployableToolbox
private val deployables: DeployableToolbox = new DeployableToolbox
private var firstTimeEvents : List[String] = List[String]()
private var firstTimeEvents: List[String] = List[String]()
/**
* Looking For Squad:<br>
* Indicates both a player state and the text on the marquee under the player nameplate.
* Should only be valid when the player is not in a squad.
*/
private var lfs : Boolean = false
private var lfs: Boolean = false
private var vehicleOwned: Option[PlanetSideGUID] = None
private var vehicleOwned : Option[PlanetSideGUID] = None
/** key - object id<br>
* value - time last used (ms)
* */
private var lastUsedEquipmentTimes : mutable.LongMap[Long] = mutable.LongMap[Long]()
*/
private var lastUsedEquipmentTimes: mutable.LongMap[Long] = mutable.LongMap[Long]()
/** exo-suit times are sorted by `Enumeration` order, which was determined by packet process<br>
* key - exo-suit id<br>
* value - time last used (ms)
* */
private val lastUsedExoSuitTimes : Array[Long] = Array.fill[Long](ExoSuitType.values.size)(0L)
*/
private val lastUsedExoSuitTimes: Array[Long] = Array.fill[Long](ExoSuitType.values.size)(0L)
/** mechanized exo-suit times are sorted by subtype distinction, which was determined by packet process<br>
* key - subtype id<br>
* value - time last used (ms)
* */
private val lastUsedMaxExoSuitTimes : Array[Long] = Array.fill[Long](4)(0L) //invalid, ai, av, aa
*/
private val lastUsedMaxExoSuitTimes: Array[Long] = Array.fill[Long](4)(0L) //invalid, ai, av, aa
/** key - object id<br>
* value - time last acquired (from a terminal) (ms)
* */
private var lastPurchaseTimes : mutable.LongMap[Long] = mutable.LongMap[Long]()
*/
private var lastPurchaseTimes: mutable.LongMap[Long] = mutable.LongMap[Long]()
/**
* To reload purchase and use timers, a string representing the item must be produced.
* Point directly from the object id to the object definition and get the `Name` from that definition.
@ -83,29 +102,29 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* key - object id<br>
* value - most basic object definition information
*/
private val objectTypeNameReference : mutable.LongMap[String] = new mutable.LongMap[String]()
private val objectTypeNameReference: mutable.LongMap[String] = new mutable.LongMap[String]()
def CharId : Long = char_id
def CharId: Long = char_id
def BEP : Long = bep
def BEP: Long = bep
def BEP_=(battleExperiencePoints : Long) : Long = {
def BEP_=(battleExperiencePoints: Long): Long = {
bep = math.max(0L, math.min(battleExperiencePoints, 4294967295L))
BEP
}
def Certifications : mutable.Set[CertificationType.Value] = certs
def Certifications: mutable.Set[CertificationType.Value] = certs
def CEP : Long = cep
def CEP: Long = cep
def CEP_=(commandExperiencePoints : Long) : Long = {
def CEP_=(commandExperiencePoints: Long): Long = {
cep = math.max(0L, math.min(commandExperiencePoints, 4294967295L))
CEP
}
def PersonalStyleFeatures : Option[Cosmetics] = pStyle
def PersonalStyleFeatures: Option[Cosmetics] = pStyle
def PersonalStyleFeatures_=(app : Cosmetics) : Option[Cosmetics] = {
def PersonalStyleFeatures_=(app: Cosmetics): Option[Cosmetics] = {
pStyle = Some(app)
pStyle
}
@ -114,7 +133,7 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* Retrieve the three implant slots for this player.
* @return an `Array` of `ImplantSlot` objects
*/
def Implants : Array[ImplantSlot] = implants
def Implants: Array[ImplantSlot] = implants
/**
* What kind of implant is installed into the given slot number?
@ -122,8 +141,9 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @param slot the slot number
* @return the tye of implant
*/
def Implant(slot : Int) : ImplantType.Value = {
if(-1 < slot && slot < implants.length) { implants(slot).Implant } else { ImplantType.None }
def Implant(slot: Int): ImplantType.Value = {
if (-1 < slot && slot < implants.length) { implants(slot).Implant }
else { ImplantType.None }
}
/**
@ -136,8 +156,9 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @param implant the implant being installed
* @return the index of the `ImplantSlot` where the implant was installed
*/
def InstallImplant(implant : ImplantDefinition) : Option[Int] = {
implants.find({p => p.Installed.contains(implant) || p.Implant == implant.Type}) match { //try to find the installed implant
def InstallImplant(implant: ImplantDefinition): Option[Int] = {
implants
.find({ p => p.Installed.contains(implant) || p.Implant == implant.Type }) match { //try to find the installed implant
case None =>
recursiveFindImplantInSlot(implants.iterator, ImplantType.None) match { //install in a free slot
case Some(slot) =>
@ -164,7 +185,7 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @param implantType the type of implant being uninstalled
* @return the index of the `ImplantSlot` where the implant was found and uninstalled
*/
def UninstallImplant(implantType : ImplantType.Value) : Option[Int] = {
def UninstallImplant(implantType: ImplantType.Value): Option[Int] = {
recursiveFindImplantInSlot(implants.iterator, implantType) match {
case Some(slot) =>
implants(slot).Implant = None
@ -183,22 +204,24 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
* @param index a defaulted index value representing the structure underlying the `Iterator` param
* @return the index where the target implant is installed
*/
@tailrec private def recursiveFindImplantInSlot(iter : Iterator[ImplantSlot], implantType : ImplantType.Value, index : Int = 0) : Option[Int] = {
if(!iter.hasNext) {
@tailrec private def recursiveFindImplantInSlot(
iter: Iterator[ImplantSlot],
implantType: ImplantType.Value,
index: Int = 0
): Option[Int] = {
if (!iter.hasNext) {
None
}
else {
} else {
val slot = iter.next
if(slot.Unlocked && slot.Implant == implantType) {
if (slot.Unlocked && slot.Implant == implantType) {
Some(index)
}
else {
} else {
recursiveFindImplantInSlot(iter, implantType, index + 1)
}
}
}
def ResetAllImplants() : Unit = {
def ResetAllImplants(): Unit = {
implants.foreach(slot => {
slot.Installed match {
case Some(_) =>
@ -210,111 +233,110 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
})
}
def EquipmentLoadouts : LoadoutManager = equipmentLoadouts
def EquipmentLoadouts: LoadoutManager = equipmentLoadouts
def SquadLoadouts : LoadoutManager = squadLoadouts
def SquadLoadouts: LoadoutManager = squadLoadouts
def Locker : LockerContainer = locker
def Locker: LockerContainer = locker
def FifthSlot : EquipmentSlot = {
def FifthSlot: EquipmentSlot = {
new OffhandEquipmentSlot(EquipmentSize.Inventory) {
val obj = new LockerEquipment(locker)
Equipment = obj
}
}
def Deployables : DeployableToolbox = deployables
def Deployables: DeployableToolbox = deployables
def FirstTimeEvents : List[String] = firstTimeEvents
def FirstTimeEvents: List[String] = firstTimeEvents
def FirstTimeEvents_=(event : String) : List[String] = FirstTimeEvents_=(List(event))
def FirstTimeEvents_=(event: String): List[String] = FirstTimeEvents_=(List(event))
def FirstTimeEvents_=(events : List[String]) : List[String] = {
def FirstTimeEvents_=(events: List[String]): List[String] = {
firstTimeEvents ++= events
FirstTimeEvents
}
def LFS : Boolean = lfs
def LFS: Boolean = lfs
def LFS_=(looking : Boolean) : Boolean = {
def LFS_=(looking: Boolean): Boolean = {
lfs = looking
LFS
}
def VehicleOwned : Option[PlanetSideGUID] = vehicleOwned
def VehicleOwned: Option[PlanetSideGUID] = vehicleOwned
def VehicleOwned_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = VehicleOwned_=(Some(guid))
def VehicleOwned_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = VehicleOwned_=(Some(guid))
def VehicleOwned_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
def VehicleOwned_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
vehicleOwned = guid
VehicleOwned
}
def GetLastUsedTime(code : Int) : Long = {
def GetLastUsedTime(code: Int): Long = {
lastUsedEquipmentTimes.get(code) match {
case Some(time) => time
case None => 0
case None => 0
}
}
def GetLastUsedTime(code : ExoSuitType.Value) : Long = {
def GetLastUsedTime(code: ExoSuitType.Value): Long = {
lastUsedExoSuitTimes(code.id)
}
def GetLastUsedTime(code : ExoSuitType.Value, subtype : Int) : Long = {
if(code == ExoSuitType.MAX) {
def GetLastUsedTime(code: ExoSuitType.Value, subtype: Int): Long = {
if (code == ExoSuitType.MAX) {
lastUsedMaxExoSuitTimes(subtype)
}
else {
} else {
GetLastUsedTime(code)
}
}
def GetAllLastUsedTimes : Map[Long, Long] = lastUsedEquipmentTimes.toMap
def GetAllLastUsedTimes: Map[Long, Long] = lastUsedEquipmentTimes.toMap
def SetLastUsedTime(code : Int, time : Long) : Unit = {
def SetLastUsedTime(code: Int, time: Long): Unit = {
lastUsedEquipmentTimes += code.toLong -> time
}
def SetLastUsedTime(code : ExoSuitType.Value) : Unit = SetLastUsedTime(code, System.currentTimeMillis())
def SetLastUsedTime(code: ExoSuitType.Value): Unit = SetLastUsedTime(code, System.currentTimeMillis())
def SetLastUsedTime(code : ExoSuitType.Value, time : Long) : Unit = {
def SetLastUsedTime(code: ExoSuitType.Value, time: Long): Unit = {
lastUsedExoSuitTimes(code.id) = time
}
def SetLastUsedTime(code : ExoSuitType.Value, subtype : Int, time : Long) : Unit = {
if(code == ExoSuitType.MAX) {
def SetLastUsedTime(code: ExoSuitType.Value, subtype: Int, time: Long): Unit = {
if (code == ExoSuitType.MAX) {
lastUsedMaxExoSuitTimes(subtype) = time
}
SetLastUsedTime(code, time)
}
def GetLastPurchaseTime(code : Int) : Long = {
def GetLastPurchaseTime(code: Int): Long = {
lastPurchaseTimes.get(code) match {
case Some(time) => time
case None => 0
case None => 0
}
}
def GetAllLastPurchaseTimes : Map[Long, Long] = lastPurchaseTimes.toMap
def GetAllLastPurchaseTimes: Map[Long, Long] = lastPurchaseTimes.toMap
def SetLastPurchaseTime(code : Int, time : Long) : Unit = {
def SetLastPurchaseTime(code: Int, time: Long): Unit = {
lastPurchaseTimes += code.toLong -> time
}
def ObjectTypeNameReference(id : Long) : String = {
def ObjectTypeNameReference(id: Long): String = {
objectTypeNameReference.get(id) match {
case Some(objectName) => objectName
case None => ""
case None => ""
}
}
def ObjectTypeNameReference(id : Long, name : String) : String = {
def ObjectTypeNameReference(id: Long, name: String): String = {
objectTypeNameReference(id) = name
name
}
def Definition : AvatarDefinition = GlobalDefinitions.avatar
def Definition: AvatarDefinition = GlobalDefinitions.avatar
/*
Merit Commendations and Ribbons
@ -326,19 +348,20 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
def canEqual(other: Any): Boolean = other.isInstanceOf[Avatar]
override def equals(other : Any) : Boolean = other match {
case that: Avatar =>
(that canEqual this) &&
name == that.name &&
faction == that.faction &&
sex == that.sex &&
head == that.head &&
voice == that.voice
case _ =>
false
}
override def equals(other: Any): Boolean =
other match {
case that: Avatar =>
(that canEqual this) &&
name == that.name &&
faction == that.faction &&
sex == that.sex &&
head == that.head &&
voice == that.voice
case _ =>
false
}
override def hashCode() : Int = {
override def hashCode(): Int = {
val state = Seq(name, faction, sex, head, voice)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
@ -347,9 +370,15 @@ class Avatar(private val char_id : Long, val name : String, val faction : Planet
}
object Avatar {
def apply(name : String, faction : PlanetSideEmpire.Value, sex : CharacterGender.Value, head : Int, voice : CharacterVoice.Value) : Avatar = {
def apply(
name: String,
faction: PlanetSideEmpire.Value,
sex: CharacterGender.Value,
head: Int,
voice: CharacterVoice.Value
): Avatar = {
new Avatar(0L, name, faction, sex, head, voice)
}
def toString(avatar : Avatar) : String = s"${avatar.faction} ${avatar.name}"
def toString(avatar: Avatar): String = s"${avatar.faction} ${avatar.name}"
}

View file

@ -1,20 +1,20 @@
// Copyright (c) 2017 PSForever
package net.psforever.objects
class BoomerDeployable(cdef : ExplosiveDeployableDefinition) extends ExplosiveDeployable(cdef) {
private var trigger : Option[BoomerTrigger] = None
class BoomerDeployable(cdef: ExplosiveDeployableDefinition) extends ExplosiveDeployable(cdef) {
private var trigger: Option[BoomerTrigger] = None
def Trigger : Option[BoomerTrigger] = trigger
def Trigger: Option[BoomerTrigger] = trigger
def Trigger_=(item : BoomerTrigger) : Option[BoomerTrigger] = {
if(trigger.isEmpty) { //can only set trigger once
def Trigger_=(item: BoomerTrigger): Option[BoomerTrigger] = {
if (trigger.isEmpty) { //can only set trigger once
trigger = Some(item)
}
Trigger
}
def Trigger_=(item : Option[BoomerTrigger]) : Option[BoomerTrigger] = {
if(item.isEmpty) {
def Trigger_=(item: Option[BoomerTrigger]): Option[BoomerTrigger] = {
if (item.isEmpty) {
trigger = None
}
Trigger

View file

@ -5,5 +5,5 @@ import net.psforever.objects.equipment.RemoteUnit
import net.psforever.types.PlanetSideEmpire
class BoomerTrigger extends SimpleItem(GlobalDefinitions.boomer_trigger) with RemoteUnit {
override def Faction_=(fact : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = Faction
override def Faction_=(fact: PlanetSideEmpire.Value): PlanetSideEmpire.Value = Faction
}

View file

@ -20,47 +20,48 @@ import net.psforever.types.CertificationType
* indicate whether the current output product is something the player is permitted to utilize.
* @param cItemDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
*/
class ConstructionItem(private val cItemDef : ConstructionItemDefinition) extends Equipment
with FireModeSwitch[ConstructionFireMode] {
private var fireModeIndex : Int = 0
private var ammoTypeIndex : Int = 0
class ConstructionItem(private val cItemDef: ConstructionItemDefinition)
extends Equipment
with FireModeSwitch[ConstructionFireMode] {
private var fireModeIndex: Int = 0
private var ammoTypeIndex: Int = 0
def FireModeIndex : Int = fireModeIndex
def FireModeIndex: Int = fireModeIndex
def FireModeIndex_=(index : Int) : Int = {
def FireModeIndex_=(index: Int): Int = {
fireModeIndex = index % Definition.Modes.length
FireModeIndex
}
def FireMode : ConstructionFireMode = Definition.Modes(fireModeIndex)
def FireMode: ConstructionFireMode = Definition.Modes(fireModeIndex)
def NextFireMode : ConstructionFireMode = {
def NextFireMode: ConstructionFireMode = {
FireModeIndex = FireModeIndex + 1
ammoTypeIndex = 0
FireMode
}
def AmmoTypeIndex : Int = ammoTypeIndex
def AmmoTypeIndex: Int = ammoTypeIndex
def AmmoTypeIndex_=(index : Int) : Int = {
def AmmoTypeIndex_=(index: Int): Int = {
ammoTypeIndex = index % FireMode.Deployables.length
AmmoTypeIndex
}
def AmmoType : DeployedItem.Value = FireMode.Deployables(ammoTypeIndex)
def AmmoType: DeployedItem.Value = FireMode.Deployables(ammoTypeIndex)
def NextAmmoType : DeployedItem.Value = {
def NextAmmoType: DeployedItem.Value = {
AmmoTypeIndex = AmmoTypeIndex + 1
FireMode.Deployables(ammoTypeIndex)
}
def ModePermissions : Set[CertificationType.Value] = FireMode.Permissions(ammoTypeIndex)
def ModePermissions: Set[CertificationType.Value] = FireMode.Permissions(ammoTypeIndex)
def Definition : ConstructionItemDefinition = cItemDef
def Definition: ConstructionItemDefinition = cItemDef
}
object ConstructionItem {
def apply(cItemDef : ConstructionItemDefinition) : ConstructionItem = {
def apply(cItemDef: ConstructionItemDefinition): ConstructionItem = {
new ConstructionItem(cItemDef)
}
}

View file

@ -5,20 +5,21 @@ object Default {
//cancellable
import akka.actor.Cancellable
protected class InternalCancellable extends Cancellable {
override def cancel : Boolean = true
override def isCancelled : Boolean = true
override def cancel: Boolean = true
override def isCancelled: Boolean = true
}
private val cancellable : Cancellable = new InternalCancellable
private val cancellable: Cancellable = new InternalCancellable
/**
* Used to initialize the value of a re-usable `Cancellable` object.
* By convention, it always acts like it has been cancelled before and can be cancelled.
* Should be replaced with pertinent `Cancellable` logic through the initialization of an executor.
*/
final def Cancellable : Cancellable = cancellable
final def Cancellable: Cancellable = cancellable
//actor
import akka.actor.{Actor => AkkaActor, ActorRef, ActorSystem, DeadLetter, Props}
/**
* An actor designed to wrap around `deadLetters` and redirect all normal messages to it.
* This measure is more to "protect" `deadLetters` than anything else.
@ -26,22 +27,23 @@ object Default {
* The original target to which the actor is assigned will not be implicitly accredited.
*/
private class DefaultActor extends AkkaActor {
def receive : Receive = {
def receive: Receive = {
case msg => context.system.deadLetters ! DeadLetter(msg, sender, self)
}
}
private var defaultRef : ActorRef = ActorRef.noSender
private var defaultRef: ActorRef = ActorRef.noSender
/**
* Instigate the default actor.
* @param sys the actor universe under which this default actor will exist
* @return the new default actor
*/
def apply(sys : ActorSystem) : ActorRef = {
if(defaultRef == ActorRef.noSender) {
def apply(sys: ActorSystem): ActorRef = {
if (defaultRef == ActorRef.noSender) {
defaultRef = sys.actorOf(Props[DefaultActor], name = s"system-default-actor")
}
defaultRef
}
final def Actor : ActorRef = defaultRef
final def Actor: ActorRef = defaultRef
}

View file

@ -16,26 +16,36 @@ object Deployables {
private val log = org.log4s.getLogger("Deployables")
object Make {
def apply(item : DeployedItem.Value) : ()=>PlanetSideGameObject with Deployable = cemap(item)
def apply(item: DeployedItem.Value): () => PlanetSideGameObject with Deployable = cemap(item)
private val cemap : Map[DeployedItem.Value, ()=>PlanetSideGameObject with Deployable] = Map(
DeployedItem.boomer -> { ()=> new BoomerDeployable(GlobalDefinitions.boomer) },
DeployedItem.he_mine -> { ()=> new ExplosiveDeployable(GlobalDefinitions.he_mine) },
DeployedItem.jammer_mine -> { ()=> new ExplosiveDeployable(GlobalDefinitions.jammer_mine) },
DeployedItem.spitfire_turret -> { ()=> new TurretDeployable(GlobalDefinitions.spitfire_turret) },
DeployedItem.spitfire_cloaked -> { ()=> new TurretDeployable(GlobalDefinitions.spitfire_cloaked) },
DeployedItem.spitfire_aa -> { ()=> new TurretDeployable(GlobalDefinitions.spitfire_aa) },
DeployedItem.motionalarmsensor -> { ()=> new SensorDeployable(GlobalDefinitions.motionalarmsensor) },
DeployedItem.sensor_shield -> { ()=> new SensorDeployable(GlobalDefinitions.sensor_shield) },
DeployedItem.tank_traps -> { ()=> new TrapDeployable(GlobalDefinitions.tank_traps) },
DeployedItem.portable_manned_turret -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
DeployedItem.portable_manned_turret -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
DeployedItem.portable_manned_turret_nc -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_nc) },
DeployedItem.portable_manned_turret_tr -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr) },
DeployedItem.portable_manned_turret_vs -> { ()=> new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs) },
DeployedItem.deployable_shield_generator -> { ()=> new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator) },
DeployedItem.router_telepad_deployable -> { () => new TelepadDeployable(GlobalDefinitions.router_telepad_deployable) }
).withDefaultValue( { ()=> new ExplosiveDeployable(GlobalDefinitions.boomer) } )
private val cemap: Map[DeployedItem.Value, () => PlanetSideGameObject with Deployable] = Map(
DeployedItem.boomer -> { () => new BoomerDeployable(GlobalDefinitions.boomer) },
DeployedItem.he_mine -> { () => new ExplosiveDeployable(GlobalDefinitions.he_mine) },
DeployedItem.jammer_mine -> { () => new ExplosiveDeployable(GlobalDefinitions.jammer_mine) },
DeployedItem.spitfire_turret -> { () => new TurretDeployable(GlobalDefinitions.spitfire_turret) },
DeployedItem.spitfire_cloaked -> { () => new TurretDeployable(GlobalDefinitions.spitfire_cloaked) },
DeployedItem.spitfire_aa -> { () => new TurretDeployable(GlobalDefinitions.spitfire_aa) },
DeployedItem.motionalarmsensor -> { () => new SensorDeployable(GlobalDefinitions.motionalarmsensor) },
DeployedItem.sensor_shield -> { () => new SensorDeployable(GlobalDefinitions.sensor_shield) },
DeployedItem.tank_traps -> { () => new TrapDeployable(GlobalDefinitions.tank_traps) },
DeployedItem.portable_manned_turret -> { () => new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
DeployedItem.portable_manned_turret -> { () => new TurretDeployable(GlobalDefinitions.portable_manned_turret) },
DeployedItem.portable_manned_turret_nc -> { () =>
new TurretDeployable(GlobalDefinitions.portable_manned_turret_nc)
},
DeployedItem.portable_manned_turret_tr -> { () =>
new TurretDeployable(GlobalDefinitions.portable_manned_turret_tr)
},
DeployedItem.portable_manned_turret_vs -> { () =>
new TurretDeployable(GlobalDefinitions.portable_manned_turret_vs)
},
DeployedItem.deployable_shield_generator -> { () =>
new ShieldGeneratorDeployable(GlobalDefinitions.deployable_shield_generator)
},
DeployedItem.router_telepad_deployable -> { () =>
new TelepadDeployable(GlobalDefinitions.router_telepad_deployable)
}
).withDefaultValue({ () => new ExplosiveDeployable(GlobalDefinitions.boomer) })
}
/**
@ -60,7 +70,7 @@ object Deployables {
* @param time length of time that the deployable is allowed to exist in the game world;
* `None` indicates the normal un-owned existence time (180 seconds)
*/
def AnnounceDestroyDeployable(target : PlanetSideGameObject with Deployable, time : Option[FiniteDuration]) : Unit = {
def AnnounceDestroyDeployable(target: PlanetSideGameObject with Deployable, time: Option[FiniteDuration]): Unit = {
val zone = target.Zone
target.OwnerName match {
case Some(owner) =>
@ -68,10 +78,13 @@ object Deployables {
zone.LocalEvents ! LocalServiceMessage(owner, LocalAction.AlertDestroyDeployable(PlanetSideGUID(0), target))
case None => ;
}
zone.LocalEvents ! LocalServiceMessage(s"${target.Faction}", LocalAction.DeployableMapIcon(
PlanetSideGUID(0),
DeploymentAction.Dismiss,
DeployableInfo(target.GUID, Deployable.Icon(target.Definition.Item), target.Position, PlanetSideGUID(0)))
zone.LocalEvents ! LocalServiceMessage(
s"${target.Faction}",
LocalAction.DeployableMapIcon(
PlanetSideGUID(0),
DeploymentAction.Dismiss,
DeployableInfo(target.GUID, Deployable.Icon(target.Definition.Item), target.Position, PlanetSideGUID(0))
)
)
zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(target), zone))
zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.AddTask(target, zone, time))
@ -86,17 +99,22 @@ object Deployables {
* @return all previously-owned deployables after they have been processed;
* boomers are listed before all other deployable types
*/
def Disown(zone : Zone, avatar : Avatar, replyTo : ActorRef) : List[PlanetSideGameObject with Deployable] = {
def Disown(zone: Zone, avatar: Avatar, replyTo: ActorRef): List[PlanetSideGameObject with Deployable] = {
val (boomers, deployables) =
avatar.Deployables.Clear()
avatar.Deployables
.Clear()
.map(zone.GUID)
.collect { case Some(obj) => obj.asInstanceOf[PlanetSideGameObject with Deployable] }
.partition(_.isInstanceOf[BoomerDeployable])
//do not change the OwnerName field at this time
boomers.collect({ case obj : BoomerDeployable =>
zone.LocalEvents.tell(LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, zone, Some(0 seconds))), replyTo) //near-instant
obj.Owner = None
obj.Trigger = None
boomers.collect({
case obj: BoomerDeployable =>
zone.LocalEvents.tell(
LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, zone, Some(0 seconds))),
replyTo
) //near-instant
obj.Owner = None
obj.Trigger = None
})
deployables.foreach(obj => {
zone.LocalEvents.tell(LocalServiceMessage.Deployables(RemoverActor.AddTask(obj, zone)), replyTo) //normal decay
@ -105,17 +123,17 @@ object Deployables {
boomers ++ deployables
}
def RemoveTelepad(vehicle: Vehicle) : Unit = {
def RemoveTelepad(vehicle: Vehicle): Unit = {
val zone = vehicle.Zone
(vehicle.Utility(UtilityType.internal_router_telepad_deployable) match {
case Some(util : Utility.InternalTelepad) =>
case Some(util: Utility.InternalTelepad) =>
val telepad = util.Telepad
util.Telepad = None
zone.GUID(telepad)
case _ =>
None
}) match {
case Some(telepad : TelepadDeployable) =>
case Some(telepad: TelepadDeployable) =>
log.info(s"BeforeUnload: deconstructing telepad $telepad that was linked to router $vehicle ...")
telepad.Active = false
zone.LocalEvents ! LocalServiceMessage.Deployables(RemoverActor.ClearSpecific(List(telepad), zone))
@ -124,13 +142,11 @@ object Deployables {
}
}
/**
* Initialize the deployables backend information.
* @param avatar the player's core
*/
def InitializeDeployableQuantities(avatar : Avatar) : Boolean = {
def InitializeDeployableQuantities(avatar: Avatar): Boolean = {
log.info("Setting up combat engineering ...")
avatar.Deployables.Initialize(avatar.Certifications.toSet)
}
@ -139,7 +155,7 @@ object Deployables {
* Initialize the UI elements for deployables.
* @param avatar the player's core
*/
def InitializeDeployableUIElements(avatar : Avatar) : List[(Int,Int,Int,Int)] = {
def InitializeDeployableUIElements(avatar: Avatar): List[(Int, Int, Int, Int)] = {
log.info("Setting up combat engineering UI ...")
avatar.Deployables.UpdateUI()
}
@ -151,7 +167,11 @@ object Deployables {
* @param certification the certification that was added
* @param certificationSet all applicable certifications
*/
def AddToDeployableQuantities(avatar : Avatar, certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : List[(Int,Int,Int,Int)] = {
def AddToDeployableQuantities(
avatar: Avatar,
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): List[(Int, Int, Int, Int)] = {
avatar.Deployables.AddToDeployableQuantities(certification, certificationSet)
avatar.Deployables.UpdateUI(certification)
}
@ -163,7 +183,11 @@ object Deployables {
* @param certification the certification that was added
* @param certificationSet all applicable certifications
*/
def RemoveFromDeployableQuantities(avatar : Avatar, certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : List[(Int,Int,Int,Int)] = {
def RemoveFromDeployableQuantities(
avatar: Avatar,
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): List[(Int, Int, Int, Int)] = {
avatar.Deployables.RemoveFromDeployableQuantities(certification, certificationSet)
avatar.Deployables.UpdateUI(certification)
}

View file

@ -18,61 +18,60 @@ import services.local.{LocalAction, LocalServiceMessage}
import scala.concurrent.duration._
class ExplosiveDeployable(cdef : ExplosiveDeployableDefinition) extends ComplexDeployable(cdef)
with JammableUnit {
class ExplosiveDeployable(cdef: ExplosiveDeployableDefinition) extends ComplexDeployable(cdef) with JammableUnit {
override def Definition : ExplosiveDeployableDefinition = cdef
override def Definition: ExplosiveDeployableDefinition = cdef
}
class ExplosiveDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId) {
class ExplosiveDeployableDefinition(private val objectId: Int) extends ComplexDeployableDefinition(objectId) {
Name = "explosive_deployable"
DeployCategory = DeployableCategory.Mines
Model = StandardResolutions.SimpleDeployables
Packet = new SmallDeployableConverter
private var detonateOnJamming : Boolean = true
private var detonateOnJamming: Boolean = true
def DetonateOnJamming : Boolean = detonateOnJamming
def DetonateOnJamming: Boolean = detonateOnJamming
def DetonateOnJamming_=(detonate : Boolean) : Boolean = {
def DetonateOnJamming_=(detonate: Boolean): Boolean = {
detonateOnJamming = detonate
DetonateOnJamming
}
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[ExplosiveDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor =
context.actorOf(Props(classOf[ExplosiveDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
}
}
object ExplosiveDeployableDefinition {
def apply(dtype : DeployedItem.Value) : ExplosiveDeployableDefinition = {
def apply(dtype: DeployedItem.Value): ExplosiveDeployableDefinition = {
new ExplosiveDeployableDefinition(dtype.id)
}
}
class ExplosiveDeployableControl(mine : ExplosiveDeployable) extends Actor
with Damageable {
class ExplosiveDeployableControl(mine: ExplosiveDeployable) extends Actor with Damageable {
def DamageableObject = mine
def receive : Receive = takesDamage
.orElse {
case _ => ;
}
def receive: Receive =
takesDamage
.orElse {
case _ => ;
}
protected def TakesDamage : Receive = {
protected def TakesDamage: Receive = {
case Vitality.Damage(applyDamageTo) =>
if(mine.CanDamage) {
if (mine.CanDamage) {
val originalHealth = mine.Health
val cause = applyDamageTo(mine)
val damage = originalHealth - mine.Health
if(Damageable.CanDamageOrJammer(mine, damage, cause)) {
val cause = applyDamageTo(mine)
val damage = originalHealth - mine.Health
if (Damageable.CanDamageOrJammer(mine, damage, cause)) {
ExplosiveDeployableControl.DamageResolution(mine, cause, damage)
}
else {
} else {
mine.Health = originalHealth
}
}
@ -80,17 +79,18 @@ class ExplosiveDeployableControl(mine : ExplosiveDeployable) extends Actor
}
object ExplosiveDeployableControl {
def DamageResolution(target : ExplosiveDeployable, cause : ResolvedProjectile, damage : Int) : Unit = {
def DamageResolution(target: ExplosiveDeployable, cause: ResolvedProjectile, damage: Int): Unit = {
target.History(cause)
if(target.Health == 0) {
if (target.Health == 0) {
DestructionAwareness(target, cause)
}
else if(!target.Jammed && Damageable.CanJammer(target, cause)) {
if(target.Jammed = {
val radius = cause.projectile.profile.DamageRadius
Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius
}) {
if(target.Definition.DetonateOnJamming) {
} else if (!target.Jammed && Damageable.CanJammer(target, cause)) {
if (
target.Jammed = {
val radius = cause.projectile.profile.DamageRadius
Vector3.DistanceSquared(cause.hit_pos, cause.target.Position) < radius * radius
}
) {
if (target.Definition.DetonateOnJamming) {
val zone = target.Zone
zone.Activity ! Zone.HotSpot.Activity(cause.target, cause.projectile.owner, cause.hit_pos)
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.Detonate(target.GUID, target))
@ -105,17 +105,23 @@ object ExplosiveDeployableControl {
* @param target na
* @param cause na
*/
def DestructionAwareness(target : ExplosiveDeployable, cause : ResolvedProjectile) : Unit = {
def DestructionAwareness(target: ExplosiveDeployable, cause: ResolvedProjectile): Unit = {
val zone = target.Zone
val attribution = zone.LivePlayers.find { p => cause.projectile.owner.Name.equals(p.Name) } match {
case Some(player) => player.GUID
case _ => PlanetSideGUID(0)
case _ => PlanetSideGUID(0)
}
target.Destroyed = true
Deployables.AnnounceDestroyDeployable(target, Some(if(target.Jammed) 0 seconds else 500 milliseconds))
zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.Destroy(target.GUID, attribution, Service.defaultPlayerGUID, target.Position))
if(target.Health == 0) {
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerEffect(Service.defaultPlayerGUID, "detonate_damaged_mine", target.GUID))
Deployables.AnnounceDestroyDeployable(target, Some(if (target.Jammed) 0 seconds else 500 milliseconds))
zone.AvatarEvents ! AvatarServiceMessage(
zone.Id,
AvatarAction.Destroy(target.GUID, attribution, Service.defaultPlayerGUID, target.Position)
)
if (target.Health == 0) {
zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerEffect(Service.defaultPlayerGUID, "detonate_damaged_mine", target.GUID)
)
}
}
}

View file

@ -14,61 +14,68 @@ import net.psforever.types.{ExoSuitType, ImplantType}
* Being jammed de-activates the implant, put it into a state of "not being ready," and causes the initialization to repeat.
*/
class ImplantSlot {
/** is this slot available for holding an implant */
private var unlocked : Boolean = false
private var unlocked: Boolean = false
/** whether this implant is ready for use */
private var initialized : Boolean = false
/** */
private var initializeTime : Long = 0L
private var initialized: Boolean = false
/**
*/
private var initializeTime: Long = 0L
/** is this implant active */
private var active : Boolean = false
private var active: Boolean = false
/** what implant is currently installed in this slot; None if there is no implant currently installed */
private var implant : Option[ImplantDefinition] = None
private var implant: Option[ImplantDefinition] = None
def InitializeTime : Long = initializeTime
def InitializeTime: Long = initializeTime
def InitializeTime_=(time : Long) : Long = {
def InitializeTime_=(time: Long): Long = {
initializeTime = time
InitializeTime
}
def Unlocked : Boolean = unlocked
def Unlocked: Boolean = unlocked
def Unlocked_=(lock : Boolean) : Boolean = {
def Unlocked_=(lock: Boolean): Boolean = {
unlocked = lock || unlocked //do not let re-lock
Unlocked
}
def Initialized : Boolean = initialized
def Initialized: Boolean = initialized
def Initialized_=(init : Boolean) : Boolean = {
def Initialized_=(init: Boolean): Boolean = {
initialized = Installed.isDefined && init
Active = Active && initialized //can not be active just yet
Initialized
}
def Active : Boolean = active
def Active: Boolean = active
def Active_=(state : Boolean) : Boolean = {
def Active_=(state: Boolean): Boolean = {
active = Initialized && state
Active
}
def Implant : ImplantType.Value = Installed match {
case Some(idef) =>
idef.Type
case None =>
Active = false
Initialized = false
ImplantType.None
}
def Implant: ImplantType.Value =
Installed match {
case Some(idef) =>
idef.Type
case None =>
Active = false
Initialized = false
ImplantType.None
}
def Implant_=(anImplant : ImplantDefinition) : ImplantType.Value = {
def Implant_=(anImplant: ImplantDefinition): ImplantType.Value = {
Implant_=(Some(anImplant))
}
def Implant_=(anImplant : Option[ImplantDefinition]) : ImplantType.Value = {
if(Unlocked) {
def Implant_=(anImplant: Option[ImplantDefinition]): ImplantType.Value = {
if (Unlocked) {
anImplant match {
case Some(_) =>
implant = anImplant
@ -81,20 +88,20 @@ class ImplantSlot {
Implant
}
def Installed : Option[ImplantDefinition] = implant
def Installed: Option[ImplantDefinition] = implant
def MaxTimer : Long = Implant match {
case ImplantType.None =>
-1L
case _ =>
Installed.get.InitializationDuration
}
def ActivationCharge : Int = {
if(Active) {
Installed.get.ActivationStaminaCost
def MaxTimer: Long =
Implant match {
case ImplantType.None =>
-1L
case _ =>
Installed.get.InitializationDuration
}
else {
def ActivationCharge: Int = {
if (Active) {
Installed.get.ActivationStaminaCost
} else {
0
}
}
@ -104,24 +111,23 @@ class ImplantSlot {
* @param suit the exo-suit being worn
* @return the amount of stamina (energy) that is consumed
*/
def Charge(suit : ExoSuitType.Value) : Int = {
if(Active) {
def Charge(suit: ExoSuitType.Value): Int = {
if (Active) {
val inst = Installed.get
inst.StaminaCost
}
else {
} else {
0
}
}
def Jammed() : Unit = {
def Jammed(): Unit = {
Active = false
Initialized = false
}
}
object ImplantSlot {
def apply() : ImplantSlot = {
def apply(): ImplantSlot = {
new ImplantSlot()
}
}

View file

@ -8,12 +8,12 @@ import net.psforever.objects.equipment.Equipment
* A one-time-use recovery item that can be applied by the player while held within their inventory.
* @param kitDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
*/
class Kit(private val kitDef : KitDefinition) extends Equipment {
def Definition : KitDefinition = kitDef
class Kit(private val kitDef: KitDefinition) extends Equipment {
def Definition: KitDefinition = kitDef
}
object Kit {
def apply(kitDef : KitDefinition) : Kit = {
def apply(kitDef: KitDefinition): Kit = {
new Kit(kitDef)
}
}

View file

@ -8,14 +8,15 @@ import scala.collection.concurrent.{Map, TrieMap}
* `LivePlayerList` is a singleton and this private class lacks exposure.
*/
private class LivePlayerList {
/** key - the session id; value - a `Player` object */
private val sessionMap : Map[Long, Avatar] = new TrieMap[Long, Avatar]
def WorldPopulation(predicate : ((_, Avatar)) => Boolean) : List[Avatar] = {
/** key - the session id; value - a `Player` object */
private val sessionMap: Map[Long, Avatar] = new TrieMap[Long, Avatar]
def WorldPopulation(predicate: ((_, Avatar)) => Boolean): List[Avatar] = {
sessionMap.filter(predicate).values.toList
}
def Add(sessionId : Long, avatar : Avatar) : Boolean = {
def Add(sessionId: Long, avatar: Avatar): Boolean = {
sessionMap.values.find(char => char.equals(avatar)) match {
case None =>
sessionMap.putIfAbsent(sessionId, avatar).isEmpty
@ -24,11 +25,11 @@ private class LivePlayerList {
}
}
def Remove(sessionId : Long) : Option[Avatar] = {
def Remove(sessionId: Long): Option[Avatar] = {
sessionMap.remove(sessionId)
}
def Shutdown : List[Avatar] = {
def Shutdown: List[Avatar] = {
val list = sessionMap.values.toList
sessionMap.clear
list
@ -48,8 +49,9 @@ private class LivePlayerList {
* &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`LivePlayerList.Remove(session)`
*/
object LivePlayerList {
/** As `LivePlayerList` is a singleton, an object of `LivePlayerList` is automatically instantiated. */
private val Instance : LivePlayerList = new LivePlayerList
private val Instance: LivePlayerList = new LivePlayerList
/**
* Given some criteria, examine the mapping of user characters and find the ones that fulfill the requirements.<br>
@ -61,7 +63,7 @@ object LivePlayerList {
* @param predicate the conditions for filtering the live `Player`s
* @return a list of users's `Player`s that fit the criteria
*/
def WorldPopulation(predicate : ((_, Avatar)) => Boolean) : List[Avatar] = Instance.WorldPopulation(predicate)
def WorldPopulation(predicate: ((_, Avatar)) => Boolean): List[Avatar] = Instance.WorldPopulation(predicate)
/**
* Create a mapped entry between the user's session and a user's character.
@ -70,7 +72,7 @@ object LivePlayerList {
* @param avatar the character
* @return `true`, if the session was association was made; `false`, otherwise
*/
def Add(sessionId : Long, avatar : Avatar) : Boolean = Instance.Add(sessionId, avatar)
def Add(sessionId: Long, avatar: Avatar): Boolean = Instance.Add(sessionId, avatar)
/**
* Remove all entries related to the given session identifier from the mappings.
@ -78,11 +80,11 @@ object LivePlayerList {
* @param sessionId the session
* @return any character that was afffected by the mapping removal
*/
def Remove(sessionId : Long) : Option[Avatar] = Instance.Remove(sessionId)
def Remove(sessionId: Long): Option[Avatar] = Instance.Remove(sessionId)
/**
* Hastily remove all mappings and ids.
* @return an unsorted list of the characters that were still online
*/
def Shutdown : List[Avatar] = Instance.Shutdown
def Shutdown: List[Avatar] = Instance.Shutdown
}

View file

@ -30,7 +30,7 @@ object LocalProjectile {
* @param context a context to allow the object to properly set up `ActorSystem` functionality
* @return the `LocalProjectile` object
*/
def Constructor(id : Int, context : ActorContext) : LocalProjectile = {
def Constructor(id: Int, context: ActorContext): LocalProjectile = {
new LocalProjectile()
}
}

View file

@ -19,62 +19,60 @@ import services.avatar.{AvatarAction, AvatarServiceMessage}
* The `Player` class refers to it as the "fifth slot" as its permanent slot number is encoded as `0x85`.
* The inventory of this object is accessed using a game world `Locker` object (`mb_locker`).
*/
class LockerContainer extends PlanetSideServerObject
with Container {
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
private val inventory = GridInventory(30, 20)
class LockerContainer extends PlanetSideServerObject with Container {
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
private val inventory = GridInventory(30, 20)
def Faction : PlanetSideEmpire.Value = faction
def Faction: PlanetSideEmpire.Value = faction
override def Faction_=(fact : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
override def Faction_=(fact: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
faction = fact
Faction
}
def Inventory : GridInventory = inventory
def Inventory: GridInventory = inventory
def VisibleSlots : Set[Int] = Set.empty[Int]
def VisibleSlots: Set[Int] = Set.empty[Int]
def Definition : EquipmentDefinition = GlobalDefinitions.locker_container
def Definition: EquipmentDefinition = GlobalDefinitions.locker_container
}
object LockerContainer {
def apply() : LockerContainer = {
def apply(): LockerContainer = {
new LockerContainer()
}
}
class LockerEquipment(locker : LockerContainer) extends Equipment
with Container {
class LockerEquipment(locker: LockerContainer) extends Equipment with Container {
private val obj = locker
override def GUID : PlanetSideGUID = obj.GUID
override def GUID: PlanetSideGUID = obj.GUID
override def GUID_=(guid : PlanetSideGUID) : PlanetSideGUID = obj.GUID_=(guid)
override def GUID_=(guid: PlanetSideGUID): PlanetSideGUID = obj.GUID_=(guid)
override def HasGUID : Boolean = obj.HasGUID
override def HasGUID: Boolean = obj.HasGUID
override def Invalidate() : Unit = obj.Invalidate()
override def Invalidate(): Unit = obj.Invalidate()
override def Faction : PlanetSideEmpire.Value = obj.Faction
override def Faction: PlanetSideEmpire.Value = obj.Faction
def Inventory : GridInventory = obj.Inventory
def Inventory: GridInventory = obj.Inventory
def VisibleSlots : Set[Int] = Set.empty[Int]
def VisibleSlots: Set[Int] = Set.empty[Int]
def Definition : EquipmentDefinition = obj.Definition
def Definition: EquipmentDefinition = obj.Definition
}
class LockerContainerControl(locker : LockerContainer, toChannel : String) extends Actor
with ContainableBehavior {
class LockerContainerControl(locker: LockerContainer, toChannel: String) extends Actor with ContainableBehavior {
def ContainerObject = locker
def receive : Receive = containerBehavior
.orElse {
case _ => ;
}
def receive: Receive =
containerBehavior
.orElse {
case _ => ;
}
def MessageDeferredCallback(msg : Any) : Unit = {
def MessageDeferredCallback(msg: Any): Unit = {
msg match {
case Containable.MoveItem(_, item, _) =>
//momentarily put item back where it was originally
@ -91,13 +89,13 @@ class LockerContainerControl(locker : LockerContainer, toChannel : String) exten
}
}
def RemoveItemFromSlotCallback(item : Equipment, slot : Int) : Unit = {
def RemoveItemFromSlotCallback(item: Equipment, slot: Int): Unit = {
val zone = locker.Zone
zone.AvatarEvents ! AvatarServiceMessage(toChannel, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, item.GUID))
}
def PutItemInSlotCallback(item : Equipment, slot : Int) : Unit = {
val zone = locker.Zone
def PutItemInSlotCallback(item: Equipment, slot: Int): Unit = {
val zone = locker.Zone
val definition = item.Definition
item.Faction = PlanetSideEmpire.NEUTRAL
zone.AvatarEvents ! AvatarServiceMessage(
@ -114,8 +112,14 @@ class LockerContainerControl(locker : LockerContainer, toChannel : String) exten
)
}
def SwapItemCallback(item : Equipment) : Unit = {
def SwapItemCallback(item: Equipment): Unit = {
val zone = locker.Zone
zone.AvatarEvents ! AvatarServiceMessage(toChannel, AvatarAction.SendResponse(Service.defaultPlayerGUID, ObjectDetachMessage(locker.GUID, item.GUID, Vector3.Zero, 0f)))
zone.AvatarEvents ! AvatarServiceMessage(
toChannel,
AvatarAction.SendResponse(
Service.defaultPlayerGUID,
ObjectDetachMessage(locker.GUID, item.GUID, Vector3.Zero, 0f)
)
)
}
}

View file

@ -4,93 +4,93 @@ package net.psforever.objects
object ObjectType extends Enumeration {
type Value = String
val AmbientSoundSource = "ambient_sound_source"
val Ammunition = "ammunition"
val AnimatedBarrier = "animated_barrier"
val Applicator = "applicator"
val Armor = "armor"
val ArmorSiphon = "armor_siphon"
val AwardStatistic = "award_statistic"
val Avatar = "avatar"
val AvatarBot = "avatar_bot"
val Ball = "ball"
val Bank = "bank"
val Barrier = "barrier"
val BfrTerminal = "bfr_terminal"
val Billboard = "billboard"
val Boomer = "boomer"
val BoomerTrigger = "boomer_trigger"
val Building = "building"
val CaptureFlag = "capture_flag"
val CaptureFlagSocket = "capture_flag_socket"
val CaptureTerminal = "capture_terminal"
val CertTerminal = "cert_terminal"
val ChainLashDamager = "chain_lash_damager"
val Dispenser = "dispenser"
val Door = "door"
val EmpBlast = "emp_blast"
val FrameVehicle = "framevehicle"
val Flag = "flag"
val FlightVehicle = "flightvehicle"
val ForceDome = "forcedome"
val ForceDomeGenerator = "forcedomegenerator"
val Game = "game"
val Generic = "generic"
val GenericTeleportion = "generic_teleportation"
val GeneratorTerminal = "generator_terminal"
val GsGenbase = "GS_genbase"
val HandGrenade = "hand_grenade"
val HeMine = "he_mine"
val HeavyWeapon = "heavy_weapon"
val HoverVehicle = "hovervehicle"
val Implant = "implant"
val AmbientSoundSource = "ambient_sound_source"
val Ammunition = "ammunition"
val AnimatedBarrier = "animated_barrier"
val Applicator = "applicator"
val Armor = "armor"
val ArmorSiphon = "armor_siphon"
val AwardStatistic = "award_statistic"
val Avatar = "avatar"
val AvatarBot = "avatar_bot"
val Ball = "ball"
val Bank = "bank"
val Barrier = "barrier"
val BfrTerminal = "bfr_terminal"
val Billboard = "billboard"
val Boomer = "boomer"
val BoomerTrigger = "boomer_trigger"
val Building = "building"
val CaptureFlag = "capture_flag"
val CaptureFlagSocket = "capture_flag_socket"
val CaptureTerminal = "capture_terminal"
val CertTerminal = "cert_terminal"
val ChainLashDamager = "chain_lash_damager"
val Dispenser = "dispenser"
val Door = "door"
val EmpBlast = "emp_blast"
val FrameVehicle = "framevehicle"
val Flag = "flag"
val FlightVehicle = "flightvehicle"
val ForceDome = "forcedome"
val ForceDomeGenerator = "forcedomegenerator"
val Game = "game"
val Generic = "generic"
val GenericTeleportion = "generic_teleportation"
val GeneratorTerminal = "generator_terminal"
val GsGenbase = "GS_genbase"
val HandGrenade = "hand_grenade"
val HeMine = "he_mine"
val HeavyWeapon = "heavy_weapon"
val HoverVehicle = "hovervehicle"
val Implant = "implant"
val ImplantInterfaceTerminal = "implant_terminal_interface"
val Lazer = "lazer"
val Locker = "locker"
val LockerContainer = "locker_container"
val LockExternal = "lock_external"
val LockSmall = "lock_small"
val MainTerminal = "main_terminal"
val Map = "map"
val MedicalTerminal = "medical_terminal"
val Medkit = "medkit"
val Monolith = "monolith"
val MonolithUnit = "monolith_unit"
val MotionAlarmSensorDest = "motion_alarm_sensor_dest"
val NanoDispenser = "nano_dispenser"
val NtuSipon = "ntu_siphon"
val OrbitalShuttlePad = "orbital_shuttle_pad"
val OrbitalStrike = "orbital_strike"
val OrderTerminal = "order_terminal"
val PainTerminal = "pain_terminal"
val Projectile = "projectile"
val RadiationCloud = "radiation_cloud"
val RearmTerminal = "rearm_terminal"
val RechargeTerminal = "recharge_terminal"
val Rek = "rek"
val RepairTerminal = "repair_terminal"
val ResourceSilo = "resource_silo"
val RespawnTube = "respawn_tube"
val SensorShield = "sensor_shield"
val ShieldGenerator = "shield_generator"
val Shifter = "shifter"
val SkyDome = "skydome"
val SpawnPlayer = "spawn_player"
val SpawnPoint = "spawn_point"
val SpawnTerminal = "spawn_terminal"
val TeleportPad = "teleport_pad"
val Terminal = "terminal"
val TradeContainer = "trade_container"
val UplinkDevice = "uplink_device"
val VanuCradleClass = "vanu_cradle_class"
val VanuModuleClass = "vanu_module_class"
val VanuModuleFactory = "vanu_module_factory"
val VanuReceptacleClass = "vanu_receptacle_class"
val Vehicle = "vehicle"
val VehicleCreationPad = "vehicle_creation_pad"
val VehicleLandingPad = "vehicle_landing_pad"
val VehicleTerminal = "vehicle_terminal"
val Warpgate = "waprgate"
val WarpZone = "warp_zone"
val Weapon = "weapon"
val Lazer = "lazer"
val Locker = "locker"
val LockerContainer = "locker_container"
val LockExternal = "lock_external"
val LockSmall = "lock_small"
val MainTerminal = "main_terminal"
val Map = "map"
val MedicalTerminal = "medical_terminal"
val Medkit = "medkit"
val Monolith = "monolith"
val MonolithUnit = "monolith_unit"
val MotionAlarmSensorDest = "motion_alarm_sensor_dest"
val NanoDispenser = "nano_dispenser"
val NtuSipon = "ntu_siphon"
val OrbitalShuttlePad = "orbital_shuttle_pad"
val OrbitalStrike = "orbital_strike"
val OrderTerminal = "order_terminal"
val PainTerminal = "pain_terminal"
val Projectile = "projectile"
val RadiationCloud = "radiation_cloud"
val RearmTerminal = "rearm_terminal"
val RechargeTerminal = "recharge_terminal"
val Rek = "rek"
val RepairTerminal = "repair_terminal"
val ResourceSilo = "resource_silo"
val RespawnTube = "respawn_tube"
val SensorShield = "sensor_shield"
val ShieldGenerator = "shield_generator"
val Shifter = "shifter"
val SkyDome = "skydome"
val SpawnPlayer = "spawn_player"
val SpawnPoint = "spawn_point"
val SpawnTerminal = "spawn_terminal"
val TeleportPad = "teleport_pad"
val Terminal = "terminal"
val TradeContainer = "trade_container"
val UplinkDevice = "uplink_device"
val VanuCradleClass = "vanu_cradle_class"
val VanuModuleClass = "vanu_module_class"
val VanuModuleFactory = "vanu_module_factory"
val VanuReceptacleClass = "vanu_receptacle_class"
val Vehicle = "vehicle"
val VehicleCreationPad = "vehicle_creation_pad"
val VehicleLandingPad = "vehicle_landing_pad"
val VehicleTerminal = "vehicle_terminal"
val Warpgate = "waprgate"
val WarpZone = "warp_zone"
val Weapon = "weapon"
}

View file

@ -8,7 +8,7 @@ import net.psforever.objects.equipment.{EquipmentSize, EquipmentSlot}
* Unlike conventional `EquipmentSlot` space, this size of allowable `Equipment` is fixed.
* @param size the permanent size of the `Equipment` allowed in this slot
*/
class OffhandEquipmentSlot(size : EquipmentSize.Value) extends EquipmentSlot {
class OffhandEquipmentSlot(size: EquipmentSize.Value) extends EquipmentSlot {
super.Size_=(size)
/**
@ -16,10 +16,11 @@ class OffhandEquipmentSlot(size : EquipmentSize.Value) extends EquipmentSlot {
* @param assignSize the changed in capacity for this slot
* @return the capacity for this slot
*/
override def Size_=(assignSize : EquipmentSize.Value) : EquipmentSize.Value = Size
override def Size_=(assignSize: EquipmentSize.Value): EquipmentSize.Value = Size
}
object OffhandEquipmentSlot {
/**
* An `EquipmentSlot` that can not be manipulated because its size is `Blocked` permanently.
*/

View file

@ -4,16 +4,16 @@ package net.psforever.objects
import net.psforever.types.PlanetSideGUID
trait OwnableByPlayer {
private var owner : Option[PlanetSideGUID] = None
private var ownerName : Option[String] = None
private var owner: Option[PlanetSideGUID] = None
private var ownerName: Option[String] = None
def Owner : Option[PlanetSideGUID] = owner
def Owner: Option[PlanetSideGUID] = owner
def Owner_=(owner : PlanetSideGUID) : Option[PlanetSideGUID] = Owner_=(Some(owner))
def Owner_=(owner: PlanetSideGUID): Option[PlanetSideGUID] = Owner_=(Some(owner))
def Owner_=(owner : Player) : Option[PlanetSideGUID] = Owner_=(Some(owner.GUID))
def Owner_=(owner: Player): Option[PlanetSideGUID] = Owner_=(Some(owner.GUID))
def Owner_=(owner : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
def Owner_=(owner: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
owner match {
case Some(_) =>
this.owner = owner
@ -23,13 +23,13 @@ trait OwnableByPlayer {
Owner
}
def OwnerName : Option[String] = ownerName
def OwnerName: Option[String] = ownerName
def OwnerName_=(owner : String) : Option[String] = OwnerName_=(Some(owner))
def OwnerName_=(owner: String): Option[String] = OwnerName_=(Some(owner))
def OwnerName_=(owner : Player) : Option[String] = OwnerName_=(Some(owner.Name))
def OwnerName_=(owner: Player): Option[String] = OwnerName_=(Some(owner.Name))
def OwnerName_=(owner : Option[String]) : Option[String] = {
def OwnerName_=(owner: Option[String]): Option[String] = {
owner match {
case Some(_) =>
ownerName = owner
@ -44,14 +44,14 @@ trait OwnableByPlayer {
* @param player na
* @return na
*/
def AssignOwnership(player : Player) : OwnableByPlayer = AssignOwnership(Some(player))
def AssignOwnership(player: Player): OwnableByPlayer = AssignOwnership(Some(player))
/**
* na
* @param playerOpt na
* @return na
*/
def AssignOwnership(playerOpt : Option[Player]) : OwnableByPlayer = {
def AssignOwnership(playerOpt: Option[Player]): OwnableByPlayer = {
playerOpt match {
case Some(player) =>
Owner = player

View file

@ -9,47 +9,48 @@ import net.psforever.types.Vector3
* A basic class that indicates an entity that exists somewhere in the world and has a globally unique identifier.
*/
abstract class PlanetSideGameObject extends IdentifiableEntity with WorldEntity {
private var entity : WorldEntity = new SimpleWorldEntity()
private var destroyed : Boolean = false
private var entity: WorldEntity = new SimpleWorldEntity()
private var destroyed: Boolean = false
def Entity : WorldEntity = entity
def Entity: WorldEntity = entity
def Entity_=(newEntity : WorldEntity) : Unit = {
def Entity_=(newEntity: WorldEntity): Unit = {
entity = newEntity
}
def Position : Vector3 = Entity.Position
def Position: Vector3 = Entity.Position
def Position_=(vec : Vector3) : Vector3 = {
def Position_=(vec: Vector3): Vector3 = {
Entity.Position = vec
}
def Orientation : Vector3 = Entity.Orientation
def Orientation: Vector3 = Entity.Orientation
def Orientation_=(vec : Vector3) : Vector3 = {
def Orientation_=(vec: Vector3): Vector3 = {
Entity.Orientation = vec
}
def Velocity : Option[Vector3] = Entity.Velocity
def Velocity: Option[Vector3] = Entity.Velocity
def Velocity_=(vec : Option[Vector3]) : Option[Vector3] = {
def Velocity_=(vec: Option[Vector3]): Option[Vector3] = {
Entity.Velocity = vec
}
def Destroyed : Boolean = destroyed
def Destroyed: Boolean = destroyed
def Destroyed_=(state : Boolean) : Boolean = {
def Destroyed_=(state: Boolean): Boolean = {
destroyed = state
Destroyed
}
def Definition : ObjectDefinition
def Definition: ObjectDefinition
}
object PlanetSideGameObject {
def toString(obj : PlanetSideGameObject) : String = {
val guid : String = if(obj.HasGUID) { obj.GUID.toString } else { "NOGUID" }
def toString(obj: PlanetSideGameObject): String = {
val guid: String = if (obj.HasGUID) { obj.GUID.toString }
else { "NOGUID" }
val P = obj.Position
s"[$guid](x,y,z=${P.x%.3f},${P.y%.3f},${P.z%.3f})"
s"[$guid](x,y,z=${P.x % .3f},${P.y % .3f},${P.z % .3f})"
}
}

View file

@ -2,7 +2,12 @@
package net.psforever.objects
import net.psforever.objects.avatar.LoadoutManager
import net.psforever.objects.definition.{AvatarDefinition, ExoSuitDefinition, ImplantDefinition, SpecialExoSuitDefinition}
import net.psforever.objects.definition.{
AvatarDefinition,
ExoSuitDefinition,
ImplantDefinition,
SpecialExoSuitDefinition
}
import net.psforever.objects.equipment.{Equipment, EquipmentSize, EquipmentSlot, JammableUnit}
import net.psforever.objects.inventory.{Container, GridInventory, InventoryItem}
import net.psforever.objects.serverobject.PlanetSideServerObject
@ -16,76 +21,79 @@ import net.psforever.types.{PlanetSideGUID, _}
import scala.annotation.tailrec
import scala.util.{Success, Try}
class Player(private val core : Avatar) extends PlanetSideServerObject
with FactionAffinity
with Vitality
with ResistanceProfile
with Container
with JammableUnit
with ZoneAware {
Health = 0 //player health is artificially managed as a part of their lifecycle; start entity as dead
class Player(private val core: Avatar)
extends PlanetSideServerObject
with FactionAffinity
with Vitality
with ResistanceProfile
with Container
with JammableUnit
with ZoneAware {
Health = 0 //player health is artificially managed as a part of their lifecycle; start entity as dead
Destroyed = true //see isAlive
private var backpack : Boolean = false
private var stamina : Int = 0
private var armor : Int = 0
private var backpack: Boolean = false
private var stamina: Int = 0
private var armor: Int = 0
private var capacitor : Float = 0f
private var capacitorState : CapacitorStateType.Value = CapacitorStateType.Idle
private var capacitorLastUsedMillis : Long = 0
private var capacitorLastChargedMillis : Long = 0
private var capacitor: Float = 0f
private var capacitorState: CapacitorStateType.Value = CapacitorStateType.Idle
private var capacitorLastUsedMillis: Long = 0
private var capacitorLastChargedMillis: Long = 0
private var maxStamina : Int = 100 //does anything affect this?
private var maxStamina: Int = 100 //does anything affect this?
private var exosuit : ExoSuitDefinition = GlobalDefinitions.Standard
private val freeHand : EquipmentSlot = new OffhandEquipmentSlot(EquipmentSize.Inventory)
private val holsters : Array[EquipmentSlot] = Array.fill[EquipmentSlot](5)(new EquipmentSlot)
private val inventory : GridInventory = GridInventory()
private var drawnSlot : Int = Player.HandsDownSlot
private var lastDrawnSlot : Int = Player.HandsDownSlot
private var backpackAccess : Option[PlanetSideGUID] = None
private var exosuit: ExoSuitDefinition = GlobalDefinitions.Standard
private val freeHand: EquipmentSlot = new OffhandEquipmentSlot(EquipmentSize.Inventory)
private val holsters: Array[EquipmentSlot] = Array.fill[EquipmentSlot](5)(new EquipmentSlot)
private val inventory: GridInventory = GridInventory()
private var drawnSlot: Int = Player.HandsDownSlot
private var lastDrawnSlot: Int = Player.HandsDownSlot
private var backpackAccess: Option[PlanetSideGUID] = None
private var facingYawUpper : Float = 0f
private var crouching : Boolean = false
private var jumping : Boolean = false
private var cloaked : Boolean = false
private var fatigued : Boolean = false // If stamina drops to 0, player is fatigued until regenerating at least 20 stamina
private var afk : Boolean = false
private var facingYawUpper: Float = 0f
private var crouching: Boolean = false
private var jumping: Boolean = false
private var cloaked: Boolean = false
private var fatigued: Boolean =
false // If stamina drops to 0, player is fatigued until regenerating at least 20 stamina
private var afk: Boolean = false
private var vehicleSeated : Option[PlanetSideGUID] = None
private var vehicleSeated: Option[PlanetSideGUID] = None
Continent = "home2" //the zone id
var spectator : Boolean = false
var silenced : Boolean = false
var death_by : Int = 0
var lastSeenStreamMessage : Array[Long] = Array.fill[Long](65535)(0L)
var lastShotSeq_time : Int = -1
var spectator: Boolean = false
var silenced: Boolean = false
var death_by: Int = 0
var lastSeenStreamMessage: Array[Long] = Array.fill[Long](65535)(0L)
var lastShotSeq_time: Int = -1
/** From PlanetsideAttributeMessage */
var PlanetsideAttribute : Array[Long] = Array.ofDim(120)
var skipStaminaRegenForTurns : Int = 0
var PlanetsideAttribute: Array[Long] = Array.ofDim(120)
var skipStaminaRegenForTurns: Int = 0
Player.SuitSetup(this, exosuit)
def CharId : Long = core.CharId
def CharId: Long = core.CharId
def Name : String = core.name
def Name: String = core.name
def Faction : PlanetSideEmpire.Value = core.faction
def Faction: PlanetSideEmpire.Value = core.faction
def Sex : CharacterGender.Value = core.sex
def Sex: CharacterGender.Value = core.sex
def Head : Int = core.head
def Head: Int = core.head
def Voice : CharacterVoice.Value = core.voice
def Voice: CharacterVoice.Value = core.voice
def LFS : Boolean = core.LFS
def LFS: Boolean = core.LFS
def isAlive : Boolean = !Destroyed
def isAlive: Boolean = !Destroyed
def isBackpack : Boolean = backpack
def isBackpack: Boolean = backpack
def Spawn : Boolean = {
if(!isAlive && !isBackpack) {
def Spawn: Boolean = {
if (!isAlive && !isBackpack) {
Destroyed = false
Health = Definition.DefaultHealth
Stamina = MaxStamina
@ -96,66 +104,64 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
isAlive
}
def Die : Boolean = {
def Die: Boolean = {
Destroyed = true
Health = 0
Stamina = 0
false
}
def Revive : Boolean = {
def Revive: Boolean = {
Destroyed = false
Health = Definition.DefaultHealth
true
}
def Release : Boolean = {
if(!isAlive) {
def Release: Boolean = {
if (!isAlive) {
backpack = true
true
}
else {
} else {
false
}
}
def Stamina : Int = stamina
def Stamina: Int = stamina
def Stamina_=(assignStamina : Int) : Int = {
stamina = if(isAlive) { math.min(math.max(0, assignStamina), MaxStamina) } else { 0 }
def Stamina_=(assignStamina: Int): Int = {
stamina = if (isAlive) { math.min(math.max(0, assignStamina), MaxStamina) }
else { 0 }
Stamina
}
def MaxStamina : Int = maxStamina
def MaxStamina: Int = maxStamina
def MaxStamina_=(max : Int) : Int = {
def MaxStamina_=(max: Int): Int = {
maxStamina = math.min(math.max(0, max), 65535)
MaxStamina
}
def Armor : Int = armor
def Armor: Int = armor
def Armor_=(assignArmor : Int) : Int = {
def Armor_=(assignArmor: Int): Int = {
armor = math.min(math.max(0, assignArmor), MaxArmor)
Armor
}
def MaxArmor : Int = exosuit.MaxArmor
def MaxArmor: Int = exosuit.MaxArmor
def Capacitor : Float = capacitor
def Capacitor: Float = capacitor
def Capacitor_=(value : Float) : Float = {
def Capacitor_=(value: Float): Float = {
val newValue = math.min(math.max(0, value), ExoSuitDef.MaxCapacitor.toFloat)
if(newValue < capacitor) {
if (newValue < capacitor) {
capacitorLastUsedMillis = System.currentTimeMillis()
capacitorLastChargedMillis = 0
}
else if(newValue > capacitor && newValue < ExoSuitDef.MaxCapacitor) {
} else if (newValue > capacitor && newValue < ExoSuitDef.MaxCapacitor) {
capacitorLastChargedMillis = System.currentTimeMillis()
capacitorLastUsedMillis = 0
}
else if(newValue > capacitor && newValue == ExoSuitDef.MaxCapacitor) {
} else if (newValue > capacitor && newValue == ExoSuitDef.MaxCapacitor) {
capacitorLastChargedMillis = 0
capacitorLastUsedMillis = 0
capacitorState = CapacitorStateType.Idle
@ -165,55 +171,51 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
capacitor
}
def CapacitorState : CapacitorStateType.Value = capacitorState
def CapacitorState_=(value : CapacitorStateType.Value) : CapacitorStateType.Value = {
def CapacitorState: CapacitorStateType.Value = capacitorState
def CapacitorState_=(value: CapacitorStateType.Value): CapacitorStateType.Value = {
value match {
case CapacitorStateType.Charging => capacitorLastChargedMillis = System.currentTimeMillis()
case CapacitorStateType.Charging => capacitorLastChargedMillis = System.currentTimeMillis()
case CapacitorStateType.Discharging => capacitorLastUsedMillis = System.currentTimeMillis()
case _ => ;
case _ => ;
}
capacitorState = value
capacitorState
}
def CapacitorLastUsedMillis = capacitorLastUsedMillis
def CapacitorLastUsedMillis = capacitorLastUsedMillis
def CapacitorLastChargedMillis = capacitorLastChargedMillis
def VisibleSlots : Set[Int] = if(exosuit.SuitType == ExoSuitType.MAX) {
Set(0)
}
else {
(0 to 4).filterNot(index => holsters(index).Size == EquipmentSize.Blocked).toSet
}
def VisibleSlots: Set[Int] =
if (exosuit.SuitType == ExoSuitType.MAX) {
Set(0)
} else {
(0 to 4).filterNot(index => holsters(index).Size == EquipmentSize.Blocked).toSet
}
override def Slot(slot : Int) : EquipmentSlot = {
if(inventory.Offset <= slot && slot <= inventory.LastIndex) {
override def Slot(slot: Int): EquipmentSlot = {
if (inventory.Offset <= slot && slot <= inventory.LastIndex) {
inventory.Slot(slot)
}
else if(slot > -1 && slot < 5) {
} else if (slot > -1 && slot < 5) {
holsters(slot)
}
else if(slot == 5) {
} else if (slot == 5) {
core.FifthSlot
}
else if(slot == Player.FreeHandSlot) {
} else if (slot == Player.FreeHandSlot) {
freeHand
}
else {
} else {
OffhandEquipmentSlot.BlockedSlot
}
}
def Holsters() : Array[EquipmentSlot] = holsters
def Holsters(): Array[EquipmentSlot] = holsters
def Inventory : GridInventory = inventory
def Inventory: GridInventory = inventory
def Locker : LockerContainer = core.Locker
def Locker: LockerContainer = core.Locker
def FifthSlot : EquipmentSlot = core.FifthSlot
def FifthSlot: EquipmentSlot = core.FifthSlot
override def Fit(obj : Equipment) : Option[Int] = {
override def Fit(obj: Equipment): Option[Int] = {
recursiveHolsterFit(holsters.iterator, obj.Size) match {
case Some(index) =>
Some(index)
@ -222,21 +224,24 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
case Some(index) =>
Some(index)
case None =>
if(freeHand.Equipment.isDefined) { None } else { Some(Player.FreeHandSlot) }
if (freeHand.Equipment.isDefined) { None }
else { Some(Player.FreeHandSlot) }
}
}
}
@tailrec private def recursiveHolsterFit(iter : Iterator[EquipmentSlot], objSize : EquipmentSize.Value, index : Int = 0) : Option[Int] = {
if(!iter.hasNext) {
@tailrec private def recursiveHolsterFit(
iter: Iterator[EquipmentSlot],
objSize: EquipmentSize.Value,
index: Int = 0
): Option[Int] = {
if (!iter.hasNext) {
None
}
else {
} else {
val slot = iter.next
if(slot.Equipment.isEmpty && slot.Size.equals(objSize)) {
if (slot.Equipment.isEmpty && slot.Size.equals(objSize)) {
Some(index)
}
else {
} else {
recursiveHolsterFit(iter, objSize, index + 1)
}
}
@ -244,73 +249,71 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
def FreeHand = freeHand
def FreeHand_=(item : Option[Equipment]) : Option[Equipment] = {
if(freeHand.Equipment.isEmpty || item.isEmpty) {
def FreeHand_=(item: Option[Equipment]): Option[Equipment] = {
if (freeHand.Equipment.isEmpty || item.isEmpty) {
freeHand.Equipment = item
}
FreeHand.Equipment
}
override def Find(guid : PlanetSideGUID) : Option[Int] = {
override def Find(guid: PlanetSideGUID): Option[Int] = {
findInHolsters(holsters.iterator, guid)
.orElse(inventory.Find(guid)) match {
case Some(index) =>
Some(index)
case None =>
if(freeHand.Equipment.isDefined && freeHand.Equipment.get.GUID == guid) {
if (freeHand.Equipment.isDefined && freeHand.Equipment.get.GUID == guid) {
Some(Player.FreeHandSlot)
}
else {
} else {
None
}
}
}
@tailrec private def findInHolsters(iter : Iterator[EquipmentSlot], guid : PlanetSideGUID, index : Int = 0) : Option[Int] = {
if(!iter.hasNext) {
@tailrec private def findInHolsters(
iter: Iterator[EquipmentSlot],
guid: PlanetSideGUID,
index: Int = 0
): Option[Int] = {
if (!iter.hasNext) {
None
}
else {
} else {
val slot = iter.next
if(slot.Equipment.isDefined && slot.Equipment.get.GUID == guid) {
if (slot.Equipment.isDefined && slot.Equipment.get.GUID == guid) {
Some(index)
}
else {
} else {
findInHolsters(iter, guid, index + 1)
}
}
}
override def Collisions(dest : Int, width : Int, height : Int) : Try[List[InventoryItem]] = {
if(-1 < dest && dest < 5) {
override def Collisions(dest: Int, width: Int, height: Int): Try[List[InventoryItem]] = {
if (-1 < dest && dest < 5) {
holsters(dest).Equipment match {
case Some(item) =>
Success(List(InventoryItem(item, dest)))
case None =>
Success(List())
}
}
else if(dest == Player.FreeHandSlot) {
} else if (dest == Player.FreeHandSlot) {
freeHand.Equipment match {
case Some(item) =>
Success(List(InventoryItem(item, dest)))
case None =>
Success(List())
}
}
else {
} else {
super.Collisions(dest, width, height)
}
}
def DrawnSlot : Int = drawnSlot
def DrawnSlot: Int = drawnSlot
def DrawnSlot_=(slot : Int) : Int = {
if(slot != drawnSlot) {
if(slot == Player.HandsDownSlot) {
def DrawnSlot_=(slot: Int): Int = {
if (slot != drawnSlot) {
if (slot == Player.HandsDownSlot) {
drawnSlot = slot
}
else if(VisibleSlots.contains(slot) && holsters(slot).Equipment.isDefined) {
} else if (VisibleSlots.contains(slot) && holsters(slot).Equipment.isDefined) {
drawnSlot = slot
lastDrawnSlot = slot
}
@ -318,12 +321,12 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
DrawnSlot
}
def LastDrawnSlot : Int = lastDrawnSlot
def LastDrawnSlot: Int = lastDrawnSlot
def ExoSuit : ExoSuitType.Value = exosuit.SuitType
def ExoSuitDef : ExoSuitDefinition = exosuit
def ExoSuit: ExoSuitType.Value = exosuit.SuitType
def ExoSuitDef: ExoSuitDefinition = exosuit
def ExoSuit_=(suit : ExoSuitType.Value) : Unit = {
def ExoSuit_=(suit: ExoSuitType.Value): Unit = {
val eSuit = ExoSuitDefinition.Select(suit, Faction)
exosuit = eSuit
Player.SuitSetup(this, eSuit)
@ -340,15 +343,15 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
def RadiationShielding = exosuit.RadiationShielding
def EquipmentLoadouts : LoadoutManager = core.EquipmentLoadouts
def EquipmentLoadouts: LoadoutManager = core.EquipmentLoadouts
def SquadLoadouts : LoadoutManager = core.SquadLoadouts
def SquadLoadouts: LoadoutManager = core.SquadLoadouts
def BEP : Long = core.BEP
def BEP: Long = core.BEP
def CEP : Long = core.CEP
def CEP: Long = core.CEP
def Certifications : Set[CertificationType.Value] = core.Certifications.toSet
def Certifications: Set[CertificationType.Value] = core.Certifications.toSet
/**
* What kind of implant is installed into the given slot number?
@ -356,71 +359,71 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
* @param slot the slot number
* @return the tye of implant
*/
def Implant(slot : Int) : ImplantType.Value = core.Implant(slot)
def Implant(slot: Int): ImplantType.Value = core.Implant(slot)
def ImplantSlot(slot: Int) : ImplantSlot = core.Implants(slot)
def ImplantSlot(slot: Int): ImplantSlot = core.Implants(slot)
/**
* A read-only `Array` of tuples representing important information about all unlocked implant slots.
* @return a maximum of three implant types, initialization times, and active flags
*/
def Implants : Array[(ImplantType.Value, Long, Boolean)] = {
core.Implants.takeWhile(_.Unlocked).map( implant => { (implant.Implant, implant.MaxTimer, implant.Active) })
def Implants: Array[(ImplantType.Value, Long, Boolean)] = {
core.Implants.takeWhile(_.Unlocked).map(implant => { (implant.Implant, implant.MaxTimer, implant.Active) })
}
def InstallImplant(implant : ImplantDefinition) : Option[Int] = core.InstallImplant(implant)
def InstallImplant(implant: ImplantDefinition): Option[Int] = core.InstallImplant(implant)
def UninstallImplant(implant : ImplantType.Value) : Option[Int] = core.UninstallImplant(implant)
def UninstallImplant(implant: ImplantType.Value): Option[Int] = core.UninstallImplant(implant)
def ResetAllImplants() : Unit = core.ResetAllImplants()
def ResetAllImplants(): Unit = core.ResetAllImplants()
def FacingYawUpper : Float = facingYawUpper
def FacingYawUpper: Float = facingYawUpper
def FacingYawUpper_=(facing : Float) : Float = {
def FacingYawUpper_=(facing: Float): Float = {
facingYawUpper = facing
FacingYawUpper
}
def Crouching : Boolean = crouching
def Crouching: Boolean = crouching
def Crouching_=(crouched : Boolean) : Boolean = {
def Crouching_=(crouched: Boolean): Boolean = {
crouching = crouched
Crouching
}
def Jumping : Boolean = jumping
def Jumping: Boolean = jumping
def Jumping_=(jumped : Boolean) : Boolean = {
def Jumping_=(jumped: Boolean): Boolean = {
jumping = jumped
Jumping
}
def Cloaked : Boolean = cloaked
def Cloaked: Boolean = cloaked
def Cloaked_=(isCloaked : Boolean) : Boolean = {
def Cloaked_=(isCloaked: Boolean): Boolean = {
cloaked = isCloaked
Cloaked
}
def Fatigued : Boolean = fatigued
def Fatigued: Boolean = fatigued
def Fatigued_=(isFatigued : Boolean) : Boolean = {
def Fatigued_=(isFatigued: Boolean): Boolean = {
fatigued = isFatigued
Fatigued
}
def AwayFromKeyboard : Boolean = afk
def AwayFromKeyboard: Boolean = afk
def AwayFromKeyboard_=(away : Boolean) : Boolean = {
def AwayFromKeyboard_=(away: Boolean): Boolean = {
afk = away
AwayFromKeyboard
}
def PersonalStyleFeatures : Option[Cosmetics] = core.PersonalStyleFeatures
def PersonalStyleFeatures: Option[Cosmetics] = core.PersonalStyleFeatures
def AddToPersonalStyle(value : PersonalStyle.Value) : (Option[Cosmetics], Option[Cosmetics]) = {
def AddToPersonalStyle(value: PersonalStyle.Value): (Option[Cosmetics], Option[Cosmetics]) = {
val original = core.PersonalStyleFeatures
if(DetailedCharacterData.isBR24(core.BEP)) {
if (DetailedCharacterData.isBR24(core.BEP)) {
core.PersonalStyleFeatures = original match {
case Some(cosmetic) =>
cosmetic + value
@ -428,51 +431,47 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
Cosmetics(value)
}
(original, core.PersonalStyleFeatures)
}
else {
} else {
(None, None)
}
}
def RemoveFromPersonalStyle(value : PersonalStyle.Value) : (Option[Cosmetics], Option[Cosmetics]) = {
def RemoveFromPersonalStyle(value: PersonalStyle.Value): (Option[Cosmetics], Option[Cosmetics]) = {
val original = core.PersonalStyleFeatures
original match {
case Some(cosmetics) =>
(original, core.PersonalStyleFeatures = cosmetics - value)
case None =>
(None, None)
}
original match {
case Some(cosmetics) =>
(original, core.PersonalStyleFeatures = cosmetics - value)
case None =>
(None, None)
}
}
private def BasicFeatureToggle(feature : PersonalStyle.Value) : (Option[Cosmetics], Option[Cosmetics]) = core.PersonalStyleFeatures match {
case Some(c : Cosmetics) =>
if(c.Styles.contains(feature)) {
RemoveFromPersonalStyle(feature)
}
else {
AddToPersonalStyle(feature)
}
case None =>
AddToPersonalStyle(feature)
}
def ToggleHelmet : (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.NoHelmet)
def ToggleShades : (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Sunglasses)
def ToggleEarpiece : (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Earpiece)
def ToggleHat : (Option[Cosmetics], Option[Cosmetics]) = {
private def BasicFeatureToggle(feature: PersonalStyle.Value): (Option[Cosmetics], Option[Cosmetics]) =
core.PersonalStyleFeatures match {
case Some(c : Cosmetics) =>
if(c.Styles.contains(PersonalStyle.BrimmedCap)) {
(RemoveFromPersonalStyle(PersonalStyle.BrimmedCap)._1,
AddToPersonalStyle(PersonalStyle.Beret)._2)
case Some(c: Cosmetics) =>
if (c.Styles.contains(feature)) {
RemoveFromPersonalStyle(feature)
} else {
AddToPersonalStyle(feature)
}
else if(c.Styles.contains(PersonalStyle.Beret)) {
case None =>
AddToPersonalStyle(feature)
}
def ToggleHelmet: (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.NoHelmet)
def ToggleShades: (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Sunglasses)
def ToggleEarpiece: (Option[Cosmetics], Option[Cosmetics]) = BasicFeatureToggle(PersonalStyle.Earpiece)
def ToggleHat: (Option[Cosmetics], Option[Cosmetics]) = {
core.PersonalStyleFeatures match {
case Some(c: Cosmetics) =>
if (c.Styles.contains(PersonalStyle.BrimmedCap)) {
(RemoveFromPersonalStyle(PersonalStyle.BrimmedCap)._1, AddToPersonalStyle(PersonalStyle.Beret)._2)
} else if (c.Styles.contains(PersonalStyle.Beret)) {
RemoveFromPersonalStyle(PersonalStyle.Beret)
}
else {
} else {
AddToPersonalStyle(PersonalStyle.BrimmedCap)
}
case None =>
@ -480,96 +479,99 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
}
}
private var usingSpecial : SpecialExoSuitDefinition.Mode.Value=>SpecialExoSuitDefinition.Mode.Value = DefaultUsingSpecial
private var usingSpecial: SpecialExoSuitDefinition.Mode.Value => SpecialExoSuitDefinition.Mode.Value =
DefaultUsingSpecial
private var gettingSpecial : ()=>SpecialExoSuitDefinition.Mode.Value = DefaultGettingSpecial
private var gettingSpecial: () => SpecialExoSuitDefinition.Mode.Value = DefaultGettingSpecial
private def ChangeSpecialAbility() : Unit = {
if(ExoSuit == ExoSuitType.MAX) {
private def ChangeSpecialAbility(): Unit = {
if (ExoSuit == ExoSuitType.MAX) {
gettingSpecial = MAXGettingSpecial
usingSpecial = Faction match {
case PlanetSideEmpire.TR => UsingAnchorsOrOverdrive
case PlanetSideEmpire.NC => UsingShield
case _ => DefaultUsingSpecial
case _ => DefaultUsingSpecial
}
}
else {
} else {
usingSpecial = DefaultUsingSpecial
gettingSpecial = DefaultGettingSpecial
}
}
def UsingSpecial : SpecialExoSuitDefinition.Mode.Value = { gettingSpecial() }
def UsingSpecial: SpecialExoSuitDefinition.Mode.Value = { gettingSpecial() }
def UsingSpecial_=(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = usingSpecial(state)
def UsingSpecial_=(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value =
usingSpecial(state)
private def DefaultUsingSpecial(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
private def DefaultUsingSpecial(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value =
SpecialExoSuitDefinition.Mode.Normal
private def UsingAnchorsOrOverdrive(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = {
private def UsingAnchorsOrOverdrive(
state: SpecialExoSuitDefinition.Mode.Value
): SpecialExoSuitDefinition.Mode.Value = {
import SpecialExoSuitDefinition.Mode._
val curr = UsingSpecial
val next = if(curr == Normal) {
if(state == Anchored || state == Overdrive) {
val next = if (curr == Normal) {
if (state == Anchored || state == Overdrive) {
state
}
else {
} else {
Normal
}
}
else if(state == Normal) {
} else if (state == Normal) {
Normal
}
else {
} else {
curr
}
MAXUsingSpecial(next)
}
private def UsingShield(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = {
private def UsingShield(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value = {
import SpecialExoSuitDefinition.Mode._
val curr = UsingSpecial
val next = if(curr == Normal) {
if(state == Shielded) {
val next = if (curr == Normal) {
if (state == Shielded) {
state
}
else {
} else {
Normal
}
}
else if(state == Normal) {
} else if (state == Normal) {
Normal
}
else {
} else {
curr
}
MAXUsingSpecial(next)
}
private def DefaultGettingSpecial() : SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
private def DefaultGettingSpecial(): SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
private def MAXUsingSpecial(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = exosuit match {
case obj : SpecialExoSuitDefinition =>
obj.UsingSpecial = state
case _ =>
SpecialExoSuitDefinition.Mode.Normal
}
private def MAXUsingSpecial(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value =
exosuit match {
case obj: SpecialExoSuitDefinition =>
obj.UsingSpecial = state
case _ =>
SpecialExoSuitDefinition.Mode.Normal
}
private def MAXGettingSpecial() : SpecialExoSuitDefinition.Mode.Value = exosuit match {
case obj : SpecialExoSuitDefinition =>
obj.UsingSpecial
case _ =>
SpecialExoSuitDefinition.Mode.Normal
}
private def MAXGettingSpecial(): SpecialExoSuitDefinition.Mode.Value =
exosuit match {
case obj: SpecialExoSuitDefinition =>
obj.UsingSpecial
case _ =>
SpecialExoSuitDefinition.Mode.Normal
}
def isAnchored : Boolean = ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Anchored
def isAnchored: Boolean =
ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Anchored
def isOverdrived : Boolean = ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Overdrive
def isOverdrived: Boolean =
ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.TR && UsingSpecial == SpecialExoSuitDefinition.Mode.Overdrive
def isShielded : Boolean = ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.NC && UsingSpecial == SpecialExoSuitDefinition.Mode.Shielded
def isShielded: Boolean =
ExoSuit == ExoSuitType.MAX && Faction == PlanetSideEmpire.NC && UsingSpecial == SpecialExoSuitDefinition.Mode.Shielded
def AccessingBackpack : Option[PlanetSideGUID] = backpackAccess
def AccessingBackpack: Option[PlanetSideGUID] = backpackAccess
def AccessingBackpack_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = {
def AccessingBackpack_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = {
AccessingBackpack = Some(guid)
}
@ -579,12 +581,12 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
* @param guid the player who wishes to access the backpack
* @return the player who is currently allowed to access the backpack
*/
def AccessingBackpack_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
def AccessingBackpack_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
guid match {
case None =>
backpackAccess = None
case Some(player) =>
if(isBackpack && backpackAccess.isEmpty) {
if (isBackpack && backpackAccess.isEmpty) {
backpackAccess = Some(player)
}
}
@ -596,94 +598,96 @@ class Player(private val core : Avatar) extends PlanetSideServerObject
* @param player a player attempting to access this backpack
* @return `true`, if the `player` is permitted access; `false`, otherwise
*/
def CanAccessBackpack(player : Player) : Boolean = {
def CanAccessBackpack(player: Player): Boolean = {
isBackpack && (backpackAccess.isEmpty || backpackAccess.contains(player.GUID))
}
def FirstTimeEvents : List[String] = core.FirstTimeEvents
def FirstTimeEvents: List[String] = core.FirstTimeEvents
def VehicleSeated : Option[PlanetSideGUID] = vehicleSeated
def VehicleSeated: Option[PlanetSideGUID] = vehicleSeated
def VehicleSeated_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = VehicleSeated_=(Some(guid))
def VehicleSeated_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = VehicleSeated_=(Some(guid))
def VehicleSeated_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
def VehicleSeated_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
vehicleSeated = guid
VehicleSeated
}
def VehicleOwned : Option[PlanetSideGUID] = core.VehicleOwned
def VehicleOwned: Option[PlanetSideGUID] = core.VehicleOwned
def VehicleOwned_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = core.VehicleOwned_=(Some(guid))
def VehicleOwned_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = core.VehicleOwned_=(Some(guid))
def VehicleOwned_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = core.VehicleOwned_=(guid)
def VehicleOwned_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = core.VehicleOwned_=(guid)
def GetLastUsedTime(code : Int) : Long = core.GetLastUsedTime(code)
def GetLastUsedTime(code: Int): Long = core.GetLastUsedTime(code)
def GetLastUsedTime(code : ExoSuitType.Value) : Long = core.GetLastUsedTime(code)
def GetLastUsedTime(code: ExoSuitType.Value): Long = core.GetLastUsedTime(code)
def GetLastUsedTime(code : ExoSuitType.Value, subtype : Int) : Long = core.GetLastUsedTime(code, subtype)
def GetLastUsedTime(code: ExoSuitType.Value, subtype: Int): Long = core.GetLastUsedTime(code, subtype)
def SetLastUsedTime(code : Int, time : Long) : Unit = core.SetLastUsedTime(code, time)
def SetLastUsedTime(code: Int, time: Long): Unit = core.SetLastUsedTime(code, time)
def SetLastUsedTime(code : ExoSuitType.Value): Unit = core.SetLastUsedTime(code)
def SetLastUsedTime(code: ExoSuitType.Value): Unit = core.SetLastUsedTime(code)
def SetLastUsedTime(code : ExoSuitType.Value, time : Long) : Unit = core.SetLastUsedTime(code, time)
def SetLastUsedTime(code: ExoSuitType.Value, time: Long): Unit = core.SetLastUsedTime(code, time)
def SetLastUsedTime(code : ExoSuitType.Value, subtype : Int): Unit = core.SetLastUsedTime(code, subtype)
def SetLastUsedTime(code: ExoSuitType.Value, subtype: Int): Unit = core.SetLastUsedTime(code, subtype)
def SetLastUsedTime(code : ExoSuitType.Value, subtype : Int, time : Long) : Unit = core.SetLastUsedTime(code, subtype, time)
def SetLastUsedTime(code: ExoSuitType.Value, subtype: Int, time: Long): Unit =
core.SetLastUsedTime(code, subtype, time)
def GetLastPurchaseTime(code : Int) : Long = core.GetLastPurchaseTime(code)
def GetLastPurchaseTime(code: Int): Long = core.GetLastPurchaseTime(code)
def SetLastPurchaseTime(code : Int, time : Long) : Unit = core.SetLastPurchaseTime(code, time)
def SetLastPurchaseTime(code: Int, time: Long): Unit = core.SetLastPurchaseTime(code, time)
def ObjectTypeNameReference(id : Long) : String = core.ObjectTypeNameReference(id)
def ObjectTypeNameReference(id: Long): String = core.ObjectTypeNameReference(id)
def ObjectTypeNameReference(id : Long, name : String) : String = core.ObjectTypeNameReference(id, name)
def ObjectTypeNameReference(id: Long, name: String): String = core.ObjectTypeNameReference(id, name)
def DamageModel = exosuit.asInstanceOf[DamageResistanceModel]
def Definition : AvatarDefinition = core.Definition
def Definition: AvatarDefinition = core.Definition
def canEqual(other: Any): Boolean = other.isInstanceOf[Player]
override def equals(other : Any) : Boolean = other match {
case that: Player =>
(that canEqual this) &&
core == that.core
case _ =>
false
}
override def equals(other: Any): Boolean =
other match {
case that: Player =>
(that canEqual this) &&
core == that.core
case _ =>
false
}
override def hashCode() : Int = {
override def hashCode(): Int = {
core.hashCode()
}
override def toString : String = Player.toString(this)
override def toString: String = Player.toString(this)
}
object Player {
final val LockerSlot : Int = 5
final val FreeHandSlot : Int = 250
final val HandsDownSlot : Int = 255
final val LockerSlot: Int = 5
final val FreeHandSlot: Int = 250
final val HandsDownSlot: Int = 255
final case class Die()
final case class ImplantActivation(slot : Int, status : Int)
final case class ImplantInitializationStart(slot : Int)
final case class UninitializeImplant(slot : Int)
final case class ImplantInitializationComplete(slot : Int)
final case class ImplantActivation(slot: Int, status: Int)
final case class ImplantInitializationStart(slot: Int)
final case class UninitializeImplant(slot: Int)
final case class ImplantInitializationComplete(slot: Int)
final case class StaminaRegen()
final case class StaminaChanged(currentStamina : Option[Int] = None)
final case class StaminaChanged(currentStamina: Option[Int] = None)
object StaminaChanged {
def apply(amount : Int) : StaminaChanged = StaminaChanged(Some(amount))
def apply(amount: Int): StaminaChanged = StaminaChanged(Some(amount))
}
def apply(core : Avatar) : Player = {
def apply(core: Avatar): Player = {
new Player(core)
}
private def SuitSetup(player : Player, eSuit : ExoSuitDefinition) : Unit = {
private def SuitSetup(player: Player, eSuit: ExoSuitDefinition): Unit = {
//inventory
player.Inventory.Clear()
player.Inventory.Resize(eSuit.InventoryScale.Width, eSuit.InventoryScale.Height)
@ -692,34 +696,35 @@ object Player {
(0 until 5).foreach(index => { player.Slot(index).Size = eSuit.Holster(index) })
}
def Respawn(player : Player) : Player = {
if(player.Release) {
def Respawn(player: Player): Player = {
if (player.Release) {
val obj = new Player(player.core)
obj.Continent = player.Continent
obj
}
else {
} else {
player
}
}
def GetHackLevel(player : Player): Int = {
if(player.Certifications.contains(CertificationType.ExpertHacking) || player.Certifications.contains(CertificationType.ElectronicsExpert)) {
def GetHackLevel(player: Player): Int = {
if (
player.Certifications.contains(CertificationType.ExpertHacking) || player.Certifications.contains(
CertificationType.ElectronicsExpert
)
) {
3
}
else if(player.Certifications.contains(CertificationType.AdvancedHacking)) {
} else if (player.Certifications.contains(CertificationType.AdvancedHacking)) {
2
}
else if (player.Certifications.contains(CertificationType.Hacking)) {
} else if (player.Certifications.contains(CertificationType.Hacking)) {
1
}
else {
} else {
0
}
}
def toString(obj : Player) : String = {
val guid = if(obj.HasGUID) { s" ${obj.Continent}-${obj.GUID.guid}" } else { "" }
def toString(obj: Player): String = {
val guid = if (obj.HasGUID) { s" ${obj.Continent}-${obj.GUID.guid}" }
else { "" }
s"${obj.core}$guid ${obj.Health}/${obj.MaxHealth} ${obj.Armor}/${obj.MaxArmor}"
}
}

View file

@ -25,17 +25,21 @@ object Players {
* @return `true`, if the next cycle of progress should occur;
* `false`, otherwise
*/
def RevivingTickAction(target : Player, user : Player, item : Tool)(progress : Float) : Boolean = {
if(!target.isAlive && !target.isBackpack &&
def RevivingTickAction(target: Player, user: Player, item: Tool)(progress: Float): Boolean = {
if (
!target.isAlive && !target.isBackpack &&
user.isAlive && !user.isMoving &&
user.Slot(user.DrawnSlot).Equipment.contains(item) && item.Magazine >= 25 &&
Vector3.Distance(target.Position, user.Position) < target.Definition.RepairDistance) {
Vector3.Distance(target.Position, user.Position) < target.Definition.RepairDistance
) {
val events = target.Zone.AvatarEvents
val uname = user.Name
events ! AvatarServiceMessage(uname, AvatarAction.SendResponse(Service.defaultPlayerGUID, RepairMessage(target.GUID, progress.toInt)))
val uname = user.Name
events ! AvatarServiceMessage(
uname,
AvatarAction.SendResponse(Service.defaultPlayerGUID, RepairMessage(target.GUID, progress.toInt))
)
true
}
else {
} else {
false
}
}
@ -48,11 +52,17 @@ object Players {
* @param medic the name of the player doing the reviving
* @param item the tool being used to revive the target player
*/
def FinishRevivingPlayer(target : Player, medic : String, item : Tool)() : Unit = {
def FinishRevivingPlayer(target: Player, medic: String, item: Tool)(): Unit = {
val name = target.Name
log.info(s"$medic had revived $name")
val magazine = item.Discharge(Some(25))
target.Zone.AvatarEvents ! AvatarServiceMessage(medic, AvatarAction.SendResponse(Service.defaultPlayerGUID, InventoryStateMessage(item.AmmoSlot.Box.GUID, item.GUID, magazine)))
target.Zone.AvatarEvents ! AvatarServiceMessage(
medic,
AvatarAction.SendResponse(
Service.defaultPlayerGUID,
InventoryStateMessage(item.AmmoSlot.Box.GUID, item.GUID, magazine)
)
)
target.Zone.AvatarEvents ! AvatarServiceMessage(name, AvatarAction.Revive(target.GUID))
}
@ -64,11 +74,14 @@ object Players {
* @param list a persistent `List` of `Equipment` in the holster slots
* @return a `List` of `Equipment` in the holster slots
*/
@tailrec def clearHolsters(iter : Iterator[EquipmentSlot], index : Int = 0, list : List[InventoryItem] = Nil) : List[InventoryItem] = {
if(!iter.hasNext) {
@tailrec def clearHolsters(
iter: Iterator[EquipmentSlot],
index: Int = 0,
list: List[InventoryItem] = Nil
): List[InventoryItem] = {
if (!iter.hasNext) {
list
}
else {
} else {
val slot = iter.next
slot.Equipment match {
case Some(equipment) =>
@ -88,13 +101,12 @@ object Players {
* @param list a `List` of all `Equipment` that is not yet assigned to a holster slot or an inventory slot
* @return the `List` of all `Equipment` not yet assigned to a holster slot or an inventory slot
*/
@tailrec def fillEmptyHolsters(iter : Iterator[EquipmentSlot], list : List[InventoryItem]) : List[InventoryItem] = {
if(!iter.hasNext) {
@tailrec def fillEmptyHolsters(iter: Iterator[EquipmentSlot], list: List[InventoryItem]): List[InventoryItem] = {
if (!iter.hasNext) {
list
}
else {
} else {
val slot = iter.next
if(slot.Equipment.isEmpty) {
if (slot.Equipment.isEmpty) {
list.find(item => item.obj.Size == slot.Size) match {
case Some(obj) =>
val index = list.indexOf(obj)
@ -103,21 +115,20 @@ object Players {
case None =>
fillEmptyHolsters(iter, list)
}
}
else {
} else {
fillEmptyHolsters(iter, list)
}
}
}
def CertificationToUseExoSuit(player : Player, exosuit : ExoSuitType.Value, subtype : Int) : Boolean = {
def CertificationToUseExoSuit(player: Player, exosuit: ExoSuitType.Value, subtype: Int): Boolean = {
ExoSuitDefinition.Select(exosuit, player.Faction).Permissions match {
case Nil =>
true
case permissions if subtype != 0 =>
val certs = player.Certifications
certs.intersect(permissions.toSet).nonEmpty &&
certs.intersect(InfantryLoadout.DetermineSubtypeC(subtype)).nonEmpty
certs.intersect(InfantryLoadout.DetermineSubtypeC(subtype)).nonEmpty
case permissions =>
player.Certifications.intersect(permissions.toSet).nonEmpty
}

View file

@ -19,82 +19,97 @@ import services.vehicle.{VehicleAction, VehicleServiceMessage}
import scala.concurrent.duration._
class SensorDeployable(cdef : SensorDeployableDefinition) extends ComplexDeployable(cdef)
with Hackable
with JammableUnit
class SensorDeployable(cdef: SensorDeployableDefinition) extends ComplexDeployable(cdef) with Hackable with JammableUnit
class SensorDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId) {
class SensorDeployableDefinition(private val objectId: Int) extends ComplexDeployableDefinition(objectId) {
Name = "sensor_deployable"
DeployCategory = DeployableCategory.Sensors
Model = StandardResolutions.SimpleDeployables
Packet = new SmallDeployableConverter
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[SensorDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor =
context.actorOf(Props(classOf[SensorDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
}
}
object SensorDeployableDefinition {
def apply(dtype : DeployedItem.Value) : SensorDeployableDefinition = {
def apply(dtype: DeployedItem.Value): SensorDeployableDefinition = {
new SensorDeployableDefinition(dtype.id)
}
}
class SensorDeployableControl(sensor : SensorDeployable) extends Actor
with JammableBehavior
with DamageableEntity
with RepairableEntity {
def JammableObject = sensor
class SensorDeployableControl(sensor: SensorDeployable)
extends Actor
with JammableBehavior
with DamageableEntity
with RepairableEntity {
def JammableObject = sensor
def DamageableObject = sensor
def RepairableObject = sensor
def receive : Receive = jammableBehavior
.orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser)
.orElse {
case _ => ;
}
def receive: Receive =
jammableBehavior
.orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser)
.orElse {
case _ => ;
}
override protected def DamageLog(msg : String) : Unit = { }
override protected def DamageLog(msg: String): Unit = {}
override protected def DestructionAwareness(target : Damageable.Target, cause : ResolvedProjectile) : Unit = {
override protected def DestructionAwareness(target: Damageable.Target, cause: ResolvedProjectile): Unit = {
super.DestructionAwareness(target, cause)
SensorDeployableControl.DestructionAwareness(sensor, PlanetSideGUID(0))
}
override def StartJammeredSound(target : Any, dur : Int) : Unit = target match {
case obj : PlanetSideServerObject if !jammedSound =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 1))
super.StartJammeredSound(obj, dur)
case _ => ;
}
override def StartJammeredStatus(target : Any, dur : Int) : Unit = target match {
case obj : PlanetSideServerObject with JammableUnit if !obj.Jammed =>
val zone = obj.Zone
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, false, 1000))
super.StartJammeredStatus(obj, dur)
case _ => ;
}
override def CancelJammeredSound(target : Any) : Unit = {
override def StartJammeredSound(target: Any, dur: Int): Unit =
target match {
case obj : PlanetSideServerObject if jammedSound =>
case obj: PlanetSideServerObject if !jammedSound =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(
obj.Zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 1)
)
super.StartJammeredSound(obj, dur)
case _ => ;
}
override def StartJammeredStatus(target: Any, dur: Int): Unit =
target match {
case obj: PlanetSideServerObject with JammableUnit if !obj.Jammed =>
val zone = obj.Zone
zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 0))
zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, false, 1000)
)
super.StartJammeredStatus(obj, dur)
case _ => ;
}
override def CancelJammeredSound(target: Any): Unit = {
target match {
case obj: PlanetSideServerObject if jammedSound =>
val zone = obj.Zone
zone.VehicleEvents ! VehicleServiceMessage(
zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 54, 0)
)
case _ => ;
}
super.CancelJammeredSound(target)
}
override def CancelJammeredStatus(target : Any) : Unit = {
override def CancelJammeredStatus(target: Any): Unit = {
target match {
case obj : PlanetSideServerObject with JammableUnit if obj.Jammed =>
sensor.Zone.LocalEvents ! LocalServiceMessage(sensor.Zone.Id, LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, true, 1000))
case obj: PlanetSideServerObject with JammableUnit if obj.Jammed =>
sensor.Zone.LocalEvents ! LocalServiceMessage(
sensor.Zone.Id,
LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", obj.GUID, true, 1000)
)
case _ => ;
}
super.CancelJammeredStatus(target)
@ -102,30 +117,33 @@ class SensorDeployableControl(sensor : SensorDeployable) extends Actor
}
object SensorDeployableControl {
/**
* na
* @param target na
* @param attribution na
*/
def DestructionAwareness(target : Damageable.Target with Deployable, attribution : PlanetSideGUID) : Unit = {
def DestructionAwareness(target: Damageable.Target with Deployable, attribution: PlanetSideGUID): Unit = {
Deployables.AnnounceDestroyDeployable(target, Some(1 seconds))
val zone = target.Zone
zone.LocalEvents ! LocalServiceMessage(zone.Id,
zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerEffectInfo(Service.defaultPlayerGUID, "on", target.GUID, false, 1000)
)
//position the explosion effect near the bulky area of the sensor stalk
val ang = target.Orientation
val explosionPos = {
val pos = target.Position
val explosionPos = {
val pos = target.Position
val yRadians = ang.y.toRadians
val d = Vector3.Rz(Vector3(0, 0.875f, 0), ang.z) * math.sin(yRadians).toFloat
val d = Vector3.Rz(Vector3(0, 0.875f, 0), ang.z) * math.sin(yRadians).toFloat
Vector3(
pos.x + d.x,
pos.y + d.y,
pos.z + math.cos(yRadians).toFloat * 0.875f
)
}
zone.LocalEvents ! LocalServiceMessage(zone.Id,
zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerEffectLocation(Service.defaultPlayerGUID, "motion_sensor_destroyed", explosionPos, ang)
)
//TODO replaced by an alternate model (charred stub)?

View file

@ -17,38 +17,42 @@ import net.psforever.types.PlanetSideGUID
import services.Service
import services.vehicle.{VehicleAction, VehicleServiceMessage}
class ShieldGeneratorDeployable(cdef : ShieldGeneratorDefinition) extends ComplexDeployable(cdef)
with Hackable
with JammableUnit
class ShieldGeneratorDeployable(cdef: ShieldGeneratorDefinition)
extends ComplexDeployable(cdef)
with Hackable
with JammableUnit
class ShieldGeneratorDefinition extends ComplexDeployableDefinition(240) {
Packet = new ShieldGeneratorConverter
DeployCategory = DeployableCategory.ShieldGenerators
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[ShieldGeneratorControl], obj), PlanetSideServerObject.UniqueActorName(obj))
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor =
context.actorOf(Props(classOf[ShieldGeneratorControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
}
}
class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
with JammableBehavior
with DamageableEntity
with RepairableEntity {
def JammableObject = gen
def DamageableObject = gen
def RepairableObject = gen
private var handleDamageToShields : Boolean = false
class ShieldGeneratorControl(gen: ShieldGeneratorDeployable)
extends Actor
with JammableBehavior
with DamageableEntity
with RepairableEntity {
def JammableObject = gen
def DamageableObject = gen
def RepairableObject = gen
private var handleDamageToShields: Boolean = false
def receive : Receive = jammableBehavior
.orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser)
.orElse {
case _ => ;
}
def receive: Receive =
jammableBehavior
.orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser)
.orElse {
case _ => ;
}
/**
* The shield generator has two upgrade paths - blocking projectiles, and providing ammunition like a terminal.
@ -59,44 +63,48 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
* @param player the user of the nano dispenser tool
* @param item the nano dispenser tool
*/
override def CanBeRepairedByNanoDispenser(player : Player, item : Tool) : Unit = {
if(gen.CanRepair) {
override def CanBeRepairedByNanoDispenser(player: Player, item: Tool): Unit = {
if (gen.CanRepair) {
super.CanBeRepairedByNanoDispenser(player, item)
}
else if(!gen.Destroyed) {
} else if (!gen.Destroyed) {
//TODO reinforced shield upgrade not implemented yet
//TODO ammunition supply upgrade not implemented yet
}
}
override protected def PerformDamage(target : Damageable.Target, applyDamageTo : ResolutionCalculations.Output) : Unit = {
val originalHealth = gen.Health
override protected def PerformDamage(
target: Damageable.Target,
applyDamageTo: ResolutionCalculations.Output
): Unit = {
val originalHealth = gen.Health
val originalShields = gen.Shields
val cause = applyDamageTo(target)
val health = gen.Health
val shields = gen.Shields
val damageToHealth = originalHealth - health
val cause = applyDamageTo(target)
val health = gen.Health
val shields = gen.Shields
val damageToHealth = originalHealth - health
val damageToShields = originalShields - shields
val damage = damageToHealth + damageToShields
if(WillAffectTarget(target, damage, cause)) {
val damage = damageToHealth + damageToShields
if (WillAffectTarget(target, damage, cause)) {
target.History(cause)
DamageLog(target,s"BEFORE=$originalHealth/$originalShields, AFTER=$health/$shields, CHANGE=$damageToHealth/$damageToShields")
DamageLog(
target,
s"BEFORE=$originalHealth/$originalShields, AFTER=$health/$shields, CHANGE=$damageToHealth/$damageToShields"
)
handleDamageToShields = damageToShields > 0
HandleDamage(target, cause, damageToHealth)
}
else {
} else {
gen.Health = originalHealth
gen.Shields = originalShields
}
}
override protected def DamageAwareness(target : Damageable.Target, cause : ResolvedProjectile, amount : Int) : Unit = {
override protected def DamageAwareness(target: Damageable.Target, cause: ResolvedProjectile, amount: Int): Unit = {
super.DamageAwareness(target, cause, amount)
ShieldGeneratorControl.DamageAwareness(gen, cause, handleDamageToShields)
handleDamageToShields = false
}
override protected def DestructionAwareness(target : Target, cause : ResolvedProjectile) : Unit = {
override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
super.DestructionAwareness(target, cause)
ShieldGeneratorControl.DestructionAwareness(gen, PlanetSideGUID(0))
}
@ -105,21 +113,28 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
while the shield generator is technically a supported jammable target, how that works is currently unknown
check the object definition for proper feature activation
*/
override def StartJammeredSound(target : Any, dur : Int) : Unit = { }
override def StartJammeredSound(target: Any, dur: Int): Unit = {}
override def StartJammeredStatus(target : Any, dur : Int) : Unit = target match {
case obj : PlanetSideServerObject with JammableUnit if !obj.Jammed =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 1))
super.StartJammeredStatus(obj, dur)
case _ => ;
}
override def CancelJammeredSound(target : Any) : Unit = { }
override def CancelJammeredStatus(target : Any) : Unit = {
override def StartJammeredStatus(target: Any, dur: Int): Unit =
target match {
case obj : PlanetSideServerObject with JammableUnit if obj.Jammed =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(obj.Zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 0))
case obj: PlanetSideServerObject with JammableUnit if !obj.Jammed =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(
obj.Zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 1)
)
super.StartJammeredStatus(obj, dur)
case _ => ;
}
override def CancelJammeredSound(target: Any): Unit = {}
override def CancelJammeredStatus(target: Any): Unit = {
target match {
case obj: PlanetSideServerObject with JammableUnit if obj.Jammed =>
obj.Zone.VehicleEvents ! VehicleServiceMessage(
obj.Zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, obj.GUID, 27, 0)
)
case _ => ;
}
super.CancelJammeredStatus(target)
@ -127,17 +142,21 @@ class ShieldGeneratorControl(gen : ShieldGeneratorDeployable) extends Actor
}
object ShieldGeneratorControl {
/**
* na
* @param target na
* @param cause na
* @param damageToShields na
*/
def DamageAwareness(target : ShieldGeneratorDeployable, cause : ResolvedProjectile, damageToShields : Boolean) : Unit = {
def DamageAwareness(target: ShieldGeneratorDeployable, cause: ResolvedProjectile, damageToShields: Boolean): Unit = {
//shields
if(damageToShields) {
if (damageToShields) {
val zone = target.Zone
zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 68, target.Shields))
zone.VehicleEvents ! VehicleServiceMessage(
zone.Id,
VehicleAction.PlanetsideAttribute(Service.defaultPlayerGUID, target.GUID, 68, target.Shields)
)
}
}
@ -146,7 +165,7 @@ object ShieldGeneratorControl {
* @param target na
* @param attribution na
*/
def DestructionAwareness(target : Damageable.Target with Deployable, attribution : PlanetSideGUID) : Unit = {
def DestructionAwareness(target: Damageable.Target with Deployable, attribution: PlanetSideGUID): Unit = {
Deployables.AnnounceDestroyDeployable(target, None)
}
}

View file

@ -4,12 +4,12 @@ package net.psforever.objects
import net.psforever.objects.definition.SimpleItemDefinition
import net.psforever.objects.equipment.Equipment
class SimpleItem(private val simpDef : SimpleItemDefinition) extends Equipment {
def Definition : SimpleItemDefinition = simpDef
class SimpleItem(private val simpDef: SimpleItemDefinition) extends Equipment {
def Definition: SimpleItemDefinition = simpDef
}
object SimpleItem {
def apply(simpDef : SimpleItemDefinition) : SimpleItem = {
def apply(simpDef: SimpleItemDefinition): SimpleItem = {
new SimpleItem(simpDef)
}
}

View file

@ -8,27 +8,31 @@ import net.psforever.types.{PlanetSideGUID, Vector3}
import scala.collection.mutable
trait SpawnPoint {
psso : PlanetSideServerObject =>
psso: PlanetSideServerObject =>
/**
* An element of the contract of `PlanetSideServerObject`;
* but, this makes it visible to a `SpawnPoint` object without casting.
* @see `Identifiable.GUID`
*/
def GUID : PlanetSideGUID
def GUID: PlanetSideGUID
/**
* An element of the contract of `PlanetSideServerObject`;
* but, this makes it visible to a `SpawnPoint` object without casting.
* @see `WorldEntity.GUID`
* @see `SpecificPoint`
*/
def Position : Vector3
def Position: Vector3
/**
* An element of the contract of `PlanetSideServerObject`;
* but, this makes it visible to a `SpawnPoint` object without casting.
* @see `WorldEntity.GUID`
* @see `SpecificPoint`
*/
def Orientation : Vector3
def Orientation: Vector3
/**
* An element of an unspoken contract with `Amenity`.
* While not all `SpawnPoint` objects will be `Amenity` objects, a subclass of the `PlanetSideServerObject` class,
@ -36,16 +40,17 @@ trait SpawnPoint {
* This should generally be themselves.
* @see `Amenity.Owner`
*/
def Owner : PlanetSideServerObject
def Owner: PlanetSideServerObject
/**
* An element of the contract of `PlanetSideServerObject`;
* but, this makes it visible to a `SpawnPoint` object without casting.
* @see `PlanetSideGameObject.Definition`
* @see `SpecificPoint`
*/
def Definition : ObjectDefinition with SpawnPointDefinition
def Definition: ObjectDefinition with SpawnPointDefinition
def Offline : Boolean = psso.Destroyed
def Offline: Boolean = psso.Destroyed
/**
* Determine a specific position and orientation in which to spawn the target.
@ -53,9 +58,9 @@ trait SpawnPoint {
* the first represents the game world position of spawning;
* the second represents the game world direction of spawning
*/
def SpecificPoint(target : PlanetSideGameObject) : (Vector3, Vector3) = {
def SpecificPoint(target: PlanetSideGameObject): (Vector3, Vector3) = {
psso.Definition match {
case d : SpawnPointDefinition =>
case d: SpawnPointDefinition =>
d.SpecificPoint(this, target)
case _ =>
SpawnPoint.Default(this, target)
@ -64,49 +69,53 @@ trait SpawnPoint {
}
object SpawnPoint {
def Default(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = (obj.Position, obj.Orientation)
def Default(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = (obj.Position, obj.Orientation)
def Tube(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = (
obj.Position + Vector3.z(1.5f),
obj.Orientation.xy + Vector3.z(obj.Orientation.z + 90 % 360)
)
def AMS(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = {
//position the player alongside either of the AMS's terminals, facing away from it
val ori = obj.Orientation
val side = if(System.currentTimeMillis() % 2 == 0) 1 else -1 //right | left
val x = ori.x
val xsin = 3 * side * math.abs(math.sin(math.toRadians(x))).toFloat + 0.5f //sin because 0-degrees is up
val z = ori.z
val zrot = (z + 90) % 360
val zrad = math.toRadians(zrot)
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * (3 * side).toFloat //x=sin, y=cos because compass-0 is East, not North
def Tube(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) =
(
obj.Position + shift + (if(x >= 330) { //ams leaning to the left
Vector3.z(xsin)
}
else { //ams leaning to the right
Vector3.z(-xsin)
}),
if(side == 1) {
obj.Position + Vector3.z(1.5f),
obj.Orientation.xy + Vector3.z(obj.Orientation.z + 90 % 360)
)
def AMS(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
//position the player alongside either of the AMS's terminals, facing away from it
val ori = obj.Orientation
val side = if (System.currentTimeMillis() % 2 == 0) 1 else -1 //right | left
val x = ori.x
val xsin = 3 * side * math.abs(math.sin(math.toRadians(x))).toFloat + 0.5f //sin because 0-degrees is up
val z = ori.z
val zrot = (z + 90) % 360
val zrad = math.toRadians(zrot)
val shift = Vector3(
math.sin(zrad).toFloat,
math.cos(zrad).toFloat,
0
) * (3 * side).toFloat //x=sin, y=cos because compass-0 is East, not North
(
obj.Position + shift + (if (x >= 330) { //ams leaning to the left
Vector3.z(xsin)
} else { //ams leaning to the right
Vector3.z(-xsin)
}),
if (side == 1) {
Vector3.z(zrot)
}
else {
} else {
Vector3.z((z - 90) % 360)
}
)
}
def Gate(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = {
def Gate(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = {
obj.Definition match {
case d : SpawnPointDefinition =>
val ori = target.Orientation
case d: SpawnPointDefinition =>
val ori = target.Orientation
val zrad = math.toRadians(ori.z)
val radius = scala.math.random.toFloat * d.UseRadius/2 + 20f //20 is definitely outside of the gating energy field
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * radius
val radius =
scala.math.random.toFloat * d.UseRadius / 2 + 20f //20 is definitely outside of the gating energy field
val shift = Vector3(math.sin(zrad).toFloat, math.cos(zrad).toFloat, 0) * radius
val altitudeShift = target.Definition match {
case vdef : VehicleDefinition if GlobalDefinitions.isFlightVehicle(vdef) =>
Vector3.z(scala.math.random.toFloat * d.UseRadius/4 + 20f)
case vdef: VehicleDefinition if GlobalDefinitions.isFlightVehicle(vdef) =>
Vector3.z(scala.math.random.toFloat * d.UseRadius / 4 + 20f)
case _ =>
Vector3.Zero
}
@ -118,46 +127,45 @@ object SpawnPoint {
}
trait SpawnPointDefinition {
private var radius : Float = 0f //m
private var delay : Long = 0 //s
private var noWarp : Option[mutable.Set[VehicleDefinition]] = None
private var spawningFunc : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = SpawnPoint.Default
private var radius: Float = 0f //m
private var delay: Long = 0 //s
private var noWarp: Option[mutable.Set[VehicleDefinition]] = None
private var spawningFunc: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = SpawnPoint.Default
def UseRadius : Float = radius
def UseRadius: Float = radius
def UseRadius_=(rad : Float) : Float = {
def UseRadius_=(rad: Float): Float = {
radius = rad
UseRadius
}
def Delay : Long = delay
def Delay: Long = delay
def Delay_=(toDelay : Long) : Long = {
def Delay_=(toDelay: Long): Long = {
delay = toDelay
Delay
}
def VehicleAllowance : Boolean = noWarp.isDefined
def VehicleAllowance: Boolean = noWarp.isDefined
def VehicleAllowance_=(allow : Boolean) : Boolean = {
if(allow && noWarp.isEmpty) {
def VehicleAllowance_=(allow: Boolean): Boolean = {
if (allow && noWarp.isEmpty) {
noWarp = Some(mutable.Set.empty[VehicleDefinition])
}
else if(!allow && noWarp.isDefined) {
} else if (!allow && noWarp.isDefined) {
noWarp = None
}
VehicleAllowance
}
def NoWarp : mutable.Set[VehicleDefinition] = {
def NoWarp: mutable.Set[VehicleDefinition] = {
noWarp.getOrElse(mutable.Set.empty[VehicleDefinition])
}
def SpecificPointFunc : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = spawningFunc
def SpecificPointFunc: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3) = spawningFunc
def SpecificPointFunc_=(func : (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3)) : Unit = {
def SpecificPointFunc_=(func: (SpawnPoint, PlanetSideGameObject) => (Vector3, Vector3)): Unit = {
spawningFunc = func
}
def SpecificPoint(obj : SpawnPoint, target : PlanetSideGameObject) : (Vector3, Vector3) = spawningFunc(obj, target)
def SpecificPoint(obj: SpawnPoint, target: PlanetSideGameObject): (Vector3, Vector3) = spawningFunc(obj, target)
}

View file

@ -4,11 +4,10 @@ package net.psforever.objects
import net.psforever.objects.ce.TelepadLike
import net.psforever.objects.definition.ConstructionItemDefinition
class Telepad(private val cdef : ConstructionItemDefinition) extends ConstructionItem(cdef)
with TelepadLike
class Telepad(private val cdef: ConstructionItemDefinition) extends ConstructionItem(cdef) with TelepadLike
object Telepad {
def apply(cdef : ConstructionItemDefinition) : Telepad = {
def apply(cdef: ConstructionItemDefinition): Telepad = {
new Telepad(cdef)
}
}
}

View file

@ -4,5 +4,4 @@ package net.psforever.objects
import net.psforever.objects.ce.{SimpleDeployable, TelepadLike}
import net.psforever.objects.definition.SimpleDeployableDefinition
class TelepadDeployable(ddef : SimpleDeployableDefinition) extends SimpleDeployable(ddef)
with TelepadLike
class TelepadDeployable(ddef: SimpleDeployableDefinition) extends SimpleDeployable(ddef) with TelepadLike

View file

@ -17,77 +17,79 @@ import scala.annotation.tailrec
* Some weapons Chainblade have ammunition but do not consume it.
* @param toolDef the `ObjectDefinition` that constructs this item and maintains some of its immutable fields
*/
class Tool(private val toolDef : ToolDefinition) extends Equipment
with FireModeSwitch[FireModeDefinition]
with JammableUnit {
class Tool(private val toolDef: ToolDefinition)
extends Equipment
with FireModeSwitch[FireModeDefinition]
with JammableUnit {
/** index of the current fire mode on the `ToolDefinition`'s list of fire modes */
private var fireModeIndex : Int = toolDef.DefaultFireModeIndex
private var fireModeIndex: Int = toolDef.DefaultFireModeIndex
/** current ammunition slot being used by this fire mode */
private var ammoSlots : List[Tool.FireModeSlot] = List.empty
var lastDischarge : Long = 0
private var ammoSlots: List[Tool.FireModeSlot] = List.empty
var lastDischarge: Long = 0
Tool.LoadDefinition(this)
def FireModeIndex : Int = fireModeIndex
def FireModeIndex: Int = fireModeIndex
def FireModeIndex_=(index : Int) : Int = {
def FireModeIndex_=(index: Int): Int = {
fireModeIndex = index % Definition.FireModes.length
FireModeIndex
}
def FireMode : FireModeDefinition = Definition.FireModes(fireModeIndex)
def FireMode: FireModeDefinition = Definition.FireModes(fireModeIndex)
def NextFireMode : FireModeDefinition = {
def NextFireMode: FireModeDefinition = {
FireModeIndex = Definition.NextFireModeIndex(FireModeIndex)
AmmoSlot.Chamber = FireMode.Chamber
FireMode
}
def ToFireMode : Int = Definition.NextFireModeIndex(FireModeIndex)
def ToFireMode: Int = Definition.NextFireModeIndex(FireModeIndex)
def ToFireMode_=(index : Int) : FireModeDefinition = {
def ToFireMode_=(index: Int): FireModeDefinition = {
FireModeIndex = index
AmmoSlot.Chamber = FireMode.Chamber
FireMode
}
def AmmoTypeIndex : Int = FireMode.AmmoTypeIndices(AmmoSlot.AmmoTypeIndex)
def AmmoTypeIndex: Int = FireMode.AmmoTypeIndices(AmmoSlot.AmmoTypeIndex)
def AmmoTypeIndex_=(index : Int) : Int = {
def AmmoTypeIndex_=(index: Int): Int = {
AmmoSlot.AmmoTypeIndex = index % FireMode.AmmoTypeIndices.length
AmmoTypeIndex
}
def AmmoType : Ammo.Value = Definition.AmmoTypes(AmmoTypeIndex).AmmoType
def AmmoType: Ammo.Value = Definition.AmmoTypes(AmmoTypeIndex).AmmoType
def NextAmmoType : Ammo.Value = {
def NextAmmoType: Ammo.Value = {
AmmoSlot.AmmoTypeIndex = AmmoSlot.AmmoTypeIndex + 1
AmmoType
}
def Projectile : ProjectileDefinition = {
def Projectile: ProjectileDefinition = {
Definition.ProjectileTypes({
val projIndices = FireMode.ProjectileTypeIndices
if(projIndices.isEmpty) {
if (projIndices.isEmpty) {
AmmoTypeIndex //e.g., bullet_9mm -> bullet_9mm_projectile, bullet_9mm_AP -> bullet_9mm_AP_projectile
}
else {
} else {
projIndices(AmmoSlot.AmmoTypeIndex) //e.g., pulsar: f.mode1 -> pulsar_projectile, f.mode2 = pulsar_ap_projectile
}
})
}
def ProjectileType : Projectiles.Value = Projectile.ProjectileType
def ProjectileType: Projectiles.Value = Projectile.ProjectileType
def Magazine : Int = AmmoSlot.Magazine
def Magazine: Int = AmmoSlot.Magazine
def Magazine_=(mag : Int) : Int = {
def Magazine_=(mag: Int): Int = {
//AmmoSlot.Magazine = Math.min(Math.max(0, mag), MaxMagazine)
AmmoSlot.Magazine = Math.max(0, mag)
Magazine
}
def MaxMagazine : Int = {
def MaxMagazine: Int = {
val fmode = FireMode
fmode.CustomMagazine.get(AmmoType) match {
case Some(magSize) =>
@ -97,30 +99,30 @@ class Tool(private val toolDef : ToolDefinition) extends Equipment
}
}
def Discharge(rounds : Option[Int] = None) : Int = {
def Discharge(rounds: Option[Int] = None): Int = {
lastDischarge = System.nanoTime()
Magazine = FireMode.Discharge(this, rounds)
}
def LastDischarge : Long = {
def LastDischarge: Long = {
lastDischarge
}
def AmmoSlot : Tool.FireModeSlot = ammoSlots(FireMode.AmmoSlotIndex)
def AmmoSlot: Tool.FireModeSlot = ammoSlots(FireMode.AmmoSlotIndex)
def AmmoSlots : List[Tool.FireModeSlot] = ammoSlots
def AmmoSlots: List[Tool.FireModeSlot] = ammoSlots
def MaxAmmoSlot : Int = ammoSlots.length
def MaxAmmoSlot: Int = ammoSlots.length
def Definition : ToolDefinition = toolDef
def Definition: ToolDefinition = toolDef
override def toString : String = Tool.toString(this)
override def toString: String = Tool.toString(this)
}
//AmmoType = Definition.AmmoTypes( (Definition.FireModes(fireModeIndex)).AmmoTypeIndices( (ammoSlots((Definition.FireModes(fireModeIndex)).AmmoSlotIndex)).AmmoTypeIndex) ).AmmoType
object Tool {
def apply(toolDef : ToolDefinition) : Tool = {
def apply(toolDef: ToolDefinition): Tool = {
new Tool(toolDef)
}
@ -128,28 +130,34 @@ object Tool {
* Use the `*Definition` that was provided to this object to initialize its fields and settings.
* @param tool the `Tool` being initialized
*/
def LoadDefinition(tool : Tool) : Unit = {
val tdef : ToolDefinition = tool.Definition
val maxSlot = tdef.FireModes.maxBy(fmode => fmode.AmmoSlotIndex).AmmoSlotIndex
def LoadDefinition(tool: Tool): Unit = {
val tdef: ToolDefinition = tool.Definition
val maxSlot = tdef.FireModes.maxBy(fmode => fmode.AmmoSlotIndex).AmmoSlotIndex
tool.ammoSlots = buildFireModes(tdef, (0 to maxSlot).iterator, tdef.FireModes.toList)
}
@tailrec private def buildFireModes(tdef : ToolDefinition, iter : Iterator[Int], fmodes : List[FireModeDefinition], list : List[FireModeSlot] = Nil) : List[FireModeSlot] = {
if(!iter.hasNext) {
@tailrec private def buildFireModes(
tdef: ToolDefinition,
iter: Iterator[Int],
fmodes: List[FireModeDefinition],
list: List[FireModeSlot] = Nil
): List[FireModeSlot] = {
if (!iter.hasNext) {
list
}
else {
} else {
val index = iter.next
fmodes.filter(fmode => fmode.AmmoSlotIndex == index) match {
case fmode :: _ =>
buildFireModes(tdef, iter, fmodes, list :+ new FireModeSlot(tdef, fmode))
case Nil =>
throw new IllegalArgumentException(s"tool ${tdef.Name} ammo slot #$index is missing a fire mode specification; do not skip")
throw new IllegalArgumentException(
s"tool ${tdef.Name} ammo slot #$index is missing a fire mode specification; do not skip"
)
}
}
}
def toString(obj : Tool) : String = {
def toString(obj: Tool): String = {
s"${obj.Definition.Name} (mode=${obj.FireModeIndex}-${obj.AmmoType})(${obj.Magazine}/${obj.MaxMagazine})"
}
@ -166,24 +174,26 @@ object Tool {
* two exclusive groups of ammunition divided into 2 cycled types and 4 cycled types -
* is an example of a weapon that benefits from this implementation.
*/
class FireModeSlot(private val tdef : ToolDefinition, private val fdef : FireModeDefinition) {
class FireModeSlot(private val tdef: ToolDefinition, private val fdef: FireModeDefinition) {
/**
* if this fire mode has multiple types of ammunition
* this is the index of the fire mode's ammo List, not a reference to the tool's ammo List
*/
private var ammoTypeIndex : Int = 0
private var ammoTypeIndex: Int = 0
/** a reference to the actual `AmmoBox` of this slot */
private var box : AmmoBox = AmmoBox(AmmoDefinition, fdef.Magazine)
private var chamber = fdef.Chamber
private var box: AmmoBox = AmmoBox(AmmoDefinition, fdef.Magazine)
private var chamber = fdef.Chamber
def AmmoTypeIndex : Int = ammoTypeIndex
def AmmoTypeIndex: Int = ammoTypeIndex
def AmmoTypeIndex_=(index : Int) : Int = {
def AmmoTypeIndex_=(index: Int): Int = {
ammoTypeIndex = index % fdef.AmmoTypeIndices.length
AmmoTypeIndex
}
private def AmmoDefinition : AmmoBoxDefinition = {
private def AmmoDefinition: AmmoBoxDefinition = {
tdef.AmmoTypes(fdef.AmmoTypeIndices(ammoTypeIndex))
}
@ -193,40 +203,39 @@ object Tool {
* Generally, convert from this index, to the index in the fire mode's ammunition list, to the index in the `ToolDefinition`'s ammunition list.
* @return the `Ammo` type that should be loaded into the magazine right now
*/
def AmmoType : Ammo.Value = AmmoDefinition.AmmoType
def AmmoType: Ammo.Value = AmmoDefinition.AmmoType
def AllAmmoTypes : List[Ammo.Value] = {
def AllAmmoTypes: List[Ammo.Value] = {
fdef.AmmoTypeIndices.map(index => tdef.AmmoTypes(fdef.AmmoTypeIndices(index)).AmmoType).toList
}
def Magazine : Int = box.Capacity
def Magazine: Int = box.Capacity
def Magazine_=(mag : Int) : Int = {
def Magazine_=(mag: Int): Int = {
box.Capacity = mag
Magazine
}
def Chamber : Int = chamber
def Chamber: Int = chamber
def Chamber_=(chmbr : Int) : Int = {
def Chamber_=(chmbr: Int): Int = {
chamber = math.min(math.max(0, chmbr), fdef.Chamber)
Chamber
}
def Box : AmmoBox = box
def Box: AmmoBox = box
def Box_=(toBox : AmmoBox) : Option[AmmoBox] = {
if(toBox.AmmoType == AmmoType) {
def Box_=(toBox: AmmoBox): Option[AmmoBox] = {
if (toBox.AmmoType == AmmoType) {
box = toBox
Some(Box)
}
else {
} else {
None
}
}
def Tool : ToolDefinition = tdef
def Tool: ToolDefinition = tdef
def Definition : FireModeDefinition = fdef
def Definition: FireModeDefinition = fdef
}
}

View file

@ -11,40 +11,39 @@ import net.psforever.objects.serverobject.damage.{Damageable, DamageableEntity}
import net.psforever.objects.serverobject.repair.RepairableEntity
import net.psforever.objects.vital.StandardResolutions
class TrapDeployable(cdef : TrapDeployableDefinition) extends ComplexDeployable(cdef)
class TrapDeployable(cdef: TrapDeployableDefinition) extends ComplexDeployable(cdef)
class TrapDeployableDefinition(objectId : Int) extends ComplexDeployableDefinition(objectId) {
class TrapDeployableDefinition(objectId: Int) extends ComplexDeployableDefinition(objectId) {
Model = StandardResolutions.SimpleDeployables
Packet = new TRAPConverter
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[TrapDeployableControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
}
}
object TrapDeployableDefinition {
def apply(dtype : DeployedItem.Value) : TrapDeployableDefinition = {
def apply(dtype: DeployedItem.Value): TrapDeployableDefinition = {
new TrapDeployableDefinition(dtype.id)
}
}
class TrapDeployableControl(trap : TrapDeployable) extends Actor
with DamageableEntity
with RepairableEntity {
class TrapDeployableControl(trap: TrapDeployable) extends Actor with DamageableEntity with RepairableEntity {
def DamageableObject = trap
def RepairableObject = trap
def receive : Receive = takesDamage
.orElse(canBeRepairedByNanoDispenser)
.orElse {
case _ =>
}
def receive: Receive =
takesDamage
.orElse(canBeRepairedByNanoDispenser)
.orElse {
case _ =>
}
override protected def DestructionAwareness(target : Damageable.Target, cause : ResolvedProjectile) : Unit = {
override protected def DestructionAwareness(target: Damageable.Target, cause: ResolvedProjectile): Unit = {
super.DestructionAwareness(target, cause)
Deployables.AnnounceDestroyDeployable(trap, None)
}

View file

@ -17,19 +17,21 @@ import net.psforever.objects.serverobject.repair.RepairableWeaponTurret
import net.psforever.objects.serverobject.turret.{TurretDefinition, WeaponTurret}
import net.psforever.objects.vital.{StandardResolutions, StandardVehicleDamage, StandardVehicleResistance}
class TurretDeployable(tdef : TurretDeployableDefinition) extends ComplexDeployable(tdef)
with WeaponTurret
with JammableUnit
with Hackable {
class TurretDeployable(tdef: TurretDeployableDefinition)
extends ComplexDeployable(tdef)
with WeaponTurret
with JammableUnit
with Hackable {
WeaponTurret.LoadDefinition(this)
def MountPoints : Map[Int, Int] = Definition.MountPoints.toMap
def MountPoints: Map[Int, Int] = Definition.MountPoints.toMap
override def Definition = tdef
}
class TurretDeployableDefinition(private val objectId : Int) extends ComplexDeployableDefinition(objectId)
with TurretDefinition {
class TurretDeployableDefinition(private val objectId: Int)
extends ComplexDeployableDefinition(objectId)
with TurretDefinition {
Name = "turret_deployable"
Packet = new SmallTurretConverter
DamageUsing = StandardVehicleDamage
@ -37,51 +39,53 @@ class TurretDeployableDefinition(private val objectId : Int) extends ComplexDepl
Model = StandardResolutions.FacilityTurrets
//override to clarify inheritance conflict
override def MaxHealth : Int = super[ComplexDeployableDefinition].MaxHealth
override def MaxHealth: Int = super[ComplexDeployableDefinition].MaxHealth
//override to clarify inheritance conflict
override def MaxHealth_=(max : Int) : Int = super[ComplexDeployableDefinition].MaxHealth_=(max)
override def MaxHealth_=(max: Int): Int = super[ComplexDeployableDefinition].MaxHealth_=(max)
override def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
override def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
obj.Actor = context.actorOf(Props(classOf[TurretControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
override def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) = {
override def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext) = {
SimpleDeployableDefinition.SimpleUninitialize(obj, context)
}
}
object TurretDeployableDefinition {
def apply(dtype : DeployedItem.Value) : TurretDeployableDefinition = {
def apply(dtype: DeployedItem.Value): TurretDeployableDefinition = {
new TurretDeployableDefinition(dtype.id)
}
}
/** control actors */
class TurretControl(turret : TurretDeployable) extends Actor
with FactionAffinityBehavior.Check
with JammableMountedWeapons //note: jammable status is reported as vehicle events, not local events
with MountableBehavior.TurretMount
with MountableBehavior.Dismount
with DamageableWeaponTurret
with RepairableWeaponTurret {
def MountableObject = turret
def JammableObject = turret
def FactionObject = turret
class TurretControl(turret: TurretDeployable)
extends Actor
with FactionAffinityBehavior.Check
with JammableMountedWeapons //note: jammable status is reported as vehicle events, not local events
with MountableBehavior.TurretMount
with MountableBehavior.Dismount
with DamageableWeaponTurret
with RepairableWeaponTurret {
def MountableObject = turret
def JammableObject = turret
def FactionObject = turret
def DamageableObject = turret
def RepairableObject = turret
def receive : Receive = checkBehavior
.orElse(jammableBehavior)
.orElse(mountBehavior)
.orElse(dismountBehavior)
.orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser)
.orElse {
case _ => ;
}
def receive: Receive =
checkBehavior
.orElse(jammableBehavior)
.orElse(mountBehavior)
.orElse(dismountBehavior)
.orElse(takesDamage)
.orElse(canBeRepairedByNanoDispenser)
.orElse {
case _ => ;
}
override protected def DestructionAwareness(target : Target, cause : ResolvedProjectile) : Unit = {
override protected def DestructionAwareness(target: Target, cause: ResolvedProjectile): Unit = {
super.DestructionAwareness(target, cause)
Deployables.AnnounceDestroyDeployable(turret, None)
}

View file

@ -66,45 +66,48 @@ import scala.util.{Success, Try}
* stores and unloads pertinent information about the `Vehicle`'s configuration;
* used in the initialization process (`loadVehicleDefinition`)
*/
class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
with Hackable
with FactionAffinity
with Mountable
with MountedWeapons
with Deployment
with Vitality
with OwnableByPlayer
with StandardResistanceProfile
with JammableUnit
with Container {
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
private var shields : Int = 0
private var decal : Int = 0
private var trunkAccess : Option[PlanetSideGUID] = None
private var jammered : Boolean = false
private var cloaked : Boolean = false
private var flying : Boolean = false
private var ntuCapacitor : Int = 0
private var capacitor : Int = 0
class Vehicle(private val vehicleDef: VehicleDefinition)
extends AmenityOwner
with Hackable
with FactionAffinity
with Mountable
with MountedWeapons
with Deployment
with Vitality
with OwnableByPlayer
with StandardResistanceProfile
with JammableUnit
with Container {
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
private var shields: Int = 0
private var decal: Int = 0
private var trunkAccess: Option[PlanetSideGUID] = None
private var jammered: Boolean = false
private var cloaked: Boolean = false
private var flying: Boolean = false
private var ntuCapacitor: Int = 0
private var capacitor: Int = 0
/**
* Permissions control who gets to access different parts of the vehicle;
* the groups are Driver (seat), Gunner (seats), Passenger (seats), and the Trunk
*/
private val groupPermissions : Array[VehicleLockState.Value] = Array(VehicleLockState.Locked, VehicleLockState.Empire, VehicleLockState.Empire, VehicleLockState.Locked)
private var seats : Map[Int, Seat] = Map.empty
private var cargoHolds : Map[Int, Cargo] = Map.empty
private var weapons : Map[Int, EquipmentSlot] = Map.empty
private var utilities : Map[Int, Utility] = Map()
private val trunk : GridInventory = GridInventory()
private val groupPermissions: Array[VehicleLockState.Value] =
Array(VehicleLockState.Locked, VehicleLockState.Empire, VehicleLockState.Empire, VehicleLockState.Locked)
private var seats: Map[Int, Seat] = Map.empty
private var cargoHolds: Map[Int, Cargo] = Map.empty
private var weapons: Map[Int, EquipmentSlot] = Map.empty
private var utilities: Map[Int, Utility] = Map()
private val trunk: GridInventory = GridInventory()
/**
* Records the GUID of the cargo vehicle (galaxy/lodestar) this vehicle is stored in for DismountVehicleCargoMsg use
* DismountVehicleCargoMsg only passes the player_guid and this vehicle's guid
*/
private var mountedIn : Option[PlanetSideGUID] = None
private var mountedIn: Option[PlanetSideGUID] = None
private var vehicleGatingManifest : Option[VehicleManifest] = None
private var previousVehicleGatingManifest : Option[VehicleManifest] = None
private var vehicleGatingManifest: Option[VehicleManifest] = None
private var previousVehicleGatingManifest: Option[VehicleManifest] = None
//init
LoadDefinition()
@ -113,15 +116,15 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* Override this method to perform any special setup that is not standardized to `*Definition`.
* @see `Vehicle.LoadDefinition`
*/
protected def LoadDefinition() : Unit = {
protected def LoadDefinition(): Unit = {
Vehicle.LoadDefinition(this)
}
def Faction : PlanetSideEmpire.Value = {
def Faction: PlanetSideEmpire.Value = {
this.faction
}
override def Faction_=(faction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
override def Faction_=(faction: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
this.faction = faction
faction
}
@ -129,13 +132,13 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
/** How long it takes to jack the vehicle in seconds, based on the hacker's certification level */
def JackingDuration: Array[Int] = Definition.JackingDuration
def MountedIn : Option[PlanetSideGUID] = {
def MountedIn: Option[PlanetSideGUID] = {
this.mountedIn
}
def MountedIn_=(cargo_vehicle_guid : PlanetSideGUID) : Option[PlanetSideGUID] = MountedIn_=(Some(cargo_vehicle_guid))
def MountedIn_=(cargo_vehicle_guid: PlanetSideGUID): Option[PlanetSideGUID] = MountedIn_=(Some(cargo_vehicle_guid))
def MountedIn_=(cargo_vehicle_guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
def MountedIn_=(cargo_vehicle_guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
cargo_vehicle_guid match {
case Some(_) =>
this.mountedIn = cargo_vehicle_guid
@ -145,61 +148,61 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
MountedIn
}
override def Health_=(assignHealth : Int) : Int = {
override def Health_=(assignHealth: Int): Int = {
//TODO should vehicle class enforce this?
if(!Destroyed) {
if (!Destroyed) {
super.Health_=(assignHealth)
}
Health
}
def Shields : Int = {
def Shields: Int = {
shields
}
def Shields_=(strength : Int) : Int = {
def Shields_=(strength: Int): Int = {
shields = math.min(math.max(0, strength), MaxShields)
Shields
}
def MaxShields : Int = {
def MaxShields: Int = {
Definition.MaxShields
}
def Decal : Int = {
def Decal: Int = {
decal
}
def Decal_=(logo : Int) : Int = {
def Decal_=(logo: Int): Int = {
decal = logo
Decal
}
def Jammered : Boolean = jammered
def Jammered: Boolean = jammered
def Jammered_=(jamState : Boolean) : Boolean = {
def Jammered_=(jamState: Boolean): Boolean = {
jammered = jamState
Jammered
}
def Cloaked : Boolean = cloaked
def Cloaked: Boolean = cloaked
def Cloaked_=(isCloaked : Boolean) : Boolean = {
def Cloaked_=(isCloaked: Boolean): Boolean = {
cloaked = isCloaked
Cloaked
}
def Flying : Boolean = flying
def Flying: Boolean = flying
def Flying_=(isFlying : Boolean) : Boolean = {
def Flying_=(isFlying: Boolean): Boolean = {
flying = isFlying
Flying
}
def NtuCapacitor : Int = ntuCapacitor
def NtuCapacitor: Int = ntuCapacitor
def NtuCapacitor_=(value: Int) : Int = {
if(value > Definition.MaxNtuCapacitor) {
def NtuCapacitor_=(value: Int): Int = {
if (value > Definition.MaxNtuCapacitor) {
ntuCapacitor = Definition.MaxNtuCapacitor
} else if (value < 0) {
ntuCapacitor = 0
@ -218,9 +221,9 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
}
def Capacitor : Int = capacitor
def Capacitor_=(value: Int) : Int = {
if(value > Definition.MaxCapacitor) {
def Capacitor_=(value: Int): Int = {
if (value > Definition.MaxCapacitor) {
capacitor = Definition.MaxCapacitor
} else if (value < 0) {
capacitor = 0
@ -235,18 +238,18 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param mountPoint an index representing the seat position / mounting point
* @return a seat number, or `None`
*/
def GetSeatFromMountPoint(mountPoint : Int) : Option[Int] = {
def GetSeatFromMountPoint(mountPoint: Int): Option[Int] = {
Definition.MountPoints.get(mountPoint)
}
def MountPoints : Map[Int, Int] = Definition.MountPoints.toMap
def MountPoints: Map[Int, Int] = Definition.MountPoints.toMap
/**
* What are the access permissions for a position on this vehicle, seats or trunk?
* @param group the group index
* @return what sort of access permission exist for this group
*/
def PermissionGroup(group : Int) : Option[VehicleLockState.Value] = {
def PermissionGroup(group: Int): Option[VehicleLockState.Value] = {
reindexPermissionsGroup(group) match {
case Some(index) =>
Some(groupPermissions(index))
@ -262,16 +265,17 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @return the new access permission for this group;
* `None`, if the group does not exist or the level of permission was not changed
*/
def PermissionGroup(group : Int, level : Long) : Option[VehicleLockState.Value] = {
def PermissionGroup(group: Int, level: Long): Option[VehicleLockState.Value] = {
reindexPermissionsGroup(group) match {
case Some(index) =>
val current = groupPermissions(index)
val next = try { VehicleLockState(level.toInt) } catch { case _ : Exception => groupPermissions(index) }
if(current != next) {
val next =
try { VehicleLockState(level.toInt) }
catch { case _: Exception => groupPermissions(index) }
if (current != next) {
groupPermissions(index) = next
PermissionGroup(index)
}
else {
} else {
None
}
case None =>
@ -285,15 +289,14 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param group the group index
* @return the modified group index
*/
private def reindexPermissionsGroup(group : Int) : Option[Int] = if(group > 9 && group < 14) {
Some(group - 10)
}
else if(group > -1 && group < 4) {
Some(group)
}
else {
None
}
private def reindexPermissionsGroup(group: Int): Option[Int] =
if (group > 9 && group < 14) {
Some(group - 10)
} else if (group > -1 && group < 4) {
Some(group)
} else {
None
}
/**
* Get the seat at the index.
@ -301,37 +304,34 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param seatNumber an index representing the seat position / mounting point
* @return a `Seat`, or `None`
*/
def Seat(seatNumber : Int) : Option[Seat] = {
if(seatNumber >= 0 && seatNumber < this.seats.size) {
def Seat(seatNumber: Int): Option[Seat] = {
if (seatNumber >= 0 && seatNumber < this.seats.size) {
this.seats.get(seatNumber)
}
else {
} else {
None
}
}
def Seats : Map[Int, Seat] = {
def Seats: Map[Int, Seat] = {
seats
}
def CargoHold(cargoNumber : Int) : Option[Cargo] = {
if(cargoNumber >= 0) {
def CargoHold(cargoNumber: Int): Option[Cargo] = {
if (cargoNumber >= 0) {
this.cargoHolds.get(cargoNumber)
}
else {
} else {
None
}
}
def CargoHolds : Map[Int, Cargo] = {
def CargoHolds: Map[Int, Cargo] = {
cargoHolds
}
def SeatPermissionGroup(seatNumber : Int) : Option[AccessPermissionGroup.Value] = {
if(seatNumber == 0) {
def SeatPermissionGroup(seatNumber: Int): Option[AccessPermissionGroup.Value] = {
if (seatNumber == 0) {
Some(AccessPermissionGroup.Driver)
}
else {
} else {
Seat(seatNumber) match {
case Some(seat) =>
seat.ControlledWeapon match {
@ -351,14 +351,14 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
}
}
def Weapons : Map[Int, EquipmentSlot] = weapons
def Weapons: Map[Int, EquipmentSlot] = weapons
/**
* Get the weapon at the index.
* @param wepNumber an index representing the seat position / mounting point
* @return a weapon, or `None`
*/
def ControlledWeapon(wepNumber : Int) : Option[Equipment] = {
def ControlledWeapon(wepNumber: Int): Option[Equipment] = {
weapons.get(wepNumber) match {
case Some(mount) =>
mount.Equipment
@ -372,45 +372,42 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param player the player
* @return a seat number, or `None` if the `player` is not actually seated in this vehicle
*/
def PassengerInSeat(player : Player) : Option[Int] = recursivePassengerInSeat(seats.iterator, player)
def PassengerInSeat(player: Player): Option[Int] = recursivePassengerInSeat(seats.iterator, player)
@tailrec private def recursivePassengerInSeat(iter : Iterator[(Int, Seat)], player : Player) : Option[Int] = {
if(!iter.hasNext) {
@tailrec private def recursivePassengerInSeat(iter: Iterator[(Int, Seat)], player: Player): Option[Int] = {
if (!iter.hasNext) {
None
}
else {
} else {
val (seatNumber, seat) = iter.next
if(seat.Occupant.contains(player)) {
if (seat.Occupant.contains(player)) {
Some(seatNumber)
}
else {
} else {
recursivePassengerInSeat(iter, player)
}
}
}
def Utilities : Map[Int, Utility] = utilities
def Utilities: Map[Int, Utility] = utilities
/**
* Get a reference to a certain `Utility` attached to this `Vehicle`.
* @param utilNumber the attachment number of the `Utility`
* @return the `Utility` or `None` (if invalid)
*/
def Utility(utilNumber : Int) : Option[PlanetSideServerObject] = {
if(utilNumber >= 0 && utilNumber < this.utilities.size) {
def Utility(utilNumber: Int): Option[PlanetSideServerObject] = {
if (utilNumber >= 0 && utilNumber < this.utilities.size) {
this.utilities.get(utilNumber) match {
case Some(util) =>
Some(util())
case None =>
None
}
}
else {
} else {
None
}
}
def Utility(utilType : UtilityType.Value) : Option[PlanetSideServerObject] = {
def Utility(utilType: UtilityType.Value): Option[PlanetSideServerObject] = {
utilities.values.find(_.UtilType == utilType) match {
case Some(util) =>
Some(util())
@ -423,35 +420,37 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
override def UndeployTime = Definition.UndeployTime
def Inventory : GridInventory = trunk
def Inventory: GridInventory = trunk
def VisibleSlots : Set[Int] = weapons.keySet
def VisibleSlots: Set[Int] = weapons.keySet
override def Slot(slotNum : Int) : EquipmentSlot = {
weapons.get(slotNum)
// .orElse(utilities.get(slotNum) match {
// case Some(_) =>
// //TODO what do now?
// None
// case None => ;
// None
// })
.orElse(Some(Inventory.Slot(slotNum))).get
override def Slot(slotNum: Int): EquipmentSlot = {
weapons
.get(slotNum)
// .orElse(utilities.get(slotNum) match {
// case Some(_) =>
// //TODO what do now?
// None
// case None => ;
// None
// })
.orElse(Some(Inventory.Slot(slotNum)))
.get
}
override def Find(guid : PlanetSideGUID) : Option[Int] = {
weapons.find({ case (_, obj) =>
obj.Equipment match {
case Some(item) =>
if(item.HasGUID && item.GUID == guid) {
true
}
else {
override def Find(guid: PlanetSideGUID): Option[Int] = {
weapons.find({
case (_, obj) =>
obj.Equipment match {
case Some(item) =>
if (item.HasGUID && item.GUID == guid) {
true
} else {
false
}
case None =>
false
}
case None =>
false
}
}
}) match {
case Some((index, _)) =>
Some(index)
@ -460,7 +459,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
}
}
override def Collisions(dest : Int, width : Int, height : Int) : Try[List[InventoryItem]] = {
override def Collisions(dest: Int, width: Int, height: Int): Try[List[InventoryItem]] = {
weapons.get(dest) match {
case Some(slot) =>
slot.Equipment match {
@ -478,13 +477,13 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* A reference to the `Vehicle` `Trunk` space.
* @return this `Vehicle` `Trunk`
*/
def Trunk : GridInventory = {
def Trunk: GridInventory = {
this.trunk
}
def AccessingTrunk : Option[PlanetSideGUID] = trunkAccess
def AccessingTrunk: Option[PlanetSideGUID] = trunkAccess
def AccessingTrunk_=(guid : PlanetSideGUID) : Option[PlanetSideGUID] = {
def AccessingTrunk_=(guid: PlanetSideGUID): Option[PlanetSideGUID] = {
AccessingTrunk = Some(guid)
}
@ -494,12 +493,12 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param guid the player who wishes to access the trunk
* @return the player who is currently allowed to access the trunk
*/
def AccessingTrunk_=(guid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
def AccessingTrunk_=(guid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
guid match {
case None =>
trunkAccess = None
case Some(player) =>
if(trunkAccess.isEmpty) {
if (trunkAccess.isEmpty) {
trunkAccess = Some(player)
}
}
@ -511,8 +510,8 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* @param player a player attempting to access this `Trunk`
* @return `true`, if the `player` is permitted access; `false`, otherwise
*/
def CanAccessTrunk(player : Player) : Boolean = {
if(trunkAccess.isEmpty || trunkAccess.contains(player.GUID)) {
def CanAccessTrunk(player: Player): Boolean = {
if (trunkAccess.isEmpty || trunkAccess.contains(player.GUID)) {
groupPermissions(3) match {
case VehicleLockState.Locked => //only the owner
Owner.isEmpty || (Owner.isDefined && player.GUID == Owner.get)
@ -521,8 +520,7 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
case VehicleLockState.Empire => //anyone of the owner's faction
faction == player.Faction
}
}
else {
} else {
false
}
}
@ -531,18 +529,18 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* Check access to the `Trunk`.
* @return the current access value for the `Vehicle` `Trunk`
*/
def TrunkLockState : VehicleLockState.Value = groupPermissions(3)
def TrunkLockState: VehicleLockState.Value = groupPermissions(3)
/**
* Trunk locations are stored as the orientation zero point being to the East. We need to convert that to a North = 0 orientation before returning the location
* @return A Vector3 of the current trunk location, orientated with North as the zero point
*/
def TrunkLocation : Vector3 = {
def TrunkLocation: Vector3 = {
val rotationRadians = -math.toRadians(Orientation.z - 90f).toFloat
Vector3.PlanarRotateAroundPoint(Position + Definition.TrunkLocation, Position, rotationRadians)
}
def PrepareGatingManifest() : VehicleManifest = {
def PrepareGatingManifest(): VehicleManifest = {
val manifest = VehicleManifest(this)
seats.collect { case (index, seat) if index > 0 => seat.Occupant = None }
vehicleGatingManifest = Some(manifest)
@ -550,14 +548,14 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
manifest
}
def PublishGatingManifest() : Option[VehicleManifest] = {
def PublishGatingManifest(): Option[VehicleManifest] = {
val out = vehicleGatingManifest
previousVehicleGatingManifest = vehicleGatingManifest
vehicleGatingManifest = None
out
}
def PreviousGatingManifest() : Option[VehicleManifest] = previousVehicleGatingManifest
def PreviousGatingManifest(): Option[VehicleManifest] = previousVehicleGatingManifest
def DamageModel = Definition.asInstanceOf[DamageResistanceModel]
@ -565,30 +563,32 @@ class Vehicle(private val vehicleDef : VehicleDefinition) extends AmenityOwner
* This is the definition entry that is used to store and unload pertinent information about the `Vehicle`.
* @return the vehicle's definition entry
*/
def Definition : VehicleDefinition = vehicleDef
def Definition: VehicleDefinition = vehicleDef
def canEqual(other: Any): Boolean = other.isInstanceOf[Vehicle]
override def equals(other : Any) : Boolean = other match {
case that: Vehicle =>
(that canEqual this) &&
hashCode() == that.hashCode()
case _ =>
false
}
override def equals(other: Any): Boolean =
other match {
case that: Vehicle =>
(that canEqual this) &&
hashCode() == that.hashCode()
case _ =>
false
}
override def hashCode() : Int = Actor.hashCode()
override def hashCode(): Int = Actor.hashCode()
/**
* Override the string representation to provide additional information.
* @return the string output
*/
override def toString : String = {
override def toString: String = {
Vehicle.toString(this)
}
}
object Vehicle {
/**
* A basic `Trait` connecting all of the actionable `Vehicle` response messages.
*/
@ -599,7 +599,7 @@ object Vehicle {
* @param player the player who sent this request message
* @param response the result of the processed request
*/
final case class VehicleMessages(player : Player, response : Exchange)
final case class VehicleMessages(player: Player, response: Exchange)
/**
* Initiate vehicle deconstruction.
@ -607,7 +607,7 @@ object Vehicle {
* @param time the delay before deconstruction should initiate;
* should initiate instantly when `None`
*/
final case class Deconstruct(time : Option[FiniteDuration] = None)
final case class Deconstruct(time: Option[FiniteDuration] = None)
/**
* The `Vehicle` will resume previous unresponsiveness to player activity.
@ -620,23 +620,23 @@ object Vehicle {
* @see `FacilityBenefitShieldChargeRequestMessage`
* @param amount the number of points to charge
*/
final case class ChargeShields(amount : Int)
final case class ChargeShields(amount: Int)
/**
* Following a successful shield charge tick, display the results of the update.
* @see `FacilityBenefitShieldChargeRequestMessage`
* @param vehicle the updated vehicle
*/
final case class UpdateShieldsCharge(vehicle : Vehicle)
final case class UpdateShieldsCharge(vehicle: Vehicle)
/**
* Change a vehicle's internal ownership property to match that of the target player.
* @param player the person who will own the vehicle, or `None` if the vehicle will go unowned
*/
final case class Ownership(player : Option[Player])
final case class Ownership(player: Option[Player])
object Ownership {
def apply(player : Player) : Ownership = Ownership(Some(player))
def apply(player: Player): Ownership = Ownership(Some(player))
}
/**
@ -644,7 +644,7 @@ object Vehicle {
* @param vehicleDef the vehicle's definition entry
* @return a `Vehicle` object
*/
def apply(vehicleDef : VehicleDefinition) : Vehicle = {
def apply(vehicleDef: VehicleDefinition): Vehicle = {
new Vehicle(vehicleDef)
}
@ -652,8 +652,8 @@ object Vehicle {
* Given a `Map` of `Utility` objects, only return the objects with a positive or zero-index position.
* @return a map of applicable utilities
*/
def EquipmentUtilities(utilities : Map[Int, Utility]) : Map[Int, Utility] = {
utilities.filter({ case(index : Int, _ : Utility) => index > -1 })
def EquipmentUtilities(utilities: Map[Int, Utility]): Map[Int, Utility] = {
utilities.filter({ case (index: Int, _: Utility) => index > -1 })
}
/**
@ -661,30 +661,35 @@ object Vehicle {
* @param vehicle the `Vehicle` being initialized
* @see `{object}.LoadDefinition`
*/
def LoadDefinition(vehicle : Vehicle) : Vehicle = {
val vdef : VehicleDefinition = vehicle.Definition
def LoadDefinition(vehicle: Vehicle): Vehicle = {
val vdef: VehicleDefinition = vehicle.Definition
//general stuff
vehicle.Health = vdef.DefaultHealth
//create weapons
vehicle.weapons = vdef.Weapons.map({case (num, definition) =>
val slot = EquipmentSlot(EquipmentSize.VehicleWeapon)
slot.Equipment = Tool(definition)
num -> slot
}).toMap
vehicle.weapons = vdef.Weapons
.map({
case (num, definition) =>
val slot = EquipmentSlot(EquipmentSize.VehicleWeapon)
slot.Equipment = Tool(definition)
num -> slot
})
.toMap
//create seats
vehicle.seats = vdef.Seats.map({ case(num, definition) => num -> Seat(definition)}).toMap
vehicle.seats = vdef.Seats.map({ case (num, definition) => num -> Seat(definition) }).toMap
// create cargo holds
vehicle.cargoHolds = vdef.Cargo.map({ case(num, definition) => num -> Cargo(definition)}).toMap
vehicle.cargoHolds = vdef.Cargo.map({ case (num, definition) => num -> Cargo(definition) }).toMap
//create utilities
vehicle.utilities = vdef.Utilities.map({
case(num, util) =>
val obj = Utility(util, vehicle)
val utilObj = obj()
vehicle.Amenities = utilObj
utilObj.LocationOffset = vdef.UtilityOffset.get(num)
num -> obj
}).toMap
vehicle.utilities = vdef.Utilities
.map({
case (num, util) =>
val obj = Utility(util, vehicle)
val utilObj = obj()
vehicle.Amenities = utilObj
utilObj.LocationOffset = vdef.UtilityOffset.get(num)
num -> obj
})
.toMap
//trunk
vdef.TrunkSize match {
case InventoryTile.None => ;
@ -699,7 +704,7 @@ object Vehicle {
* Provide a fixed string representation.
* @return the string output
*/
def toString(obj : Vehicle) : String = {
def toString(obj: Vehicle): String = {
val occupancy = obj.Seats.values.count(seat => seat.isOccupied)
s"${obj.Definition.Name}, owned by ${obj.Owner}: (${obj.Health}/${obj.MaxHealth})(${obj.Shields}/${obj.MaxShields}) ($occupancy)"
}

View file

@ -20,7 +20,7 @@ object Vehicles {
* @param player na
* @return na
*/
def Own(vehicle : Vehicle, player : Player) : Option[Vehicle] = Own(vehicle, Some(player))
def Own(vehicle: Vehicle, player: Player): Option[Vehicle] = Own(vehicle, Some(player))
/**
* na
@ -28,12 +28,15 @@ object Vehicles {
* @param playerOpt na
* @return na
*/
def Own(vehicle : Vehicle, playerOpt : Option[Player]) : Option[Vehicle] = {
def Own(vehicle: Vehicle, playerOpt: Option[Player]): Option[Vehicle] = {
playerOpt match {
case Some(tplayer) =>
tplayer.VehicleOwned = vehicle.GUID
vehicle.AssignOwnership(playerOpt)
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(vehicle.Zone.Id, VehicleAction.Ownership(tplayer.GUID, vehicle.GUID))
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
vehicle.Zone.Id,
VehicleAction.Ownership(tplayer.GUID, vehicle.GUID)
)
Vehicles.ReloadAccessPermissions(vehicle, tplayer.Name)
Some(vehicle)
case None =>
@ -48,26 +51,31 @@ object Vehicles {
* @return the vehicle, if it had a previous owner;
* `None`, otherwise
*/
def Disown(guid : PlanetSideGUID, vehicle : Vehicle) : Option[Vehicle] = vehicle.Zone.GUID(vehicle.Owner) match {
case Some(player : Player) =>
if(player.VehicleOwned.contains(guid)) {
player.VehicleOwned = None
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(player.Name, VehicleAction.Ownership(player.GUID, PlanetSideGUID(0)))
}
vehicle.AssignOwnership(None)
val empire = VehicleLockState.Empire.id
val factionChannel = s"${vehicle.Faction}"
(0 to 2).foreach(group => {
vehicle.PermissionGroup(group, empire)
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(factionChannel,
VehicleAction.SeatPermissions(Service.defaultPlayerGUID, guid, group, empire)
)
})
ReloadAccessPermissions(vehicle, player.Name)
Some(vehicle)
case _ =>
None
}
def Disown(guid: PlanetSideGUID, vehicle: Vehicle): Option[Vehicle] =
vehicle.Zone.GUID(vehicle.Owner) match {
case Some(player: Player) =>
if (player.VehicleOwned.contains(guid)) {
player.VehicleOwned = None
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
player.Name,
VehicleAction.Ownership(player.GUID, PlanetSideGUID(0))
)
}
vehicle.AssignOwnership(None)
val empire = VehicleLockState.Empire.id
val factionChannel = s"${vehicle.Faction}"
(0 to 2).foreach(group => {
vehicle.PermissionGroup(group, empire)
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
factionChannel,
VehicleAction.SeatPermissions(Service.defaultPlayerGUID, guid, group, empire)
)
})
ReloadAccessPermissions(vehicle, player.Name)
Some(vehicle)
case _ =>
None
}
/**
* Disassociate a player from a vehicle that he owns.
@ -76,7 +84,8 @@ object Vehicles {
* This is the player side of vehicle ownership removal.
* @param player the player
*/
def Disown(player : Player, zone : Zone) : Option[Vehicle] = Disown(player, Some(zone))
def Disown(player: Player, zone: Zone): Option[Vehicle] = Disown(player, Some(zone))
/**
* Disassociate a player from a vehicle that he owns.
* The vehicle must exist in the game world on the specified continent.
@ -84,12 +93,12 @@ object Vehicles {
* This is the player side of vehicle ownership removal.
* @param player the player
*/
def Disown(player : Player, zoneOpt : Option[Zone]) : Option[Vehicle] = {
def Disown(player: Player, zoneOpt: Option[Zone]): Option[Vehicle] = {
player.VehicleOwned match {
case Some(vehicle_guid) =>
player.VehicleOwned = None
zoneOpt.getOrElse(player.Zone).GUID(vehicle_guid) match {
case Some(vehicle : Vehicle) =>
case Some(vehicle: Vehicle) =>
Disown(player, vehicle)
case _ =>
None
@ -106,21 +115,23 @@ object Vehicles {
* This is the vehicle side of vehicle ownership removal.
* @param player the player
*/
def Disown(player : Player, vehicle : Vehicle) : Option[Vehicle] = {
def Disown(player: Player, vehicle: Vehicle): Option[Vehicle] = {
val pguid = player.GUID
if(vehicle.Owner.contains(pguid)) {
if (vehicle.Owner.contains(pguid)) {
vehicle.AssignOwnership(None)
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(player.Name, VehicleAction.Ownership(pguid, PlanetSideGUID(0)))
val vguid = vehicle.GUID
val vguid = vehicle.GUID
val empire = VehicleLockState.Empire.id
(0 to 2).foreach(group => {
vehicle.PermissionGroup(group, empire)
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(s"${vehicle.Faction}", VehicleAction.SeatPermissions(pguid, vguid, group, empire))
vehicle.Zone.VehicleEvents ! VehicleServiceMessage(
s"${vehicle.Faction}",
VehicleAction.SeatPermissions(pguid, vguid, group, empire)
)
})
ReloadAccessPermissions(vehicle, player.Name)
Some(vehicle)
}
else {
} else {
None
}
}
@ -134,7 +145,7 @@ object Vehicles {
* The most important examples include either the player or the vehicle itself spawning in for the first time.
* @param vehicle the `Vehicle`
*/
def ReloadAccessPermissions(vehicle : Vehicle, toChannel : String) : Unit = {
def ReloadAccessPermissions(vehicle: Vehicle, toChannel: String): Unit = {
val vehicle_guid = vehicle.GUID
(0 to 3).foreach(group => {
vehicle.Zone.AvatarEvents ! AvatarServiceMessage(
@ -170,16 +181,16 @@ object Vehicles {
* @return `true`, if all passengers of the vehicle, and its cargo vehicles, etc., have reported being in the same zone;
* `false`, if no manifest entry exists, or if the vehicle is moving to the same zone
*/
def AllGatedOccupantsInSameZone(vehicle : Vehicle) : Boolean = {
def AllGatedOccupantsInSameZone(vehicle: Vehicle): Boolean = {
val vzone = vehicle.Zone
vehicle.PreviousGatingManifest() match {
case Some(manifest) if vzone != manifest.origin =>
val manifestPassengers = manifest.passengers.collect { case (name, _) => name } :+ manifest.driverName
val manifestPassengers = manifest.passengers.collect { case (name, _) => name } :+ manifest.driverName
val manifestPassengerResults = manifestPassengers.map { name => vzone.Players.exists(_.name.equals(name)) }
manifestPassengerResults.forall(_ == true) &&
vehicle.CargoHolds.values
.collect { case hold if hold.isOccupied => AllGatedOccupantsInSameZone(hold.Occupant.get) }
.forall(_ == true)
vehicle.CargoHolds.values
.collect { case hold if hold.isOccupied => AllGatedOccupantsInSameZone(hold.Occupant.get) }
.forall(_ == true)
case _ =>
false
}
@ -192,11 +203,10 @@ object Vehicles {
* @return the orientation as an `Integer` value;
* `0` for almost all cases
*/
def CargoOrientation(vehicle : Vehicle) : Int = {
if(vehicle.Definition == GlobalDefinitions.router) {
def CargoOrientation(vehicle: Vehicle): Int = {
if (vehicle.Definition == GlobalDefinitions.router) {
1
}
else {
} else {
0
}
}
@ -208,17 +218,22 @@ object Vehicles {
* @param hacker the one whoi performed the hack and will inherit ownership of the target vehicle
* @param unk na; used by `HackMessage` as `unk5`
*/
def FinishHackingVehicle(target : Vehicle, hacker : Player, unk : Long)(): Unit = {
def FinishHackingVehicle(target: Vehicle, hacker: Player, unk: Long)(): Unit = {
log.info(s"Vehicle guid: ${target.GUID} has been jacked")
import scala.concurrent.duration._
val zone = target.Zone
// Forcefully dismount any cargo
target.CargoHolds.values.foreach(cargoHold => {
target.CargoHolds.values.foreach(cargoHold => {
cargoHold.Occupant match {
case Some(cargo : Vehicle) => {
case Some(cargo: Vehicle) => {
cargo.Seats(0).Occupant match {
case Some(cargoDriver: Player) =>
CargoBehavior.HandleVehicleCargoDismount(target.Zone, cargo.GUID, bailed = target.Flying, requestedByPassenger = false, kicked = true )
CargoBehavior.HandleVehicleCargoDismount(
target.Zone,
cargo.GUID,
bailed = target.Flying,
requestedByPassenger = false,
kicked = true
)
case None =>
log.error("FinishHackingVehicle: vehicle in cargo hold missing driver")
CargoBehavior.HandleVehicleCargoDismount(cargo.GUID, cargo, target.GUID, target, false, false, true)
@ -233,20 +248,23 @@ object Vehicles {
case Some(tplayer) =>
seat.Occupant = None
tplayer.VehicleSeated = None
if(tplayer.HasGUID) {
zone.VehicleEvents ! VehicleServiceMessage(zone.Id, VehicleAction.KickPassenger(tplayer.GUID, 4, unk2 = false, target.GUID))
if (tplayer.HasGUID) {
zone.VehicleEvents ! VehicleServiceMessage(
zone.Id,
VehicleAction.KickPassenger(tplayer.GUID, 4, unk2 = false, target.GUID)
)
}
case None => ;
}
})
// If the vehicle can fly and is flying deconstruct it, and well played to whomever managed to hack a plane in mid air. I'm impressed.
if(target.Definition.CanFly && target.Flying) {
if (target.Definition.CanFly && target.Flying) {
// todo: Should this force the vehicle to land in the same way as when a pilot bails with passengers on board?
target.Actor ! Vehicle.Deconstruct()
} else { // Otherwise handle ownership transfer as normal
// Remove ownership of our current vehicle, if we have one
hacker.VehicleOwned match {
case Some(guid : PlanetSideGUID) =>
case Some(guid: PlanetSideGUID) =>
zone.GUID(guid) match {
case Some(vehicle: Vehicle) =>
Vehicles.Disown(hacker, vehicle)
@ -270,9 +288,15 @@ object Vehicles {
Vehicles.Own(target, hacker)
//todo: Send HackMessage -> HackCleared to vehicle? can be found in packet captures. Not sure if necessary.
// And broadcast the faction change to other clients
zone.AvatarEvents ! AvatarServiceMessage(zone.Id, AvatarAction.SetEmpire(Service.defaultPlayerGUID, target.GUID, hacker.Faction))
zone.AvatarEvents ! AvatarServiceMessage(
zone.Id,
AvatarAction.SetEmpire(Service.defaultPlayerGUID, target.GUID, hacker.Faction)
)
}
zone.LocalEvents ! LocalServiceMessage(zone.Id, LocalAction.TriggerSound(hacker.GUID, TriggeredSound.HackVehicle, target.Position, 30, 0.49803925f))
zone.LocalEvents ! LocalServiceMessage(
zone.Id,
LocalAction.TriggerSound(hacker.GUID, TriggeredSound.HackVehicle, target.Position, 30, 0.49803925f)
)
// Clean up after specific vehicles, e.g. remove router telepads
// If AMS is deployed, swap it to the new faction
target.Definition match {

View file

@ -6,14 +6,14 @@ package net.psforever.objects.avatar
* #121 is the most important.
*/
object Avatars extends Enumeration {
final val avatar = Value(121)
final val avatar_bot = Value(122)
final val avatar_bot_agile = Value(123)
final val avatar_bot_agile_no_weapon = Value(124)
final val avatar_bot_max = Value(125)
final val avatar_bot_max_no_weapon = Value(126)
final val avatar_bot_reinforced = Value(127)
final val avatar = Value(121)
final val avatar_bot = Value(122)
final val avatar_bot_agile = Value(123)
final val avatar_bot_agile_no_weapon = Value(124)
final val avatar_bot_max = Value(125)
final val avatar_bot_max_no_weapon = Value(126)
final val avatar_bot_reinforced = Value(127)
final val avatar_bot_reinforced_no_weapon = Value(128)
final val avatar_bot_standard = Value(129)
final val avatar_bot_standard_no_weapon = Value(130)
final val avatar_bot_standard = Value(129)
final val avatar_bot_standard_no_weapon = Value(130)
}

View file

@ -7,13 +7,14 @@ import scala.collection.mutable
object Certification {
object Dependencies {
/**
* Find the certifications that are immediately dependent on the target certification.
* (For `A`, find all `B` that are `B ⇒ A`.)
* @param certification the target certification
* @return all connected certifications
*/
def From(certification : CertificationType.Value) : Set[CertificationType.Value] = dependencies(certification).toSet
def From(certification: CertificationType.Value): Set[CertificationType.Value] = dependencies(certification).toSet
/**
* Find all certifications that are dependent on the target certification.
@ -21,14 +22,13 @@ object Certification {
* @param certification the target certification
* @return all connected certifications
*/
def FromAll(certification : CertificationType.Value) : Set[CertificationType.Value] = {
var available : List[CertificationType.Value] = List(certification)
var allocated : mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
def FromAll(certification: CertificationType.Value): Set[CertificationType.Value] = {
var available: List[CertificationType.Value] = List(certification)
var allocated: mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
do {
available = available.flatMap(cert => dependencies(cert))
allocated ++= available
}
while(available.nonEmpty)
} while (available.nonEmpty)
allocated.toSet
}
@ -38,7 +38,7 @@ object Certification {
* @param certification the target certification
* @return all connected certifications
*/
def For(certification : CertificationType.Value) : Set[CertificationType.Value] = {
def For(certification: CertificationType.Value): Set[CertificationType.Value] = {
(for {
(cert, certs) <- dependencies
if certs contains certification
@ -51,16 +51,15 @@ object Certification {
* @param certification the target certification
* @return all connected certifications
*/
def ForAll(certification : CertificationType.Value) : Set[CertificationType.Value] = {
var available : List[CertificationType.Value] = List(certification)
var allocated : mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
def ForAll(certification: CertificationType.Value): Set[CertificationType.Value] = {
var available: List[CertificationType.Value] = List(certification)
var allocated: mutable.ListBuffer[CertificationType.Value] = mutable.ListBuffer.empty[CertificationType.Value]
do {
available = available.flatMap {
For
}
allocated ++= available
}
while(available.nonEmpty)
} while (available.nonEmpty)
allocated.toSet
}
@ -72,83 +71,80 @@ object Certification {
* @param certification the target certification
* @return all connected certifications
*/
def Like(certification : CertificationType.Value) : Set[CertificationType.Value] = certification match {
case AssaultBuggy =>
Set(Harasser)
case LightScout =>
Set(AirCavalryScout, AssaultBuggy, Harasser)
case UniMAX =>
Set(AAMAX, AIMAX, AVMAX)
case AdvancedEngineering =>
Set(AssaultEngineering, FortificationEngineering)
case ElectronicsExpert =>
Set(DataCorruption, ExpertHacking)
case _ =>
Set.empty[CertificationType.Value]
}
def Like(certification: CertificationType.Value): Set[CertificationType.Value] =
certification match {
case AssaultBuggy =>
Set(Harasser)
case LightScout =>
Set(AirCavalryScout, AssaultBuggy, Harasser)
case UniMAX =>
Set(AAMAX, AIMAX, AVMAX)
case AdvancedEngineering =>
Set(AssaultEngineering, FortificationEngineering)
case ElectronicsExpert =>
Set(DataCorruption, ExpertHacking)
case _ =>
Set.empty[CertificationType.Value]
}
private val dependencies : Map[CertificationType.Value, List[CertificationType.Value]] = Map(
StandardAssault -> List(),
AgileExoSuit -> List(),
ReinforcedExoSuit -> List(),
InfiltrationSuit -> List(Phantasm),
AIMAX -> List(),
AVMAX -> List(),
AAMAX -> List(),
UniMAX -> List(),
StandardAssault -> List(),
MediumAssault -> List(AntiVehicular, HeavyAssault, Sniping, SpecialAssault),
AntiVehicular -> List(),
HeavyAssault -> List(),
Sniping -> List(),
SpecialAssault -> List(EliteAssault),
EliteAssault -> List(),
ATV -> List(Switchblade),
Switchblade -> List(),
Harasser -> List(),
AssaultBuggy -> List(),
LightScout -> List(AirCavalryAssault),
GroundSupport -> List(),
GroundTransport -> List(),
ArmoredAssault1 -> List(ArmoredAssault2),
ArmoredAssault2 -> List(BattleFrameRobotics, Flail),
Flail -> List(),
AirCavalryScout -> List(AirCavalryAssault),
AirCavalryAssault -> List(AirCavalryInterceptor),
AirCavalryInterceptor -> List(),
AirSupport -> List(GalaxyGunship),
GalaxyGunship -> List(),
Phantasm -> List(),
BattleFrameRobotics -> List(BFRAntiInfantry, BFRAntiAircraft),
BFRAntiInfantry -> List(),
BFRAntiAircraft -> List(),
Medical -> List(AdvancedMedical),
AdvancedMedical -> List(),
Engineering -> List(CombatEngineering),
CombatEngineering -> List(AdvancedEngineering, AssaultEngineering, FortificationEngineering),
AdvancedEngineering -> List(),
AssaultEngineering -> List(),
private val dependencies: Map[CertificationType.Value, List[CertificationType.Value]] = Map(
StandardAssault -> List(),
AgileExoSuit -> List(),
ReinforcedExoSuit -> List(),
InfiltrationSuit -> List(Phantasm),
AIMAX -> List(),
AVMAX -> List(),
AAMAX -> List(),
UniMAX -> List(),
StandardAssault -> List(),
MediumAssault -> List(AntiVehicular, HeavyAssault, Sniping, SpecialAssault),
AntiVehicular -> List(),
HeavyAssault -> List(),
Sniping -> List(),
SpecialAssault -> List(EliteAssault),
EliteAssault -> List(),
ATV -> List(Switchblade),
Switchblade -> List(),
Harasser -> List(),
AssaultBuggy -> List(),
LightScout -> List(AirCavalryAssault),
GroundSupport -> List(),
GroundTransport -> List(),
ArmoredAssault1 -> List(ArmoredAssault2),
ArmoredAssault2 -> List(BattleFrameRobotics, Flail),
Flail -> List(),
AirCavalryScout -> List(AirCavalryAssault),
AirCavalryAssault -> List(AirCavalryInterceptor),
AirCavalryInterceptor -> List(),
AirSupport -> List(GalaxyGunship),
GalaxyGunship -> List(),
Phantasm -> List(),
BattleFrameRobotics -> List(BFRAntiInfantry, BFRAntiAircraft),
BFRAntiInfantry -> List(),
BFRAntiAircraft -> List(),
Medical -> List(AdvancedMedical),
AdvancedMedical -> List(),
Engineering -> List(CombatEngineering),
CombatEngineering -> List(AdvancedEngineering, AssaultEngineering, FortificationEngineering),
AdvancedEngineering -> List(),
AssaultEngineering -> List(),
FortificationEngineering -> List(),
Hacking -> List(AdvancedHacking),
AdvancedHacking -> List(DataCorruption, ElectronicsExpert, ExpertHacking),
DataCorruption -> List(),
ElectronicsExpert -> List(),
ExpertHacking -> List()
Hacking -> List(AdvancedHacking),
AdvancedHacking -> List(DataCorruption, ElectronicsExpert, ExpertHacking),
DataCorruption -> List(),
ElectronicsExpert -> List(),
ExpertHacking -> List()
)
}
object Cost {
/**
* For a certification, get its point cost.
* @param certification the certification
* @return the cost
*/
def Of(certification : CertificationType.Value) : Int = points(certification)
def Of(certification: CertificationType.Value): Int = points(certification)
/**
* For a list of certifications, find the point cost of all unique certifications.
@ -156,7 +152,7 @@ object Certification {
* @param certifications the certification list
* @return the total cost
*/
def Of(certifications : List[CertificationType.Value]) : Int = Of(certifications.toSet)
def Of(certifications: List[CertificationType.Value]): Int = Of(certifications.toSet)
/**
* For a set of certifications, find the point cost of all certifications.
@ -164,70 +160,65 @@ object Certification {
* @param certifications the certification list
* @return the total cost
*/
def Of(certifications : Set[CertificationType.Value]) : Int = OfAll(certifications.toList)
def Of(certifications: Set[CertificationType.Value]): Int = OfAll(certifications.toList)
/**
* For a list of certifications, find the point cost of all certifications, counting any duplicates.
* @param certifications the certification list
* @return the total cost
*/
def OfAll(certifications : List[CertificationType.Value]) : Int = {
def OfAll(certifications: List[CertificationType.Value]): Int = {
certifications map points sum
}
import CertificationType._
private val points : Map[CertificationType.Value, Int] = Map(
StandardExoSuit -> 0,
AgileExoSuit -> 0,
ReinforcedExoSuit -> 3,
InfiltrationSuit -> 2,
AAMAX -> 2,
AIMAX -> 3,
AVMAX -> 3,
UniMAX -> 6,
StandardAssault -> 0,
MediumAssault -> 2,
AntiVehicular -> 3,
HeavyAssault -> 4,
Sniping -> 3,
SpecialAssault -> 3,
EliteAssault -> 1,
ATV -> 1,
Switchblade -> 1,
Harasser -> 1,
AssaultBuggy -> 3,
LightScout -> 5,
GroundSupport -> 2,
GroundTransport -> 2,
ArmoredAssault1 -> 2,
ArmoredAssault2 -> 3,
Flail -> 1,
AirCavalryScout -> 3,
AirCavalryAssault -> 2,
AirCavalryInterceptor -> 2,
AirSupport -> 3,
GalaxyGunship -> 2,
Phantasm -> 3,
BattleFrameRobotics -> 4,
BFRAntiInfantry -> 1,
BFRAntiAircraft -> 1,
Medical -> 3,
AdvancedMedical -> 2,
Engineering -> 3,
CombatEngineering -> 2,
AdvancedEngineering -> 5,
AssaultEngineering -> 3,
private val points: Map[CertificationType.Value, Int] = Map(
StandardExoSuit -> 0,
AgileExoSuit -> 0,
ReinforcedExoSuit -> 3,
InfiltrationSuit -> 2,
AAMAX -> 2,
AIMAX -> 3,
AVMAX -> 3,
UniMAX -> 6,
StandardAssault -> 0,
MediumAssault -> 2,
AntiVehicular -> 3,
HeavyAssault -> 4,
Sniping -> 3,
SpecialAssault -> 3,
EliteAssault -> 1,
ATV -> 1,
Switchblade -> 1,
Harasser -> 1,
AssaultBuggy -> 3,
LightScout -> 5,
GroundSupport -> 2,
GroundTransport -> 2,
ArmoredAssault1 -> 2,
ArmoredAssault2 -> 3,
Flail -> 1,
AirCavalryScout -> 3,
AirCavalryAssault -> 2,
AirCavalryInterceptor -> 2,
AirSupport -> 3,
GalaxyGunship -> 2,
Phantasm -> 3,
BattleFrameRobotics -> 4,
BFRAntiInfantry -> 1,
BFRAntiAircraft -> 1,
Medical -> 3,
AdvancedMedical -> 2,
Engineering -> 3,
CombatEngineering -> 2,
AdvancedEngineering -> 5,
AssaultEngineering -> 3,
FortificationEngineering -> 3,
Hacking -> 3,
AdvancedHacking -> 2,
DataCorruption -> 3,
ElectronicsExpert -> 4,
ExpertHacking -> 2
Hacking -> 3,
AdvancedHacking -> 2,
DataCorruption -> 3,
ElectronicsExpert -> 4,
ExpertHacking -> 2
)
}
}

View file

@ -11,15 +11,14 @@ import net.psforever.types.{PlanetSideEmpire, Vector3}
import services.Service
import services.avatar.{AvatarAction, AvatarServiceMessage}
class CorpseControl(player : Player) extends Actor
with ContainableBehavior {
class CorpseControl(player: Player) extends Actor with ContainableBehavior {
def ContainerObject = player
//private [this] val log = org.log4s.getLogger(player.Name)
def receive : Receive = containerBehavior.orElse { case _ => ; }
def receive: Receive = containerBehavior.orElse { case _ => ; }
def MessageDeferredCallback(msg : Any) : Unit = {
def MessageDeferredCallback(msg: Any): Unit = {
msg match {
case Containable.MoveItem(_, item, _) =>
//momentarily put item back where it was originally
@ -36,18 +35,18 @@ class CorpseControl(player : Player) extends Actor
}
}
def RemoveItemFromSlotCallback(item : Equipment, slot : Int) : Unit = {
val obj = ContainerObject
val zone = obj.Zone
def RemoveItemFromSlotCallback(item: Equipment, slot: Int): Unit = {
val obj = ContainerObject
val zone = obj.Zone
val events = zone.AvatarEvents
item.Faction = PlanetSideEmpire.NEUTRAL
events ! AvatarServiceMessage(zone.Id, AvatarAction.ObjectDelete(Service.defaultPlayerGUID, item.GUID))
}
def PutItemInSlotCallback(item : Equipment, slot : Int) : Unit = {
val obj = ContainerObject
val zone = obj.Zone
val events = zone.AvatarEvents
def PutItemInSlotCallback(item: Equipment, slot: Int): Unit = {
val obj = ContainerObject
val zone = obj.Zone
val events = zone.AvatarEvents
val definition = item.Definition
events ! AvatarServiceMessage(
zone.Id,
@ -63,10 +62,11 @@ class CorpseControl(player : Player) extends Actor
)
}
def SwapItemCallback(item : Equipment) : Unit = {
val obj = ContainerObject
def SwapItemCallback(item: Equipment): Unit = {
val obj = ContainerObject
val zone = obj.Zone
zone.AvatarEvents ! AvatarServiceMessage(zone.Id,
zone.AvatarEvents ! AvatarServiceMessage(
zone.Id,
AvatarAction.SendResponse(
Service.defaultPlayerGUID,
ObjectDetachMessage(obj.GUID, item.GUID, Vector3.Zero, 0f)

View file

@ -23,29 +23,36 @@ import scala.collection.mutable
* these structures are updated to reflect proper count.
*/
class DeployableToolbox {
/**
* a map of bins for keeping track of the quantities of deployables in a category
* keys: categories, values: quantity storage object
*/
private val categoryCounts = DeployableCategory.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
private val categoryCounts =
DeployableCategory.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
categoryCounts(DeployableCategory.Telepads).Max = 1024
/**
* a map of bins for keeping track of the quantities of individual deployables
* keys: deployable types, values: quantity storage object
*/
private val deployableCounts = DeployedItem.values.toSeq.map(value => { value -> new DeployableToolbox.Bin }).toMap
deployableCounts(DeployedItem.router_telepad_deployable).Max = 1024
/**
* a map of tracked/owned individual deployables
* keys: categories, values: deployable objects
*/
private val deployableLists =
DeployableCategory.values.toSeq.map(value => { value -> mutable.ListBuffer[DeployableToolbox.AcceptableDeployable]() }).toMap
DeployableCategory.values.toSeq
.map(value => { value -> mutable.ListBuffer[DeployableToolbox.AcceptableDeployable]() })
.toMap
/**
* can only be initialized once
* set during the `Initialization` method primarily, and in `Add` and in `Remove` if not
*/
private var initialized : Boolean = false
private var initialized: Boolean = false
/**
* Set up the initial deployable counts by providing certification values to be used in category and unit selection.
@ -53,13 +60,12 @@ class DeployableToolbox {
* @return `true`, if this is the first time and actual "initialization" is performed;
* `false`, otherwise
*/
def Initialize(certifications : Set[CertificationType.Value]) : Boolean = {
if(!initialized) {
def Initialize(certifications: Set[CertificationType.Value]): Boolean = {
if (!initialized) {
DeployableToolbox.Initialize(deployableCounts, categoryCounts, certifications)
initialized = true
true
}
else {
} else {
false
}
}
@ -72,7 +78,10 @@ class DeployableToolbox {
* occasionally, important former certification values are required for additional configuration;
* the new certification should already have been added to this group
*/
def AddToDeployableQuantities(certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = {
def AddToDeployableQuantities(
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): Unit = {
initialized = true
DeployableToolbox.AddToDeployableQuantities(deployableCounts, categoryCounts, certification, certificationSet)
}
@ -86,7 +95,10 @@ class DeployableToolbox {
* occasionally, important former certification values are required for additional configuration;
* the new certification should already have been excluded from this group
*/
def RemoveFromDeployableQuantities(certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = {
def RemoveFromDeployableQuantities(
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): Unit = {
initialized = true
DeployableToolbox.RemoveFromDeployablesQuantities(deployableCounts, categoryCounts, certification, certificationSet)
}
@ -100,7 +112,7 @@ class DeployableToolbox {
* @return `true`, if it can be managed under the current conditions;
* `false`, otherwise
*/
def Accept(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
def Accept(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
Valid(obj) && Available(obj) && !Contains(obj)
}
@ -111,9 +123,9 @@ class DeployableToolbox {
* @return `true`, if both category maximum and deployable type maximum are positive non-zero integers;
* `false`, otherwise
*/
def Valid(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
def Valid(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Max > 0 &&
categoryCounts(obj.Definition.DeployCategory).Max > 0
categoryCounts(obj.Definition.DeployCategory).Max > 0
}
/**
@ -124,9 +136,9 @@ class DeployableToolbox {
* @return `true`, if the deployable can be added to the support lists and counted;
* `false`, otherwise
*/
def Available(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Available &&
categoryCounts(obj.Definition.DeployCategory).Available
def Available(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Available &&
categoryCounts(obj.Definition.DeployCategory).Available
}
/**
@ -136,7 +148,7 @@ class DeployableToolbox {
* @return `true`, if the deployable can be found in one of the lists;
* `false`, otherwise
*/
def Contains(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
def Contains(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
deployableLists(obj.Definition.DeployCategory).contains(obj)
}
@ -152,18 +164,17 @@ class DeployableToolbox {
* @return `true`, if the deployable is added;
* `false`, otherwise
*/
def Add(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
val category = obj.Definition.DeployCategory
def Add(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
val category = obj.Definition.DeployCategory
val dCategory = categoryCounts(category)
val dType = deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item))
val dList = deployableLists(category)
if(dCategory.Available() && dType.Available() && !dList.contains(obj)) {
val dType = deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item))
val dList = deployableLists(category)
if (dCategory.Available() && dType.Available() && !dList.contains(obj)) {
dCategory.Current += 1
dType.Current += 1
dList += obj
true
}
else {
} else {
false
}
}
@ -179,16 +190,15 @@ class DeployableToolbox {
* @return `true`, if the deployable is added;
* `false`, otherwise
*/
def Remove(obj : DeployableToolbox.AcceptableDeployable) : Boolean = {
val category = obj.Definition.DeployCategory
def Remove(obj: DeployableToolbox.AcceptableDeployable): Boolean = {
val category = obj.Definition.DeployCategory
val deployables = deployableLists(category)
if(deployables.contains(obj)) {
if (deployables.contains(obj)) {
categoryCounts(category).Current -= 1
deployableCounts(DeployableToolbox.UnifiedType(obj.Definition.Item)).Current -= 1
deployables -= obj
true
}
else {
} else {
false
}
}
@ -199,7 +209,7 @@ class DeployableToolbox {
* @param obj the example deployable
* @return any deployable that is found
*/
def DisplaceFirst(obj : DeployableToolbox.AcceptableDeployable) : Option[DeployableToolbox.AcceptableDeployable] = {
def DisplaceFirst(obj: DeployableToolbox.AcceptableDeployable): Option[DeployableToolbox.AcceptableDeployable] = {
DisplaceFirst(obj, { d => d.Definition.Item == obj.Definition.Item })
}
@ -213,11 +223,14 @@ class DeployableToolbox {
* @param rule the testing rule for determining a valid deployable
* @return any deployable that is found
*/
def DisplaceFirst(obj : DeployableToolbox.AcceptableDeployable, rule : (Deployable)=> Boolean) : Option[DeployableToolbox.AcceptableDeployable] = {
val definition = obj.Definition
val category = definition.DeployCategory
def DisplaceFirst(
obj: DeployableToolbox.AcceptableDeployable,
rule: (Deployable) => Boolean
): Option[DeployableToolbox.AcceptableDeployable] = {
val definition = obj.Definition
val category = definition.DeployCategory
val categoryList = deployableLists(category)
if(categoryList.nonEmpty) {
if (categoryList.nonEmpty) {
val found = categoryList.find(rule) match {
case Some(target) =>
categoryList.remove(categoryList.indexOf(target))
@ -227,8 +240,7 @@ class DeployableToolbox {
categoryCounts(category).Current -= 1
deployableCounts(DeployableToolbox.UnifiedType(found.Definition.Item)).Current -= 1
Some(found)
}
else {
} else {
None
}
}
@ -239,15 +251,14 @@ class DeployableToolbox {
* @param category the target category
* @return any deployable that is found
*/
def DisplaceFirst(category : DeployableCategory.Value) : Option[DeployableToolbox.AcceptableDeployable] = {
def DisplaceFirst(category: DeployableCategory.Value): Option[DeployableToolbox.AcceptableDeployable] = {
val categoryList = deployableLists(category)
if(categoryList.nonEmpty) {
if (categoryList.nonEmpty) {
val found = categoryList.remove(0)
categoryCounts(category).Current -= 1
deployableCounts(DeployableToolbox.UnifiedType(found.Definition.Item)).Current -= 1
Some(found)
}
else {
} else {
None
}
}
@ -257,7 +268,7 @@ class DeployableToolbox {
* @param filter the example deployable
* @return a list of globally unique identifiers that should be valid for the current zone
*/
def Deployables(filter : DeployableToolbox.AcceptableDeployable) : List[PlanetSideGUID] = {
def Deployables(filter: DeployableToolbox.AcceptableDeployable): List[PlanetSideGUID] = {
Deployables(filter.Definition.Item)
}
@ -266,10 +277,11 @@ class DeployableToolbox {
* @param filter the type of deployable
* @return a list of globally unique identifiers that should be valid for the current zone
*/
def Deployables(filter : DeployedItem.Value) : List[PlanetSideGUID] = {
def Deployables(filter: DeployedItem.Value): List[PlanetSideGUID] = {
deployableLists(Deployable.Category.Of(filter))
.filter(entry => { entry.Definition.Item == filter })
.map(_.GUID).toList
.map(_.GUID)
.toList
}
/**
@ -277,7 +289,7 @@ class DeployableToolbox {
* @param filter the example deployable
* @return a list of globally unique identifiers that should be valid for the current zone
*/
def Category(filter : DeployableToolbox.AcceptableDeployable) : List[PlanetSideGUID] = {
def Category(filter: DeployableToolbox.AcceptableDeployable): List[PlanetSideGUID] = {
Category(filter.Definition.DeployCategory)
}
@ -286,7 +298,7 @@ class DeployableToolbox {
* @param filter the type of deployable
* @return a list of globally unique identifiers that should be valid for the current zone
*/
def Category(filter : DeployableCategory.Value) : List[PlanetSideGUID] = {
def Category(filter: DeployableCategory.Value): List[PlanetSideGUID] = {
deployableLists(filter).map(_.GUID).toList
}
@ -295,7 +307,7 @@ class DeployableToolbox {
* @param item the example deployable
* @return the current quantity of deployables and the maximum number
*/
def CountDeployable(item : DeployedItem.Value) : (Int, Int) = {
def CountDeployable(item: DeployedItem.Value): (Int, Int) = {
val dType = deployableCounts(DeployableToolbox.UnifiedType(item))
(dType.Current, dType.Max)
}
@ -305,21 +317,21 @@ class DeployableToolbox {
* @param item the example deployable
* @return the current quantity of deployables and the maximum number
*/
def CountCategory(item : DeployedItem.Value) : (Int, Int) = {
def CountCategory(item: DeployedItem.Value): (Int, Int) = {
val dCat = categoryCounts(Deployable.Category.Of(DeployableToolbox.UnifiedType(item)))
(dCat.Current, dCat.Max)
}
def UpdateUIElement(entry : DeployedItem.Value) : List[(Int,Int,Int,Int)] = {
val toEntry = DeployableToolbox.UnifiedType(entry)
def UpdateUIElement(entry: DeployedItem.Value): List[(Int, Int, Int, Int)] = {
val toEntry = DeployableToolbox.UnifiedType(entry)
val (curr, max) = Deployable.UI(toEntry)
val dType = deployableCounts(toEntry)
val dType = deployableCounts(toEntry)
List((curr, dType.Current, max, dType.Max))
}
def UpdateUI() : List[(Int,Int,Int,Int)] = DeployedItem.values flatMap UpdateUIElement toList
def UpdateUI(): List[(Int, Int, Int, Int)] = DeployedItem.values flatMap UpdateUIElement toList
def UpdateUI(entry : CertificationType.Value) : List[(Int,Int,Int,Int)] = {
def UpdateUI(entry: CertificationType.Value): List[(Int, Int, Int, Int)] = {
import CertificationType._
entry match {
case AdvancedHacking =>
@ -327,19 +339,26 @@ class DeployableToolbox {
case CombatEngineering =>
List(
DeployedItem.boomer, DeployedItem.he_mine, DeployedItem.spitfire_turret, DeployedItem.motionalarmsensor
DeployedItem.boomer,
DeployedItem.he_mine,
DeployedItem.spitfire_turret,
DeployedItem.motionalarmsensor
) flatMap UpdateUIElement
case AssaultEngineering =>
List(
DeployedItem.jammer_mine, DeployedItem.portable_manned_turret, DeployedItem.deployable_shield_generator
DeployedItem.jammer_mine,
DeployedItem.portable_manned_turret,
DeployedItem.deployable_shield_generator
) flatMap UpdateUIElement
case FortificationEngineering =>
List(
DeployedItem.boomer,
DeployedItem.he_mine,
DeployedItem.spitfire_turret, DeployedItem.spitfire_cloaked, DeployedItem.spitfire_aa,
DeployedItem.spitfire_turret,
DeployedItem.spitfire_cloaked,
DeployedItem.spitfire_aa,
DeployedItem.motionalarmsensor,
DeployedItem.tank_traps
) flatMap UpdateUIElement
@ -352,7 +371,7 @@ class DeployableToolbox {
}
}
def UpdateUI(certifications : List[CertificationType.Value]) : List[(Int,Int,Int,Int)] = {
def UpdateUI(certifications: List[CertificationType.Value]): List[(Int, Int, Int, Int)] = {
certifications flatMap UpdateUI
}
@ -361,11 +380,11 @@ class DeployableToolbox {
* @param item the deployable type
* @return a list of globally unique identifiers that should be valid for the current zone
*/
def ClearDeployable(item : DeployedItem.Value) : List[PlanetSideGUID] = {
val uitem = DeployableToolbox.UnifiedType(item)
val category = Deployable.Category.Of(uitem)
def ClearDeployable(item: DeployedItem.Value): List[PlanetSideGUID] = {
val uitem = DeployableToolbox.UnifiedType(item)
val category = Deployable.Category.Of(uitem)
val categoryList = deployableLists(category)
val (out, in) = categoryList.partition(_.Definition.Item == item)
val (out, in) = categoryList.partition(_.Definition.Item == item)
categoryList.clear()
categoryList ++= in
@ -379,13 +398,13 @@ class DeployableToolbox {
* @param item the deployable type belonging to a category
* @return a list of globally unique identifiers that should be valid for the current zone
*/
def ClearCategory(item : DeployedItem.Value) : List[PlanetSideGUID] = {
def ClearCategory(item: DeployedItem.Value): List[PlanetSideGUID] = {
val category = Deployable.Category.Of(DeployableToolbox.UnifiedType(item))
val out = deployableLists(category).map(_.GUID).toList
val out = deployableLists(category).map(_.GUID).toList
deployableLists(category).clear()
categoryCounts(category).Current = 0
(Deployable.Category.Includes(category) map DeployableToolbox.UnifiedType toSet)
.foreach({item : DeployedItem.Value => deployableCounts(item).Current = 0 })
.foreach({ item: DeployedItem.Value => deployableCounts(item).Current = 0 })
out
}
@ -393,7 +412,7 @@ class DeployableToolbox {
* Remove all managed deployables.
* @return a list of globally unique identifiers that should be valid for the current zone
*/
def Clear() : List[PlanetSideGUID] = {
def Clear(): List[PlanetSideGUID] = {
val out = deployableLists.values.flatten.map(_.GUID).toList
deployableLists.values.foreach(_.clear())
deployableCounts.values.foreach(_.Current = 0)
@ -403,6 +422,7 @@ class DeployableToolbox {
}
object DeployableToolbox {
/**
* A `type` intended to properly define the minimum acceptable conditions for a `Deployable` object.
*/
@ -413,26 +433,28 @@ object DeployableToolbox {
* There are deployable numbers organized by deploybale type and by deployable category.
*/
private class Bin {
/** the maximum number of deployables for this criteria that can be managed */
private var max : Int = 0
private var max: Int = 0
/** the current number of deployables for this criteria that are being managed */
private var current : Int = 0
private var current: Int = 0
def Current : Int = current
def Current: Int = current
def Current_=(curr : Int) : Int = {
def Current_=(curr: Int): Int = {
current = curr
Current
}
def Max : Int = max
def Max: Int = max
def Max_=(mx : Int) : Int = {
def Max_=(mx: Int): Int = {
max = mx
Max
}
def Available() : Boolean = current < max
def Available(): Boolean = current < max
}
/**
@ -441,12 +463,14 @@ object DeployableToolbox {
* @param item the type of deployable
* @return the corrected deployable type
*/
def UnifiedType(item : DeployedItem.Value) : DeployedItem.Value = item match {
case DeployedItem.portable_manned_turret_nc | DeployedItem.portable_manned_turret_tr | DeployedItem.portable_manned_turret_vs =>
DeployedItem.portable_manned_turret
case _ =>
item
}
def UnifiedType(item: DeployedItem.Value): DeployedItem.Value =
item match {
case DeployedItem.portable_manned_turret_nc | DeployedItem.portable_manned_turret_tr |
DeployedItem.portable_manned_turret_vs =>
DeployedItem.portable_manned_turret
case _ =>
item
}
/**
* Hardcoded maximum values for the category and type initialization.
@ -454,9 +478,13 @@ object DeployableToolbox {
* @param categories a reference to the category `Bin` object
* @param certifications a group of certifications for the initial values
*/
private def Initialize(counts : Map[DeployedItem.Value, DeployableToolbox.Bin], categories : Map[DeployableCategory.Value, DeployableToolbox.Bin], certifications : Set[CertificationType.Value]) : Unit = {
private def Initialize(
counts: Map[DeployedItem.Value, DeployableToolbox.Bin],
categories: Map[DeployableCategory.Value, DeployableToolbox.Bin],
certifications: Set[CertificationType.Value]
): Unit = {
import CertificationType._
if(certifications.contains(AdvancedEngineering)) {
if (certifications.contains(AdvancedEngineering)) {
counts(DeployedItem.boomer).Max = 25
counts(DeployedItem.he_mine).Max = 25
counts(DeployedItem.jammer_mine).Max = 20
@ -478,12 +506,11 @@ object DeployableToolbox {
categories(DeployableCategory.FieldTurrets).Max = 1
categories(DeployableCategory.ShieldGenerators).Max = 1
if(certifications.contains(AdvancedHacking)) {
if (certifications.contains(AdvancedHacking)) {
counts(DeployedItem.sensor_shield).Max = 25
}
}
else if(certifications.contains(CombatEngineering)) {
if(certifications.contains(AssaultEngineering)) {
} else if (certifications.contains(CombatEngineering)) {
if (certifications.contains(AssaultEngineering)) {
counts(DeployedItem.jammer_mine).Max = 20
counts(DeployedItem.portable_manned_turret).Max = 1 //the below turret types are unified
//counts(DeployedItem.portable_manned_turret_nc).Max = 1
@ -493,7 +520,7 @@ object DeployableToolbox {
categories(DeployableCategory.FieldTurrets).Max = 1
categories(DeployableCategory.ShieldGenerators).Max = 1
}
if(certifications.contains(FortificationEngineering)) {
if (certifications.contains(FortificationEngineering)) {
counts(DeployedItem.boomer).Max = 25
counts(DeployedItem.he_mine).Max = 25
counts(DeployedItem.spitfire_turret).Max = 15
@ -506,8 +533,7 @@ object DeployableToolbox {
categories(DeployableCategory.SmallTurrets).Max = 15
categories(DeployableCategory.Sensors).Max = 25
categories(DeployableCategory.TankTraps).Max = 5
}
else {
} else {
counts(DeployedItem.boomer).Max = 20
counts(DeployedItem.he_mine).Max = 20
counts(DeployedItem.spitfire_turret).Max = 10
@ -518,11 +544,11 @@ object DeployableToolbox {
categories(DeployableCategory.Sensors).Max = 20
}
if(certifications.contains(AdvancedHacking)) {
if (certifications.contains(AdvancedHacking)) {
counts(DeployedItem.sensor_shield).Max = 20
}
}
if(certifications.contains(CertificationType.GroundSupport)) {
if (certifications.contains(CertificationType.GroundSupport)) {
counts(DeployedItem.router_telepad_deployable).Max = 1024
categories(DeployableCategory.Telepads).Max = 1024
}
@ -535,12 +561,17 @@ object DeployableToolbox {
* @param certification the new certification
* @param certificationSet the group of previous certifications being tracked
*/
def AddToDeployableQuantities(counts : Map[DeployedItem.Value, DeployableToolbox.Bin], categories : Map[DeployableCategory.Value, DeployableToolbox.Bin], certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = {
def AddToDeployableQuantities(
counts: Map[DeployedItem.Value, DeployableToolbox.Bin],
categories: Map[DeployableCategory.Value, DeployableToolbox.Bin],
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): Unit = {
import CertificationType._
if(certificationSet contains certification) {
if (certificationSet contains certification) {
certification match {
case AdvancedHacking =>
if(certificationSet contains CombatEngineering) {
if (certificationSet contains CombatEngineering) {
counts(DeployedItem.sensor_shield).Max = 20
}
@ -553,7 +584,7 @@ object DeployableToolbox {
categories(DeployableCategory.Mines).Max = 20
categories(DeployableCategory.SmallTurrets).Max = 10
categories(DeployableCategory.Sensors).Max = 20
if(certificationSet contains AdvancedHacking) {
if (certificationSet contains AdvancedHacking) {
counts(DeployedItem.sensor_shield).Max = 20
}
@ -582,11 +613,21 @@ object DeployableToolbox {
categories(DeployableCategory.TankTraps).Max = 5
case AdvancedEngineering =>
if(!certificationSet.contains(AssaultEngineering)) {
AddToDeployableQuantities(counts, categories, AssaultEngineering, certificationSet ++ Set(AssaultEngineering))
if (!certificationSet.contains(AssaultEngineering)) {
AddToDeployableQuantities(
counts,
categories,
AssaultEngineering,
certificationSet ++ Set(AssaultEngineering)
)
}
if(!certificationSet.contains(FortificationEngineering)) {
AddToDeployableQuantities(counts, categories, FortificationEngineering, certificationSet ++ Set(FortificationEngineering))
if (!certificationSet.contains(FortificationEngineering)) {
AddToDeployableQuantities(
counts,
categories,
FortificationEngineering,
certificationSet ++ Set(FortificationEngineering)
)
}
// case GroundSupport =>
@ -605,9 +646,14 @@ object DeployableToolbox {
* @param certification the new certification
* @param certificationSet the group of previous certifications being tracked
*/
def RemoveFromDeployablesQuantities(counts : Map[DeployedItem.Value, DeployableToolbox.Bin], categories : Map[DeployableCategory.Value, DeployableToolbox.Bin], certification : CertificationType.Value, certificationSet : Set[CertificationType.Value]) : Unit = {
def RemoveFromDeployablesQuantities(
counts: Map[DeployedItem.Value, DeployableToolbox.Bin],
categories: Map[DeployableCategory.Value, DeployableToolbox.Bin],
certification: CertificationType.Value,
certificationSet: Set[CertificationType.Value]
): Unit = {
import CertificationType._
if(!certificationSet.contains(certification)) {
if (!certificationSet.contains(certification)) {
certification match {
case AdvancedHacking =>
counts(DeployedItem.sensor_shield).Max = 0
@ -625,17 +671,17 @@ object DeployableToolbox {
case AssaultEngineering =>
counts(DeployedItem.jammer_mine).Max = 0
counts(DeployedItem.portable_manned_turret).Max = 0 //the below turret types are unified
counts(DeployedItem.portable_manned_turret).Max = 0 //the below turret types are unified
//counts(DeployedItem.portable_manned_turret_nc).Max = 0
//counts(DeployedItem.portable_manned_turret_tr).Max = 0
//counts(DeployedItem.portable_manned_turret_vs).Max = 0
counts(DeployedItem.deployable_shield_generator).Max = 0
categories(DeployableCategory.Sensors).Max = if(certificationSet contains CombatEngineering) 20 else 0
categories(DeployableCategory.Sensors).Max = if (certificationSet contains CombatEngineering) 20 else 0
categories(DeployableCategory.FieldTurrets).Max = 0
categories(DeployableCategory.ShieldGenerators).Max = 0
case FortificationEngineering =>
val ce : Int = if(certificationSet contains CombatEngineering) 1 else 0 //true = 1, false = 0
val ce: Int = if (certificationSet contains CombatEngineering) 1 else 0 //true = 1, false = 0
counts(DeployedItem.boomer).Max = ce * 20
counts(DeployedItem.he_mine).Max = ce * 20
counts(DeployedItem.spitfire_turret).Max = ce * 10
@ -650,10 +696,10 @@ object DeployableToolbox {
categories(DeployableCategory.TankTraps).Max = 0
case AdvancedEngineering =>
if(!certificationSet.contains(AssaultEngineering)) {
if (!certificationSet.contains(AssaultEngineering)) {
RemoveFromDeployablesQuantities(counts, categories, AssaultEngineering, certificationSet)
}
if(!certificationSet.contains(FortificationEngineering)) {
if (!certificationSet.contains(FortificationEngineering)) {
RemoveFromDeployablesQuantities(counts, categories, FortificationEngineering, certificationSet)
}

View file

@ -3,12 +3,16 @@ package net.psforever.objects.avatar
object FirstTimeEvents {
object TR {
val InfantryWeapons : Set[String] = Set(
"used_chainblade","used_repeater","used_cycler","used_mini_chaingun","used_striker",
val InfantryWeapons: Set[String] = Set(
"used_chainblade",
"used_repeater",
"used_cycler",
"used_mini_chaingun",
"used_striker",
"used_anniversary_guna"
)
val Vehicles : Set[String] = Set(
val Vehicles: Set[String] = Set(
"used_heavy_grenade_launcher",
"used_apc_tr_weapon",
"used_15mm_chaingun",
@ -18,27 +22,38 @@ object FirstTimeEvents {
"used_colossus_cluster_bomb_pod",
"used_colossus_dual_100mm_cannons",
"used_colossus_tank_cannon",
"visited_threemanheavybuggy","visited_battlewagon","visited_apc_tr","visited_prowler",
"visited_colossus_flight","visited_colossus_gunner"
"visited_threemanheavybuggy",
"visited_battlewagon",
"visited_apc_tr",
"visited_prowler",
"visited_colossus_flight",
"visited_colossus_gunner"
)
val Other : Set[String] = Set(
"used_trhev_dualcycler","used_trhev_pounder","used_trhev_burster",
"used_colossus_dual_100mm_cannons","used_colossus_tank_cannon",
val Other: Set[String] = Set(
"used_trhev_dualcycler",
"used_trhev_pounder",
"used_trhev_burster",
"used_colossus_dual_100mm_cannons",
"used_colossus_tank_cannon",
"used_energy_gun_tr",
"visited_portable_manned_turret_tr"
)
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Other
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Other
}
object NC {
val InfantryWeapons : Set[String] = Set(
"used_magcutter","used_isp","used_gauss","used_r_shotgun","used_hunterseeker",
val InfantryWeapons: Set[String] = Set(
"used_magcutter",
"used_isp",
"used_gauss",
"used_r_shotgun",
"used_hunterseeker",
"used_anniversary_gun"
)
val Vehicles : Set[String] = Set(
val Vehicles: Set[String] = Set(
"used_firebird",
"used_gauss_cannon",
"used_apc_nc_weapon",
@ -48,26 +63,36 @@ object FirstTimeEvents {
"used_peregrine_mechhammer",
"used_peregrine_particle_cannon",
"used_peregrine_sparrow",
"visited_twomanheavybuggy","visited_thunderer","visited_apc_nc","visited_vanguard",
"visited_peregrine_flight","visited_peregrine_gunner"
"visited_twomanheavybuggy",
"visited_thunderer",
"visited_apc_nc",
"visited_vanguard",
"visited_peregrine_flight",
"visited_peregrine_gunner"
)
val Other : Set[String] = Set(
"used_nchev_scattercannon","used_nchev_falcon","used_nchev_sparrow",
val Other: Set[String] = Set(
"used_nchev_scattercannon",
"used_nchev_falcon",
"used_nchev_sparrow",
"used_energy_gun_nc",
"visited_portable_manned_turret_nc"
)
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Other
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Other
}
object VS {
val InfantryWeapons : Set[String] = Set(
"used_forceblade","used_beamer","used_pulsar","used_lasher","used_lancer",
val InfantryWeapons: Set[String] = Set(
"used_forceblade",
"used_beamer",
"used_pulsar",
"used_lasher",
"used_lancer",
"used_anniversary_gunb"
)
val Vehicles : Set[String] = Set(
val Vehicles: Set[String] = Set(
"used_fluxpod",
"used_apc_vs_weapon",
"used_heavy_rail_beam",
@ -78,27 +103,45 @@ object FirstTimeEvents {
"used_aphelion_immolation_cannon",
"used_aphelion_plasma_rocket_pod",
"used_aphelion_ppa",
"visited_twomanhoverbuggy","visited_aurora","visited_apc_vs","visited_magrider",
"visited_aphelion_flight","visited_aphelion_gunner"
"visited_twomanhoverbuggy",
"visited_aurora",
"visited_apc_vs",
"visited_magrider",
"visited_aphelion_flight",
"visited_aphelion_gunner"
)
val Other : Set[String] = Set(
"used_vshev_quasar","used_vshev_comet","used_vshev_starfire",
val Other: Set[String] = Set(
"used_vshev_quasar",
"used_vshev_comet",
"used_vshev_starfire",
"used_energy_gun_vs",
"visited_portable_manned_turret_vs"
)
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Other
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Other
}
object Standard {
val InfantryWeapons : Set[String] = Set(
"used_grenade_plasma","used_grenade_jammer","used_grenade_frag",
val InfantryWeapons: Set[String] = Set(
"used_grenade_plasma",
"used_grenade_jammer",
"used_grenade_frag",
"used_katana",
"used_ilc9","used_suppressor","used_punisher","used_flechette","used_phoenix","used_thumper","used_rocklet","used_bolt_driver","used_heavy_sniper","used_oicw","used_flamethrower"
"used_ilc9",
"used_suppressor",
"used_punisher",
"used_flechette",
"used_phoenix",
"used_thumper",
"used_rocklet",
"used_bolt_driver",
"used_heavy_sniper",
"used_oicw",
"used_flamethrower"
)
val Vehicles : Set[String] = Set(
val Vehicles: Set[String] = Set(
"used_armor_siphon",
"used_ntu_siphon",
"used_ballgun",
@ -116,50 +159,95 @@ object FirstTimeEvents {
"used_vulture_nose_cannon",
"used_vulture_tail_cannon",
"used_liberator_bombardier",
"visited_ams","visited_ant",
"visited_quadassault","visited_fury","visited_quadstealth",
"visited_two_man_assault_buggy","visited_skyguard",
"visited_mediumtransport","visited_apc","visited_lightning",
"visited_mosquito","visited_lightgunship","visited_wasp",
"visited_liberator","visited_vulture","visited_dropship","visited_galaxy_gunship",
"visited_phantasm","visited_lodestar"
"visited_ams",
"visited_ant",
"visited_quadassault",
"visited_fury",
"visited_quadstealth",
"visited_two_man_assault_buggy",
"visited_skyguard",
"visited_mediumtransport",
"visited_apc",
"visited_lightning",
"visited_mosquito",
"visited_lightgunship",
"visited_wasp",
"visited_liberator",
"visited_vulture",
"visited_dropship",
"visited_galaxy_gunship",
"visited_phantasm",
"visited_lodestar"
)
val Facilities : Set[String] = Set(
"visited_broadcast_warpgate","visited_warpgate_small",
"visited_respawn_terminal","visited_deconstruction_terminal",
"visited_capture_terminal","visited_secondary_capture","visited_LLU_socket","visited_resource_silo",
"visited_med_terminal","visited_adv_med_terminal","visited_repair_silo",
"visited_order_terminal","visited_certification_terminal","visited_implant_terminal","visited_locker",
"visited_ground_vehicle_terminal","visited_bfr_terminal","visited_air_vehicle_terminal","visited_galaxy_terminal",
"visited_generator","visited_generator_terminal",
"visited_wall_turret","used_phalanx","used_phalanx_avcombo","used_phalanx_flakcombo",
val Facilities: Set[String] = Set(
"visited_broadcast_warpgate",
"visited_warpgate_small",
"visited_respawn_terminal",
"visited_deconstruction_terminal",
"visited_capture_terminal",
"visited_secondary_capture",
"visited_LLU_socket",
"visited_resource_silo",
"visited_med_terminal",
"visited_adv_med_terminal",
"visited_repair_silo",
"visited_order_terminal",
"visited_certification_terminal",
"visited_implant_terminal",
"visited_locker",
"visited_ground_vehicle_terminal",
"visited_bfr_terminal",
"visited_air_vehicle_terminal",
"visited_galaxy_terminal",
"visited_generator",
"visited_generator_terminal",
"visited_wall_turret",
"used_phalanx",
"used_phalanx_avcombo",
"used_phalanx_flakcombo",
"visited_external_door_lock"
)
val Other : Set[String] = Set(
val Other: Set[String] = Set(
"used_command_uplink",
"used_med_app","used_nano_dispenser","used_bank","used_ace","used_advanced_ace","used_rek","used_trek","used_laze_pointer","used_telepad",
"visited_motion_sensor","visited_sensor_shield",
"visited_spitfire_turret","visited_spitfire_cloaked","visited_spitfire_aa",
"visited_shield_generator","visited_tank_traps"
"used_med_app",
"used_nano_dispenser",
"used_bank",
"used_ace",
"used_advanced_ace",
"used_rek",
"used_trek",
"used_laze_pointer",
"used_telepad",
"visited_motion_sensor",
"visited_sensor_shield",
"visited_spitfire_turret",
"visited_spitfire_cloaked",
"visited_spitfire_aa",
"visited_shield_generator",
"visited_tank_traps"
)
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
}
object Cavern {
val InfantryWeapons : Set[String] = Set(
"used_spiker","used_radiator","used_maelstrom"
val InfantryWeapons: Set[String] = Set(
"used_spiker",
"used_radiator",
"used_maelstrom"
)
val Vehicles : Set[String] = Set(
val Vehicles: Set[String] = Set(
"used_scythe",
"used_flail_weapon",
"visited_switchblade","visited_flail","visited_router"
"visited_switchblade",
"visited_flail",
"visited_router"
)
val Facilities : Set[String] = Set(
val Facilities: Set[String] = Set(
"used_ancient_turret_weapon",
"visited_vanu_control_console",
"visited_ancient_air_vehicle_terminal",
@ -172,21 +260,43 @@ object FirstTimeEvents {
"visited_energy_crystal"
)
val Other : Set[String] = Set(
val Other: Set[String] = Set(
"visited_vanu_module"
)
val All : Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
val All: Set[String] = InfantryWeapons ++ Vehicles ++ Facilities ++ Other
}
val Maps : Set[String] = Set(
"map01","map02","map03","map04","map05","map06","map07","map08","map09","map10",
"map11","map12","map13","map14","map15","map16",
"ugd01","ugd02","ugd03","ugd04","ugd05","ugd06",
"map96","map97","map98","map99"
val Maps: Set[String] = Set(
"map01",
"map02",
"map03",
"map04",
"map05",
"map06",
"map07",
"map08",
"map09",
"map10",
"map11",
"map12",
"map13",
"map14",
"map15",
"map16",
"ugd01",
"ugd02",
"ugd03",
"ugd04",
"ugd05",
"ugd06",
"map96",
"map97",
"map98",
"map99"
)
val Monoliths : Set[String] = Set(
val Monoliths: Set[String] = Set(
"visited_monolith_amerish",
"visited_monolith_ceryshen",
"visited_monolith_cyssor",
@ -198,7 +308,7 @@ object FirstTimeEvents {
"visited_monolith_solsar"
)
val Gingerman : Set[String] = Set(
val Gingerman: Set[String] = Set(
"visited_gingerman_atar",
"visited_gingerman_dahaka",
"visited_gingerman_hvar",
@ -211,7 +321,7 @@ object FirstTimeEvents {
"visited_gingerman_zal"
)
val Sled : Set[String] = Set(
val Sled: Set[String] = Set(
"visited_sled01",
"visited_sled02",
"visited_sled04",
@ -222,7 +332,7 @@ object FirstTimeEvents {
"visited_sled09"
)
val Snowman : Set[String] = Set(
val Snowman: Set[String] = Set(
"visited_snowman_amerish",
"visited_snowman_ceryshen",
"visited_snowman_cyssor",
@ -234,7 +344,7 @@ object FirstTimeEvents {
"visited_snowman_solsar"
)
val Charlie : Set[String] = Set(
val Charlie: Set[String] = Set(
"visited_charlie01",
"visited_charlie02",
"visited_charlie03",
@ -246,22 +356,58 @@ object FirstTimeEvents {
"visited_charlie09"
)
val BattleRanks : Set[String] = Set(
"xpe_battle_rank_1","xpe_battle_rank_2","xpe_battle_rank_3","xpe_battle_rank_4","xpe_battle_rank_5",
"xpe_battle_rank_6","xpe_battle_rank_7","xpe_battle_rank_8","xpe_battle_rank_9","xpe_battle_rank_10",
"xpe_battle_rank_11","xpe_battle_rank_12","xpe_battle_rank_13","xpe_battle_rank_14","xpe_battle_rank_15",
"xpe_battle_rank_16","xpe_battle_rank_17","xpe_battle_rank_18","xpe_battle_rank_19","xpe_battle_rank_20",
"xpe_battle_rank_21","xpe_battle_rank_22","xpe_battle_rank_23","xpe_battle_rank_24","xpe_battle_rank_25",
"xpe_battle_rank_26","xpe_battle_rank_27","xpe_battle_rank_28","xpe_battle_rank_29","xpe_battle_rank_30",
"xpe_battle_rank_31","xpe_battle_rank_32","xpe_battle_rank_33","xpe_battle_rank_34","xpe_battle_rank_35",
"xpe_battle_rank_36","xpe_battle_rank_37","xpe_battle_rank_38","xpe_battle_rank_39","xpe_battle_rank_40"
val BattleRanks: Set[String] = Set(
"xpe_battle_rank_1",
"xpe_battle_rank_2",
"xpe_battle_rank_3",
"xpe_battle_rank_4",
"xpe_battle_rank_5",
"xpe_battle_rank_6",
"xpe_battle_rank_7",
"xpe_battle_rank_8",
"xpe_battle_rank_9",
"xpe_battle_rank_10",
"xpe_battle_rank_11",
"xpe_battle_rank_12",
"xpe_battle_rank_13",
"xpe_battle_rank_14",
"xpe_battle_rank_15",
"xpe_battle_rank_16",
"xpe_battle_rank_17",
"xpe_battle_rank_18",
"xpe_battle_rank_19",
"xpe_battle_rank_20",
"xpe_battle_rank_21",
"xpe_battle_rank_22",
"xpe_battle_rank_23",
"xpe_battle_rank_24",
"xpe_battle_rank_25",
"xpe_battle_rank_26",
"xpe_battle_rank_27",
"xpe_battle_rank_28",
"xpe_battle_rank_29",
"xpe_battle_rank_30",
"xpe_battle_rank_31",
"xpe_battle_rank_32",
"xpe_battle_rank_33",
"xpe_battle_rank_34",
"xpe_battle_rank_35",
"xpe_battle_rank_36",
"xpe_battle_rank_37",
"xpe_battle_rank_38",
"xpe_battle_rank_39",
"xpe_battle_rank_40"
)
val CommandRanks : Set[String] = Set(
"xpe_command_rank_1","xpe_command_rank_2","xpe_command_rank_3","xpe_command_rank_4","xpe_command_rank_5"
val CommandRanks: Set[String] = Set(
"xpe_command_rank_1",
"xpe_command_rank_2",
"xpe_command_rank_3",
"xpe_command_rank_4",
"xpe_command_rank_5"
)
val Training : Set[String] = Set(
val Training: Set[String] = Set(
"training_welcome",
"training_map",
"training_hart",
@ -275,13 +421,13 @@ object FirstTimeEvents {
"training_implants"
)
val OldTraining : Set[String] = Set(
val OldTraining: Set[String] = Set(
"training_start_tr",
"training_start_nc",
"training_start_vs"
)
val Generic : Set[String] = Set(
val Generic: Set[String] = Set(
"xpe_overhead_map",
"xpe_mail_alert",
"xpe_join_platoon",

View file

@ -2,14 +2,13 @@
package net.psforever.objects.avatar
import net.psforever.objects.loadouts.Loadout
import net.psforever.types.LoadoutType
import scala.util.Success
class LoadoutManager(size : Int) {
private val entries : Array[Option[Loadout]] = Array.fill[Option[Loadout]](size)(None)
class LoadoutManager(size: Int) {
private val entries: Array[Option[Loadout]] = Array.fill[Option[Loadout]](size)(None)
def SaveLoadout(owner : Any, label : String, line : Int) : Unit = {
def SaveLoadout(owner: Any, label: String, line: Int): Unit = {
Loadout.Create(owner, label) match {
case Success(loadout) if entries.length > line =>
entries(line) = Some(loadout)
@ -17,13 +16,14 @@ class LoadoutManager(size : Int) {
}
}
def LoadLoadout(line : Int) : Option[Loadout] = entries.lift(line).flatten
def LoadLoadout(line: Int): Option[Loadout] = entries.lift(line).flatten
def DeleteLoadout(line : Int) : Unit = {
if(entries.length > line) {
def DeleteLoadout(line: Int): Unit = {
if (entries.length > line) {
entries(line) = None
}
}
def Loadouts : Seq[(Int, Loadout)] = entries.zipWithIndex.collect { case(Some(loadout), index) => (index, loadout) } toSeq
def Loadouts: Seq[(Int, Loadout)] =
entries.zipWithIndex.collect { case (Some(loadout), index) => (index, loadout) } toSeq
}

View file

@ -7,27 +7,29 @@ import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinit
import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{PlanetSideEmpire, Vector3}
final case class ComplexDeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition,
faction : PlanetSideEmpire.Value,
health : Int,
shields : Int,
ownerName : String,
position : Vector3,
orientation : Vector3) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj_def.Name)
override def Faction = faction
def Definition : ObjectDefinition with BaseDeployableDefinition = obj_def
def Health = health
def Shields = shields
def OwnerName = ownerName
def Position = position
def Orientation = orientation
def Velocity = None
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
final case class ComplexDeployableSource(
obj_def: ObjectDefinition with BaseDeployableDefinition,
faction: PlanetSideEmpire.Value,
health: Int,
shields: Int,
ownerName: String,
position: Vector3,
orientation: Vector3
) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj_def.Name)
override def Faction = faction
def Definition: ObjectDefinition with BaseDeployableDefinition = obj_def
def Health = health
def Shields = shields
def OwnerName = ownerName
def Position = position
def Orientation = orientation
def Velocity = None
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
}
object ComplexDeployableSource {
def apply(obj : ComplexDeployable) : ComplexDeployableSource = {
def apply(obj: ComplexDeployable): ComplexDeployableSource = {
ComplexDeployableSource(
obj.Definition,
obj.Faction,
@ -39,7 +41,7 @@ object ComplexDeployableSource {
)
}
def apply(obj : TurretDeployable) : ComplexDeployableSource = {
def apply(obj: TurretDeployable): ComplexDeployableSource = {
ComplexDeployableSource(
obj.Definition,
obj.Faction,

View file

@ -7,25 +7,27 @@ import net.psforever.objects.definition.{BaseDeployableDefinition, ObjectDefinit
import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{PlanetSideEmpire, Vector3}
final case class DeployableSource(obj_def : ObjectDefinition with BaseDeployableDefinition,
faction : PlanetSideEmpire.Value,
health : Int,
ownerName : String,
position : Vector3,
orientation : Vector3) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj_def.Name)
override def Faction = faction
def Definition : ObjectDefinition with BaseDeployableDefinition = obj_def
def Health = health
def OwnerName = ownerName
def Position = position
def Orientation = orientation
def Velocity = None
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
final case class DeployableSource(
obj_def: ObjectDefinition with BaseDeployableDefinition,
faction: PlanetSideEmpire.Value,
health: Int,
ownerName: String,
position: Vector3,
orientation: Vector3
) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj_def.Name)
override def Faction = faction
def Definition: ObjectDefinition with BaseDeployableDefinition = obj_def
def Health = health
def OwnerName = ownerName
def Position = position
def Orientation = orientation
def Velocity = None
def Modifiers = obj_def.asInstanceOf[ResistanceProfile]
}
object DeployableSource {
def apply(obj : PlanetSideGameObject with Deployable) : DeployableSource = {
def apply(obj: PlanetSideGameObject with Deployable): DeployableSource = {
DeployableSource(
obj.Definition,
obj.Faction,

View file

@ -6,22 +6,24 @@ import net.psforever.objects.serverobject.affinity.FactionAffinity
import net.psforever.objects.vital.resistance.ResistanceProfileMutators
import net.psforever.types.{PlanetSideEmpire, Vector3}
final case class ObjectSource(obj : PlanetSideGameObject with FactionAffinity,
faction : PlanetSideEmpire.Value,
position : Vector3,
orientation : Vector3,
velocity : Option[Vector3]) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj.Definition.Name)
final case class ObjectSource(
obj: PlanetSideGameObject with FactionAffinity,
faction: PlanetSideEmpire.Value,
position: Vector3,
orientation: Vector3,
velocity: Option[Vector3]
) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj.Definition.Name)
override def Faction = faction
def Definition = obj.Definition
def Position = position
def Orientation = orientation
def Velocity = velocity
def Modifiers = new ResistanceProfileMutators { }
def Definition = obj.Definition
def Position = position
def Orientation = orientation
def Velocity = velocity
def Modifiers = new ResistanceProfileMutators {}
}
object ObjectSource {
def apply(obj : PlanetSideGameObject with FactionAffinity) : ObjectSource = {
def apply(obj: PlanetSideGameObject with FactionAffinity): ObjectSource = {
ObjectSource(
obj,
obj.Faction,

View file

@ -6,36 +6,49 @@ import net.psforever.objects.definition.{ExoSuitDefinition, ObjectDefinition}
import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{ExoSuitType, PlanetSideEmpire, Vector3}
final case class PlayerSource(name : String,
char_id : Long,
obj_def : ObjectDefinition,
faction : PlanetSideEmpire.Value,
exosuit : ExoSuitType.Value,
seated : Boolean,
health : Int,
armor : Int,
position : Vector3,
orientation : Vector3,
velocity : Option[Vector3],
modifiers : ResistanceProfile) extends SourceEntry {
override def Name = name
final case class PlayerSource(
name: String,
char_id: Long,
obj_def: ObjectDefinition,
faction: PlanetSideEmpire.Value,
exosuit: ExoSuitType.Value,
seated: Boolean,
health: Int,
armor: Int,
position: Vector3,
orientation: Vector3,
velocity: Option[Vector3],
modifiers: ResistanceProfile
) extends SourceEntry {
override def Name = name
override def Faction = faction
override def CharId = char_id
def Definition = obj_def
def ExoSuit = exosuit
def Seated = seated
def Health = health
def Armor = armor
def Position = position
def Orientation = orientation
def Velocity = velocity
def Modifiers = modifiers
override def CharId = char_id
def Definition = obj_def
def ExoSuit = exosuit
def Seated = seated
def Health = health
def Armor = armor
def Position = position
def Orientation = orientation
def Velocity = velocity
def Modifiers = modifiers
}
object PlayerSource {
def apply(tplayer : Player) : PlayerSource = {
PlayerSource(tplayer.Name, tplayer.CharId, tplayer.Definition, tplayer.Faction, tplayer.ExoSuit, tplayer.VehicleSeated.nonEmpty,
tplayer.Health, tplayer.Armor, tplayer.Position, tplayer.Orientation, tplayer.Velocity,
ExoSuitDefinition.Select(tplayer.ExoSuit, tplayer.Faction))
def apply(tplayer: Player): PlayerSource = {
PlayerSource(
tplayer.Name,
tplayer.CharId,
tplayer.Definition,
tplayer.Faction,
tplayer.ExoSuit,
tplayer.VehicleSeated.nonEmpty,
tplayer.Health,
tplayer.Armor,
tplayer.Position,
tplayer.Orientation,
tplayer.Velocity,
ExoSuitDefinition.Select(tplayer.ExoSuit, tplayer.Faction)
)
}
}

View file

@ -28,51 +28,57 @@ import net.psforever.types.Vector3
* @param fire_time when the weapon discharged was recorded;
* defaults to `System.nanoTime`
*/
final case class Projectile(profile : ProjectileDefinition,
tool_def : ToolDefinition,
fire_mode : FireModeDefinition,
owner : SourceEntry,
attribute_to : Int,
shot_origin : Vector3,
shot_angle : Vector3,
fire_time: Long = System.nanoTime) extends PlanetSideGameObject {
final case class Projectile(
profile: ProjectileDefinition,
tool_def: ToolDefinition,
fire_mode: FireModeDefinition,
owner: SourceEntry,
attribute_to: Int,
shot_origin: Vector3,
shot_angle: Vector3,
fire_time: Long = System.nanoTime
) extends PlanetSideGameObject {
Position = shot_origin
Orientation = shot_angle
Velocity = {
val initVel : Int = profile.InitialVelocity //initial velocity
val radAngle : Double = math.toRadians(shot_angle.y) //angle of elevation
val rise : Float = initVel * math.sin(radAngle).toFloat //z
val ground : Float = initVel * math.cos(radAngle).toFloat //base
val initVel: Int = profile.InitialVelocity //initial velocity
val radAngle: Double = math.toRadians(shot_angle.y) //angle of elevation
val rise: Float = initVel * math.sin(radAngle).toFloat //z
val ground: Float = initVel * math.cos(radAngle).toFloat //base
Vector3.Rz(Vector3(0, -ground, 0), shot_angle.z) + Vector3.z(rise)
}
/** Information about the current world coordinates and orientation of the projectile */
val current : SimpleWorldEntity = new SimpleWorldEntity()
private var resolved : ProjectileResolution.Value = ProjectileResolution.Unresolved
val current: SimpleWorldEntity = new SimpleWorldEntity()
private var resolved: ProjectileResolution.Value = ProjectileResolution.Unresolved
/**
* Mark the projectile as being "encountered" or "managed" at least once.
*/
def Resolve() : Unit = {
def Resolve(): Unit = {
resolved = ProjectileResolution.Resolved
}
def Miss() : Unit = {
def Miss(): Unit = {
resolved = ProjectileResolution.MissedShot
}
def isResolved : Boolean = resolved == ProjectileResolution.Resolved || resolved == ProjectileResolution.MissedShot
def isResolved: Boolean = resolved == ProjectileResolution.Resolved || resolved == ProjectileResolution.MissedShot
def isMiss : Boolean = resolved == ProjectileResolution.MissedShot
def isMiss: Boolean = resolved == ProjectileResolution.MissedShot
def Definition = profile
}
object Projectile {
/** the first projectile GUID used by all clients internally */
final val BaseUID : Int = 40100
final val BaseUID: Int = 40100
/** all clients progress through 40100 to 40124 normally, skipping only for long-lived projectiles
* 40125 to 40149 are being reserved as a guard against undetected overflow */
final val RangeUID : Int = 40150
* 40125 to 40149 are being reserved as a guard against undetected overflow
*/
final val RangeUID: Int = 40150
/**
* Overloaded constructor for an `Unresolved` projectile.
@ -84,7 +90,14 @@ object Projectile {
* @param shot_angle in which direction the projectile was aimed when it was discharged
* @return the `Projectile` object
*/
def apply(profile : ProjectileDefinition, tool_def : ToolDefinition, fire_mode : FireModeDefinition, owner : PlanetSideGameObject with FactionAffinity, shot_origin : Vector3, shot_angle : Vector3) : Projectile = {
def apply(
profile: ProjectileDefinition,
tool_def: ToolDefinition,
fire_mode: FireModeDefinition,
owner: PlanetSideGameObject with FactionAffinity,
shot_origin: Vector3,
shot_angle: Vector3
): Projectile = {
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), tool_def.ObjectId, shot_origin, shot_angle)
}
@ -99,7 +112,15 @@ object Projectile {
* @param shot_angle in which direction the projectile was aimed when it was discharged
* @return the `Projectile` object
*/
def apply(profile : ProjectileDefinition, tool_def : ToolDefinition, fire_mode : FireModeDefinition, owner : PlanetSideGameObject with FactionAffinity, attribute_to : Int, shot_origin : Vector3, shot_angle : Vector3) : Projectile = {
def apply(
profile: ProjectileDefinition,
tool_def: ToolDefinition,
fire_mode: FireModeDefinition,
owner: PlanetSideGameObject with FactionAffinity,
attribute_to: Int,
shot_origin: Vector3,
shot_angle: Vector3
): Projectile = {
Projectile(profile, tool_def, fire_mode, SourceEntry(owner), attribute_to, shot_origin, shot_angle)
}
}

View file

@ -7,12 +7,11 @@ package net.psforever.objects.ballistics
object ProjectileResolution extends Enumeration {
type Type = Value
val
Unresolved, //original basic non-resolution
MissedShot, //projectile did not encounter any collision object and was despawned
Resolved, //a general "projectile encountered something" status with a more specific resolution
Hit, //direct hit, one target
Splash, //area of effect damage, potentially multiple targets
Lash //lashing damage, potentially multiple targets
val Unresolved, //original basic non-resolution
MissedShot, //projectile did not encounter any collision object and was despawned
Resolved, //a general "projectile encountered something" status with a more specific resolution
Hit, //direct hit, one target
Splash, //area of effect damage, potentially multiple targets
Lash //lashing damage, potentially multiple targets
= Value
}

View file

@ -7,143 +7,143 @@ package net.psforever.objects.ballistics
object Projectiles extends Enumeration {
final val no_projectile = Value(0)
final val bullet_105mm_projectile = Value(1)
final val bullet_12mm_projectile = Value(4)
final val bullet_12mm_projectileb = Value(5)
final val bullet_150mm_projectile = Value(7)
final val bullet_15mm_apc_projectile = Value(10)
final val bullet_15mm_projectile = Value(11)
final val bullet_20mm_apc_projectile = Value(17)
final val bullet_20mm_projectile = Value(18)
final val bullet_25mm_projectile = Value(20)
final val bullet_35mm_projectile = Value(22)
final val bullet_75mm_apc_projectile = Value(26)
final val bullet_75mm_projectile = Value(27)
final val bullet_9mm_AP_projectile = Value(30)
final val bullet_9mm_projectile = Value(31)
final val anniversary_projectilea = Value(58)
final val anniversary_projectileb = Value(59)
final val aphelion_immolation_cannon_projectile = Value(87)
final val aphelion_laser_projectile = Value(91)
final val aphelion_plasma_rocket_projectile = Value(99)
final val aphelion_ppa_projectile = Value(103)
final val aphelion_starfire_projectile = Value(108)
final val bolt_projectile = Value(147)
final val burster_projectile = Value(155)
final val chainblade_projectile = Value(176)
final val colossus_100mm_projectile = Value(181)
final val colossus_burster_projectile = Value(188)
final val colossus_chaingun_projectile = Value(193)
final val colossus_cluster_bomb_projectile = Value(197)
final val colossus_tank_cannon_projectile = Value(207)
final val comet_projectile = Value(210)
final val dualcycler_projectile = Value(266)
final val dynomite_projectile = Value(268)
final val energy_cell_projectile = Value(273)
final val energy_gun_nc_projectile = Value(277)
final val energy_gun_tr_projectile = Value(279)
final val energy_gun_vs_projectile = Value(281)
final val enhanced_energy_cell_projectile = Value(282)
final val enhanced_quasar_projectile = Value(283)
final val falcon_projectile = Value(286)
final val firebird_missile_projectile = Value(288)
final val flail_projectile = Value(296)
final val flamethrower_fireball = Value(302)
final val flamethrower_projectile = Value(303)
final val flux_cannon_apc_projectile = Value(305)
final val flux_cannon_thresher_projectile = Value(308)
final val fluxpod_projectile = Value(311)
final val forceblade_projectile = Value(325)
final val frag_cartridge_projectile = Value(328)
final val frag_cartridge_projectile_b = Value(329)
final val frag_grenade_projectile = Value(332)
final val frag_grenade_projectile_enh = Value(333)
final val galaxy_gunship_gun_projectile = Value(341)
final val gauss_cannon_projectile = Value(348)
final val grenade_projectile = Value(372)
final val heavy_grenade_projectile = Value(392)
final val heavy_rail_beam_projectile = Value(395)
final val heavy_sniper_projectile = Value(397)
final val hellfire_projectile = Value(400)
final val hunter_seeker_missile_dumbfire = Value(404)
final val hunter_seeker_missile_projectile = Value(405)
final val jammer_cartridge_projectile = Value(414)
final val jammer_cartridge_projectile_b = Value(415)
final val jammer_grenade_projectile = Value(418)
final val jammer_grenade_projectile_enh = Value(419)
final val katana_projectile = Value(422)
final val katana_projectileb = Value(423)
final val lancer_projectile = Value(427)
final val lasher_projectile = Value(430)
final val lasher_projectile_ap = Value(431)
final val bullet_105mm_projectile = Value(1)
final val bullet_12mm_projectile = Value(4)
final val bullet_12mm_projectileb = Value(5)
final val bullet_150mm_projectile = Value(7)
final val bullet_15mm_apc_projectile = Value(10)
final val bullet_15mm_projectile = Value(11)
final val bullet_20mm_apc_projectile = Value(17)
final val bullet_20mm_projectile = Value(18)
final val bullet_25mm_projectile = Value(20)
final val bullet_35mm_projectile = Value(22)
final val bullet_75mm_apc_projectile = Value(26)
final val bullet_75mm_projectile = Value(27)
final val bullet_9mm_AP_projectile = Value(30)
final val bullet_9mm_projectile = Value(31)
final val anniversary_projectilea = Value(58)
final val anniversary_projectileb = Value(59)
final val aphelion_immolation_cannon_projectile = Value(87)
final val aphelion_laser_projectile = Value(91)
final val aphelion_plasma_rocket_projectile = Value(99)
final val aphelion_ppa_projectile = Value(103)
final val aphelion_starfire_projectile = Value(108)
final val bolt_projectile = Value(147)
final val burster_projectile = Value(155)
final val chainblade_projectile = Value(176)
final val colossus_100mm_projectile = Value(181)
final val colossus_burster_projectile = Value(188)
final val colossus_chaingun_projectile = Value(193)
final val colossus_cluster_bomb_projectile = Value(197)
final val colossus_tank_cannon_projectile = Value(207)
final val comet_projectile = Value(210)
final val dualcycler_projectile = Value(266)
final val dynomite_projectile = Value(268)
final val energy_cell_projectile = Value(273)
final val energy_gun_nc_projectile = Value(277)
final val energy_gun_tr_projectile = Value(279)
final val energy_gun_vs_projectile = Value(281)
final val enhanced_energy_cell_projectile = Value(282)
final val enhanced_quasar_projectile = Value(283)
final val falcon_projectile = Value(286)
final val firebird_missile_projectile = Value(288)
final val flail_projectile = Value(296)
final val flamethrower_fireball = Value(302)
final val flamethrower_projectile = Value(303)
final val flux_cannon_apc_projectile = Value(305)
final val flux_cannon_thresher_projectile = Value(308)
final val fluxpod_projectile = Value(311)
final val forceblade_projectile = Value(325)
final val frag_cartridge_projectile = Value(328)
final val frag_cartridge_projectile_b = Value(329)
final val frag_grenade_projectile = Value(332)
final val frag_grenade_projectile_enh = Value(333)
final val galaxy_gunship_gun_projectile = Value(341)
final val gauss_cannon_projectile = Value(348)
final val grenade_projectile = Value(372)
final val heavy_grenade_projectile = Value(392)
final val heavy_rail_beam_projectile = Value(395)
final val heavy_sniper_projectile = Value(397)
final val hellfire_projectile = Value(400)
final val hunter_seeker_missile_dumbfire = Value(404)
final val hunter_seeker_missile_projectile = Value(405)
final val jammer_cartridge_projectile = Value(414)
final val jammer_cartridge_projectile_b = Value(415)
final val jammer_grenade_projectile = Value(418)
final val jammer_grenade_projectile_enh = Value(419)
final val katana_projectile = Value(422)
final val katana_projectileb = Value(423)
final val lancer_projectile = Value(427)
final val lasher_projectile = Value(430)
final val lasher_projectile_ap = Value(431)
final val liberator_bomb_cluster_bomblet_projectile = Value(436)
final val liberator_bomb_cluster_projectile = Value(437)
final val liberator_bomb_projectile = Value(438)
final val maelstrom_grenade_projectile = Value(465)
final val maelstrom_grenade_projectile_contact = Value(466)
final val maelstrom_stream_projectile = Value(467)
final val magcutter_projectile = Value(469)
final val melee_ammo_projectile = Value(541)
final val meteor_common = Value(543)
final val meteor_projectile_b_large = Value(544)
final val meteor_projectile_b_medium = Value(545)
final val meteor_projectile_b_small = Value(546)
final val meteor_projectile_large = Value(547)
final val meteor_projectile_medium = Value(548)
final val meteor_projectile_small = Value(549)
final val mine_projectile = Value(551)
final val mine_sweeper_projectile = Value(554)
final val mine_sweeper_projectile_enh = Value(555)
final val oicw_little_buddy = Value(601)
final val oicw_projectile = Value(602)
final val pellet_gun_projectile = Value(631)
final val peregrine_dual_machine_gun_projectile = Value(639)
final val peregrine_mechhammer_projectile = Value(647)
final val peregrine_particle_cannon_projectile = Value(654)
final val peregrine_rocket_pod_projectile = Value(657)
final val peregrine_sparrow_projectile = Value(661)
final val phalanx_av_projectile = Value(665)
final val phalanx_flak_projectile = Value(667)
final val phalanx_projectile = Value(669)
final val phoenix_missile_guided_projectile = Value(675)
final val phoenix_missile_projectile = Value(676)
final val plasma_cartridge_projectile = Value(678)
final val plasma_cartridge_projectile_b = Value(679)
final val plasma_grenade_projectile = Value(682)
final val plasma_grenade_projectile_B = Value(683)
final val pounder_projectile = Value(694)
final val pounder_projectile_enh = Value(695)
final val ppa_projectile = Value(696)
final val pulsar_ap_projectile = Value(702)
final val pulsar_projectile = Value(703)
final val quasar_projectile = Value(713)
final val radiator_grenade_projectile = Value(718)
final val radiator_sticky_projectile = Value(719)
final val reaver_rocket_projectile = Value(723)
final val rocket_projectile = Value(735)
final val rocklet_flak_projectile = Value(738)
final val rocklet_jammer_projectile = Value(739)
final val scattercannon_projectile = Value(746)
final val scythe_projectile = Value(748)
final val scythe_projectile_slave = Value(749)
final val shotgun_shell_AP_projectile = Value(757)
final val shotgun_shell_projectile = Value(758)
final val six_shooter_projectile = Value(763)
final val skyguard_flak_cannon_projectile = Value(787)
final val sparrow_projectile = Value(792)
final val sparrow_secondary_projectile = Value(793)
final val spiker_projectile = Value(818)
final val spitfire_aa_ammo_projectile = Value(821)
final val spitfire_ammo_projectile = Value(824)
final val starfire_projectile = Value(831)
final val striker_missile_projectile = Value(840)
final val striker_missile_targeting_projectile = Value(841)
final val trek_projectile = Value(878)
final val vanu_sentry_turret_projectile = Value(944)
final val vulture_bomb_projectile = Value(988)
final val vulture_nose_bullet_projectile = Value(989)
final val vulture_tail_bullet_projectile = Value(991)
final val wasp_gun_projectile = Value(999)
final val wasp_rocket_projectile = Value(1001)
final val winchester_projectile = Value(1005)
final val liberator_bomb_cluster_projectile = Value(437)
final val liberator_bomb_projectile = Value(438)
final val maelstrom_grenade_projectile = Value(465)
final val maelstrom_grenade_projectile_contact = Value(466)
final val maelstrom_stream_projectile = Value(467)
final val magcutter_projectile = Value(469)
final val melee_ammo_projectile = Value(541)
final val meteor_common = Value(543)
final val meteor_projectile_b_large = Value(544)
final val meteor_projectile_b_medium = Value(545)
final val meteor_projectile_b_small = Value(546)
final val meteor_projectile_large = Value(547)
final val meteor_projectile_medium = Value(548)
final val meteor_projectile_small = Value(549)
final val mine_projectile = Value(551)
final val mine_sweeper_projectile = Value(554)
final val mine_sweeper_projectile_enh = Value(555)
final val oicw_little_buddy = Value(601)
final val oicw_projectile = Value(602)
final val pellet_gun_projectile = Value(631)
final val peregrine_dual_machine_gun_projectile = Value(639)
final val peregrine_mechhammer_projectile = Value(647)
final val peregrine_particle_cannon_projectile = Value(654)
final val peregrine_rocket_pod_projectile = Value(657)
final val peregrine_sparrow_projectile = Value(661)
final val phalanx_av_projectile = Value(665)
final val phalanx_flak_projectile = Value(667)
final val phalanx_projectile = Value(669)
final val phoenix_missile_guided_projectile = Value(675)
final val phoenix_missile_projectile = Value(676)
final val plasma_cartridge_projectile = Value(678)
final val plasma_cartridge_projectile_b = Value(679)
final val plasma_grenade_projectile = Value(682)
final val plasma_grenade_projectile_B = Value(683)
final val pounder_projectile = Value(694)
final val pounder_projectile_enh = Value(695)
final val ppa_projectile = Value(696)
final val pulsar_ap_projectile = Value(702)
final val pulsar_projectile = Value(703)
final val quasar_projectile = Value(713)
final val radiator_grenade_projectile = Value(718)
final val radiator_sticky_projectile = Value(719)
final val reaver_rocket_projectile = Value(723)
final val rocket_projectile = Value(735)
final val rocklet_flak_projectile = Value(738)
final val rocklet_jammer_projectile = Value(739)
final val scattercannon_projectile = Value(746)
final val scythe_projectile = Value(748)
final val scythe_projectile_slave = Value(749)
final val shotgun_shell_AP_projectile = Value(757)
final val shotgun_shell_projectile = Value(758)
final val six_shooter_projectile = Value(763)
final val skyguard_flak_cannon_projectile = Value(787)
final val sparrow_projectile = Value(792)
final val sparrow_secondary_projectile = Value(793)
final val spiker_projectile = Value(818)
final val spitfire_aa_ammo_projectile = Value(821)
final val spitfire_ammo_projectile = Value(824)
final val starfire_projectile = Value(831)
final val striker_missile_projectile = Value(840)
final val striker_missile_targeting_projectile = Value(841)
final val trek_projectile = Value(878)
final val vanu_sentry_turret_projectile = Value(944)
final val vulture_bomb_projectile = Value(988)
final val vulture_nose_bullet_projectile = Value(989)
final val vulture_tail_bullet_projectile = Value(991)
final val wasp_gun_projectile = Value(999)
final val wasp_rocket_projectile = Value(1001)
final val winchester_projectile = Value(1005)
}

View file

@ -15,10 +15,12 @@ import net.psforever.types.Vector3
* @param damage_model the kind of damage model to which the `target` is/was subject
* @param hit_pos where the projectile hit
*/
final case class ResolvedProjectile(resolution : ProjectileResolution.Value,
projectile : Projectile,
target : SourceEntry,
damage_model : DamageResistanceModel,
hit_pos : Vector3) {
val hit_time : Long = System.nanoTime
final case class ResolvedProjectile(
resolution: ProjectileResolution.Value,
projectile: Projectile,
target: SourceEntry,
damage_model: DamageResistanceModel,
hit_pos: Vector3
) {
val hit_time: Long = System.nanoTime
}

View file

@ -10,37 +10,38 @@ import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{PlanetSideEmpire, Vector3}
trait SourceEntry extends WorldEntity {
def Name : String = ""
def Definition : ObjectDefinition
def CharId : Long = 0L
def Faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
def Position_=(pos : Vector3) = Position
def Orientation_=(pos : Vector3) = Position
def Velocity_=(pos : Option[Vector3]) = Velocity
def Modifiers : ResistanceProfile
def Name: String = ""
def Definition: ObjectDefinition
def CharId: Long = 0L
def Faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
def Position_=(pos: Vector3) = Position
def Orientation_=(pos: Vector3) = Position
def Velocity_=(pos: Option[Vector3]) = Velocity
def Modifiers: ResistanceProfile
}
object SourceEntry {
final val None = new SourceEntry() {
def Definition = null
def Position = Vector3.Zero
def Definition = null
def Position = Vector3.Zero
def Orientation = Vector3.Zero
def Velocity = Some(Vector3.Zero)
def Modifiers = null
def Velocity = Some(Vector3.Zero)
def Modifiers = null
}
def apply(target : PlanetSideGameObject with FactionAffinity) : SourceEntry = {
def apply(target: PlanetSideGameObject with FactionAffinity): SourceEntry = {
target match {
case obj : Player => PlayerSource(obj)
case obj : Vehicle => VehicleSource(obj)
case obj : ComplexDeployable => ComplexDeployableSource(obj)
case obj : SimpleDeployable => DeployableSource(obj)
case _ => ObjectSource(target)
case obj: Player => PlayerSource(obj)
case obj: Vehicle => VehicleSource(obj)
case obj: ComplexDeployable => ComplexDeployableSource(obj)
case obj: SimpleDeployable => DeployableSource(obj)
case _ => ObjectSource(target)
}
}
def NameFormat(name : String) : String = {
name.replace("_", " ")
def NameFormat(name: String): String = {
name
.replace("_", " ")
.split(" ")
.map(_.capitalize)
.mkString(" ")

View file

@ -6,27 +6,29 @@ import net.psforever.objects.definition.VehicleDefinition
import net.psforever.objects.vital.resistance.ResistanceProfile
import net.psforever.types.{PlanetSideEmpire, Vector3}
final case class VehicleSource(obj_def : VehicleDefinition,
faction : PlanetSideEmpire.Value,
health : Int,
shields : Int,
position : Vector3,
orientation : Vector3,
velocity : Option[Vector3],
modifiers : ResistanceProfile) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj_def.Name)
override def Faction = faction
def Definition : VehicleDefinition = obj_def
def Health = health
def Shields = shields
def Position = position
def Orientation = orientation
def Velocity = velocity
def Modifiers = modifiers
final case class VehicleSource(
obj_def: VehicleDefinition,
faction: PlanetSideEmpire.Value,
health: Int,
shields: Int,
position: Vector3,
orientation: Vector3,
velocity: Option[Vector3],
modifiers: ResistanceProfile
) extends SourceEntry {
override def Name = SourceEntry.NameFormat(obj_def.Name)
override def Faction = faction
def Definition: VehicleDefinition = obj_def
def Health = health
def Shields = shields
def Position = position
def Orientation = orientation
def Velocity = velocity
def Modifiers = modifiers
}
object VehicleSource {
def apply(obj : Vehicle) : VehicleSource = {
def apply(obj: Vehicle): VehicleSource = {
VehicleSource(
obj.Definition,
obj.Faction,

View file

@ -4,19 +4,18 @@ package net.psforever.objects.ce
import net.psforever.objects.definition.ComplexDeployableDefinition
import net.psforever.objects.serverobject.PlanetSideServerObject
abstract class ComplexDeployable(cdef : ComplexDeployableDefinition) extends PlanetSideServerObject
with Deployable {
private var shields : Int = 0
abstract class ComplexDeployable(cdef: ComplexDeployableDefinition) extends PlanetSideServerObject with Deployable {
private var shields: Int = 0
def Shields : Int = shields
def Shields: Int = shields
def Shields_=(toShields : Int) : Int = {
def Shields_=(toShields: Int): Int = {
shields = math.min(math.max(0, toShields), MaxShields)
Shields
}
def MaxShields : Int = {
0//Definition.MaxShields
def MaxShields: Int = {
0 //Definition.MaxShields
}
def Definition = cdef

View file

@ -9,83 +9,80 @@ import net.psforever.objects.zones.ZoneAware
import net.psforever.packet.game.DeployableIcon
import net.psforever.types.PlanetSideEmpire
trait Deployable extends FactionAffinity
with Vitality
with OwnableByPlayer
with ZoneAware {
this : PlanetSideGameObject =>
private var faction : PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
trait Deployable extends FactionAffinity with Vitality with OwnableByPlayer with ZoneAware {
this: PlanetSideGameObject =>
private var faction: PlanetSideEmpire.Value = PlanetSideEmpire.NEUTRAL
def MaxHealth : Int
def MaxHealth: Int
def Faction : PlanetSideEmpire.Value = faction
def Faction: PlanetSideEmpire.Value = faction
override def Faction_=(toFaction : PlanetSideEmpire.Value) : PlanetSideEmpire.Value = {
override def Faction_=(toFaction: PlanetSideEmpire.Value): PlanetSideEmpire.Value = {
faction = toFaction
Faction
}
def DamageModel : DamageResistanceModel = Definition.asInstanceOf[DamageResistanceModel]
def DamageModel: DamageResistanceModel = Definition.asInstanceOf[DamageResistanceModel]
def Definition : DeployableDefinition
def Definition: DeployableDefinition
}
object Deployable {
object Category {
def Of(item : DeployedItem.Value) : DeployableCategory.Value = deployablesToCategories(item)
def Of(item: DeployedItem.Value): DeployableCategory.Value = deployablesToCategories(item)
def Includes(category : DeployableCategory.Value) : List[DeployedItem.Value] = {
def Includes(category: DeployableCategory.Value): List[DeployedItem.Value] = {
(for {
(ce, cat) <- deployablesToCategories
if cat == category
} yield ce) toList
}
def OfAll() : Map[DeployedItem.Value, DeployableCategory.Value] = deployablesToCategories
def OfAll(): Map[DeployedItem.Value, DeployableCategory.Value] = deployablesToCategories
private val deployablesToCategories : Map[DeployedItem.Value, DeployableCategory.Value] = Map(
DeployedItem.boomer -> DeployableCategory.Boomers,
DeployedItem.he_mine -> DeployableCategory.Mines,
DeployedItem.jammer_mine -> DeployableCategory.Mines,
DeployedItem.spitfire_turret -> DeployableCategory.SmallTurrets,
DeployedItem.motionalarmsensor -> DeployableCategory.Sensors,
DeployedItem.spitfire_cloaked -> DeployableCategory.SmallTurrets,
DeployedItem.spitfire_aa -> DeployableCategory.SmallTurrets,
private val deployablesToCategories: Map[DeployedItem.Value, DeployableCategory.Value] = Map(
DeployedItem.boomer -> DeployableCategory.Boomers,
DeployedItem.he_mine -> DeployableCategory.Mines,
DeployedItem.jammer_mine -> DeployableCategory.Mines,
DeployedItem.spitfire_turret -> DeployableCategory.SmallTurrets,
DeployedItem.motionalarmsensor -> DeployableCategory.Sensors,
DeployedItem.spitfire_cloaked -> DeployableCategory.SmallTurrets,
DeployedItem.spitfire_aa -> DeployableCategory.SmallTurrets,
DeployedItem.deployable_shield_generator -> DeployableCategory.ShieldGenerators,
DeployedItem.tank_traps -> DeployableCategory.TankTraps,
DeployedItem.portable_manned_turret -> DeployableCategory.FieldTurrets,
DeployedItem.portable_manned_turret_nc -> DeployableCategory.FieldTurrets,
DeployedItem.portable_manned_turret_tr -> DeployableCategory.FieldTurrets,
DeployedItem.portable_manned_turret_vs -> DeployableCategory.FieldTurrets,
DeployedItem.sensor_shield -> DeployableCategory.Sensors,
DeployedItem.router_telepad_deployable -> DeployableCategory.Telepads
DeployedItem.tank_traps -> DeployableCategory.TankTraps,
DeployedItem.portable_manned_turret -> DeployableCategory.FieldTurrets,
DeployedItem.portable_manned_turret_nc -> DeployableCategory.FieldTurrets,
DeployedItem.portable_manned_turret_tr -> DeployableCategory.FieldTurrets,
DeployedItem.portable_manned_turret_vs -> DeployableCategory.FieldTurrets,
DeployedItem.sensor_shield -> DeployableCategory.Sensors,
DeployedItem.router_telepad_deployable -> DeployableCategory.Telepads
)
}
object Icon {
def apply(item : DeployedItem.Value) : DeployableIcon.Value = ceicon(item.id)
def apply(item: DeployedItem.Value): DeployableIcon.Value = ceicon(item.id)
private val ceicon : Map[Int, DeployableIcon.Value] = Map(
DeployedItem.boomer.id -> DeployableIcon.Boomer,
DeployedItem.he_mine.id -> DeployableIcon.HEMine,
DeployedItem.jammer_mine.id -> DeployableIcon.DisruptorMine,
DeployedItem.spitfire_turret.id -> DeployableIcon.SpitfireTurret,
DeployedItem.spitfire_cloaked.id -> DeployableIcon.ShadowTurret,
DeployedItem.spitfire_aa.id -> DeployableIcon.CerebusTurret,
DeployedItem.motionalarmsensor.id -> DeployableIcon.MotionAlarmSensor,
DeployedItem.sensor_shield.id -> DeployableIcon.SensorDisruptor,
DeployedItem.tank_traps.id -> DeployableIcon.TRAP,
DeployedItem.portable_manned_turret.id -> DeployableIcon.FieldTurret,
DeployedItem.portable_manned_turret_tr.id -> DeployableIcon.FieldTurret,
DeployedItem.portable_manned_turret_nc.id -> DeployableIcon.FieldTurret,
DeployedItem.portable_manned_turret_vs.id -> DeployableIcon.FieldTurret,
private val ceicon: Map[Int, DeployableIcon.Value] = Map(
DeployedItem.boomer.id -> DeployableIcon.Boomer,
DeployedItem.he_mine.id -> DeployableIcon.HEMine,
DeployedItem.jammer_mine.id -> DeployableIcon.DisruptorMine,
DeployedItem.spitfire_turret.id -> DeployableIcon.SpitfireTurret,
DeployedItem.spitfire_cloaked.id -> DeployableIcon.ShadowTurret,
DeployedItem.spitfire_aa.id -> DeployableIcon.CerebusTurret,
DeployedItem.motionalarmsensor.id -> DeployableIcon.MotionAlarmSensor,
DeployedItem.sensor_shield.id -> DeployableIcon.SensorDisruptor,
DeployedItem.tank_traps.id -> DeployableIcon.TRAP,
DeployedItem.portable_manned_turret.id -> DeployableIcon.FieldTurret,
DeployedItem.portable_manned_turret_tr.id -> DeployableIcon.FieldTurret,
DeployedItem.portable_manned_turret_nc.id -> DeployableIcon.FieldTurret,
DeployedItem.portable_manned_turret_vs.id -> DeployableIcon.FieldTurret,
DeployedItem.deployable_shield_generator.id -> DeployableIcon.AegisShieldGenerator,
DeployedItem.router_telepad_deployable.id -> DeployableIcon.RouterTelepad
DeployedItem.router_telepad_deployable.id -> DeployableIcon.RouterTelepad
).withDefaultValue(DeployableIcon.Boomer)
}
object UI {
def apply(item : DeployedItem.Value) : (Int, Int) = planetsideAttribute(item)
def apply(item: DeployedItem.Value): (Int, Int) = planetsideAttribute(item)
/**
* The attribute values to be invoked in `PlanetsideAttributeMessage` packets
@ -93,21 +90,21 @@ object Deployable {
* The first number is for the actual count field.
* The second number is for the maximum count field.
*/
private val planetsideAttribute : Map[DeployedItem.Value, (Int, Int)] = Map(
DeployedItem.boomer -> (94, 83),
DeployedItem.he_mine -> (95, 84),
DeployedItem.jammer_mine -> (96, 85),
DeployedItem.spitfire_turret -> (97, 86),
DeployedItem.motionalarmsensor -> (98, 87),
DeployedItem.spitfire_cloaked -> (99, 88),
DeployedItem.spitfire_aa -> (100, 89),
private val planetsideAttribute: Map[DeployedItem.Value, (Int, Int)] = Map(
DeployedItem.boomer -> (94, 83),
DeployedItem.he_mine -> (95, 84),
DeployedItem.jammer_mine -> (96, 85),
DeployedItem.spitfire_turret -> (97, 86),
DeployedItem.motionalarmsensor -> (98, 87),
DeployedItem.spitfire_cloaked -> (99, 88),
DeployedItem.spitfire_aa -> (100, 89),
DeployedItem.deployable_shield_generator -> (101, 90),
DeployedItem.tank_traps -> (102, 91),
DeployedItem.portable_manned_turret -> (103, 92),
DeployedItem.portable_manned_turret_nc -> (103, 92),
DeployedItem.portable_manned_turret_tr -> (103, 92),
DeployedItem.portable_manned_turret_vs -> (103, 92),
DeployedItem.sensor_shield -> (104, 93)
).withDefaultValue((0,0))
DeployedItem.tank_traps -> (102, 91),
DeployedItem.portable_manned_turret -> (103, 92),
DeployedItem.portable_manned_turret_nc -> (103, 92),
DeployedItem.portable_manned_turret_tr -> (103, 92),
DeployedItem.portable_manned_turret_vs -> (103, 92),
DeployedItem.sensor_shield -> (104, 93)
).withDefaultValue((0, 0))
}
}

View file

@ -4,14 +4,5 @@ package net.psforever.objects.ce
object DeployableCategory extends Enumeration {
type Type = Value
val
Boomers,
Mines,
SmallTurrets,
Sensors,
TankTraps,
FieldTurrets,
ShieldGenerators,
Telepads
= Value
val Boomers, Mines, SmallTurrets, Sensors, TankTraps, FieldTurrets, ShieldGenerators, Telepads = Value
}

View file

@ -4,19 +4,19 @@ package net.psforever.objects.ce
object DeployedItem extends Enumeration {
type Type = Value
final val boomer = Value(148)
final val boomer = Value(148)
final val deployable_shield_generator = Value(240)
final val he_mine = Value(388)
final val jammer_mine = Value(420) //disruptor mine
final val motionalarmsensor = Value(575)
final val sensor_shield = Value(752) //sensor disruptor
final val spitfire_aa = Value(819) //cerebus turret
final val spitfire_cloaked = Value(825) //shadow turret
final val spitfire_turret = Value(826)
final val tank_traps = Value(849) //trap
final val portable_manned_turret = Value(685)
final val portable_manned_turret_nc = Value(686)
final val portable_manned_turret_tr = Value(687)
final val portable_manned_turret_vs = Value(688)
final val router_telepad_deployable = Value(744)
final val he_mine = Value(388)
final val jammer_mine = Value(420) //disruptor mine
final val motionalarmsensor = Value(575)
final val sensor_shield = Value(752) //sensor disruptor
final val spitfire_aa = Value(819) //cerebus turret
final val spitfire_cloaked = Value(825) //shadow turret
final val spitfire_turret = Value(826)
final val tank_traps = Value(849) //trap
final val portable_manned_turret = Value(685)
final val portable_manned_turret_nc = Value(686)
final val portable_manned_turret_tr = Value(687)
final val portable_manned_turret_vs = Value(688)
final val router_telepad_deployable = Value(744)
}

View file

@ -4,8 +4,7 @@ package net.psforever.objects.ce
import net.psforever.objects.PlanetSideGameObject
import net.psforever.objects.definition.SimpleDeployableDefinition
abstract class SimpleDeployable(cdef : SimpleDeployableDefinition) extends PlanetSideGameObject
with Deployable {
abstract class SimpleDeployable(cdef: SimpleDeployableDefinition) extends PlanetSideGameObject with Deployable {
Health = Definition.MaxHealth
def Definition = cdef

View file

@ -10,37 +10,37 @@ import net.psforever.objects.zones.Zone
import net.psforever.types.PlanetSideGUID
trait TelepadLike {
private var router : Option[PlanetSideGUID] = None
private var activated : Boolean = false
private var router: Option[PlanetSideGUID] = None
private var activated: Boolean = false
def Router : Option[PlanetSideGUID] = router
def Router: Option[PlanetSideGUID] = router
def Router_=(rguid : PlanetSideGUID) : Option[PlanetSideGUID] = Router_=(Some(rguid))
def Router_=(rguid: PlanetSideGUID): Option[PlanetSideGUID] = Router_=(Some(rguid))
def Router_=(rguid : Option[PlanetSideGUID]) : Option[PlanetSideGUID] = {
def Router_=(rguid: Option[PlanetSideGUID]): Option[PlanetSideGUID] = {
router match {
case None =>
router = rguid
case Some(_) =>
if(rguid.isEmpty || rguid.contains(PlanetSideGUID(0))) {
if (rguid.isEmpty || rguid.contains(PlanetSideGUID(0))) {
router = None
}
}
Router
}
def Active : Boolean = activated
def Active: Boolean = activated
def Active_=(state : Boolean) : Boolean = {
def Active_=(state: Boolean): Boolean = {
activated = state
Active
}
}
object TelepadLike {
final case class Activate(obj : PlanetSideGameObject with TelepadLike)
final case class Activate(obj: PlanetSideGameObject with TelepadLike)
final case class Deactivate(obj : PlanetSideGameObject with TelepadLike)
final case class Deactivate(obj: PlanetSideGameObject with TelepadLike)
/**
* Assemble some logic for a provided object.
@ -48,10 +48,10 @@ object TelepadLike {
* anticipating a `Terminal` object using this same definition
* @param context hook to the local `Actor` system
*/
def Setup(obj : Amenity, context : ActorContext) : Unit = {
def Setup(obj: Amenity, context: ActorContext): Unit = {
obj.asInstanceOf[TelepadLike].Router = obj.Owner.GUID
import akka.actor.Props
if(obj.Actor == Default.Actor) {
if (obj.Actor == Default.Actor) {
obj.Actor = context.actorOf(Props(classOf[TelepadControl], obj), PlanetSideServerObject.UniqueActorName(obj))
}
}
@ -64,20 +64,19 @@ object TelepadLike {
* @param zone where the router is located
* @return the pair of units that compose the teleportation system
*/
def AppraiseTeleportationSystem(router : Vehicle, zone : Zone) : Option[(Utility.InternalTelepad, TelepadDeployable)] = {
def AppraiseTeleportationSystem(router: Vehicle, zone: Zone): Option[(Utility.InternalTelepad, TelepadDeployable)] = {
import net.psforever.objects.vehicles.UtilityType
import net.psforever.types.DriveState
router.Utility(UtilityType.internal_router_telepad_deployable) match {
//if the vehicle has an internal telepad, it is allowed to be a Router (that's a weird way of saying it)
case Some(util : Utility.InternalTelepad) =>
case Some(util: Utility.InternalTelepad) =>
//check for a readied remote telepad
zone.GUID(util.Telepad) match {
case Some(telepad : TelepadDeployable) =>
case Some(telepad: TelepadDeployable) =>
//determine whether to activate both the Router's internal telepad and the deployed remote telepad
if(router.DeploymentState == DriveState.Deployed && util.Active && telepad.Active) {
if (router.DeploymentState == DriveState.Deployed && util.Active && telepad.Active) {
Some((util, telepad))
}
else {
} else {
None
}
case _ =>
@ -96,8 +95,8 @@ object TelepadLike {
* a placeholder like this is easy to reason around.
* @param obj an entity that extends `TelepadLike`
*/
class TelepadControl(obj : TelepadLike) extends akka.actor.Actor {
def receive : akka.actor.Actor.Receive = {
class TelepadControl(obj: TelepadLike) extends akka.actor.Actor {
def receive: akka.actor.Actor.Receive = {
case _ => ;
}
}

View file

@ -4,19 +4,19 @@ package net.psforever.objects.definition
import net.psforever.objects.definition.converter.AmmoBoxConverter
import net.psforever.objects.equipment.Ammo
class AmmoBoxDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
class AmmoBoxDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
import net.psforever.objects.equipment.EquipmentSize
private val ammoType : Ammo.Value = Ammo(objectId) //let throw NoSuchElementException
private var capacity : Int = 1
private val ammoType: Ammo.Value = Ammo(objectId) //let throw NoSuchElementException
private var capacity: Int = 1
Name = "ammo box"
Size = EquipmentSize.Inventory
Packet = AmmoBoxDefinition.converter
def AmmoType : Ammo.Value = ammoType
def AmmoType: Ammo.Value = ammoType
def Capacity : Int = capacity
def Capacity: Int = capacity
def Capacity_=(capacity : Int) : Int = {
def Capacity_=(capacity: Int): Int = {
this.capacity = capacity
Capacity
}
@ -25,11 +25,11 @@ class AmmoBoxDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
object AmmoBoxDefinition {
private val converter = new AmmoBoxConverter()
def apply(objectId: Int) : AmmoBoxDefinition = {
def apply(objectId: Int): AmmoBoxDefinition = {
new AmmoBoxDefinition(objectId)
}
def apply(ammoType : Ammo.Value) : AmmoBoxDefinition = {
def apply(ammoType: Ammo.Value): AmmoBoxDefinition = {
new AmmoBoxDefinition(ammoType.id)
}
}

View file

@ -9,8 +9,7 @@ import net.psforever.objects.vital.VitalityDefinition
* The definition for game objects that look like other people, and also for players.
* @param objectId the object's identifier number
*/
class AvatarDefinition(objectId : Int) extends ObjectDefinition(objectId)
with VitalityDefinition {
class AvatarDefinition(objectId: Int) extends ObjectDefinition(objectId) with VitalityDefinition {
Avatars(objectId) //let throw NoSuchElementException
Packet = AvatarDefinition.converter
}
@ -18,11 +17,11 @@ class AvatarDefinition(objectId : Int) extends ObjectDefinition(objectId)
object AvatarDefinition {
private val converter = new AvatarConverter()
def apply(objectId: Int) : AvatarDefinition = {
def apply(objectId: Int): AvatarDefinition = {
new AvatarDefinition(objectId)
}
def apply(avatar : Avatars.Value) : AvatarDefinition = {
def apply(avatar: Avatars.Value): AvatarDefinition = {
new AvatarDefinition(avatar.id)
}
}

View file

@ -2,21 +2,21 @@
package net.psforever.objects.definition
abstract class BasicDefinition {
private var name : String = "definition"
private var descriptor : Option[String] = None
private var name: String = "definition"
private var descriptor: Option[String] = None
def Name : String = name
def Name: String = name
def Name_=(name : String) : String = {
def Name_=(name: String): String = {
this.name = name
Name
}
def Descriptor : String = descriptor.getOrElse(Name)
def Descriptor: String = descriptor.getOrElse(Name)
def Descriptor_=(description : String) : String = Descriptor_=(Some(description))
def Descriptor_=(description: String): String = Descriptor_=(Some(description))
def Descriptor_=(description : Option[String]) : String = {
def Descriptor_=(description: Option[String]): String = {
descriptor = description
Descriptor
}

View file

@ -7,26 +7,28 @@ import net.psforever.objects.vehicles.CargoVehicleRestriction
* The definition for a cargo hold.
*/
class CargoDefinition extends BasicDefinition {
/** a restriction on the type of exo-suit a person can wear */
private var vehicleRestriction : CargoVehicleRestriction.Value = CargoVehicleRestriction.Small
private var vehicleRestriction: CargoVehicleRestriction.Value = CargoVehicleRestriction.Small
/** the user can escape while the vehicle is moving */
private var bailable : Boolean = true
private var bailable: Boolean = true
Name = "cargo"
def CargoRestriction : CargoVehicleRestriction.Value = {
def CargoRestriction: CargoVehicleRestriction.Value = {
this.vehicleRestriction
}
def CargoRestriction_=(restriction : CargoVehicleRestriction.Value) : CargoVehicleRestriction.Value = {
def CargoRestriction_=(restriction: CargoVehicleRestriction.Value): CargoVehicleRestriction.Value = {
this.vehicleRestriction = restriction
restriction
}
def Bailable : Boolean = {
def Bailable: Boolean = {
this.bailable
}
def Bailable_=(canBail : Boolean) : Boolean = {
def Bailable_=(canBail: Boolean): Boolean = {
this.bailable = canBail
canBail
}

View file

@ -8,39 +8,39 @@ import net.psforever.types.CertificationType
import scala.collection.mutable.ListBuffer
class ConstructionItemDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
class ConstructionItemDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
CItem(objectId) //let throw NoSuchElementException
private val modes : ListBuffer[ConstructionFireMode] = ListBuffer()
private val modes: ListBuffer[ConstructionFireMode] = ListBuffer()
Packet = new ACEConverter
def Modes : ListBuffer[ConstructionFireMode] = modes
def Modes: ListBuffer[ConstructionFireMode] = modes
}
object ConstructionItemDefinition {
def apply(objectId : Int) : ConstructionItemDefinition = {
def apply(objectId: Int): ConstructionItemDefinition = {
new ConstructionItemDefinition(objectId)
}
def apply(cItem : CItem.Value) : ConstructionItemDefinition = {
def apply(cItem: CItem.Value): ConstructionItemDefinition = {
new ConstructionItemDefinition(cItem.id)
}
}
class ConstructionFireMode {
private val deployables : ListBuffer[DeployedItem.Value] = ListBuffer.empty
private val permissions : ListBuffer[Set[CertificationType.Value]] = ListBuffer.empty
private val deployables: ListBuffer[DeployedItem.Value] = ListBuffer.empty
private val permissions: ListBuffer[Set[CertificationType.Value]] = ListBuffer.empty
def Permissions : ListBuffer[Set[CertificationType.Value]] = permissions
def Permissions: ListBuffer[Set[CertificationType.Value]] = permissions
def Deployables : ListBuffer[DeployedItem.Value] = deployables
def Deployables: ListBuffer[DeployedItem.Value] = deployables
def Item(deployable : DeployedItem.Value) : ListBuffer[DeployedItem.Value] = {
def Item(deployable: DeployedItem.Value): ListBuffer[DeployedItem.Value] = {
deployables += deployable
permissions += Set.empty[CertificationType.Value]
deployables
}
def Item(deployPair : (DeployedItem.Value, Set[CertificationType.Value])) : ListBuffer[DeployedItem.Value] = {
def Item(deployPair: (DeployedItem.Value, Set[CertificationType.Value])): ListBuffer[DeployedItem.Value] = {
val (deployable, permission) = deployPair
deployables += deployable
permissions += permission

View file

@ -8,31 +8,34 @@ import net.psforever.objects.inventory.InventoryTile
* The definition for any piece of `Equipment`.
* @param objectId the object's identifier number
*/
abstract class EquipmentDefinition(objectId : Int) extends ObjectDefinition(objectId) {
abstract class EquipmentDefinition(objectId: Int) extends ObjectDefinition(objectId) {
/** the size of the item when placed in an EquipmentSlot / holster / mounting */
private var size : EquipmentSize.Value = EquipmentSize.Blocked
private var size: EquipmentSize.Value = EquipmentSize.Blocked
/** the size of the item when placed in the grid inventory space */
private var tile : InventoryTile = InventoryTile.Tile11
private var tile: InventoryTile = InventoryTile.Tile11
/** a correction for the z-coordinate for some dropped items to avoid sinking into the ground */
private var dropOffset : Float = 0f
private var dropOffset: Float = 0f
def Size : EquipmentSize.Value = size
def Size: EquipmentSize.Value = size
def Size_=(newSize : EquipmentSize.Value) : EquipmentSize.Value = {
def Size_=(newSize: EquipmentSize.Value): EquipmentSize.Value = {
size = newSize
Size
}
def Tile : InventoryTile = tile
def Tile: InventoryTile = tile
def Tile_=(newTile : InventoryTile) : InventoryTile = {
def Tile_=(newTile: InventoryTile): InventoryTile = {
tile = newTile
Tile
}
def DropOffset : Float = dropOffset
def DropOffset: Float = dropOffset
def DropOffset(offset : Float) : Float = {
def DropOffset(offset: Float): Float = {
dropOffset = offset
DropOffset
}

View file

@ -13,112 +13,112 @@ import net.psforever.types.{CertificationType, ExoSuitType, PlanetSideEmpire}
* Players are influenced by the exo-suit they wear in a variety of ways, with speed and available equipment slots being major differences.
* @param suitType the `Enumeration` corresponding to this exo-suit
*/
class ExoSuitDefinition(private val suitType : ExoSuitType.Value) extends BasicDefinition
with ResistanceProfileMutators
with DamageResistanceModel {
protected var permissions : List[CertificationType.Value] = List.empty
protected var maxArmor : Int = 0
protected val holsters : Array[EquipmentSize.Value] = Array.fill[EquipmentSize.Value](5)(EquipmentSize.Blocked)
protected var inventoryScale : InventoryTile = InventoryTile.Tile11 //override with custom InventoryTile
protected var inventoryOffset : Int = 0
protected var maxCapacitor : Int = 0
protected var capacitorRechargeDelayMillis : Int = 0
protected var capacitorRechargePerSecond : Int = 0
protected var capacitorDrainPerSecond : Int = 0
class ExoSuitDefinition(private val suitType: ExoSuitType.Value)
extends BasicDefinition
with ResistanceProfileMutators
with DamageResistanceModel {
protected var permissions: List[CertificationType.Value] = List.empty
protected var maxArmor: Int = 0
protected val holsters: Array[EquipmentSize.Value] = Array.fill[EquipmentSize.Value](5)(EquipmentSize.Blocked)
protected var inventoryScale: InventoryTile = InventoryTile.Tile11 //override with custom InventoryTile
protected var inventoryOffset: Int = 0
protected var maxCapacitor: Int = 0
protected var capacitorRechargeDelayMillis: Int = 0
protected var capacitorRechargePerSecond: Int = 0
protected var capacitorDrainPerSecond: Int = 0
Name = "exo-suit"
DamageUsing = StandardInfantryDamage
ResistUsing = StandardInfantryResistance
Model = StandardResolutions.Infantry
def SuitType : ExoSuitType.Value = suitType
def SuitType: ExoSuitType.Value = suitType
def MaxArmor : Int = maxArmor
def MaxArmor: Int = maxArmor
def MaxArmor_=(armor : Int) : Int = {
def MaxArmor_=(armor: Int): Int = {
maxArmor = math.min(math.max(0, armor), 65535)
MaxArmor
}
def MaxCapacitor : Int = maxCapacitor
def MaxCapacitor: Int = maxCapacitor
def MaxCapacitor_=(value : Int) : Int = {
def MaxCapacitor_=(value: Int): Int = {
maxCapacitor = value
maxCapacitor
}
def CapacitorRechargeDelayMillis : Int = capacitorRechargeDelayMillis
def CapacitorRechargeDelayMillis: Int = capacitorRechargeDelayMillis
def CapacitorRechargeDelayMillis_=(value : Int) : Int = {
def CapacitorRechargeDelayMillis_=(value: Int): Int = {
capacitorRechargeDelayMillis = value
capacitorRechargeDelayMillis
}
def CapacitorRechargePerSecond : Int = capacitorRechargePerSecond
def CapacitorRechargePerSecond: Int = capacitorRechargePerSecond
def CapacitorRechargePerSecond_=(value : Int) : Int = {
def CapacitorRechargePerSecond_=(value: Int): Int = {
capacitorRechargePerSecond = value
capacitorRechargePerSecond
}
def CapacitorDrainPerSecond : Int = capacitorDrainPerSecond
def CapacitorDrainPerSecond: Int = capacitorDrainPerSecond
def CapacitorDrainPerSecond_=(value : Int) : Int = {
def CapacitorDrainPerSecond_=(value: Int): Int = {
capacitorDrainPerSecond = value
capacitorDrainPerSecond
}
def InventoryScale : InventoryTile = inventoryScale
def InventoryScale: InventoryTile = inventoryScale
def InventoryScale_=(scale : InventoryTile) : InventoryTile = {
def InventoryScale_=(scale: InventoryTile): InventoryTile = {
inventoryScale = scale
InventoryScale
}
def InventoryOffset : Int = inventoryOffset
def InventoryOffset: Int = inventoryOffset
def InventoryOffset_=(offset : Int) : Int = {
def InventoryOffset_=(offset: Int): Int = {
inventoryOffset = math.min(math.max(0, offset), 65535)
InventoryOffset
}
def Holsters : Array[EquipmentSize.Value] = holsters
def Holsters: Array[EquipmentSize.Value] = holsters
def Holster(slot : Int) : EquipmentSize.Value = {
if(slot >= 0 && slot < 5) {
def Holster(slot: Int): EquipmentSize.Value = {
if (slot >= 0 && slot < 5) {
holsters(slot)
}
else {
} else {
EquipmentSize.Blocked
}
}
def Holster(slot : Int, value : EquipmentSize.Value) : EquipmentSize.Value = {
if(slot >= 0 && slot < 5) {
def Holster(slot: Int, value: EquipmentSize.Value): EquipmentSize.Value = {
if (slot >= 0 && slot < 5) {
holsters(slot) = value
holsters(slot)
}
else {
} else {
EquipmentSize.Blocked
}
}
def Permissions : List[CertificationType.Value] = permissions
def Permissions: List[CertificationType.Value] = permissions
def Permissions_=(certs : List[CertificationType.Value]) : List[CertificationType.Value] = {
def Permissions_=(certs: List[CertificationType.Value]): List[CertificationType.Value] = {
permissions = certs
Permissions
}
def Use : ExoSuitDefinition = this
def Use: ExoSuitDefinition = this
def canEqual(other: Any): Boolean = other.isInstanceOf[ExoSuitDefinition]
override def equals(other: Any): Boolean = other match {
case that: ExoSuitDefinition =>
(that canEqual this) &&
suitType == that.suitType
case _ => false
}
override def equals(other: Any): Boolean =
other match {
case that: ExoSuitDefinition =>
(that canEqual this) &&
suitType == that.suitType
case _ => false
}
override def hashCode(): Int = {
val state = Seq(suitType)
@ -126,20 +126,20 @@ class ExoSuitDefinition(private val suitType : ExoSuitType.Value) extends BasicD
}
}
class SpecialExoSuitDefinition(private val suitType : ExoSuitType.Value) extends ExoSuitDefinition(suitType) {
class SpecialExoSuitDefinition(private val suitType: ExoSuitType.Value) extends ExoSuitDefinition(suitType) {
Name = "heavy_armor"
Descriptor = "heavy_armor"
private var activatedSpecial : SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
private var activatedSpecial: SpecialExoSuitDefinition.Mode.Value = SpecialExoSuitDefinition.Mode.Normal
def UsingSpecial : SpecialExoSuitDefinition.Mode.Value = activatedSpecial
def UsingSpecial: SpecialExoSuitDefinition.Mode.Value = activatedSpecial
def UsingSpecial_=(state : SpecialExoSuitDefinition.Mode.Value) : SpecialExoSuitDefinition.Mode.Value = {
def UsingSpecial_=(state: SpecialExoSuitDefinition.Mode.Value): SpecialExoSuitDefinition.Mode.Value = {
activatedSpecial = state
UsingSpecial
}
override def Use : ExoSuitDefinition = {
override def Use: ExoSuitDefinition = {
val obj = new SpecialExoSuitDefinition(SuitType)
obj.Permissions = Permissions
obj.MaxArmor = MaxArmor
@ -165,24 +165,19 @@ class SpecialExoSuitDefinition(private val suitType : ExoSuitType.Value) extends
}
object SpecialExoSuitDefinition {
def apply(suitType : ExoSuitType.Value) : SpecialExoSuitDefinition = {
def apply(suitType: ExoSuitType.Value): SpecialExoSuitDefinition = {
new SpecialExoSuitDefinition(suitType)
}
object Mode extends Enumeration {
type Type = Value
val
Normal,
Anchored,
Overdrive,
Shielded
= Value
val Normal, Anchored, Overdrive, Shielded = Value
}
}
object ExoSuitDefinition {
def apply(suitType : ExoSuitType.Value) : ExoSuitDefinition = {
def apply(suitType: ExoSuitType.Value): ExoSuitDefinition = {
new ExoSuitDefinition(suitType)
}
@ -192,16 +187,17 @@ object ExoSuitDefinition {
* @param faction the faction the player belongs to for this exosuit
* @return the exo-suit definition
*/
def Select(suit : ExoSuitType.Value, faction : PlanetSideEmpire.Value) : ExoSuitDefinition = {
def Select(suit: ExoSuitType.Value, faction: PlanetSideEmpire.Value): ExoSuitDefinition = {
suit match {
case ExoSuitType.Infiltration => GlobalDefinitions.Infiltration.Use
case ExoSuitType.Agile => GlobalDefinitions.Agile.Use
case ExoSuitType.Reinforced => GlobalDefinitions.Reinforced.Use
case ExoSuitType.MAX => faction match {
case PlanetSideEmpire.TR => GlobalDefinitions.TRMAX.Use
case PlanetSideEmpire.NC => GlobalDefinitions.NCMAX.Use
case PlanetSideEmpire.VS => GlobalDefinitions.VSMAX.Use
}
case ExoSuitType.Agile => GlobalDefinitions.Agile.Use
case ExoSuitType.Reinforced => GlobalDefinitions.Reinforced.Use
case ExoSuitType.MAX =>
faction match {
case PlanetSideEmpire.TR => GlobalDefinitions.TRMAX.Use
case PlanetSideEmpire.NC => GlobalDefinitions.NCMAX.Use
case PlanetSideEmpire.VS => GlobalDefinitions.VSMAX.Use
}
case _ => GlobalDefinitions.Standard.Use
}
}

View file

@ -17,16 +17,20 @@ import scala.collection.mutable
* @param implantType the type of implant that is defined
* @see `ImplantType`
*/
class ImplantDefinition(private val implantType : Int) extends BasicDefinition {
class ImplantDefinition(private val implantType: Int) extends BasicDefinition {
ImplantType(implantType)
/** how long it takes the implant to become ready for activation; is milliseconds */
private var initializationDuration : Long = 0L
private var initializationDuration: Long = 0L
/** a passive certification is activated as soon as it is ready (or other condition) */
private var passive : Boolean = false
private var passive: Boolean = false
/** how much turning on the implant costs */
private var activationStaminaCost : Int = 0
private var activationStaminaCost: Int = 0
/** how much energy does this implant cost to remain activate per interval tick */
private var staminaCost : Int = 0
private var staminaCost: Int = 0
/**
* How often in milliseconds the stamina cost will be applied, per exo-suit type
@ -37,59 +41,59 @@ class ImplantDefinition(private val implantType : Int) extends BasicDefinition {
* stamina_consumption_interval3 = Rexo
* stamina_consumption_interval4 = MAX?
*/
private var costIntervalDefault : Int = 0
private val costIntervalByExoSuit = mutable.HashMap[ExoSuitType.Value, Int]().withDefaultValue(CostIntervalDefault)
private var costIntervalDefault: Int = 0
private val costIntervalByExoSuit = mutable.HashMap[ExoSuitType.Value, Int]().withDefaultValue(CostIntervalDefault)
Name = "implant"
def InitializationDuration : Long = initializationDuration
def InitializationDuration: Long = initializationDuration
def InitializationDuration_=(time : Long) : Long = {
def InitializationDuration_=(time: Long): Long = {
initializationDuration = math.max(0, time)
InitializationDuration
}
def Passive : Boolean = passive
def Passive: Boolean = passive
def Passive_=(isPassive : Boolean) : Boolean = {
def Passive_=(isPassive: Boolean): Boolean = {
passive = isPassive
Passive
}
def ActivationStaminaCost : Int = activationStaminaCost
def ActivationStaminaCost: Int = activationStaminaCost
def ActivationStaminaCost_=(charge : Int) : Int = {
def ActivationStaminaCost_=(charge: Int): Int = {
activationStaminaCost = math.max(0, charge)
ActivationStaminaCost
}
def StaminaCost : Int = staminaCost
def StaminaCost: Int = staminaCost
def StaminaCost_=(charge : Int) : Int = {
def StaminaCost_=(charge: Int): Int = {
staminaCost = math.max(0, charge)
StaminaCost
}
def CostIntervalDefault : Int = {
def CostIntervalDefault: Int = {
costIntervalDefault
}
def CostIntervalDefault_=(interval : Int) : Int = {
def CostIntervalDefault_=(interval: Int): Int = {
costIntervalDefault = interval
CostIntervalDefault
}
def GetCostIntervalByExoSuit(exosuit : ExoSuitType.Value) : Int = costIntervalByExoSuit.getOrElse(exosuit, CostIntervalDefault)
def CostIntervalByExoSuitHashMap : mutable.Map[ExoSuitType.Value, Int] = costIntervalByExoSuit
def GetCostIntervalByExoSuit(exosuit: ExoSuitType.Value): Int =
costIntervalByExoSuit.getOrElse(exosuit, CostIntervalDefault)
def CostIntervalByExoSuitHashMap: mutable.Map[ExoSuitType.Value, Int] = costIntervalByExoSuit
def Type : ImplantType.Value = ImplantType(implantType)
def Type: ImplantType.Value = ImplantType(implantType)
}
object ImplantDefinition {
def apply(implantType : Int) : ImplantDefinition = {
def apply(implantType: Int): ImplantDefinition = {
new ImplantDefinition(implantType)
}
def apply(implantType : ImplantType.Value) : ImplantDefinition = {
def apply(implantType: ImplantType.Value): ImplantDefinition = {
new ImplantDefinition(implantType.id)
}
}

View file

@ -8,7 +8,7 @@ import net.psforever.objects.equipment.Kits
* The definition for a personal one-time-use recovery item.
* @param objectId the object's identifier number
*/
class KitDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
class KitDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
import net.psforever.objects.equipment.EquipmentSize
import net.psforever.objects.inventory.InventoryTile
Kits(objectId) //let throw NoSuchElementException
@ -21,11 +21,11 @@ class KitDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
object KitDefinition {
private val converter = new KitConverter()
def apply(objectId: Int) : KitDefinition = {
def apply(objectId: Int): KitDefinition = {
new KitDefinition(objectId)
}
def apply(kit : Kits.Value) : KitDefinition = {
def apply(kit: Kits.Value): KitDefinition = {
new KitDefinition(kit.id)
}
}

View file

@ -17,26 +17,28 @@ import net.psforever.objects.definition.converter.{ObjectCreateConverter, Packet
* So long as it is an `ObjectCreatePacket`, those methods can be called correctly for a game object of the desired type.
* @param objectId the object's identifier number
*/
abstract class ObjectDefinition(private val objectId : Int) extends BasicDefinition {
abstract class ObjectDefinition(private val objectId: Int) extends BasicDefinition {
/** a data converter for this type of object */
protected var packet : PacketConverter = new ObjectCreateConverter[PlanetSideGameObject]() { }
protected var packet: PacketConverter = new ObjectCreateConverter[PlanetSideGameObject]() {}
Name = "object definition"
/**
* Get the conversion object.
* @return
*/
final def Packet : ObjectCreateConverter[PlanetSideGameObject] = packet.asInstanceOf[ObjectCreateConverter[PlanetSideGameObject]]
final def Packet: ObjectCreateConverter[PlanetSideGameObject] =
packet.asInstanceOf[ObjectCreateConverter[PlanetSideGameObject]]
/**
* Assign this definition a conversion object.
* @param pkt the new converter
* @return the current converter, after assignment
*/
final def Packet_=(pkt : ObjectCreateConverter[_]) : PacketConverter = {
final def Packet_=(pkt: ObjectCreateConverter[_]): PacketConverter = {
packet = pkt
Packet
}
def ObjectId : Int = objectId
def ObjectId: Int = objectId
}

View file

@ -10,168 +10,170 @@ import net.psforever.objects.vital.{DamageType, StandardDamageProfile}
* `Tool` objects emit `ProjectileDefinition` objects and that is later wrapped into a `Projectile` object.
* @param objectId the object's identifier number
*/
class ProjectileDefinition(objectId : Int) extends ObjectDefinition(objectId)
with JammingUnit
with StandardDamageProfile {
private val projectileType : Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException
private var acceleration : Int = 0
private var accelerationUntil : Float = 0f
private var damageType : DamageType.Value = DamageType.None
private var damageTypeSecondary : DamageType.Value = DamageType.None
private var degradeDelay : Float = 1f
private var degradeMultiplier : Float = 1f
private var initialVelocity : Int = 1
private var lifespan : Float = 1f
private var damageAtEdge : Float = 1f
private var damageRadius : Float = 1f
private var useDamage1Subtract : Boolean = false
private var existsOnRemoteClients : Boolean = false //`true` spawns a server-managed object
private var remoteClientData : (Int, Int) = (0, 0) //artificial values; for ObjectCreateMessage packet (oicw_little_buddy is undefined)
private var autoLock : Boolean = false
private var additionalEffect : Boolean = false
private var jammerProjectile : Boolean = false
class ProjectileDefinition(objectId: Int)
extends ObjectDefinition(objectId)
with JammingUnit
with StandardDamageProfile {
private val projectileType: Projectiles.Value = Projectiles(objectId) //let throw NoSuchElementException
private var acceleration: Int = 0
private var accelerationUntil: Float = 0f
private var damageType: DamageType.Value = DamageType.None
private var damageTypeSecondary: DamageType.Value = DamageType.None
private var degradeDelay: Float = 1f
private var degradeMultiplier: Float = 1f
private var initialVelocity: Int = 1
private var lifespan: Float = 1f
private var damageAtEdge: Float = 1f
private var damageRadius: Float = 1f
private var useDamage1Subtract: Boolean = false
private var existsOnRemoteClients: Boolean = false //`true` spawns a server-managed object
private var remoteClientData: (Int, Int) =
(0, 0) //artificial values; for ObjectCreateMessage packet (oicw_little_buddy is undefined)
private var autoLock: Boolean = false
private var additionalEffect: Boolean = false
private var jammerProjectile: Boolean = false
//derived calculations
private var distanceMax : Float = 0f
private var distanceFromAcceleration : Float = 0f
private var distanceNoDegrade : Float = 0f
private var finalVelocity : Float = 0f
private var distanceMax: Float = 0f
private var distanceFromAcceleration: Float = 0f
private var distanceNoDegrade: Float = 0f
private var finalVelocity: Float = 0f
Name = "projectile"
def ProjectileType : Projectiles.Value = projectileType
def ProjectileType: Projectiles.Value = projectileType
def UseDamage1Subtract : Boolean = useDamage1Subtract
def UseDamage1Subtract: Boolean = useDamage1Subtract
def UseDamage1Subtract_=(useDamage1Subtract : Boolean) : Boolean = {
def UseDamage1Subtract_=(useDamage1Subtract: Boolean): Boolean = {
this.useDamage1Subtract = useDamage1Subtract
UseDamage1Subtract
}
def Acceleration : Int = acceleration
def Acceleration: Int = acceleration
def Acceleration_=(accel : Int) : Int = {
def Acceleration_=(accel: Int): Int = {
acceleration = accel
Acceleration
}
def AccelerationUntil : Float = accelerationUntil
def AccelerationUntil: Float = accelerationUntil
def AccelerationUntil_=(accelUntil : Float) : Float = {
def AccelerationUntil_=(accelUntil: Float): Float = {
accelerationUntil = accelUntil
AccelerationUntil
}
def ProjectileDamageType : DamageType.Value = damageType
def ProjectileDamageType: DamageType.Value = damageType
def ProjectileDamageType_=(damageType1 : DamageType.Value) : DamageType.Value = {
def ProjectileDamageType_=(damageType1: DamageType.Value): DamageType.Value = {
damageType = damageType1
ProjectileDamageType
}
def ProjectileDamageTypeSecondary : DamageType.Value = damageTypeSecondary
def ProjectileDamageTypeSecondary: DamageType.Value = damageTypeSecondary
def ProjectileDamageTypeSecondary_=(damageTypeSecondary1 : DamageType.Value) : DamageType.Value = {
def ProjectileDamageTypeSecondary_=(damageTypeSecondary1: DamageType.Value): DamageType.Value = {
damageTypeSecondary = damageTypeSecondary1
ProjectileDamageTypeSecondary
}
def DegradeDelay : Float = degradeDelay
def DegradeDelay: Float = degradeDelay
def DegradeDelay_=(degradeDelay : Float) : Float = {
def DegradeDelay_=(degradeDelay: Float): Float = {
this.degradeDelay = degradeDelay
DegradeDelay
}
def DegradeMultiplier : Float = degradeMultiplier
def DegradeMultiplier: Float = degradeMultiplier
def DegradeMultiplier_=(degradeMultiplier : Float) : Float = {
def DegradeMultiplier_=(degradeMultiplier: Float): Float = {
this.degradeMultiplier = degradeMultiplier
DegradeMultiplier
}
def InitialVelocity : Int = initialVelocity
def InitialVelocity: Int = initialVelocity
def InitialVelocity_=(initialVelocity : Int) : Int = {
def InitialVelocity_=(initialVelocity: Int): Int = {
this.initialVelocity = initialVelocity
InitialVelocity
}
def Lifespan : Float = lifespan
def Lifespan: Float = lifespan
def Lifespan_=(lifespan : Float) : Float = {
def Lifespan_=(lifespan: Float): Float = {
this.lifespan = lifespan
Lifespan
}
def DamageAtEdge : Float = damageAtEdge
def DamageAtEdge: Float = damageAtEdge
def DamageAtEdge_=(damageAtEdge : Float) : Float = {
def DamageAtEdge_=(damageAtEdge: Float): Float = {
this.damageAtEdge = damageAtEdge
DamageAtEdge
}
def DamageRadius : Float = damageRadius
def DamageRadius: Float = damageRadius
def DamageRadius_=(damageRadius : Float) : Float = {
def DamageRadius_=(damageRadius: Float): Float = {
this.damageRadius = damageRadius
DamageRadius
}
def ExistsOnRemoteClients : Boolean = existsOnRemoteClients
def ExistsOnRemoteClients: Boolean = existsOnRemoteClients
def ExistsOnRemoteClients_=(existsOnRemoteClients : Boolean) : Boolean = {
def ExistsOnRemoteClients_=(existsOnRemoteClients: Boolean): Boolean = {
this.existsOnRemoteClients = existsOnRemoteClients
ExistsOnRemoteClients
}
def RemoteClientData : (Int, Int) = remoteClientData
def RemoteClientData: (Int, Int) = remoteClientData
def RemoteClientData_=(remoteClientData : (Int, Int)) : (Int, Int) = {
def RemoteClientData_=(remoteClientData: (Int, Int)): (Int, Int) = {
this.remoteClientData = remoteClientData
RemoteClientData
}
def AutoLock : Boolean = autoLock
def AutoLock: Boolean = autoLock
def AutoLock_=(lockState : Boolean) : Boolean = {
def AutoLock_=(lockState: Boolean): Boolean = {
autoLock = lockState
AutoLock
}
def AdditionalEffect : Boolean = additionalEffect
def AdditionalEffect: Boolean = additionalEffect
def AdditionalEffect_=(effect : Boolean) : Boolean = {
def AdditionalEffect_=(effect: Boolean): Boolean = {
additionalEffect = effect
AdditionalEffect
}
def JammerProjectile : Boolean = jammerProjectile
def JammerProjectile: Boolean = jammerProjectile
def JammerProjectile_=(effect : Boolean) : Boolean = {
def JammerProjectile_=(effect: Boolean): Boolean = {
jammerProjectile = effect
JammerProjectile
}
def DistanceMax : Float = distanceMax //accessor only
def DistanceMax: Float = distanceMax //accessor only
def DistanceFromAcceleration : Float = distanceFromAcceleration //accessor only
def DistanceFromAcceleration: Float = distanceFromAcceleration //accessor only
def DistanceNoDegrade : Float = distanceNoDegrade //accessor only
def DistanceNoDegrade: Float = distanceNoDegrade //accessor only
def FinalVelocity : Float = finalVelocity //accessor only
def FinalVelocity: Float = finalVelocity //accessor only
}
object ProjectileDefinition {
def apply(projectileType : Projectiles.Value) : ProjectileDefinition = {
def apply(projectileType: Projectiles.Value): ProjectileDefinition = {
new ProjectileDefinition(projectileType.id)
}
def CalculateDerivedFields(pdef : ProjectileDefinition) : Unit = {
val (distanceMax, distanceFromAcceleration, finalVelocity) : (Float, Float, Float) = if(pdef.Acceleration == 0) {
def CalculateDerivedFields(pdef: ProjectileDefinition): Unit = {
val (distanceMax, distanceFromAcceleration, finalVelocity): (Float, Float, Float) = if (pdef.Acceleration == 0) {
(pdef.InitialVelocity * pdef.Lifespan, 0, pdef.InitialVelocity.toFloat)
}
else {
val distanceFromAcceleration = (pdef.AccelerationUntil * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.AccelerationUntil * pdef.AccelerationUntil)
val finalVelocity = pdef.InitialVelocity + pdef.Acceleration * pdef.AccelerationUntil
} else {
val distanceFromAcceleration =
(pdef.AccelerationUntil * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.AccelerationUntil * pdef.AccelerationUntil)
val finalVelocity = pdef.InitialVelocity + pdef.Acceleration * pdef.AccelerationUntil
val distanceAfterAcceleration = finalVelocity * (pdef.Lifespan - pdef.AccelerationUntil)
(distanceFromAcceleration + distanceAfterAcceleration, distanceFromAcceleration, finalVelocity)
}
@ -179,13 +181,11 @@ object ProjectileDefinition {
pdef.distanceFromAcceleration = distanceFromAcceleration
pdef.finalVelocity = finalVelocity
pdef.distanceNoDegrade = if(pdef.DegradeDelay == 0f) {
pdef.distanceNoDegrade = if (pdef.DegradeDelay == 0f) {
pdef.distanceMax
}
else if(pdef.DegradeDelay < pdef.AccelerationUntil) {
} else if (pdef.DegradeDelay < pdef.AccelerationUntil) {
(pdef.DegradeDelay * pdef.InitialVelocity) + (0.5f * pdef.Acceleration * pdef.DegradeDelay * pdef.DegradeDelay)
}
else {
} else {
pdef.distanceFromAcceleration + pdef.finalVelocity * (pdef.DegradeDelay - pdef.AccelerationUntil)
}
}

View file

@ -7,41 +7,44 @@ import net.psforever.objects.vehicles.SeatArmorRestriction
* The definition for a seat.
*/
class SeatDefinition extends BasicDefinition {
/** a restriction on the type of exo-suit a person can wear */
private var armorRestriction : SeatArmorRestriction.Value = SeatArmorRestriction.NoMax
private var armorRestriction: SeatArmorRestriction.Value = SeatArmorRestriction.NoMax
/** the user can escape while the vehicle is moving */
private var bailable : Boolean = false
private var bailable: Boolean = false
/** any controlled weapon */
private var weaponMount : Option[Int] = None
private var weaponMount: Option[Int] = None
Name = "seat"
def ArmorRestriction : SeatArmorRestriction.Value = {
def ArmorRestriction: SeatArmorRestriction.Value = {
this.armorRestriction
}
def ArmorRestriction_=(restriction : SeatArmorRestriction.Value) : SeatArmorRestriction.Value = {
def ArmorRestriction_=(restriction: SeatArmorRestriction.Value): SeatArmorRestriction.Value = {
this.armorRestriction = restriction
restriction
}
def Bailable : Boolean = {
def Bailable: Boolean = {
this.bailable
}
def Bailable_=(canBail : Boolean) : Boolean = {
def Bailable_=(canBail: Boolean): Boolean = {
this.bailable = canBail
canBail
}
def ControlledWeapon : Option[Int] = {
def ControlledWeapon: Option[Int] = {
this.weaponMount
}
def ControlledWeapon_=(wep : Int) : Option[Int] = {
def ControlledWeapon_=(wep: Int): Option[Int] = {
ControlledWeapon_=(Some(wep))
}
def ControlledWeapon_=(wep : Option[Int]) : Option[Int] = {
def ControlledWeapon_=(wep: Option[Int]): Option[Int] = {
this.weaponMount = wep
ControlledWeapon
}

View file

@ -7,66 +7,72 @@ import net.psforever.objects.ce.{Deployable, DeployableCategory, DeployedItem}
import net.psforever.objects.definition.converter.SmallDeployableConverter
import net.psforever.objects.serverobject.PlanetSideServerObject
import net.psforever.objects.vital.resistance.ResistanceProfileMutators
import net.psforever.objects.vital.{DamageResistanceModel, NoResistanceSelection, StandardDeployableDamage, VitalityDefinition}
import net.psforever.objects.vital.{
DamageResistanceModel,
NoResistanceSelection,
StandardDeployableDamage,
VitalityDefinition
}
import scala.concurrent.duration._
trait BaseDeployableDefinition {
private var category : DeployableCategory.Value = DeployableCategory.Boomers
private var deployTime : Long = (1 second).toMillis //ms
private var category: DeployableCategory.Value = DeployableCategory.Boomers
private var deployTime: Long = (1 second).toMillis //ms
def Item : DeployedItem.Value
def Item: DeployedItem.Value
def DeployCategory : DeployableCategory.Value = category
def DeployCategory: DeployableCategory.Value = category
def DeployCategory_=(cat : DeployableCategory.Value) : DeployableCategory.Value = {
def DeployCategory_=(cat: DeployableCategory.Value): DeployableCategory.Value = {
category = cat
DeployCategory
}
def DeployTime : Long = deployTime
def DeployTime: Long = deployTime
def DeployTime_=(time : FiniteDuration) : Long = DeployTime_=(time.toMillis)
def DeployTime_=(time: FiniteDuration): Long = DeployTime_=(time.toMillis)
def DeployTime_=(time: Long) : Long = {
def DeployTime_=(time: Long): Long = {
deployTime = time
DeployTime
}
def Initialize(obj : PlanetSideGameObject with Deployable, context : ActorContext) : Unit = { }
def Initialize(obj: PlanetSideGameObject with Deployable, context: ActorContext): Unit = {}
def Initialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) : Unit = { }
def Initialize(obj: PlanetSideServerObject with Deployable, context: ActorContext): Unit = {}
def Uninitialize(obj : PlanetSideGameObject with Deployable, context : ActorContext) : Unit = { }
def Uninitialize(obj: PlanetSideGameObject with Deployable, context: ActorContext): Unit = {}
def Uninitialize(obj : PlanetSideServerObject with Deployable, context : ActorContext) : Unit = { }
def Uninitialize(obj: PlanetSideServerObject with Deployable, context: ActorContext): Unit = {}
}
abstract class DeployableDefinition(objectId : Int) extends ObjectDefinition(objectId)
with DamageResistanceModel
with ResistanceProfileMutators
with VitalityDefinition
with BaseDeployableDefinition {
abstract class DeployableDefinition(objectId: Int)
extends ObjectDefinition(objectId)
with DamageResistanceModel
with ResistanceProfileMutators
with VitalityDefinition
with BaseDeployableDefinition {
private val item = DeployedItem(objectId) //let throw NoSuchElementException
DamageUsing = StandardDeployableDamage
ResistUsing = NoResistanceSelection
def Item : DeployedItem.Value = item
def Item: DeployedItem.Value = item
}
class SimpleDeployableDefinition(objectId : Int) extends DeployableDefinition(objectId) {
class SimpleDeployableDefinition(objectId: Int) extends DeployableDefinition(objectId) {
Packet = new SmallDeployableConverter
}
abstract class ComplexDeployableDefinition(objectId : Int) extends DeployableDefinition(objectId)
abstract class ComplexDeployableDefinition(objectId: Int) extends DeployableDefinition(objectId)
object SimpleDeployableDefinition {
def apply(item : DeployedItem.Value) : SimpleDeployableDefinition =
def apply(item: DeployedItem.Value): SimpleDeployableDefinition =
new SimpleDeployableDefinition(item.id)
def SimpleUninitialize(obj : PlanetSideGameObject, context : ActorContext) : Unit = { }
def SimpleUninitialize(obj: PlanetSideGameObject, context: ActorContext): Unit = {}
def SimpleUninitialize(obj : PlanetSideServerObject, context : ActorContext) : Unit = {
def SimpleUninitialize(obj: PlanetSideServerObject, context: ActorContext): Unit = {
context.stop(obj.Actor)
obj.Actor = Default.Actor
}

View file

@ -3,7 +3,7 @@ package net.psforever.objects.definition
import net.psforever.objects.equipment.SItem
class SimpleItemDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
class SimpleItemDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
import net.psforever.objects.equipment.EquipmentSize
SItem(objectId) //let throw NoSuchElementException
Name = "tool"
@ -11,11 +11,11 @@ class SimpleItemDefinition(objectId : Int) extends EquipmentDefinition(objectId)
}
object SimpleItemDefinition {
def apply(objectId : Int) : SimpleItemDefinition = {
def apply(objectId: Int): SimpleItemDefinition = {
new SimpleItemDefinition(objectId)
}
def apply(simpItem : SItem.Value) : SimpleItemDefinition = {
def apply(simpItem: SItem.Value): SimpleItemDefinition = {
new SimpleItemDefinition(simpItem.id)
}
}

View file

@ -6,27 +6,27 @@ import net.psforever.objects.equipment.FireModeDefinition
import scala.collection.mutable
class ToolDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
private val ammoTypes : mutable.ListBuffer[AmmoBoxDefinition] = new mutable.ListBuffer[AmmoBoxDefinition]
private val projectileTypes : mutable.ListBuffer[ProjectileDefinition] = new mutable.ListBuffer[ProjectileDefinition]
private val fireModes : mutable.ListBuffer[FireModeDefinition] = new mutable.ListBuffer[FireModeDefinition]
private var defaultFireModeIndex : Option[Int] = None
class ToolDefinition(objectId: Int) extends EquipmentDefinition(objectId) {
private val ammoTypes: mutable.ListBuffer[AmmoBoxDefinition] = new mutable.ListBuffer[AmmoBoxDefinition]
private val projectileTypes: mutable.ListBuffer[ProjectileDefinition] = new mutable.ListBuffer[ProjectileDefinition]
private val fireModes: mutable.ListBuffer[FireModeDefinition] = new mutable.ListBuffer[FireModeDefinition]
private var defaultFireModeIndex: Option[Int] = None
Name = "tool"
Packet = ToolDefinition.converter
def AmmoTypes : mutable.ListBuffer[AmmoBoxDefinition] = ammoTypes
def AmmoTypes: mutable.ListBuffer[AmmoBoxDefinition] = ammoTypes
def ProjectileTypes : mutable.ListBuffer[ProjectileDefinition] = projectileTypes
def ProjectileTypes: mutable.ListBuffer[ProjectileDefinition] = projectileTypes
def FireModes : mutable.ListBuffer[FireModeDefinition] = fireModes
def FireModes: mutable.ListBuffer[FireModeDefinition] = fireModes
def NextFireModeIndex(index : Int) : Int = index + 1
def NextFireModeIndex(index: Int): Int = index + 1
def DefaultFireModeIndex : Int = defaultFireModeIndex.getOrElse(0)
def DefaultFireModeIndex: Int = defaultFireModeIndex.getOrElse(0)
def DefaultFireModeIndex_=(index : Int) : Int = DefaultFireModeIndex_=(Some(index))
def DefaultFireModeIndex_=(index: Int): Int = DefaultFireModeIndex_=(Some(index))
def DefaultFireModeIndex_=(index : Option[Int]) : Int = {
def DefaultFireModeIndex_=(index: Option[Int]): Int = {
defaultFireModeIndex = index
DefaultFireModeIndex
}
@ -35,7 +35,7 @@ class ToolDefinition(objectId : Int) extends EquipmentDefinition(objectId) {
object ToolDefinition {
private val converter = new ToolConverter()
def apply(objectId : Int) : ToolDefinition = {
def apply(objectId: Int): ToolDefinition = {
new ToolDefinition(objectId)
}
}

View file

@ -15,37 +15,39 @@ import scala.concurrent.duration._
* An object definition system used to construct and retain the parameters of various vehicles.
* @param objectId the object id that is associated with this sort of `Vehicle`
*/
class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
with VitalityDefinition
with ResistanceProfileMutators
with DamageResistanceModel {
/** vehicle shields offered through amp station facility benefits (generally: 20% of health + 1) */
private var maxShields : Int = 0
/* key - seat index, value - seat object */
private val seats : mutable.HashMap[Int, SeatDefinition] = mutable.HashMap[Int, SeatDefinition]()
private val cargo : mutable.HashMap[Int, CargoDefinition] = mutable.HashMap[Int, CargoDefinition]()
/* key - entry point index, value - seat index */
private val mountPoints : mutable.HashMap[Int, Int] = mutable.HashMap()
/* key - seat index (where this weapon attaches during object construction), value - the weapon on an EquipmentSlot */
private val weapons : mutable.HashMap[Int, ToolDefinition] = mutable.HashMap[Int, ToolDefinition]()
private var deployment : Boolean = false
private val utilities : mutable.HashMap[Int, UtilityType.Value] = mutable.HashMap()
private val utilityOffsets : mutable.HashMap[Int, Vector3] = mutable.HashMap()
private var deploymentTime_Deploy : Int = 0 //ms
private var deploymentTime_Undeploy : Int = 0 //ms
private var trunkSize : InventoryTile = InventoryTile.None
private var trunkOffset : Int = 0
class VehicleDefinition(objectId: Int)
extends ObjectDefinition(objectId)
with VitalityDefinition
with ResistanceProfileMutators
with DamageResistanceModel {
/** The position offset of the trunk, orientation as East = 0 */
private var trunkLocation : Vector3 = Vector3.Zero
private var canCloak : Boolean = false
private var canFly : Boolean = false
private var canBeOwned : Boolean = true
private var serverVehicleOverrideSpeeds : (Int, Int) = (0, 0)
private var deconTime : Option[FiniteDuration] = None
private var maxCapacitor : Int = 0
private var maxNtuCapacitor : Int = 0
private var destroyedModel : Option[DestroyedVehicle.Value] = None
/** vehicle shields offered through amp station facility benefits (generally: 20% of health + 1) */
private var maxShields: Int = 0
/* key - seat index, value - seat object */
private val seats: mutable.HashMap[Int, SeatDefinition] = mutable.HashMap[Int, SeatDefinition]()
private val cargo: mutable.HashMap[Int, CargoDefinition] = mutable.HashMap[Int, CargoDefinition]()
/* key - entry point index, value - seat index */
private val mountPoints: mutable.HashMap[Int, Int] = mutable.HashMap()
/* key - seat index (where this weapon attaches during object construction), value - the weapon on an EquipmentSlot */
private val weapons: mutable.HashMap[Int, ToolDefinition] = mutable.HashMap[Int, ToolDefinition]()
private var deployment: Boolean = false
private val utilities: mutable.HashMap[Int, UtilityType.Value] = mutable.HashMap()
private val utilityOffsets: mutable.HashMap[Int, Vector3] = mutable.HashMap()
private var deploymentTime_Deploy: Int = 0 //ms
private var deploymentTime_Undeploy: Int = 0 //ms
private var trunkSize: InventoryTile = InventoryTile.None
private var trunkOffset: Int = 0
/** The position offset of the trunk, orientation as East = 0 */
private var trunkLocation: Vector3 = Vector3.Zero
private var canCloak: Boolean = false
private var canFly: Boolean = false
private var canBeOwned: Boolean = true
private var serverVehicleOverrideSpeeds: (Int, Int) = (0, 0)
private var deconTime: Option[FiniteDuration] = None
private var maxCapacitor: Int = 0
private var maxNtuCapacitor: Int = 0
private var destroyedModel: Option[DestroyedVehicle.Value] = None
Name = "vehicle"
Packet = VehicleDefinition.converter
DamageUsing = StandardVehicleDamage
@ -54,135 +56,135 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
RepairDistance = 10
RepairRestoresAt = 1
def MaxShields : Int = maxShields
def MaxShields: Int = maxShields
def MaxShields_=(shields : Int) : Int = {
def MaxShields_=(shields: Int): Int = {
maxShields = shields
MaxShields
}
def Seats : mutable.HashMap[Int, SeatDefinition] = seats
def Seats: mutable.HashMap[Int, SeatDefinition] = seats
def Cargo : mutable.HashMap[Int, CargoDefinition] = cargo
def Cargo: mutable.HashMap[Int, CargoDefinition] = cargo
def MountPoints : mutable.HashMap[Int, Int] = mountPoints
def MountPoints: mutable.HashMap[Int, Int] = mountPoints
def CanBeOwned : Boolean = canBeOwned
def CanBeOwned: Boolean = canBeOwned
def CanBeOwned_=(ownable : Boolean) : Boolean = {
def CanBeOwned_=(ownable: Boolean): Boolean = {
canBeOwned = ownable
CanBeOwned
}
def CanCloak : Boolean = canCloak
def CanCloak: Boolean = canCloak
def CanCloak_=(cloakable : Boolean) : Boolean = {
def CanCloak_=(cloakable: Boolean): Boolean = {
canCloak = cloakable
CanCloak
}
def CanFly : Boolean = canFly
def CanFly: Boolean = canFly
def CanFly_=(flying : Boolean) : Boolean = {
def CanFly_=(flying: Boolean): Boolean = {
canFly = flying
CanFly
}
def Weapons : mutable.HashMap[Int, ToolDefinition] = weapons
def Weapons: mutable.HashMap[Int, ToolDefinition] = weapons
def Deployment : Boolean = deployment
def Deployment: Boolean = deployment
def Deployment_=(deployable : Boolean) : Boolean = {
def Deployment_=(deployable: Boolean): Boolean = {
deployment = deployable
Deployment
}
def Utilities : mutable.HashMap[Int, UtilityType.Value] = utilities
def Utilities: mutable.HashMap[Int, UtilityType.Value] = utilities
def UtilityOffset : mutable.HashMap[Int, Vector3] = utilityOffsets
def UtilityOffset: mutable.HashMap[Int, Vector3] = utilityOffsets
def DeployTime : Int = deploymentTime_Deploy
def DeployTime: Int = deploymentTime_Deploy
def DeployTime_=(dtime : Int) : Int = {
def DeployTime_=(dtime: Int): Int = {
deploymentTime_Deploy = dtime
DeployTime
}
def DeconstructionTime : Option[FiniteDuration] = deconTime
def DeconstructionTime: Option[FiniteDuration] = deconTime
def DeconstructionTime_=(time : FiniteDuration) : Option[FiniteDuration] = {
def DeconstructionTime_=(time: FiniteDuration): Option[FiniteDuration] = {
deconTime_=(Some(time))
DeconstructionTime
}
def DeconstructionTime_=(time : Option[FiniteDuration]) : Option[FiniteDuration] = {
def DeconstructionTime_=(time: Option[FiniteDuration]): Option[FiniteDuration] = {
deconTime = time
DeconstructionTime
}
def UndeployTime : Int = deploymentTime_Undeploy
def UndeployTime: Int = deploymentTime_Undeploy
def UndeployTime_=(dtime : Int) : Int = {
def UndeployTime_=(dtime: Int): Int = {
deploymentTime_Undeploy = dtime
UndeployTime
}
def TrunkSize : InventoryTile = trunkSize
def TrunkSize: InventoryTile = trunkSize
def TrunkSize_=(tile : InventoryTile) : InventoryTile = {
def TrunkSize_=(tile: InventoryTile): InventoryTile = {
trunkSize = tile
TrunkSize
}
def TrunkOffset : Int = trunkOffset
def TrunkOffset: Int = trunkOffset
def TrunkOffset_=(offset : Int) : Int = {
def TrunkOffset_=(offset: Int): Int = {
trunkOffset = offset
TrunkOffset
}
def TrunkLocation : Vector3 = trunkLocation
def TrunkLocation: Vector3 = trunkLocation
def TrunkLocation_=(location : Vector3) : Vector3 = {
def TrunkLocation_=(location: Vector3): Vector3 = {
trunkLocation = location
TrunkLocation
}
def AutoPilotSpeeds : (Int, Int) = serverVehicleOverrideSpeeds
def AutoPilotSpeeds: (Int, Int) = serverVehicleOverrideSpeeds
def AutoPilotSpeeds_=(speeds : (Int, Int)) : (Int, Int) = {
def AutoPilotSpeeds_=(speeds: (Int, Int)): (Int, Int) = {
serverVehicleOverrideSpeeds = speeds
AutoPilotSpeeds
}
def AutoPilotSpeed1 : Int = serverVehicleOverrideSpeeds._1
def AutoPilotSpeed1: Int = serverVehicleOverrideSpeeds._1
def AutoPilotSpeed2 : Int = serverVehicleOverrideSpeeds._2
def AutoPilotSpeed2: Int = serverVehicleOverrideSpeeds._2
def MaxNtuCapacitor : Int = maxNtuCapacitor
def MaxNtuCapacitor: Int = maxNtuCapacitor
def MaxNtuCapacitor_=(max: Int) : Int = {
def MaxNtuCapacitor_=(max: Int): Int = {
maxNtuCapacitor = max
MaxNtuCapacitor
}
def MaxCapacitor : Int = maxCapacitor
def MaxCapacitor: Int = maxCapacitor
def MaxCapacitor_=(max: Int) : Int = {
def MaxCapacitor_=(max: Int): Int = {
maxCapacitor = max
MaxCapacitor
}
private var jackDuration = Array(0, 0, 0, 0)
private var jackDuration = Array(0, 0, 0, 0)
def JackingDuration: Array[Int] = jackDuration
def JackingDuration_=(arr: Array[Int]) : Array[Int] = {
def JackingDuration_=(arr: Array[Int]): Array[Int] = {
jackDuration = arr
arr
}
def DestroyedModel : Option[DestroyedVehicle.Value] = destroyedModel
def DestroyedModel: Option[DestroyedVehicle.Value] = destroyedModel
def DestroyedModel_=(model : Option[DestroyedVehicle.Value]) : Option[DestroyedVehicle.Value] = {
def DestroyedModel_=(model: Option[DestroyedVehicle.Value]): Option[DestroyedVehicle.Value] = {
destroyedModel = model
DestroyedModel
}
@ -191,7 +193,7 @@ class VehicleDefinition(objectId : Int) extends ObjectDefinition(objectId)
object VehicleDefinition {
private val converter = new VehicleConverter
def apply(objectId: Int) : VehicleDefinition = {
def apply(objectId: Int): VehicleDefinition = {
new VehicleDefinition(objectId)
}
}

View file

@ -8,7 +8,7 @@ import net.psforever.types.PlanetSideGUID
import scala.util.{Success, Try}
class ACEConverter extends ObjectCreateConverter[ConstructionItem]() {
override def ConstructorData(obj : ConstructionItem) : Try[HandheldData] = {
override def ConstructorData(obj: ConstructionItem): Try[HandheldData] = {
Success(
HandheldData(
CommonFieldData(
@ -27,7 +27,7 @@ class ACEConverter extends ObjectCreateConverter[ConstructionItem]() {
)
}
override def DetailedConstructorData(obj : ConstructionItem) : Try[DetailedConstructionToolData] = {
override def DetailedConstructorData(obj: ConstructionItem): Try[DetailedConstructionToolData] = {
Success(
DetailedConstructionToolData(
CommonFieldData(

View file

@ -8,11 +8,11 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import scala.util.{Success, Try}
class AmmoBoxConverter extends ObjectCreateConverter[AmmoBox] {
override def ConstructorData(obj : AmmoBox) : Try[CommonFieldData] = {
override def ConstructorData(obj: AmmoBox): Try[CommonFieldData] = {
Success(CommonFieldData()(false))
}
override def DetailedConstructorData(obj : AmmoBox) : Try[DetailedAmmoBoxData] = {
override def DetailedConstructorData(obj: AmmoBox): Try[DetailedAmmoBoxData] = {
Success(
DetailedAmmoBoxData(
CommonFieldData(

View file

@ -10,10 +10,10 @@ import scala.annotation.tailrec
import scala.util.{Success, Try}
class AvatarConverter extends ObjectCreateConverter[Player]() {
override def ConstructorData(obj : Player) : Try[PlayerData] = {
override def ConstructorData(obj: Player): Try[PlayerData] = {
import AvatarConverter._
Success(
if(obj.VehicleSeated.isEmpty) {
if (obj.VehicleSeated.isEmpty) {
PlayerData(
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
MakeAppearanceData(obj),
@ -21,8 +21,7 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
MakeInventoryData(obj),
GetDrawnSlot(obj)
)
}
else {
} else {
PlayerData(
MakeAppearanceData(obj),
MakeCharacterData(obj),
@ -33,10 +32,10 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
)
}
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = {
override def DetailedConstructorData(obj: Player): Try[DetailedPlayerData] = {
import AvatarConverter._
Success(
if(obj.VehicleSeated.isEmpty) {
if (obj.VehicleSeated.isEmpty) {
DetailedPlayerData.apply(
PlacementData(obj.Position, obj.Orientation, obj.Velocity),
MakeAppearanceData(obj),
@ -44,8 +43,7 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
MakeDetailedInventoryData(obj),
GetDrawnSlot(obj)
)
}
else {
} else {
DetailedPlayerData.apply(
MakeAppearanceData(obj),
MakeDetailedCharacterData(obj),
@ -58,14 +56,15 @@ class AvatarConverter extends ObjectCreateConverter[Player]() {
}
object AvatarConverter {
/**
* Compose some data from a `Player` into a representation common to both `CharacterData` and `DetailedCharacterData`.
* @param obj the `Player` game object
* @return the resulting `CharacterAppearanceData`
*/
def MakeAppearanceData(obj : Player) : Int=>CharacterAppearanceData = {
val alt_model_flag : Boolean = obj.isBackpack
val aa : Int=>CharacterAppearanceA = CharacterAppearanceA(
def MakeAppearanceData(obj: Player): Int => CharacterAppearanceData = {
val alt_model_flag: Boolean = obj.isBackpack
val aa: Int => CharacterAppearanceA = CharacterAppearanceA(
BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, obj.Voice),
CommonFieldData(
obj.Faction,
@ -86,7 +85,7 @@ object AvatarConverter {
0,
0
)
val ab : (Boolean,Int)=>CharacterAppearanceB = CharacterAppearanceB(
val ab: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB(
0L,
outfit_name = "",
outfit_logo = 0,
@ -109,14 +108,13 @@ object AvatarConverter {
CharacterAppearanceData(aa, ab, RibbonBars())
}
def MakeCharacterData(obj : Player) : (Boolean,Boolean)=>CharacterData = {
def MakeCharacterData(obj: Player): (Boolean, Boolean) => CharacterData = {
val MaxArmor = obj.MaxArmor
CharacterData(
StatConverter.Health(obj.Health, obj.MaxHealth),
if(MaxArmor == 0) {
if (MaxArmor == 0) {
0
}
else {
} else {
StatConverter.Health(obj.Armor, MaxArmor)
},
DressBattleRank(obj),
@ -127,43 +125,59 @@ object AvatarConverter {
)
}
def MakeDetailedCharacterData(obj : Player) : Option[Int]=>DetailedCharacterData = {
val bep : Long = obj.BEP
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None }
val ba : DetailedCharacterA = DetailedCharacterA(
def MakeDetailedCharacterData(obj: Player): Option[Int] => DetailedCharacterData = {
val bep: Long = obj.BEP
val maxOpt: Option[Long] = if (obj.ExoSuit == ExoSuitType.MAX) { Some(0L) }
else { None }
val ba: DetailedCharacterA = DetailedCharacterA(
bep,
obj.CEP,
0L, 0L, 0L,
obj.MaxHealth, obj.Health,
0L,
0L,
0L,
obj.MaxHealth,
obj.Health,
false,
obj.Armor,
0L,
obj.MaxStamina, obj.Stamina,
obj.MaxStamina,
obj.Stamina,
maxOpt,
0, 0, 0L,
0,
0,
0L,
List(0, 0, 0, 0, 0, 0),
obj.Certifications.toList.sortBy(_.id) //TODO is sorting necessary?
)
val bb : (Long, Option[Int])=>DetailedCharacterB = DetailedCharacterB(
val bb: (Long, Option[Int]) => DetailedCharacterB = DetailedCharacterB(
None,
MakeImplantEntries(obj),
Nil, Nil,
Nil,
Nil,
obj.FirstTimeEvents,
tutorials = List.empty[String], //TODO tutorial list
0L, 0L, 0L, 0L, 0L,
0L,
0L,
0L,
0L,
0L,
Some(DCDExtra2(0, 0)),
Nil, Nil, false,
Nil,
Nil,
false,
MakeCosmetics(obj)
)
pad_length : Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
pad_length: Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
}
def MakeInventoryData(obj : Player) : InventoryData = {
def MakeInventoryData(obj: Player): InventoryData = {
InventoryData(MakeHolsters(obj, BuildEquipment).sortBy(_.parentSlot))
}
def MakeDetailedInventoryData(obj : Player) : InventoryData = {
InventoryData((MakeHolsters(obj, BuildDetailedEquipment) ++ MakeFifthSlot(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot))
def MakeDetailedInventoryData(obj: Player): InventoryData = {
InventoryData(
(MakeHolsters(obj, BuildDetailedEquipment) ++ MakeFifthSlot(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)
)
}
/**
@ -172,18 +186,15 @@ object AvatarConverter {
* @param obj the `Player` game object
* @return the resulting uniform upgrade level
*/
private def DressBattleRank(obj : Player) : UniformStyle.Value = {
val bep : Long = obj.BEP
if(bep > 2583440) { //BR25+
private def DressBattleRank(obj: Player): UniformStyle.Value = {
val bep: Long = obj.BEP
if (bep > 2583440) { //BR25+
UniformStyle.ThirdUpgrade
}
else if(bep > 308989) { //BR14+
} else if (bep > 308989) { //BR14+
UniformStyle.SecondUpgrade
}
else if(bep > 44999) { //BR7+
} else if (bep > 44999) { //BR7+
UniformStyle.FirstUpgrade
}
else { //BR1+
} else { //BR1+
UniformStyle.Normal
}
}
@ -194,24 +205,19 @@ object AvatarConverter {
* @param obj the `Player` game object
* @return the resulting uniform upgrade level
*/
private def DressCommandRank(obj : Player) : Int = {
private def DressCommandRank(obj: Player): Int = {
val cep = obj.CEP
if(cep > 599999) {
if (cep > 599999) {
5
}
else if(cep > 299999) {
} else if (cep > 299999) {
4
}
else if(cep > 149999) {
} else if (cep > 149999) {
3
}
else if(cep > 49999) {
} else if (cep > 49999) {
2
}
else if(cep > 9999) {
} else if (cep > 9999) {
1
}
else {
} else {
0
}
}
@ -222,17 +228,19 @@ object AvatarConverter {
* @return the resulting implant `List`
* @see `ImplantEntry` in `DetailedCharacterData`
*/
private def MakeImplantEntries(obj : Player) : List[ImplantEntry] = {
private def MakeImplantEntries(obj: Player): List[ImplantEntry] = {
//val numImplants : Int = DetailedCharacterData.numberOfImplantSlots(obj.BEP)
//val implants = obj.Implants
obj.Implants.map({ case(implant, initialization, _) =>
if(initialization == 0) {
ImplantEntry(implant, None)
}
else {
ImplantEntry(implant, Some(math.max(0,initialization).toInt))
}
}).toList
obj.Implants
.map({
case (implant, initialization, _) =>
if (initialization == 0) {
ImplantEntry(implant, None)
} else {
ImplantEntry(implant, Some(math.max(0, initialization).toInt))
}
})
.toList
}
/**
@ -240,12 +248,12 @@ object AvatarConverter {
* @param implants a `Sequence` of `ImplantSlot` objects
* @return the effect of an active implant
*/
private def MakeImplantEffectList(implants : Seq[(ImplantType.Value, Long, Boolean)]) : List[ImplantEffects.Value] = {
private def MakeImplantEffectList(implants: Seq[(ImplantType.Value, Long, Boolean)]): List[ImplantEffects.Value] = {
implants.collect {
case (ImplantType.AdvancedRegen,_,true) => ImplantEffects.RegenEffects
case (ImplantType.DarklightVision,_,true) => ImplantEffects.DarklightEffects
case (ImplantType.PersonalShield,_,true) => ImplantEffects.PersonalShieldEffects
case (ImplantType.Surge,_,true) => ImplantEffects.SurgeEffects
case (ImplantType.AdvancedRegen, _, true) => ImplantEffects.RegenEffects
case (ImplantType.DarklightVision, _, true) => ImplantEffects.DarklightEffects
case (ImplantType.PersonalShield, _, true) => ImplantEffects.PersonalShieldEffects
case (ImplantType.Surge, _, true) => ImplantEffects.SurgeEffects
}.toList
}
@ -257,11 +265,10 @@ object AvatarConverter {
* @see `Cosmetics`
* @return the `Cosmetics` options
*/
def MakeCosmetics(obj : Player) : Option[Cosmetics] =
if(DetailedCharacterData.isBR24(obj.BEP)) {
def MakeCosmetics(obj: Player): Option[Cosmetics] =
if (DetailedCharacterData.isBR24(obj.BEP)) {
obj.PersonalStyleFeatures.orElse(Some(Cosmetics()))
}
else {
} else {
None
}
@ -272,11 +279,16 @@ object AvatarConverter {
* @param obj the `Player` game object
* @return a list of all items that were in the inventory in decoded packet form
*/
private def MakeInventory(obj : Player) : List[InternalSlot] = {
private def MakeInventory(obj: Player): List[InternalSlot] = {
obj.Inventory.Items
.map(item => {
val equip : Equipment = item.obj
InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.DetailedConstructorData(equip).get)
val equip: Equipment = item.obj
InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
item.start,
equip.Definition.Packet.DetailedConstructorData(equip).get
)
})
}
@ -289,7 +301,7 @@ object AvatarConverter {
* @param builder the function used to transform to the decoded packet form
* @return a list of all items that were in the holsters in decoded packet form
*/
private def MakeHolsters(obj : Player, builder : (Int, Equipment) => InternalSlot) : List[InternalSlot] = {
private def MakeHolsters(obj: Player, builder: (Int, Equipment) => InternalSlot): List[InternalSlot] = {
recursiveMakeHolsters(obj.Holsters().iterator, builder)
}
@ -300,7 +312,7 @@ object AvatarConverter {
* @param obj the `Player` game object
* @return a list of any item that was in the fifth holster in decoded packet form
*/
private def MakeFifthSlot(obj : Player) : List[InternalSlot] = {
private def MakeFifthSlot(obj: Player): List[InternalSlot] = {
obj.Slot(5).Equipment match {
case Some(equip) =>
BuildDetailedEquipment(5, equip) :: Nil
@ -315,7 +327,7 @@ object AvatarConverter {
* @param equip the game object
* @return the game object in decoded packet form
*/
private def BuildEquipment(index : Int, equip : Equipment) : InternalSlot = {
private def BuildEquipment(index: Int, equip: Equipment): InternalSlot = {
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.ConstructorData(equip).get)
}
@ -325,8 +337,13 @@ object AvatarConverter {
* @param equip the game object
* @return the game object in decoded packet form
*/
def BuildDetailedEquipment(index : Int, equip : Equipment) : InternalSlot = {
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.DetailedConstructorData(equip).get)
def BuildDetailedEquipment(index: Int, equip: Equipment): InternalSlot = {
InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
index,
equip.Definition.Packet.DetailedConstructorData(equip).get
)
}
/**
@ -337,22 +354,25 @@ object AvatarConverter {
* @param index which holster is currently being explored
* @return the `List` of inventory data created from the holsters
*/
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], builder : (Int, Equipment) => InternalSlot, list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = {
if(!iter.hasNext) {
@tailrec private def recursiveMakeHolsters(
iter: Iterator[EquipmentSlot],
builder: (Int, Equipment) => InternalSlot,
list: List[InternalSlot] = Nil,
index: Int = 0
): List[InternalSlot] = {
if (!iter.hasNext) {
list
}
else {
val slot : EquipmentSlot = iter.next
if(slot.Equipment.isDefined) {
val equip : Equipment = slot.Equipment.get
} else {
val slot: EquipmentSlot = iter.next
if (slot.Equipment.isDefined) {
val equip: Equipment = slot.Equipment.get
recursiveMakeHolsters(
iter,
builder,
list :+ builder(index, equip),
index + 1
)
}
else {
} else {
recursiveMakeHolsters(iter, builder, list, index + 1)
}
}
@ -363,10 +383,10 @@ object AvatarConverter {
* @param obj the `Player` game object
* @return the holster's Enumeration value
*/
def GetDrawnSlot(obj : Player) : DrawnSlot.Value = {
def GetDrawnSlot(obj: Player): DrawnSlot.Value = {
obj.DrawnSlot match {
case Player.HandsDownSlot | Player.FreeHandSlot => DrawnSlot.None
case n => DrawnSlot(n)
case n => DrawnSlot(n)
}
}
}

View file

@ -8,13 +8,15 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import scala.util.{Success, Try}
class BoomerTriggerConverter extends ObjectCreateConverter[SimpleItem]() {
override def ConstructorData(obj : SimpleItem) : Try[HandheldData] = {
override def ConstructorData(obj: SimpleItem): Try[HandheldData] = {
Success(HandheldData(CommonFieldData()))
}
override def DetailedConstructorData(obj : SimpleItem) : Try[DetailedConstructionToolData] = {
Success(DetailedConstructionToolData(
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0))
))
override def DetailedConstructorData(obj: SimpleItem): Try[DetailedConstructionToolData] = {
Success(
DetailedConstructionToolData(
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0))
)
)
}
}

View file

@ -2,7 +2,7 @@
package net.psforever.objects.definition.converter
import net.psforever.objects.{Player, Tool}
import net.psforever.objects.equipment.{Equipment, EquipmentSlot}
import net.psforever.objects.equipment.EquipmentSlot
import net.psforever.packet.game.objectcreate._
import net.psforever.types.{PlanetSideGUID, _}
@ -15,9 +15,10 @@ import scala.util.{Failure, Success, Try}
* Details that would not be apparent on that screen such as implants or certifications are ignored.
*/
class CharacterSelectConverter extends AvatarConverter {
override def ConstructorData(obj : Player) : Try[PlayerData] = Failure(new Exception("CharacterSelectConverter should not be used to generate CharacterData"))
override def ConstructorData(obj: Player): Try[PlayerData] =
Failure(new Exception("CharacterSelectConverter should not be used to generate CharacterData"))
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = {
override def DetailedConstructorData(obj: Player): Try[DetailedPlayerData] = {
Success(
DetailedPlayerData.apply(
PlacementData(0, 0, 0),
@ -35,8 +36,8 @@ class CharacterSelectConverter extends AvatarConverter {
* @see `AvatarConverter.MakeAppearanceData`
* @return the resulting `CharacterAppearanceData`
*/
private def MakeAppearanceData(obj : Player) : Int=>CharacterAppearanceData = {
val aa : Int=>CharacterAppearanceA = CharacterAppearanceA(
private def MakeAppearanceData(obj: Player): Int => CharacterAppearanceData = {
val aa: Int => CharacterAppearanceA = CharacterAppearanceA(
BasicCharacterData(obj.Name, obj.Faction, obj.Sex, obj.Head, CharacterVoice.Mute),
CommonFieldData(
obj.Faction,
@ -57,7 +58,7 @@ class CharacterSelectConverter extends AvatarConverter {
0,
0
)
val ab : (Boolean,Int)=>CharacterAppearanceB = CharacterAppearanceB(
val ab: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB(
0L,
outfit_name = "",
outfit_logo = 0,
@ -80,35 +81,49 @@ class CharacterSelectConverter extends AvatarConverter {
CharacterAppearanceData(aa, ab, RibbonBars())
}
private def MakeDetailedCharacterData(obj : Player) : Option[Int]=>DetailedCharacterData = {
val bep : Long = obj.BEP
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None }
val ba : DetailedCharacterA = DetailedCharacterA(
private def MakeDetailedCharacterData(obj: Player): Option[Int] => DetailedCharacterData = {
val bep: Long = obj.BEP
val maxOpt: Option[Long] = if (obj.ExoSuit == ExoSuitType.MAX) { Some(0L) }
else { None }
val ba: DetailedCharacterA = DetailedCharacterA(
bep,
obj.CEP,
0L, 0L, 0L,
1, 1,
0L,
0L,
0L,
1,
1,
false,
0,
0L,
1, 1,
1,
1,
maxOpt,
0, 0, 0L,
0,
0,
0L,
List(0, 0, 0, 0, 0, 0),
certs = List.empty[CertificationType.Value]
)
val bb : (Long, Option[Int])=>DetailedCharacterB = DetailedCharacterB(
val bb: (Long, Option[Int]) => DetailedCharacterB = DetailedCharacterB(
None,
MakeImplantEntries(obj), //necessary for correct stream length
Nil, Nil,
Nil,
Nil,
firstTimeEvents = List.empty[String],
tutorials = List.empty[String],
0L, 0L, 0L, 0L, 0L,
0L,
0L,
0L,
0L,
0L,
Some(DCDExtra2(0, 0)),
Nil, Nil, false,
Nil,
Nil,
false,
AvatarConverter.MakeCosmetics(obj)
)
pad_length : Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
pad_length: Option[Int] => DetailedCharacterData(ba, bb(bep, pad_length))(pad_length)
}
/**
@ -117,7 +132,7 @@ class CharacterSelectConverter extends AvatarConverter {
* @return the resulting implant `List`
* @see `ImplantEntry` in `DetailedCharacterData`
*/
private def MakeImplantEntries(obj : Player) : List[ImplantEntry] = {
private def MakeImplantEntries(obj: Player): List[ImplantEntry] = {
List.fill[ImplantEntry](DetailedCharacterData.numberOfImplantSlots(obj.BEP))(ImplantEntry(ImplantType.None, None))
}
@ -129,14 +144,17 @@ class CharacterSelectConverter extends AvatarConverter {
* @see `AvatarConverter.recursiveMakeHolsters`
* @return the `List` of inventory data created from the holsters
*/
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = {
if(!iter.hasNext) {
@tailrec private def recursiveMakeHolsters(
iter: Iterator[EquipmentSlot],
list: List[InternalSlot] = Nil,
index: Int = 0
): List[InternalSlot] = {
if (!iter.hasNext) {
list
}
else {
val slot : EquipmentSlot = iter.next
} else {
val slot: EquipmentSlot = iter.next
slot.Equipment match {
case Some(equip : Tool) =>
case Some(equip: Tool) =>
val jammed = equip.Jammed
equip.Jammed = false
val slot = AvatarConverter.BuildDetailedEquipment(index, equip)

View file

@ -3,12 +3,12 @@ package net.psforever.objects.definition.converter
import net.psforever.objects.SimpleItem
import net.psforever.packet.game.objectcreate.{CommonFieldData, DetailedCommandDetonaterData, HandheldData}
import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import net.psforever.types.PlanetSideGUID
import scala.util.{Success, Try}
class CommandDetonaterConverter extends ObjectCreateConverter[SimpleItem]() {
override def ConstructorData(obj : SimpleItem) : Try[HandheldData] = {
override def ConstructorData(obj: SimpleItem): Try[HandheldData] = {
Success(
HandheldData(
CommonFieldData(
@ -26,7 +26,7 @@ class CommandDetonaterConverter extends ObjectCreateConverter[SimpleItem]() {
)
}
override def DetailedConstructorData(obj : SimpleItem) : Try[DetailedCommandDetonaterData] = {
override def DetailedConstructorData(obj: SimpleItem): Try[DetailedCommandDetonaterData] = {
Success(
DetailedCommandDetonaterData(
CommonFieldData(

View file

@ -10,13 +10,13 @@ import scala.annotation.tailrec
import scala.util.{Failure, Success, Try}
class CorpseConverter extends AvatarConverter {
override def ConstructorData(obj : Player) : Try[PlayerData] =
override def ConstructorData(obj: Player): Try[PlayerData] =
Failure(new Exception("CorpseConverter should not be used to generate CharacterData"))
override def DetailedConstructorData(obj : Player) : Try[DetailedPlayerData] = {
override def DetailedConstructorData(obj: Player): Try[DetailedPlayerData] = {
Success(
DetailedPlayerData.apply(
PlacementData(obj.Position, Vector3(0,0, obj.Orientation.z)),
PlacementData(obj.Position, Vector3(0, 0, obj.Orientation.z)),
MakeAppearanceData(obj),
MakeDetailedCharacterData(obj),
InventoryData((MakeHolsters(obj) ++ MakeInventory(obj)).sortBy(_.parentSlot)),
@ -30,8 +30,8 @@ class CorpseConverter extends AvatarConverter {
* @param obj the `Player` game object
* @return the resulting `CharacterAppearanceData`
*/
private def MakeAppearanceData(obj : Player) : Int=>CharacterAppearanceData = {
val aa : Int=>CharacterAppearanceA = CharacterAppearanceA(
private def MakeAppearanceData(obj: Player): Int => CharacterAppearanceData = {
val aa: Int => CharacterAppearanceA = CharacterAppearanceA(
BasicCharacterData(obj.Name, obj.Faction, CharacterGender.Male, 0, CharacterVoice.Mute),
CommonFieldData(
obj.Faction,
@ -52,7 +52,7 @@ class CorpseConverter extends AvatarConverter {
0,
0
)
val ab : (Boolean,Int)=>CharacterAppearanceB = CharacterAppearanceB(
val ab: (Boolean, Int) => CharacterAppearanceB = CharacterAppearanceB(
0L,
outfit_name = "",
outfit_logo = 0,
@ -75,34 +75,48 @@ class CorpseConverter extends AvatarConverter {
CharacterAppearanceData(aa, ab, RibbonBars())
}
private def MakeDetailedCharacterData(obj : Player) : Option[Int]=>DetailedCharacterData = {
val maxOpt : Option[Long] = if(obj.ExoSuit == ExoSuitType.MAX) { Some(0L) } else { None }
val ba : DetailedCharacterA = DetailedCharacterA(
private def MakeDetailedCharacterData(obj: Player): Option[Int] => DetailedCharacterData = {
val maxOpt: Option[Long] = if (obj.ExoSuit == ExoSuitType.MAX) { Some(0L) }
else { None }
val ba: DetailedCharacterA = DetailedCharacterA(
bep = 0L,
cep = 0L,
0L, 0L, 0L,
0, 0,
0L,
0L,
0L,
0,
0,
false,
0,
0L,
0, 0,
0,
0,
maxOpt,
0, 0, 0L,
0,
0,
0L,
List(0, 0, 0, 0, 0, 0),
certs = List.empty[CertificationType.Value]
)
val bb : (Long, Option[Int])=>DetailedCharacterB = DetailedCharacterB(
val bb: (Long, Option[Int]) => DetailedCharacterB = DetailedCharacterB(
None,
implants = List.empty[ImplantEntry],
Nil, Nil,
Nil,
Nil,
firstTimeEvents = List.empty[String],
tutorials = List.empty[String],
0L, 0L, 0L, 0L, 0L,
0L,
0L,
0L,
0L,
0L,
Some(DCDExtra2(0, 0)),
Nil, Nil, false,
Nil,
Nil,
false,
cosmetics = None
)
(pad_length : Option[Int]) => DetailedCharacterData(ba, bb(0, pad_length))(pad_length)
(pad_length: Option[Int]) => DetailedCharacterData(ba, bb(0, pad_length))(pad_length)
}
/**
@ -112,11 +126,11 @@ class CorpseConverter extends AvatarConverter {
* @param obj the `Player` game object
* @return a list of all items that were in the inventory in decoded packet form
*/
private def MakeInventory(obj : Player) : List[InternalSlot] = {
private def MakeInventory(obj: Player): List[InternalSlot] = {
obj.Inventory.Items
.map(item => {
val equip : Equipment = item.obj
BuildEquipment(item.start, equip)
val equip: Equipment = item.obj
BuildEquipment(item.start, equip)
})
}
@ -128,7 +142,7 @@ class CorpseConverter extends AvatarConverter {
* @param obj the `Player` game object
* @return a list of all items that were in the holsters in decoded packet form
*/
private def MakeHolsters(obj : Player) : List[InternalSlot] = {
private def MakeHolsters(obj: Player): List[InternalSlot] = {
recursiveMakeHolsters(obj.Holsters().iterator)
}
@ -139,21 +153,23 @@ class CorpseConverter extends AvatarConverter {
* @param index which holster is currently being explored
* @return the `List` of inventory data created from the holsters
*/
@tailrec private def recursiveMakeHolsters(iter : Iterator[EquipmentSlot], list : List[InternalSlot] = Nil, index : Int = 0) : List[InternalSlot] = {
if(!iter.hasNext) {
@tailrec private def recursiveMakeHolsters(
iter: Iterator[EquipmentSlot],
list: List[InternalSlot] = Nil,
index: Int = 0
): List[InternalSlot] = {
if (!iter.hasNext) {
list
}
else {
val slot : EquipmentSlot = iter.next
if(slot.Equipment.isDefined) {
val equip : Equipment = slot.Equipment.get
} else {
val slot: EquipmentSlot = iter.next
if (slot.Equipment.isDefined) {
val equip: Equipment = slot.Equipment.get
recursiveMakeHolsters(
iter,
list :+ BuildEquipment(index, equip),
index + 1
)
}
else {
} else {
recursiveMakeHolsters(iter, list, index + 1)
}
}
@ -165,8 +181,13 @@ class CorpseConverter extends AvatarConverter {
* @param equip the game object
* @return the game object in decoded packet form
*/
private def BuildEquipment(index : Int, equip : Equipment) : InternalSlot = {
InternalSlot(equip.Definition.ObjectId, equip.GUID, index, equip.Definition.Packet.DetailedConstructorData(equip).get)
private def BuildEquipment(index: Int, equip: Equipment): InternalSlot = {
InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
index,
equip.Definition.Packet.DetailedConstructorData(equip).get
)
}
}

View file

@ -7,14 +7,17 @@ import net.psforever.packet.game.objectcreate.{DestroyedVehicleData, PlacementDa
import scala.util.{Failure, Success, Try}
class DestroyedVehicleConverter extends ObjectCreateConverter[Vehicle]() {
override def DetailedConstructorData(obj : Vehicle) : Try[DestroyedVehicleData] =
Failure(new Exception("DestroyedVehicleConverter should not be used to generate detailed DestroyedVehicleData (nothing should)"))
override def DetailedConstructorData(obj: Vehicle): Try[DestroyedVehicleData] =
Failure(
new Exception(
"DestroyedVehicleConverter should not be used to generate detailed DestroyedVehicleData (nothing should)"
)
)
override def ConstructorData(obj : Vehicle) : Try[DestroyedVehicleData] = {
if(obj.Health > 0) {
override def ConstructorData(obj: Vehicle): Try[DestroyedVehicleData] = {
if (obj.Health > 0) {
Failure(new Exception("Vehicle used on DestroyedVehicleConverter has not yet been destroyed (Health == 0)"))
}
else {
} else {
Success(DestroyedVehicleData(PlacementData(obj.Position, obj.Orientation)))
}
}

View file

@ -8,12 +8,12 @@ import net.psforever.types.PlanetSideGUID
import scala.util.{Failure, Success, Try}
class DroppodConverter extends ObjectCreateConverter[Vehicle]() {
override def DetailedConstructorData(obj : Vehicle) : Try[DroppodData] =
override def DetailedConstructorData(obj: Vehicle): Try[DroppodData] =
Failure(new Exception("DroppodConverter should not be used to generate detailed DroppodData (nothing should)"))
override def ConstructorData(obj : Vehicle) : Try[DroppodData] = {
override def ConstructorData(obj: Vehicle): Try[DroppodData] = {
val health = StatConverter.Health(obj.Health, obj.MaxHealth)
if(health > 0) { //active
if (health > 0) { //active
Success(
DroppodData(
CommonFieldDataWithPlacement(
@ -29,7 +29,7 @@ class DroppodConverter extends ObjectCreateConverter[Vehicle]() {
v5 = None,
obj.Owner match {
case Some(owner) => owner
case None => PlanetSideGUID(0)
case None => PlanetSideGUID(0)
}
)
),
@ -38,8 +38,7 @@ class DroppodConverter extends ObjectCreateConverter[Vehicle]() {
unk = false
)
)
}
else { //destroyed
} else { //destroyed
Success(
DroppodData(
CommonFieldDataWithPlacement(

View file

@ -10,9 +10,9 @@ import net.psforever.types.PlanetSideGUID
import scala.util.{Failure, Success, Try}
class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
override def ConstructorData(obj : TurretDeployable) : Try[OneMannedFieldTurretData] = {
override def ConstructorData(obj: TurretDeployable): Try[OneMannedFieldTurretData] = {
val health = StatConverter.Health(obj.Health, obj.MaxHealth)
if(health > 3) {
if (health > 3) {
Success(
OneMannedFieldTurretData(
CommonFieldDataWithPlacement(
@ -28,7 +28,7 @@ class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
None,
obj.Owner match {
case Some(owner) => owner
case None => PlanetSideGUID(0)
case None => PlanetSideGUID(0)
}
)
),
@ -36,8 +36,7 @@ class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
Some(InventoryData(FieldTurretConverter.MakeMountings(obj)))
)
)
}
else {
} else {
Success(
OneMannedFieldTurretData(
CommonFieldDataWithPlacement(
@ -60,17 +59,19 @@ class FieldTurretConverter extends ObjectCreateConverter[TurretDeployable]() {
}
}
override def DetailedConstructorData(obj : TurretDeployable) : Try[OneMannedFieldTurretData] =
override def DetailedConstructorData(obj: TurretDeployable): Try[OneMannedFieldTurretData] =
Failure(new Exception("converter should not be used to generate detailed OneMannedFieldTurretData"))
}
object FieldTurretConverter {
private def MakeMountings(obj : WeaponTurret) : List[InventoryItemData.InventoryItem] = {
obj.Weapons.map({
case(index, slot) =>
val equip : Equipment = slot.Equipment.get
val equipDef = equip.Definition
InventoryItemData(equipDef.ObjectId, equip.GUID, index, equipDef.Packet.ConstructorData(equip).get)
}).toList
private def MakeMountings(obj: WeaponTurret): List[InventoryItemData.InventoryItem] = {
obj.Weapons
.map({
case (index, slot) =>
val equip: Equipment = slot.Equipment.get
val equipDef = equip.Definition
InventoryItemData(equipDef.ObjectId, equip.GUID, index, equipDef.Packet.ConstructorData(equip).get)
})
.toList
}
}

View file

@ -9,7 +9,7 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import scala.util.{Failure, Success, Try}
class InternalTelepadDeployableConverter extends ObjectCreateConverter[PlanetSideGameObject with TelepadLike]() {
override def ConstructorData(obj : PlanetSideGameObject with TelepadLike) : Try[TelepadDeployableData] = {
override def ConstructorData(obj: PlanetSideGameObject with TelepadLike): Try[TelepadDeployableData] = {
obj.Router match {
case Some(PlanetSideGUID(0)) =>
Failure(new IllegalStateException("InternalTelepadDeployableConverter: knowledge of parent Router is null"))
@ -34,7 +34,9 @@ class InternalTelepadDeployableConverter extends ObjectCreateConverter[PlanetSid
)
case None =>
Failure(new IllegalStateException("InternalTelepadDeployableConverter: telepad needs to know id of its parent Router"))
Failure(
new IllegalStateException("InternalTelepadDeployableConverter: telepad needs to know id of its parent Router")
)
}
}
}

View file

@ -7,11 +7,11 @@ import net.psforever.packet.game.objectcreate.{CommonFieldData, DetailedAmmoBoxD
import scala.util.{Success, Try}
class KitConverter extends ObjectCreateConverter[Kit]() {
override def ConstructorData(obj : Kit) : Try[CommonFieldData] = {
override def ConstructorData(obj: Kit): Try[CommonFieldData] = {
Success(CommonFieldData()(false))
}
override def DetailedConstructorData(obj : Kit) : Try[DetailedAmmoBoxData] = {
override def DetailedConstructorData(obj: Kit): Try[DetailedAmmoBoxData] = {
Success(DetailedAmmoBoxData(0, 1))
}
}

View file

@ -10,7 +10,7 @@ import net.psforever.types.{PlanetSideEmpire, PlanetSideGUID}
import scala.util.{Success, Try}
class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]() {
override def ConstructorData(obj : LockerEquipment) : Try[LockerContainerData] = {
override def ConstructorData(obj: LockerEquipment): Try[LockerContainerData] = {
MakeInventory(obj.Inventory) match {
case Nil =>
Success(LockerContainerData(None))
@ -19,18 +19,21 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]()
}
}
override def DetailedConstructorData(obj : LockerEquipment) : Try[DetailedLockerContainerData] = {
if(obj.Inventory.Size > 0) {
Success(DetailedLockerContainerData(
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
Some(InventoryData(MakeDetailedInventory(obj.Inventory)))
))
}
else {
Success(DetailedLockerContainerData(
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
None
))
override def DetailedConstructorData(obj: LockerEquipment): Try[DetailedLockerContainerData] = {
if (obj.Inventory.Size > 0) {
Success(
DetailedLockerContainerData(
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
Some(InventoryData(MakeDetailedInventory(obj.Inventory)))
)
)
} else {
Success(
DetailedLockerContainerData(
CommonFieldData(PlanetSideEmpire.NEUTRAL, false, false, true, None, false, None, None, PlanetSideGUID(0)),
None
)
)
}
}
@ -40,13 +43,18 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]()
* @param inv the inventory container
* @return a list of all items that were in the inventory in decoded packet form
*/
private def MakeInventory(inv : GridInventory) : List[InternalSlot] = {
private def MakeInventory(inv: GridInventory): List[InternalSlot] = {
inv.Items
.map(item => {
val equip : Equipment = item.obj
InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.ConstructorData(equip).get)
val equip: Equipment = item.obj
InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
item.start,
equip.Definition.Packet.ConstructorData(equip).get
)
})
}
}
/**
* Transform a list of contained items into a list of contained `InternalSlot` objects.
@ -54,11 +62,16 @@ class LockerContainerConverter extends ObjectCreateConverter[LockerEquipment]()
* @param inv the inventory container
* @return a list of all items that were in the inventory in decoded packet form
*/
private def MakeDetailedInventory(inv : GridInventory) : List[InternalSlot] = {
private def MakeDetailedInventory(inv: GridInventory): List[InternalSlot] = {
inv.Items
.map(item => {
val equip : Equipment = item.obj
InternalSlot(equip.Definition.ObjectId, equip.GUID, item.start, equip.Definition.Packet.DetailedConstructorData(equip).get)
val equip: Equipment = item.obj
InternalSlot(
equip.Definition.ObjectId,
equip.GUID,
item.start,
equip.Definition.Packet.DetailedConstructorData(equip).get
)
})
}
}

Some files were not shown because too many files have changed in this diff Show more