11use message:: eldenring:: {
2- ObjectIdentifier , PlayRegionArea , RequestCreateBloodstainParams ,
3- RequestGetBloodstainListParams , RequestGetDeadingGhostParams , ResponseCreateBloodstainParams ,
4- ResponseGetBloodstainListParams , ResponseGetBloodstainListParamsEntry ,
5- ResponseGetDeadingGhostParams ,
2+ BloodstainAdvertisementData , ObjectIdentifier , PlayRegionArea , Position ,
3+ RequestCreateBloodstainParams , RequestGetBloodstainListParams , RequestGetDeadingGhostParams ,
4+ ResponseCreateBloodstainParams , ResponseGetBloodstainListParams ,
5+ ResponseGetBloodstainListParamsEntry , ResponseGetDeadingGhostParams ,
66} ;
77use sqlx:: Row ;
8+ use wire:: deserialize;
89
910use crate :: handler:: HandleRequest ;
1011
@@ -56,7 +57,23 @@ const SELECT_BY_ID_QUERY: &str = "
5657 SELECT *
5758 FROM bloodstains
5859 WHERE bloodstain_id = $1" ;
60+
5961const ROUNDTABLE_PLAY_REGION_ID : i32 = 1110000 ;
62+ /// BBOX defining the PVP-enabled area within the Roundtable Hold
63+ /// (lower part where player can be invaded by npc invader)
64+ const ROUNDTABLE_PVP_ENABLED_AREA_BBOX : [ ( f32 , f32 , f32 ) ; 2 ] =
65+ [ ( -325.0 , -35.0 , -325.0 ) , ( -245.0 , -25.0 , -245.0 ) ] ;
66+
67+ fn is_in_bbox ( pos : Position , bbox : [ ( f32 , f32 , f32 ) ; 2 ] ) -> bool {
68+ let min = bbox[ 0 ] ;
69+ let max = bbox[ 1 ] ;
70+ pos. x >= min. 0
71+ && pos. x <= max. 0
72+ && pos. y >= min. 1
73+ && pos. y <= max. 1
74+ && pos. z >= min. 2
75+ && pos. z <= max. 2
76+ }
6077
6178impl HandleRequest < Box < RequestCreateBloodstainParams > , ResponseCreateBloodstainParams >
6279 for DefaultClientHandler < ' _ >
@@ -65,11 +82,15 @@ impl HandleRequest<Box<RequestCreateBloodstainParams>, ResponseCreateBloodstainP
6582 & mut self ,
6683 request : & Box < RequestCreateBloodstainParams > ,
6784 ) -> Result < ResponseCreateBloodstainParams , Box < dyn std:: error:: Error > > {
68- if request. area . play_region == ROUNDTABLE_PLAY_REGION_ID {
69- // Don't store bloodstains in the Roundtable Hold area.
70- return Ok ( ResponseCreateBloodstainParams {
71- identifier : ObjectIdentifier ( 0 ) ,
72- } ) ;
85+ if request. area . play_region as i32 == ROUNDTABLE_PLAY_REGION_ID {
86+ // check that location is in the pvp-enabled area of the roundtable
87+ let adv_data: BloodstainAdvertisementData = deserialize ( & request. advertisement_data ) ?;
88+ let pos = adv_data. location . position ;
89+ if !is_in_bbox ( pos, ROUNDTABLE_PVP_ENABLED_AREA_BBOX ) {
90+ return Ok ( ResponseCreateBloodstainParams {
91+ identifier : ObjectIdentifier ( 0 ) ,
92+ } ) ;
93+ }
7394 }
7495 let bloodstain_id = sqlx:: query ( INSERT_QUERY )
7596 . bind ( self . session . player_id )
@@ -100,7 +121,6 @@ impl HandleRequest<Box<RequestGetBloodstainListParams>, ResponseGetBloodstainLis
100121 . search_areas
101122 . iter ( )
102123 . map ( |a| a. play_region as i32 )
103- . filter ( |& pr| pr != ROUNDTABLE_PLAY_REGION_ID )
104124 . collect :: < Vec < i32 > > ( ) ;
105125
106126 if play_regions. is_empty ( ) {
0 commit comments