meta data for this page
  •  

📚 差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
后一修订版
前一修订版
scripting:world:character [2024/06/14 03:51] bibiboxsscripting:world:character [2025/06/02 14:43] (当前版本) wpr
行 4: 行 4:
 ## Event ## Event
  
-### OnCharacterSpawn( character )+### OnCharacterSpawn( character, isCreate )
  
 > 当角色**被生成、被调用`Respawn()`**时触发。 > 当角色**被生成、被调用`Respawn()`**时触发。
 +
 +> **注意:如果此时调用`character.Owner`将始终返回`null`,因为玩家绑定角色不可能在`OnCharacterSpawn`前绑定。**
  
  
行 29: 行 31:
 function OnCharacterKill( killer: Character, character: Character, reason: int ) function OnCharacterKill( killer: Character, character: Character, reason: int )
 ``` ```
- 
- 
- 
-### OnCharacterTriggerEntered( character, entity ) 
- 
-> 当角色附近有新的实体对象**进入范围**时调用。 
-> 
-> **实体对象:`World/Entity`类成员。** 
- 
- 
- 
-### OnCharacterTriggerExited( character, entity ) 
- 
-> 当角色附近有新的实体对象**离开范围**时调用。 
-> 
-> **实体对象:`World/Entity`类成员。** 
  
  
行 55: 行 41:
 function OnCharacterPropChange( character: Character, oldProp: Prop, newProp: Prop ) function OnCharacterPropChange( character: Character, oldProp: Prop, newProp: Prop )
 ``` ```
- 
- 
- 
-### OnCharacterPropCountChange( character, oldCount, newCount ) 
- 
-> 当角色背包池总数(`character.PropCount`)发生变化时调用。 
-> 
  
  
行 77: 行 56:
  
  
-### OnCharacterPropActionBefore( character, prop ) +### OnCharacterPropAction( character, prop, hitPos 
  
-> 当角色手中道具**即将被使用之前**调用,此事件将关键决定当前道具是否允许使用+> 当角色手中道具**每次被使用一次**调用(例如:每次挥拳、开枪等)
 > >
-> **注意:此事件拥有返回值,默认返回`1`,如果返回`0`则表示不允许本次使用**+> **注意:`hitPos`参数表示当前物品最终造成伤害的位置但投掷类物品等无法确定最终位置,所以此处将只返回起点位置
  
-```javascript +[note2]
-function OnCharacterPropActionBefore( character: Character, prop: Prop ): int +
-```+
  
-```javascript +补充:如果`character.CanAction == false`此事件将在角色尝试发起攻击后立即触发(仅单次触发,使是连续攻击道具,但不会发起攻击。
-function OnCharacterPropActionBefore( character, prop ) +
-+
-    if(prop == 0 && character.Health <50) +
-    { +
-        //当玩家血量小于50,且Prop==0时拦截使用请求,不会触发任何效果 +
-        return 0; +
-    } +
-     +
-    return 1; //此处可忽略默认返回1(放行使用请求 +
-+
-```+
  
- +[/note]
- +
-### OnCharacterPropAction( character, prop, hitPos )  +
- +
-> 当角色手中道具**每次被使用一次**时调用(例如:每次挥拳、开枪等)。 +
->  +
-> **注意:`hitPos`参数表示当前物品最终造成伤害的位置,但投掷类物品等无法确定最终位置,所以此处将只返回起点位置。**+
  
 ```javascript ```javascript
行 126: 行 86:
  
  
-### OnCharacterDamage( character, damage, from, type, isImmunity )+### OnCharacterDamage( character, damage, from, type, isImmunity, localHitPos )
  
 > 当角色**被尝试造成任何伤害**时调用,如果造成伤害,会在`OnCharacterHealthChange()`之后调用。 > 当角色**被尝试造成任何伤害**时调用,如果造成伤害,会在`OnCharacterHealthChange()`之后调用。
行 140: 行 100:
  type:伤害类型  type:伤害类型
  isImmunity:是否免疫伤害(如果为true,则表示没有造成伤害,可能被Immunity\Group拦截了)  isImmunity:是否免疫伤害(如果为true,则表示没有造成伤害,可能被Immunity\Group拦截了)
 + localHitPos:受击位置的本地坐标
 */ */
 ``` ```
行 198: 行 159:
 ### ==Vehicle交互事件== ### ==Vehicle交互事件==
  
-> 有关角色与拾取物的交互行为,具体内容请访问[Vehicle文档](scripting/world/vehicle)查看。+> 有关角色与载具的交互行为,具体内容请访问[Vehicle文档](scripting/world/vehicle)查看。
  
  
行 321: 行 282:
  
 > 设置角色透明度(0~255),默认值是`255`。 > 设置角色透明度(0~255),默认值是`255`。
 +>
 +> **注意:此方法不会修改手持物品透明度(`character.PropAlpha`)。`**
  
 ```javascript ```javascript
行 328: 行 291:
  
  
-### character.AlphaTime+### character.Angle
  
-> 设置角色透明渐变时间默认值`1.0`+> 设置角色方向(Y轴)修改角色角度的主要方式
  
 ```javascript ```javascript
-character.AlphaTime 1.0; //float+character.Angle 0.0; //0~360
 ``` ```
  
  
  
-### character.Angle+### character.EulerAngle
  
-设置角色角度方向(Y轴)这是修改角色角度的主要方式+获取角色欧拉角度,通常使用`character.Angle`
  
 ```javascript ```javascript
-character.Angle = 0.0; //0~360+character.EulerAngle: Vector
 ``` ```
  
  
  
-### character.EulerAngle+### character.HAngle
  
-> 设置角色欧拉角度。 +> 设置角色本地偏移角度(水平),可模拟【Q|E】侧身等行为。 
-> + 
-> 根据引擎角色机制,修改除Y轴外其他角度时,常规情况下,`X\Z轴`会在短时间内自动Lerp重置到`0.0`(类似不倒翁)。+```javascript 
 +character.HAngle = 0.0; //float 
 +``` 
 + 
 + 
 + 
 +### character.VAngle 
 + 
 +> 设置角色本地偏移角度前后,可模拟前后侧身等行为
  
 ```javascript ```javascript
-character.EulerAngle Vector(00, 0);+character.VAngle = 0.0; //float
 ``` ```
  
行 366: 行 337:
 ```javascript ```javascript
 character.Health = 100; character.Health = 100;
 +```
 +
 +
 +
 +### character.DefaultHealth
 +
 +> 获取角色默认血量。
 +
 +```javascript
 +character.DefaultHealth: int
 ``` ```
  
行 406: 行 387:
 ### character.BodyHeight ### character.BodyHeight
  
-> 获取角色身体高度,不同的角色可能有不同高度,通常为头顶上方高度(例如:人类默认`2.0`)+> 获取角色身体高度(本地偏移量),不同的角色类型可能有不同高度,通常为头部偏高一点位置
  
-> 可能用于获取头顶`Bubble`显示的高度。+扩展:可能用于获取头顶`Bubble`显示的高度。
  
 ```javascript ```javascript
行 426: 行 407:
 ``` ```
  
- 
- 
-### character.TriggerDistance 
- 
-> 设置角色触发检测范围,此属性将影响`character.GetTrigger()`相关检测距离,默认是`1.5`。 
- 
-```javascript 
-character.TriggerDistance = 1.55; //float 
-``` 
  
  
行 451: 行 423:
 ### character.AITarget ### character.AITarget
  
-> 为当前角色设置一个AI目标**对象**,详情参考[《CharacterAI》文档](scripting/extend/character_ai)。+> 为当前角色设置一个AI目标**对象**,详情参考[《CharacterAI》文档](developer/extend/character_ai)。
 > >
 > **注意:当前属性被设置成为`null`的值后,属性`AITargetPos`将被设置为`default`,==两种Target属性只能同时存在一个==。** > **注意:当前属性被设置成为`null`的值后,属性`AITargetPos`将被设置为`default`,==两种Target属性只能同时存在一个==。**
行 463: 行 435:
 ### character.AITargetPos ### character.AITargetPos
  
-> 为当前角色设置一个AI目标**坐标**,详情参考[《CharacterAI》文档](scripting/extend/character_ai)。+> 为当前角色设置一个AI目标**坐标**,详情参考[《CharacterAI》文档](developer/extend/character_ai)。
 > >
 > **注意:当前属性被设置成为`null`的值后,属性`AITargetPos`将被设置为`VECTOR_NULL`(常量,表示无意义\空坐标),==两种Target属性只能同时存在一个==。** > **注意:当前属性被设置成为`null`的值后,属性`AITargetPos`将被设置为`VECTOR_NULL`(常量,表示无意义\空坐标),==两种Target属性只能同时存在一个==。**
行 475: 行 447:
 ### character.AIState ### character.AIState
  
-> 为当前角色设置一个AI状态(行为\性格),详情参考[《CharacterAI》文档](scripting/extend/character_ai)。+> 为当前角色设置一个AI状态(行为\性格),详情参考[《CharacterAI》文档](developer/extend/character_ai)。
  
 ```javascript ```javascript
行 485: 行 457:
 ### character.AIMoveState ### character.AIMoveState
  
-> 为当前角色设置一个AI移动行为状态(自动\行走\奔跑),详情参考[《CharacterAI》文档](scripting/extend/character_ai)。+> 为当前角色设置一个AI移动行为状态(自动\行走\奔跑),详情参考[《CharacterAI》文档](developer/extend/character_ai)。
  
 ```javascript ```javascript
行 495: 行 467:
 ### character.AIDistance ### character.AIDistance
  
-> 为当前角色设置一个AI距离属性(不同AI状态有不同的意义),详情参考[《CharacterAI》文档](scripting/extend/character_ai)。+> 为当前角色设置一个AI距离属性(不同AI状态有不同的意义),详情参考[《CharacterAI》文档](developer/extend/character_ai)。
  
 ```javascript ```javascript
-character.AIDistance = 3.0; //float+character.AIDistance = 32; //float
 ``` ```
  
行 543: 行 515:
 ### character.Skin ### character.Skin
  
-> 设置角色皮肤贴图,内置ID参考[《世界资源实例汇总》](reference/instances),设置为`-1`可请求一个随机皮肤(如存在)。 +> 设置角色皮肤\贴图,内置ID参考[《世界资源实例汇总》](reference/instances),设置为`-1`可请求一个随机皮肤(如存在)。
-+
-> *注意:需自行确保皮肤贴图及ID正确,理论上人类也可以穿上**动物或外部导入皮肤**(如存在),但同时也会导致贴图异常。*+
  
 ```javascript ```javascript
行 592: 行 562:
 ```javascript ```javascript
 character.AdditionSpeedMultiplier = 1.0; character.AdditionSpeedMultiplier = 1.0;
 +```
 +
 +
 +
 +### character.SwimMultiplier
 +
 +> 设置角色**游泳速度**倍数(相对于`character.Speed`),默认为`0.6`。
 +
 +```javascript
 +character.SwimMultiplier= 0.3;
 +```
 +
 +
 +
 +### character.CrouchMultiplier
 +
 +> 设置角色**蹲下速度**倍数(相对于`character.Speed`),默认为`0.8`。
 +
 +```javascript
 +character.CrouchMultiplier = 0.8;
 +```
 +
 +
 +
 +### character.JumpMultiplier
 +
 +> 设置角色**跳跃高度**倍数,默认为`1.0`。
 +
 +```javascript
 +character.JumpMultiplier = 1.0;
 ``` ```
  
行 602: 行 602:
 ```javascript ```javascript
 character.ActionContinue; //int character.ActionContinue; //int
 +```
 +
 +
 +
 +### character.IsAI
 +
 +> 获取角色是否为NPC(AI)。
 +
 +```javascript
 +character.IsAI: bool
 +```
 +
 +
 +
 +### character.IsPlayer
 +
 +> 获取角色是否为玩家控制的角色。
 +
 +```javascript
 +character.IsPlayer: bool
 ``` ```
  
行 683: 行 703:
  
 ```javascript ```javascript
-character.IsPassenger: bool+character.IsExtend: bool
 ``` ```
  
行 689: 行 709:
  
 ### character.Color ### character.Color
 +
 +[note3]
 +此属性当前是过时的,等待新版API同步。
 +[/note]
  
 > 设置角色的**主要颜色**,此属性主要用于人形角色。 > 设置角色的**主要颜色**,此属性主要用于人形角色。
行 700: 行 724:
 ```javascript ```javascript
 character.Color = Color(255, 204, 153); character.Color = Color(255, 204, 153);
-character.Color1 = Color(255, 204, 153); //另一种属性映射,意义相同 
-``` 
- 
- 
- 
-### character.Color2 
- 
-> 设置角色的**次要颜色**,此属性主要用于人形角色。 
-> 
-> 在人形角色实例修改时,将会修改目标角色的**头发颜色**。 
-> 
-> 在其他角色实例修改时,可能不会有期望的效果。 
- 
-```javascript 
-character.Color2 = Color(255, 255, 0); 
 ``` ```
  
行 721: 行 730:
 ### character.Immunity ### character.Immunity
  
-> 设定角色的免疫属性(可叠加位Flag),设置为`-1`自动识别完全免疫(所有Flag相加后的结果)。+> 设定角色的[免疫属性](reference/instances "免疫属性")(可叠加位Flag),设置为`-1`自动识别完全免疫(所有Flag相加后的结果)。
  
 ```javascript ```javascript
行 731: 行 740:
 ``` ```
  
-| Type | 说明                   | 
-| ---- | ---------------------- | 
-| 0    | 无                     | 
-| 1    | 无视常规\挥动攻击      | 
-| 2    | 无视子弹攻击           | 
-| 4    | 无视爆炸伤害           | 
-| 8    | 无视碰撞(及掉落)伤害 | 
-| 16    | 无视火焰伤害 | 
  
  
行 756: 行 757:
  
 > 设置角色**锁定行动开关`HasAction`**,当功能被锁定后,除引擎内置强制事件外(例如:角色死亡),无法修改`HasAction`属性(即使手持物品)。 > 设置角色**锁定行动开关`HasAction`**,当功能被锁定后,除引擎内置强制事件外(例如:角色死亡),无法修改`HasAction`属性(即使手持物品)。
 +
 +> 注意:如果希望控制Action执行,可能要找的是`character.CanAction`,而非此方法。
  
 ```javascript ```javascript
行 781: 行 784:
 ```javascript ```javascript
 character.FrozenFocus = false; //bool character.FrozenFocus = false; //bool
 +```
 +
 +
 +
 +### character.FocusMode
 +
 +> 设置角色**专注聚焦模式开关**,此属性开启后角色将始终保持**(仅)聚焦动作**,此功能更适合用于第一人称游戏使用。
 +
 +[note2]
 +
 +注意:此模式不会强制锁定`HasFocus`,同时也不会修改默认移动速度,仅强制**锁定聚焦动作**。
 +
 +[/note]
 +
 +```javascript
 +character.FocusMode = false; //bool
 +```
 +
 +
 +
 +### character.StandAction
 +
 +> 设置角色**强制站立Action开关**,当属性开启后,角色在Action时将被强制设为站立状态**(禁止移动攻击)**,此属性默认关闭。
 +
 +> 扩展引导:当角色手持道具发生改变时,检测`Prop.ID`是否为希望站立攻击的道具,并`if | else`激活&取消此属性。
 +
 +```javascript
 +character.StandAction = false; //bool
 +```
 +
 +
 +
 +### character.DriveAction
 +
 +> 设置角色**载具驾驶&乘坐Action开关**,当属性开启后,角色乘坐载具时可进行Action或射击,此属性默认开启。
 +>
 +> **注意:角色在乘坐载具攻击时,不会对自身载具造成伤害(不包括爆炸类道具)。**
 +
 +```javascript
 +character.DriveAction = true; //bool
 +```
 +
 +
 +
 +### character.CanAction
 +
 +> 设置角色是否可以发起攻击,默认为`true`。
 +>
 +> 扩展引导:此方法可用于实现武器子弹不足时无法射击等功能。
 +
 +[note2]
 +
 +注意:此属性被设置为`false`后仍然会触发`OnCharacterPropAction`(仅单次触发,即使是连续攻击道具),因此可提前判断`character.CanAction`作不同条件处理。
 +
 +[/note]
 +
 +```javascript
 +character.CanAction = true;
 ``` ```
  
行 797: 行 858:
  
  
-### character.Frozen+### character.Shadow
  
-> 设置角色冻结状态冻结后将无法移动、驾驶等操作+> 设置角色阴影开关默认开启`true`
 > >
 +
 +```javascript
 +character.Shadow = true;
 +```
 +
 +
 +
 +### character.Frozen
 +
 +> 设置角色冻结状态,冻结后将无法移动、驾驶等操作(被动操作除外)。
  
 ```javascript ```javascript
行 810: 行 881:
 ### character.FlyMode ### character.FlyMode
  
-> 设置角色飞行模式(不是一种手机模式),角色将可以进行飞天悬空移动+> 设置角色飞行模式(不是一种手机模式),角色将可以进行飞天移动。
 > >
-> **注意:当角色死亡,将自动取消飞行模式。**+> **注意:当角色死亡、乘坐或离开载具,将自动取消飞行模式,同时无法激活。** 
 + 
 +[note2] 
 +如果目标角色是NPC,则将寻路模式改为飞天移动,同时将直奔目标方向移动(忽略碰撞)。 
 +[/note]
  
 ```javascript ```javascript
行 830: 行 905:
 ```javascript ```javascript
 character.FlyTime: float character.FlyTime: float
 +```
 +
 +
 +
 +### character.SidelingControl
 +
 +> 设置角色侧身控制开关(允许玩家`Q|E`向左右侧身,适合于射击等玩法),默认`true`。
 +
 +```javascript
 +character.SidelingControl: bool
 ``` ```
  
行 914: 行 999:
 ```javascript ```javascript
 character.PropCount = 0; character.PropCount = 0;
 +```
 +
 +
 +
 +### character.PropAlpha
 +
 +> 设置**角色手持物品**透明度,默认值是`255`。
 +
 +```javascript
 +character.PropAlpha = 255;
 ``` ```
  
行 927: 行 1022:
  
 ```javascript ```javascript
-function Character.Create( type: int, pos: Vector, angle: float = 0 ): Character+function Character.Create( type: int, pos: Vector, angle: float = 0, skin: number ): Character
 ``` ```
  
行 934: 行 1029:
 Character.Create(0, Vector(0, 0, 0), 0); Character.Create(0, Vector(0, 0, 0), 0);
 ``` ```
 +
 +- **`type`:**生物类型
 +- **`pos`:**坐标位置
 +- **`angle`:**角度
 +- **`skin`:**皮肤ID(人形角色更多使用)
 +- **`randomStyle`:**是否随机样式(执行`character.RandomStyle()`)
  
  
行 996: 行 1097:
  
 ```javascript ```javascript
-function character.Damage( damage: int, from: Entity = null, reason: int = 0 )+function character.Damage( damage: int, from: Entity = null, reason: int = 0, localHitPos: Vector = Vector(0, 0, 0) ) 
 +``` 
 + 
 + 
 + 
 +### character.RandomStyle() 
 + 
 +> 随机当前角色样式(配色`character.Color1 | characterColor2`)。 
 +
 +> 此方法主要用于**人形角色**,对于其他类型角色更多是模型随机叠加颜色。 
 + 
 +```javascript 
 +function character.RandomStyle()
 ``` ```
  
行 1007: 行 1120:
 ```javascript ```javascript
 function character.Action() function character.Action()
 +```
 +
 +
 +
 +### character.Jump()
 +
 +> 使当前角色立即执行一次`Jump`跳跃行为,因为连续跳跃间隔及其他冻结等限制,跳跃指令并非每次都执行成功。
 +
 +```javascript
 +function character.Jump( multiple: float = 1.0 )
 ``` ```
  
行 1134: 行 1257:
 ```javascript ```javascript
 function character.EnterVehicle( vehicle: Vehicle ): bool //是否进入成功 function character.EnterVehicle( vehicle: Vehicle ): bool //是否进入成功
-``` 
- 
- 
- 
-### character.GetTriggerCount() 
- 
-> 获取角色范围触发实例数量,此功能可获取某个角色`character.TriggerDistance`范围内的实例数量。 
-> 
-> 实体通常包括:角色、载具、拾取物、检查点等。 
- 
-```javascript 
-function character.GetTriggerCount(): int 
-``` 
- 
- 
- 
-### character.GetTrigger() 
- 
-> 获取角色范围触发实例(根据索引),此功能可获取某个角色`character.TriggerDistance`范围内的实例对象。 
- 
-```javascript 
-function character.GetTrigger( index: int ): Entity 
-``` 
- 
-```javascript 
-//遍历某个角色范围内所有实例对象,可用于扩展上车、拾取物品、使用等操作 
-for(let i=0;i<character.GetTriggerCount();i++) 
-{ 
-    let target = character.GetTrigger(i); 
-    DLog("trigger[" + i + "]: " + target.GetType()); 
-} 
 ``` ```
  
行 1246: 行 1338:
 > 设置\播放一段当前角色的**自定义动作**(例如:挥手、躺下、坐下等),详细动作ID参考[《世界资源实例汇总》](reference/instances)。 > 设置\播放一段当前角色的**自定义动作**(例如:挥手、躺下、坐下等),详细动作ID参考[《世界资源实例汇总》](reference/instances)。
 > >
-> **注意:如果希望主动停止\中断播放动作,使用参数的此方法即可(`character.SetAnim()`)。**+> **注意:如果希望主动停止\中断播放动作,使用默认参数即可(`character.SetAnim(-1)`)。**
  
 ```javascript ```javascript
-function character.SetAnim( anim: int, loop: bool = false )+function character.SetAnim( anim: int = -1, loop: bool = false )
 ``` ```
  
-- **anim:**播放动作ID+- **anim:**播放动作ID(-1表示停止播放)
 - **loop:**是否循环播放(直到主动停止播放) - **loop:**是否循环播放(直到主动停止播放)
  
  
  
-### character.SetExtend()+### character.SetRemodel()
  
-设置角色扩展属性(例如:人形角色的头部、头发),==**此功能更多只适用于人形角色**==+绑定角色**重写模型对象**。
 > >
 +> 此方法允许将当前角色替换为一个`Model`对象,与`SetNodeExtend(0)`不同的是,此方法会将模型变为真正意义上的角色,并且继承碰撞及伤害。
 +>
 +> 重写模型对象同时只能绑定一个,如果有新的对象被绑定则会解绑旧对象。
 +>
 +> **(参数设置为`null`可解除绑定)**
  
 ```javascript ```javascript
-function character.SetExtendtypeindex, index: int )+function character.SetRemodelmodelModel )
 ``` ```
- 
-- **type:**角色扩展类型(人形角色:0=头部\1=头发) 
-- **index:**角色扩展索引 
  
  
  
-### character.GetExtend()+### character.GetRemodel()
  
-> 获取角色扩展属性+> 获取角色**重写模型对象**
  
 ```javascript ```javascript
-function character.GetExtendtype: int ): int+function character.GetRemodel(): Model
 ``` ```
  
行 1288: 行 1382:
 > >
 > **补充:当模型对象被绑定后,想要【读写】位置、角度、缩放(`Pos | Angle | Scale`)等信息时,坐标空间默认为【本地空间】而不是“世界空间”。** > **补充:当模型对象被绑定后,想要【读写】位置、角度、缩放(`Pos | Angle | Scale`)等信息时,坐标空间默认为【本地空间】而不是“世界空间”。**
 +
 +[note2]
 +**注意:父子节点之间不会产生物理碰撞。**
 +[/note]
  
 ```javascript ```javascript
行 1310: 行 1408:
 | 节点位置(Node) | 说明                       | | 节点位置(Node) | 说明                       |
 | ---------------- | -------------------------- | | ---------------- | -------------------------- |
 +| -1 | 角色自身节点(不受动作影响) |
 | 0                | 头部(支持动物角色)                       | | 0                | 头部(支持动物角色)                       |
 | 1                | 身体(支持动物角色)                      | | 1                | 身体(支持动物角色)                      |
-               | 手持物品(关键、右手位置 |+               | 手持物品位置Prop)                   |
 | 4                | 左手位置                   | | 4                | 左手位置                   |
 | 5                | 右手位置                   | | 5                | 右手位置                   |
行 1343: 行 1442:
  
 - **node:**角色节点位置(索引) - **node:**角色节点位置(索引)
 +
  
  
行 1350: 行 1450:
  
 ```javascript ```javascript
-function character.GetNodeExtendPos( node: int ): Vector+function character.GetNodeExtendPos( node: int, isLocal: bool = false ): Vector
 ``` ```
  
 - **node:**角色节点位置(索引) - **node:**角色节点位置(索引)
 +- **isLocal:**是否获取本地空间结果
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +